Merge pull request #27784 from yongtang/10262016-vendor-swarmkit

Revendor swarmkit to 0ec7c6ee4b3185ec4e3d6bd65f8f5542b1761421
This commit is contained in:
Andrea Luzzardi 2016-10-26 14:20:13 -07:00 committed by GitHub
commit d6a5d54086
49 changed files with 3054 additions and 1510 deletions

View file

@ -147,7 +147,7 @@ clone git github.com/docker/containerd 52ef1ceb4b660c42cf4ea9013180a5663968d4c7
clone git github.com/tonistiigi/fifo 8c56881ce5e63e19e2dfc495c8af0fb90916467d
# cluster
clone git github.com/docker/swarmkit 3b221eb0391d34ae0b9dac65df02b5b64de6dff2
clone git github.com/docker/swarmkit 0ec7c6ee4b3185ec4e3d6bd65f8f5542b1761421
clone git github.com/golang/mock bd3c8e81be01eef76d4b503f5e687d2d1354d2d9
clone git github.com/gogo/protobuf v0.3
clone git github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a

View file

@ -48,9 +48,11 @@ func New(config *Config) (*Agent, error) {
return nil, err
}
worker := newWorker(config.DB, config.Executor)
a := &Agent{
config: config,
worker: newWorker(config.DB, config.Executor),
worker: worker,
sessionq: make(chan sessionOperation),
started: make(chan struct{}),
stopped: make(chan struct{}),
@ -278,8 +280,8 @@ func (a *Agent) handleSessionMessage(ctx context.Context, message *api.SessionMe
if message.Node != nil {
if a.node == nil || !nodesEqual(a.node, message.Node) {
if a.config.NotifyRoleChange != nil {
a.config.NotifyRoleChange <- message.Node.Spec.Role
if a.config.NotifyNodeChange != nil {
a.config.NotifyNodeChange <- message.Node.Copy()
}
a.node = message.Node.Copy()
if err := a.config.Executor.Configure(ctx, a.node); err != nil {

View file

@ -24,8 +24,8 @@ type Config struct {
// DB used for task storage. Must be open for the lifetime of the agent.
DB *bolt.DB
// NotifyRoleChange channel receives new roles from session messages.
NotifyRoleChange chan<- api.NodeRole
// NotifyNodeChange channel receives new node changes from session messages.
NotifyNodeChange chan<- *api.Node
// Credentials is credentials for grpc connection to manager.
Credentials credentials.TransportCredentials

View file

@ -277,7 +277,7 @@ func Do(ctx context.Context, task *api.Task, ctlr Controller) (*api.TaskStatus,
}
switch status.State {
case api.TaskStateNew, api.TaskStateAllocated, api.TaskStateAssigned:
case api.TaskStateNew, api.TaskStatePending, api.TaskStateAssigned:
return transition(api.TaskStateAccepted, "accepted")
case api.TaskStateAccepted:
return transition(api.TaskStatePreparing, "preparing")

View file

@ -21,3 +21,25 @@ type Executor interface {
// manager to the executor.
SetNetworkBootstrapKeys([]*api.EncryptionKey) error
}
// SecretsProvider is implemented by objects that can store secrets, typically
// an executor.
type SecretsProvider interface {
Secrets() SecretsManager
}
// SecretGetter contains secret data necessary for the Controller.
type SecretGetter interface {
// Get returns the the secret with a specific secret ID, if available.
// When the secret is not available, the return will be nil.
Get(secretID string) *api.Secret
}
// SecretsManager is the interface for secret storage and updates.
type SecretsManager interface {
SecretGetter
Add(secrets ...api.Secret) // add one or more secrets
Remove(secrets []string) // remove the secrets by ID
Reset() // remove all secrets
}

View file

@ -1,53 +0,0 @@
package agent
import (
"sync"
"github.com/docker/swarmkit/api"
)
// secrets is a map that keeps all the currenty available secrets to the agent
// mapped by secret ID
type secrets struct {
mu sync.RWMutex
m map[string]api.Secret
}
func newSecrets() *secrets {
return &secrets{
m: make(map[string]api.Secret),
}
}
// Get returns a secret by ID. If the secret doesn't exist, returns nil.
func (s *secrets) Get(secretID string) api.Secret {
s.mu.RLock()
defer s.mu.RUnlock()
return s.m[secretID]
}
// Add adds one or more secrets to the secret map
func (s *secrets) Add(secrets ...api.Secret) {
s.mu.Lock()
defer s.mu.Unlock()
for _, secret := range secrets {
s.m[secret.ID] = secret
}
}
// Remove removes one or more secrets by ID from the secret map. Succeeds
// whether or not the given IDs are in the map.
func (s *secrets) Remove(secrets []string) {
s.mu.Lock()
defer s.mu.Unlock()
for _, secret := range secrets {
delete(s.m, secret)
}
}
// Reset removes all the secrets
func (s *secrets) Reset() {
s.mu.Lock()
defer s.mu.Unlock()
s.m = make(map[string]api.Secret)
}

View file

@ -42,7 +42,6 @@ type worker struct {
db *bolt.DB
executor exec.Executor
listeners map[*statusReporterKey]struct{}
secrets *secrets
taskManagers map[string]*taskManager
mu sync.RWMutex
@ -54,7 +53,6 @@ func newWorker(db *bolt.DB, executor exec.Executor) *worker {
executor: executor,
listeners: make(map[*statusReporterKey]struct{}),
taskManagers: make(map[string]*taskManager),
secrets: newSecrets(),
}
}
@ -255,6 +253,15 @@ func reconcileTaskState(ctx context.Context, w *worker, assignments []*api.Assig
}
func reconcileSecrets(ctx context.Context, w *worker, assignments []*api.AssignmentChange, fullSnapshot bool) error {
var secrets exec.SecretsManager
provider, ok := w.executor.(exec.SecretsProvider)
if !ok {
log.G(ctx).Warn("secrets update ignored; executor does not support secrets")
return nil
}
secrets = provider.Secrets()
var (
updatedSecrets []api.Secret
removedSecrets []string
@ -278,11 +285,11 @@ func reconcileSecrets(ctx context.Context, w *worker, assignments []*api.Assignm
// If this was a complete set of secrets, we're going to clear the secrets map and add all of them
if fullSnapshot {
w.secrets.Reset()
secrets.Reset()
} else {
w.secrets.Remove(removedSecrets)
secrets.Remove(removedSecrets)
}
w.secrets.Add(updatedSecrets...)
secrets.Add(updatedSecrets...)
return nil
}

View file

@ -459,6 +459,28 @@ func (m *GetSecretResponse) Reset() { *m = GetSecretResponse{
func (*GetSecretResponse) ProtoMessage() {}
func (*GetSecretResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{40} }
type UpdateSecretRequest struct {
// SecretID is the secret ID to update.
SecretID string `protobuf:"bytes,1,opt,name=secret_id,json=secretId,proto3" json:"secret_id,omitempty"`
// SecretVersion is the version of the secret being updated.
SecretVersion *Version `protobuf:"bytes,2,opt,name=secret_version,json=secretVersion" json:"secret_version,omitempty"`
// Spec is the new spec to apply to the Secret
// Only some fields are allowed to be updated.
Spec *SecretSpec `protobuf:"bytes,3,opt,name=spec" json:"spec,omitempty"`
}
func (m *UpdateSecretRequest) Reset() { *m = UpdateSecretRequest{} }
func (*UpdateSecretRequest) ProtoMessage() {}
func (*UpdateSecretRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{41} }
type UpdateSecretResponse struct {
Secret *Secret `protobuf:"bytes,1,opt,name=secret" json:"secret,omitempty"`
}
func (m *UpdateSecretResponse) Reset() { *m = UpdateSecretResponse{} }
func (*UpdateSecretResponse) ProtoMessage() {}
func (*UpdateSecretResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{42} }
// ListSecretRequest is the request to list all non-internal secrets in the secret store,
// or all secrets filtered by (name or name prefix or id prefix) and labels.
type ListSecretsRequest struct {
@ -467,7 +489,7 @@ type ListSecretsRequest struct {
func (m *ListSecretsRequest) Reset() { *m = ListSecretsRequest{} }
func (*ListSecretsRequest) ProtoMessage() {}
func (*ListSecretsRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{41} }
func (*ListSecretsRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{43} }
type ListSecretsRequest_Filters struct {
Names []string `protobuf:"bytes,1,rep,name=names" json:"names,omitempty"`
@ -479,7 +501,7 @@ type ListSecretsRequest_Filters struct {
func (m *ListSecretsRequest_Filters) Reset() { *m = ListSecretsRequest_Filters{} }
func (*ListSecretsRequest_Filters) ProtoMessage() {}
func (*ListSecretsRequest_Filters) Descriptor() ([]byte, []int) {
return fileDescriptorControl, []int{41, 0}
return fileDescriptorControl, []int{43, 0}
}
// ListSecretResponse contains a list of all the secrets that match the name or
@ -492,7 +514,7 @@ type ListSecretsResponse struct {
func (m *ListSecretsResponse) Reset() { *m = ListSecretsResponse{} }
func (*ListSecretsResponse) ProtoMessage() {}
func (*ListSecretsResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{42} }
func (*ListSecretsResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{44} }
// CreateSecretRequest specifies a new secret (it will not update an existing
// secret) to create.
@ -502,7 +524,7 @@ type CreateSecretRequest struct {
func (m *CreateSecretRequest) Reset() { *m = CreateSecretRequest{} }
func (*CreateSecretRequest) ProtoMessage() {}
func (*CreateSecretRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{43} }
func (*CreateSecretRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{45} }
// CreateSecretResponse contains the newly created `Secret`` corresponding to the
// name in `CreateSecretRequest`. The `Secret.Spec.Data` field should be nil instead
@ -513,7 +535,7 @@ type CreateSecretResponse struct {
func (m *CreateSecretResponse) Reset() { *m = CreateSecretResponse{} }
func (*CreateSecretResponse) ProtoMessage() {}
func (*CreateSecretResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{44} }
func (*CreateSecretResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{46} }
// RemoveSecretRequest contains the ID of the secret that should be removed. This
// removes all versions of the secret.
@ -523,7 +545,7 @@ type RemoveSecretRequest struct {
func (m *RemoveSecretRequest) Reset() { *m = RemoveSecretRequest{} }
func (*RemoveSecretRequest) ProtoMessage() {}
func (*RemoveSecretRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{45} }
func (*RemoveSecretRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{47} }
// RemoveSecretResponse is an empty object indicating the successful removal of
// a secret.
@ -532,7 +554,7 @@ type RemoveSecretResponse struct {
func (m *RemoveSecretResponse) Reset() { *m = RemoveSecretResponse{} }
func (*RemoveSecretResponse) ProtoMessage() {}
func (*RemoveSecretResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{46} }
func (*RemoveSecretResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{48} }
func init() {
proto.RegisterType((*GetNodeRequest)(nil), "docker.swarmkit.v1.GetNodeRequest")
@ -581,6 +603,8 @@ func init() {
proto.RegisterType((*UpdateClusterResponse)(nil), "docker.swarmkit.v1.UpdateClusterResponse")
proto.RegisterType((*GetSecretRequest)(nil), "docker.swarmkit.v1.GetSecretRequest")
proto.RegisterType((*GetSecretResponse)(nil), "docker.swarmkit.v1.GetSecretResponse")
proto.RegisterType((*UpdateSecretRequest)(nil), "docker.swarmkit.v1.UpdateSecretRequest")
proto.RegisterType((*UpdateSecretResponse)(nil), "docker.swarmkit.v1.UpdateSecretResponse")
proto.RegisterType((*ListSecretsRequest)(nil), "docker.swarmkit.v1.ListSecretsRequest")
proto.RegisterType((*ListSecretsRequest_Filters)(nil), "docker.swarmkit.v1.ListSecretsRequest.Filters")
proto.RegisterType((*ListSecretsResponse)(nil), "docker.swarmkit.v1.ListSecretsResponse")
@ -762,6 +786,14 @@ func (p *authenticatedWrapperControlServer) GetSecret(ctx context.Context, r *Ge
return p.local.GetSecret(ctx, r)
}
func (p *authenticatedWrapperControlServer) UpdateSecret(ctx context.Context, r *UpdateSecretRequest) (*UpdateSecretResponse, error) {
if err := p.authorize(ctx, []string{"swarm-manager"}); err != nil {
return nil, err
}
return p.local.UpdateSecret(ctx, r)
}
func (p *authenticatedWrapperControlServer) ListSecrets(ctx context.Context, r *ListSecretsRequest) (*ListSecretsResponse, error) {
if err := p.authorize(ctx, []string{"swarm-manager"}); err != nil {
@ -1491,6 +1523,32 @@ func (m *GetSecretResponse) Copy() *GetSecretResponse {
return o
}
func (m *UpdateSecretRequest) Copy() *UpdateSecretRequest {
if m == nil {
return nil
}
o := &UpdateSecretRequest{
SecretID: m.SecretID,
SecretVersion: m.SecretVersion.Copy(),
Spec: m.Spec.Copy(),
}
return o
}
func (m *UpdateSecretResponse) Copy() *UpdateSecretResponse {
if m == nil {
return nil
}
o := &UpdateSecretResponse{
Secret: m.Secret.Copy(),
}
return o
}
func (m *ListSecretsRequest) Copy() *ListSecretsRequest {
if m == nil {
return nil
@ -2203,6 +2261,34 @@ func (this *GetSecretResponse) GoString() string {
s = append(s, "}")
return strings.Join(s, "")
}
func (this *UpdateSecretRequest) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 7)
s = append(s, "&api.UpdateSecretRequest{")
s = append(s, "SecretID: "+fmt.Sprintf("%#v", this.SecretID)+",\n")
if this.SecretVersion != nil {
s = append(s, "SecretVersion: "+fmt.Sprintf("%#v", this.SecretVersion)+",\n")
}
if this.Spec != nil {
s = append(s, "Spec: "+fmt.Sprintf("%#v", this.Spec)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *UpdateSecretResponse) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 5)
s = append(s, "&api.UpdateSecretResponse{")
if this.Secret != nil {
s = append(s, "Secret: "+fmt.Sprintf("%#v", this.Secret)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *ListSecretsRequest) GoString() string {
if this == nil {
return "nil"
@ -2358,6 +2444,12 @@ type ControlClient interface {
// - Returns `InvalidArgument` if the `GetSecretRequest.SecretID` is empty.
// - Returns an error if getting fails.
GetSecret(ctx context.Context, in *GetSecretRequest, opts ...grpc.CallOption) (*GetSecretResponse, error)
// UpdateSecret returns a `UpdateSecretResponse` with a `Secret` with the same
// id as `GetSecretRequest.SecretID`
// - Returns `NotFound` if the Secret with the given id is not found.
// - Returns `InvalidArgument` if the `GetSecretRequest.SecretID` is empty.
// - Returns an error if updating fails.
UpdateSecret(ctx context.Context, in *UpdateSecretRequest, opts ...grpc.CallOption) (*UpdateSecretResponse, error)
// ListSecrets returns a `ListSecretResponse` with a list all non-internal `Secret`s being
// managed, or all secrets matching any name in `ListSecretsRequest.Names`, any
// name prefix in `ListSecretsRequest.NamePrefixes`, any id in
@ -2565,6 +2657,15 @@ func (c *controlClient) GetSecret(ctx context.Context, in *GetSecretRequest, opt
return out, nil
}
func (c *controlClient) UpdateSecret(ctx context.Context, in *UpdateSecretRequest, opts ...grpc.CallOption) (*UpdateSecretResponse, error) {
out := new(UpdateSecretResponse)
err := grpc.Invoke(ctx, "/docker.swarmkit.v1.Control/UpdateSecret", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *controlClient) ListSecrets(ctx context.Context, in *ListSecretsRequest, opts ...grpc.CallOption) (*ListSecretsResponse, error) {
out := new(ListSecretsResponse)
err := grpc.Invoke(ctx, "/docker.swarmkit.v1.Control/ListSecrets", in, out, c.cc, opts...)
@ -2620,6 +2721,12 @@ type ControlServer interface {
// - Returns `InvalidArgument` if the `GetSecretRequest.SecretID` is empty.
// - Returns an error if getting fails.
GetSecret(context.Context, *GetSecretRequest) (*GetSecretResponse, error)
// UpdateSecret returns a `UpdateSecretResponse` with a `Secret` with the same
// id as `GetSecretRequest.SecretID`
// - Returns `NotFound` if the Secret with the given id is not found.
// - Returns `InvalidArgument` if the `GetSecretRequest.SecretID` is empty.
// - Returns an error if updating fails.
UpdateSecret(context.Context, *UpdateSecretRequest) (*UpdateSecretResponse, error)
// ListSecrets returns a `ListSecretResponse` with a list all non-internal `Secret`s being
// managed, or all secrets matching any name in `ListSecretsRequest.Names`, any
// name prefix in `ListSecretsRequest.NamePrefixes`, any id in
@ -3003,6 +3110,24 @@ func _Control_GetSecret_Handler(srv interface{}, ctx context.Context, dec func(i
return interceptor(ctx, in, info, handler)
}
func _Control_UpdateSecret_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateSecretRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ControlServer).UpdateSecret(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/docker.swarmkit.v1.Control/UpdateSecret",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ControlServer).UpdateSecret(ctx, req.(*UpdateSecretRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Control_ListSecrets_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListSecretsRequest)
if err := dec(in); err != nil {
@ -3141,6 +3266,10 @@ var _Control_serviceDesc = grpc.ServiceDesc{
MethodName: "GetSecret",
Handler: _Control_GetSecret_Handler,
},
{
MethodName: "UpdateSecret",
Handler: _Control_UpdateSecret_Handler,
},
{
MethodName: "ListSecrets",
Handler: _Control_ListSecrets_Handler,
@ -4775,6 +4904,78 @@ func (m *GetSecretResponse) MarshalTo(data []byte) (int, error) {
return i, nil
}
func (m *UpdateSecretRequest) Marshal() (data []byte, err error) {
size := m.Size()
data = make([]byte, size)
n, err := m.MarshalTo(data)
if err != nil {
return nil, err
}
return data[:n], nil
}
func (m *UpdateSecretRequest) MarshalTo(data []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if len(m.SecretID) > 0 {
data[i] = 0xa
i++
i = encodeVarintControl(data, i, uint64(len(m.SecretID)))
i += copy(data[i:], m.SecretID)
}
if m.SecretVersion != nil {
data[i] = 0x12
i++
i = encodeVarintControl(data, i, uint64(m.SecretVersion.Size()))
n26, err := m.SecretVersion.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n26
}
if m.Spec != nil {
data[i] = 0x1a
i++
i = encodeVarintControl(data, i, uint64(m.Spec.Size()))
n27, err := m.Spec.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n27
}
return i, nil
}
func (m *UpdateSecretResponse) Marshal() (data []byte, err error) {
size := m.Size()
data = make([]byte, size)
n, err := m.MarshalTo(data)
if err != nil {
return nil, err
}
return data[:n], nil
}
func (m *UpdateSecretResponse) MarshalTo(data []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if m.Secret != nil {
data[i] = 0xa
i++
i = encodeVarintControl(data, i, uint64(m.Secret.Size()))
n28, err := m.Secret.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n28
}
return i, nil
}
func (m *ListSecretsRequest) Marshal() (data []byte, err error) {
size := m.Size()
data = make([]byte, size)
@ -4794,11 +4995,11 @@ func (m *ListSecretsRequest) MarshalTo(data []byte) (int, error) {
data[i] = 0xa
i++
i = encodeVarintControl(data, i, uint64(m.Filters.Size()))
n26, err := m.Filters.MarshalTo(data[i:])
n29, err := m.Filters.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n26
i += n29
}
return i, nil
}
@ -4932,11 +5133,11 @@ func (m *CreateSecretRequest) MarshalTo(data []byte) (int, error) {
data[i] = 0xa
i++
i = encodeVarintControl(data, i, uint64(m.Spec.Size()))
n27, err := m.Spec.MarshalTo(data[i:])
n30, err := m.Spec.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n27
i += n30
}
return i, nil
}
@ -4960,11 +5161,11 @@ func (m *CreateSecretResponse) MarshalTo(data []byte) (int, error) {
data[i] = 0xa
i++
i = encodeVarintControl(data, i, uint64(m.Secret.Size()))
n28, err := m.Secret.MarshalTo(data[i:])
n31, err := m.Secret.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n28
i += n31
}
return i, nil
}
@ -5725,6 +5926,37 @@ func (p *raftProxyControlServer) GetSecret(ctx context.Context, r *GetSecretRequ
return resp, err
}
func (p *raftProxyControlServer) UpdateSecret(ctx context.Context, r *UpdateSecretRequest) (*UpdateSecretResponse, error) {
conn, err := p.connSelector.LeaderConn(ctx)
if err != nil {
if err == raftselector.ErrIsLeader {
return p.local.UpdateSecret(ctx, r)
}
return nil, err
}
modCtx, err := p.runCtxMods(ctx)
if err != nil {
return nil, err
}
resp, err := NewControlClient(conn).UpdateSecret(modCtx, r)
if err != nil {
if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") {
return resp, err
}
conn, err := p.pollNewLeaderConn(ctx)
if err != nil {
if err == raftselector.ErrIsLeader {
return p.local.UpdateSecret(ctx, r)
}
return nil, err
}
return NewControlClient(conn).UpdateSecret(modCtx, r)
}
return resp, err
}
func (p *raftProxyControlServer) ListSecrets(ctx context.Context, r *ListSecretsRequest) (*ListSecretsResponse, error) {
conn, err := p.connSelector.LeaderConn(ctx)
@ -6448,6 +6680,34 @@ func (m *GetSecretResponse) Size() (n int) {
return n
}
func (m *UpdateSecretRequest) Size() (n int) {
var l int
_ = l
l = len(m.SecretID)
if l > 0 {
n += 1 + l + sovControl(uint64(l))
}
if m.SecretVersion != nil {
l = m.SecretVersion.Size()
n += 1 + l + sovControl(uint64(l))
}
if m.Spec != nil {
l = m.Spec.Size()
n += 1 + l + sovControl(uint64(l))
}
return n
}
func (m *UpdateSecretResponse) Size() (n int) {
var l int
_ = l
if m.Secret != nil {
l = m.Secret.Size()
n += 1 + l + sovControl(uint64(l))
}
return n
}
func (m *ListSecretsRequest) Size() (n int) {
var l int
_ = l
@ -7088,6 +7348,28 @@ func (this *GetSecretResponse) String() string {
}, "")
return s
}
func (this *UpdateSecretRequest) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&UpdateSecretRequest{`,
`SecretID:` + fmt.Sprintf("%v", this.SecretID) + `,`,
`SecretVersion:` + strings.Replace(fmt.Sprintf("%v", this.SecretVersion), "Version", "Version", 1) + `,`,
`Spec:` + strings.Replace(fmt.Sprintf("%v", this.Spec), "SecretSpec", "SecretSpec", 1) + `,`,
`}`,
}, "")
return s
}
func (this *UpdateSecretResponse) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&UpdateSecretResponse{`,
`Secret:` + strings.Replace(fmt.Sprintf("%v", this.Secret), "Secret", "Secret", 1) + `,`,
`}`,
}, "")
return s
}
func (this *ListSecretsRequest) String() string {
if this == nil {
return "nil"
@ -12083,6 +12365,234 @@ func (m *GetSecretResponse) Unmarshal(data []byte) error {
}
return nil
}
func (m *UpdateSecretRequest) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowControl
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: UpdateSecretRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: UpdateSecretRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field SecretID", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowControl
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthControl
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.SecretID = string(data[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field SecretVersion", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowControl
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthControl
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.SecretVersion == nil {
m.SecretVersion = &Version{}
}
if err := m.SecretVersion.Unmarshal(data[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Spec", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowControl
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthControl
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.Spec == nil {
m.Spec = &SecretSpec{}
}
if err := m.Spec.Unmarshal(data[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipControl(data[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthControl
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *UpdateSecretResponse) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowControl
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: UpdateSecretResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: UpdateSecretResponse: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Secret", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowControl
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthControl
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.Secret == nil {
m.Secret = &Secret{}
}
if err := m.Secret.Unmarshal(data[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipControl(data[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthControl
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *ListSecretsRequest) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
@ -12903,114 +13413,117 @@ var (
func init() { proto.RegisterFile("control.proto", fileDescriptorControl) }
var fileDescriptorControl = []byte{
// 1731 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x5a, 0x5f, 0x6f, 0x1b, 0xc5,
0x16, 0xaf, 0xed, 0x24, 0x4e, 0x8e, 0x93, 0xb4, 0x99, 0x38, 0xf7, 0x5a, 0xdb, 0x5e, 0xa7, 0xda,
0xde, 0xa6, 0x8e, 0xd4, 0xeb, 0xf4, 0xba, 0x54, 0x94, 0x22, 0xfe, 0x25, 0xa6, 0xc1, 0xfd, 0x13,
0xaa, 0x4d, 0x0b, 0xbc, 0x45, 0x8e, 0x3d, 0x0d, 0x8b, 0x1d, 0xaf, 0xd9, 0xdd, 0xa4, 0xad, 0x78,
0x01, 0x09, 0x24, 0x3e, 0x02, 0xaf, 0xbc, 0xf2, 0x80, 0xc4, 0x27, 0xe0, 0xb5, 0xe2, 0x89, 0x47,
0x9e, 0x2c, 0x6a, 0x09, 0x89, 0x27, 0xc4, 0x27, 0x40, 0x68, 0x66, 0xce, 0xec, 0xae, 0xd7, 0xb3,
0xbb, 0x76, 0x12, 0x94, 0x3e, 0x65, 0x77, 0xf6, 0x77, 0xe6, 0x9c, 0x99, 0xf3, 0x9b, 0x9f, 0xcf,
0x1c, 0x05, 0xe6, 0x1a, 0x56, 0xc7, 0xb5, 0xad, 0x76, 0xb9, 0x6b, 0x5b, 0xae, 0x45, 0x48, 0xd3,
0x6a, 0xb4, 0xa8, 0x5d, 0x76, 0x9e, 0xd4, 0xed, 0xfd, 0x96, 0xe9, 0x96, 0x0f, 0xff, 0xaf, 0xe5,
0x9c, 0x2e, 0x6d, 0x38, 0x02, 0xa0, 0xcd, 0x59, 0xbb, 0x9f, 0xd0, 0x86, 0x2b, 0x5f, 0x73, 0xee,
0xb3, 0x2e, 0x95, 0x2f, 0xf9, 0x3d, 0x6b, 0xcf, 0xe2, 0x8f, 0x6b, 0xec, 0x09, 0x47, 0x17, 0xbb,
0xed, 0x83, 0x3d, 0xb3, 0xb3, 0x26, 0xfe, 0x88, 0x41, 0xfd, 0x06, 0xcc, 0x6f, 0x52, 0x77, 0xcb,
0x6a, 0x52, 0x83, 0x7e, 0x7a, 0x40, 0x1d, 0x97, 0x5c, 0x82, 0x6c, 0xc7, 0x6a, 0xd2, 0x1d, 0xb3,
0x59, 0x48, 0x5d, 0x4c, 0x95, 0x66, 0xd6, 0xa1, 0xdf, 0x5b, 0x9e, 0x62, 0x88, 0x5a, 0xd5, 0x98,
0x62, 0x9f, 0x6a, 0x4d, 0xfd, 0x2d, 0x38, 0xeb, 0x99, 0x39, 0x5d, 0xab, 0xe3, 0x50, 0x72, 0x15,
0x26, 0xd8, 0x47, 0x6e, 0x94, 0xab, 0x14, 0xca, 0xc3, 0x0b, 0x28, 0x73, 0x3c, 0x47, 0xe9, 0xbd,
0x0c, 0x9c, 0xbb, 0x67, 0x3a, 0x7c, 0x0a, 0x47, 0xba, 0xbe, 0x0d, 0xd9, 0xc7, 0x66, 0xdb, 0xa5,
0xb6, 0x83, 0xb3, 0x5c, 0x55, 0xcd, 0x12, 0x36, 0x2b, 0xdf, 0x16, 0x36, 0x86, 0x34, 0xd6, 0xbe,
0xc8, 0x40, 0x16, 0x07, 0x49, 0x1e, 0x26, 0x3b, 0xf5, 0x7d, 0xca, 0x66, 0xcc, 0x94, 0x66, 0x0c,
0xf1, 0x42, 0xd6, 0x20, 0x67, 0x36, 0x77, 0xba, 0x36, 0x7d, 0x6c, 0x3e, 0xa5, 0x4e, 0x21, 0xcd,
0xbe, 0xad, 0xcf, 0xf7, 0x7b, 0xcb, 0x50, 0xab, 0x3e, 0xc0, 0x51, 0x03, 0xcc, 0xa6, 0x7c, 0x26,
0x0f, 0x60, 0xaa, 0x5d, 0xdf, 0xa5, 0x6d, 0xa7, 0x90, 0xb9, 0x98, 0x29, 0xe5, 0x2a, 0x37, 0xc7,
0x89, 0xac, 0x7c, 0x8f, 0x9b, 0xbe, 0xdb, 0x71, 0xed, 0x67, 0x06, 0xce, 0x43, 0x6a, 0x90, 0xdb,
0xa7, 0xfb, 0xbb, 0xd4, 0x76, 0x3e, 0x36, 0xbb, 0x4e, 0x61, 0xe2, 0x62, 0xa6, 0x34, 0x5f, 0xb9,
0x12, 0xb5, 0x6d, 0xdb, 0x5d, 0xda, 0x28, 0xdf, 0xf7, 0xf0, 0x46, 0xd0, 0x96, 0x54, 0x60, 0xd2,
0xb6, 0xda, 0xd4, 0x29, 0x4c, 0xf2, 0x49, 0x2e, 0x44, 0xee, 0xbd, 0xd5, 0xa6, 0x86, 0x80, 0x92,
0x4b, 0x30, 0xc7, 0xb6, 0xc2, 0xdf, 0x83, 0x29, 0xbe, 0x3f, 0xb3, 0x6c, 0x50, 0xae, 0x5a, 0x7b,
0x0d, 0x72, 0x81, 0xd0, 0xc9, 0x39, 0xc8, 0xb4, 0xe8, 0x33, 0x41, 0x0b, 0x83, 0x3d, 0xb2, 0xdd,
0x3d, 0xac, 0xb7, 0x0f, 0x68, 0x21, 0xcd, 0xc7, 0xc4, 0xcb, 0xad, 0xf4, 0xcd, 0x94, 0xbe, 0x01,
0x0b, 0x81, 0xed, 0x40, 0x8e, 0x94, 0x61, 0x92, 0x65, 0x5f, 0x24, 0x23, 0x8e, 0x24, 0x02, 0xa6,
0x7f, 0x97, 0x82, 0x85, 0x47, 0xdd, 0x66, 0xdd, 0xa5, 0xe3, 0x32, 0x94, 0xbc, 0x09, 0xb3, 0x1c,
0x74, 0x48, 0x6d, 0xc7, 0xb4, 0x3a, 0x3c, 0xc0, 0x5c, 0xe5, 0xbc, 0xca, 0xe3, 0x07, 0x02, 0x62,
0xe4, 0x98, 0x01, 0xbe, 0x90, 0x6b, 0x30, 0xc1, 0x8e, 0x5b, 0x21, 0xc3, 0xed, 0x2e, 0xc4, 0xe5,
0xc5, 0xe0, 0x48, 0x7d, 0x1d, 0x48, 0x30, 0xd6, 0x23, 0x1d, 0x8b, 0x2d, 0x58, 0x30, 0xe8, 0xbe,
0x75, 0x38, 0xfe, 0x7a, 0xf3, 0x30, 0xf9, 0xd8, 0xb2, 0x1b, 0x22, 0x13, 0xd3, 0x86, 0x78, 0xd1,
0xf3, 0x40, 0x82, 0xf3, 0x89, 0x98, 0xf0, 0xd0, 0x3f, 0xac, 0x3b, 0xad, 0x80, 0x0b, 0xb7, 0xee,
0xb4, 0x42, 0x2e, 0x18, 0x82, 0xb9, 0x60, 0x9f, 0xbc, 0x43, 0x2f, 0xcc, 0xfc, 0xd5, 0xb1, 0x8f,
0x71, 0xab, 0xe3, 0x78, 0x8e, 0xd2, 0x6f, 0xca, 0xd5, 0x8d, 0xed, 0xda, 0x5b, 0x47, 0xd0, 0xbb,
0xfe, 0x17, 0x8a, 0x08, 0x1b, 0x3c, 0x82, 0x88, 0x04, 0xcd, 0x86, 0x45, 0xe4, 0xdb, 0x53, 0x14,
0x11, 0x55, 0x64, 0x4a, 0x11, 0x59, 0x83, 0x9c, 0x43, 0xed, 0x43, 0xb3, 0xc1, 0xd8, 0x21, 0x44,
0x04, 0x43, 0xd8, 0x16, 0xc3, 0xb5, 0xaa, 0x63, 0x00, 0x42, 0x6a, 0x4d, 0x87, 0xac, 0xc0, 0x34,
0x72, 0x49, 0xa8, 0xc5, 0xcc, 0x7a, 0xae, 0xdf, 0x5b, 0xce, 0x0a, 0x32, 0x39, 0x46, 0x56, 0xb0,
0xc9, 0x21, 0x55, 0x98, 0x6f, 0x52, 0xc7, 0xb4, 0x69, 0x73, 0xc7, 0x71, 0xeb, 0x2e, 0xea, 0xc3,
0x7c, 0xe5, 0x3f, 0x51, 0x29, 0xde, 0x66, 0x28, 0x63, 0x0e, 0x8d, 0xf8, 0x9b, 0x42, 0x64, 0xb2,
// 1777 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x5a, 0xcf, 0x6f, 0xdb, 0xc6,
0x12, 0x8e, 0x24, 0xdb, 0xb2, 0x47, 0x96, 0x13, 0xaf, 0x95, 0x3c, 0x81, 0xc9, 0x93, 0x03, 0xe6,
0xc5, 0x91, 0x81, 0x3c, 0x39, 0x4f, 0x79, 0x41, 0xd3, 0x14, 0xfd, 0x65, 0xbb, 0x71, 0x95, 0x1f,
0x6e, 0x40, 0x27, 0x6d, 0x6f, 0x86, 0x2c, 0x6d, 0x5c, 0x56, 0xb2, 0xa8, 0x92, 0xb4, 0x93, 0xa0,
0x97, 0x16, 0x68, 0x81, 0xfe, 0x09, 0xbd, 0xf6, 0xda, 0x02, 0x3d, 0xf7, 0xd6, 0x6b, 0xd0, 0x53,
0x8f, 0x3d, 0x19, 0x8d, 0x80, 0x02, 0x3d, 0x15, 0xfd, 0x0b, 0x8a, 0x62, 0x77, 0x67, 0x49, 0x8a,
0x5a, 0x92, 0x92, 0xe5, 0xc2, 0x39, 0x99, 0x5c, 0x7e, 0xb3, 0x33, 0xbb, 0xf3, 0xed, 0xa7, 0xd9,
0x81, 0x21, 0xdf, 0xb0, 0x3a, 0xae, 0x6d, 0xb5, 0x2b, 0x5d, 0xdb, 0x72, 0x2d, 0x42, 0x9a, 0x56,
0xa3, 0x45, 0xed, 0x8a, 0xf3, 0xa4, 0x6e, 0xef, 0xb5, 0x4c, 0xb7, 0x72, 0xf0, 0x3f, 0x2d, 0xe7,
0x74, 0x69, 0xc3, 0x11, 0x00, 0x2d, 0x6f, 0xed, 0x7c, 0x4c, 0x1b, 0xae, 0x7c, 0xcd, 0xb9, 0xcf,
0xba, 0x54, 0xbe, 0x14, 0x76, 0xad, 0x5d, 0x8b, 0x3f, 0xae, 0xb0, 0x27, 0x1c, 0x5d, 0xe8, 0xb6,
0xf7, 0x77, 0xcd, 0xce, 0x8a, 0xf8, 0x23, 0x06, 0xf5, 0x1b, 0x30, 0xb7, 0x41, 0xdd, 0x4d, 0xab,
0x49, 0x0d, 0xfa, 0xc9, 0x3e, 0x75, 0x5c, 0x72, 0x09, 0xb2, 0x1d, 0xab, 0x49, 0xb7, 0xcd, 0x66,
0x31, 0x75, 0x31, 0x55, 0x9e, 0x59, 0x85, 0xde, 0xe1, 0xe2, 0x14, 0x43, 0xd4, 0xd6, 0x8d, 0x29,
0xf6, 0xa9, 0xd6, 0xd4, 0xdf, 0x84, 0xd3, 0x9e, 0x99, 0xd3, 0xb5, 0x3a, 0x0e, 0x25, 0x57, 0x61,
0x82, 0x7d, 0xe4, 0x46, 0xb9, 0x6a, 0xb1, 0x32, 0xb8, 0x80, 0x0a, 0xc7, 0x73, 0x94, 0x7e, 0x98,
0x81, 0x33, 0xf7, 0x4c, 0x87, 0x4f, 0xe1, 0x48, 0xd7, 0xb7, 0x21, 0xfb, 0xd8, 0x6c, 0xbb, 0xd4,
0x76, 0x70, 0x96, 0xab, 0xaa, 0x59, 0xc2, 0x66, 0x95, 0xdb, 0xc2, 0xc6, 0x90, 0xc6, 0xda, 0xe7,
0x19, 0xc8, 0xe2, 0x20, 0x29, 0xc0, 0x64, 0xa7, 0xbe, 0x47, 0xd9, 0x8c, 0x99, 0xf2, 0x8c, 0x21,
0x5e, 0xc8, 0x0a, 0xe4, 0xcc, 0xe6, 0x76, 0xd7, 0xa6, 0x8f, 0xcd, 0xa7, 0xd4, 0x29, 0xa6, 0xd9,
0xb7, 0xd5, 0xb9, 0xde, 0xe1, 0x22, 0xd4, 0xd6, 0x1f, 0xe0, 0xa8, 0x01, 0x66, 0x53, 0x3e, 0x93,
0x07, 0x30, 0xd5, 0xae, 0xef, 0xd0, 0xb6, 0x53, 0xcc, 0x5c, 0xcc, 0x94, 0x73, 0xd5, 0x9b, 0xa3,
0x44, 0x56, 0xb9, 0xc7, 0x4d, 0xdf, 0xe9, 0xb8, 0xf6, 0x33, 0x03, 0xe7, 0x21, 0x35, 0xc8, 0xed,
0xd1, 0xbd, 0x1d, 0x6a, 0x3b, 0x1f, 0x99, 0x5d, 0xa7, 0x38, 0x71, 0x31, 0x53, 0x9e, 0xab, 0x5e,
0x89, 0xda, 0xb6, 0xad, 0x2e, 0x6d, 0x54, 0xee, 0x7b, 0x78, 0x23, 0x68, 0x4b, 0xaa, 0x30, 0x69,
0x5b, 0x6d, 0xea, 0x14, 0x27, 0xf9, 0x24, 0x17, 0x22, 0xf7, 0xde, 0x6a, 0x53, 0x43, 0x40, 0xc9,
0x25, 0xc8, 0xb3, 0xad, 0xf0, 0xf7, 0x60, 0x8a, 0xef, 0xcf, 0x2c, 0x1b, 0x94, 0xab, 0xd6, 0x5e,
0x85, 0x5c, 0x20, 0x74, 0x72, 0x06, 0x32, 0x2d, 0xfa, 0x4c, 0xd0, 0xc2, 0x60, 0x8f, 0x6c, 0x77,
0x0f, 0xea, 0xed, 0x7d, 0x5a, 0x4c, 0xf3, 0x31, 0xf1, 0x72, 0x2b, 0x7d, 0x33, 0xa5, 0xaf, 0xc1,
0x7c, 0x60, 0x3b, 0x90, 0x23, 0x15, 0x98, 0x64, 0xd9, 0x17, 0xc9, 0x88, 0x23, 0x89, 0x80, 0xe9,
0xdf, 0xa6, 0x60, 0xfe, 0x51, 0xb7, 0x59, 0x77, 0xe9, 0xa8, 0x0c, 0x25, 0x6f, 0xc0, 0x2c, 0x07,
0x1d, 0x50, 0xdb, 0x31, 0xad, 0x0e, 0x0f, 0x30, 0x57, 0x3d, 0xaf, 0xf2, 0xf8, 0xbe, 0x80, 0x18,
0x39, 0x66, 0x80, 0x2f, 0xe4, 0x1a, 0x4c, 0xb0, 0xe3, 0x56, 0xcc, 0x70, 0xbb, 0x0b, 0x71, 0x79,
0x31, 0x38, 0x52, 0x5f, 0x05, 0x12, 0x8c, 0xf5, 0x48, 0xc7, 0x62, 0x13, 0xe6, 0x0d, 0xba, 0x67,
0x1d, 0x8c, 0xbe, 0xde, 0x02, 0x4c, 0x3e, 0xb6, 0xec, 0x86, 0xc8, 0xc4, 0xb4, 0x21, 0x5e, 0xf4,
0x02, 0x90, 0xe0, 0x7c, 0x22, 0x26, 0x3c, 0xf4, 0x0f, 0xeb, 0x4e, 0x2b, 0xe0, 0xc2, 0xad, 0x3b,
0xad, 0x90, 0x0b, 0x86, 0x60, 0x2e, 0xd8, 0x27, 0xef, 0xd0, 0x0b, 0x33, 0x7f, 0x75, 0xec, 0x63,
0xdc, 0xea, 0x38, 0x9e, 0xa3, 0xf4, 0x9b, 0x72, 0x75, 0x23, 0xbb, 0xf6, 0xd6, 0x11, 0xf4, 0xae,
0xff, 0x85, 0x22, 0xc2, 0x06, 0x8f, 0x20, 0x22, 0x41, 0xb3, 0x41, 0x11, 0xf9, 0xe6, 0x04, 0x45,
0x44, 0x15, 0x99, 0x52, 0x44, 0x56, 0x20, 0xe7, 0x50, 0xfb, 0xc0, 0x6c, 0x30, 0x76, 0x08, 0x11,
0xc1, 0x10, 0xb6, 0xc4, 0x70, 0x6d, 0xdd, 0x31, 0x00, 0x21, 0xb5, 0xa6, 0x43, 0x96, 0x60, 0x1a,
0xb9, 0x24, 0xd4, 0x62, 0x66, 0x35, 0xd7, 0x3b, 0x5c, 0xcc, 0x0a, 0x32, 0x39, 0x46, 0x56, 0xb0,
0xc9, 0x21, 0xeb, 0x30, 0xd7, 0xa4, 0x8e, 0x69, 0xd3, 0xe6, 0xb6, 0xe3, 0xd6, 0x5d, 0xd4, 0x87,
0xb9, 0xea, 0xbf, 0xa3, 0x52, 0xbc, 0xc5, 0x50, 0x46, 0x1e, 0x8d, 0xf8, 0x9b, 0x42, 0x64, 0xb2,
0xff, 0x88, 0xc8, 0xe0, 0x76, 0xf9, 0x22, 0xc3, 0x58, 0x13, 0x2b, 0x32, 0x9c, 0x46, 0x02, 0xa6,
0xdf, 0x85, 0xfc, 0x86, 0x4d, 0xeb, 0x2e, 0xc5, 0x2d, 0x93, 0x44, 0xba, 0x8e, 0x0a, 0x20, 0x58,
0xb4, 0xac, 0x9a, 0x06, 0x2d, 0x02, 0x22, 0xb0, 0x05, 0x4b, 0xa1, 0xc9, 0x30, 0xaa, 0x1b, 0x90,
0xc5, 0x34, 0xe0, 0x84, 0xe7, 0x63, 0x26, 0x34, 0x24, 0x56, 0x7f, 0x07, 0x16, 0x36, 0xa9, 0x1b,
0x8a, 0xec, 0x2a, 0x80, 0x9f, 0x75, 0x3c, 0x35, 0x73, 0xfd, 0xde, 0xf2, 0x8c, 0x97, 0x74, 0x63,
0xc6, 0xcb, 0xb9, 0x7e, 0x17, 0x48, 0x70, 0x8a, 0xe3, 0xc5, 0xf3, 0x63, 0x0a, 0xf2, 0x42, 0xe5,
0x8e, 0x13, 0x13, 0xa9, 0xc2, 0x59, 0x89, 0x1e, 0x43, 0xa0, 0xe7, 0xd1, 0x46, 0x6a, 0xf4, 0xf5,
0x01, 0x8d, 0x1e, 0x3d, 0x43, 0xa1, 0x05, 0x1c, 0x6f, 0x47, 0xaa, 0x90, 0x17, 0xd2, 0x74, 0xac,
0x24, 0xfd, 0x1b, 0x96, 0x42, 0xb3, 0xa0, 0xc6, 0xfd, 0x9e, 0x86, 0x45, 0xc6, 0x71, 0x1c, 0xf7,
0x64, 0xae, 0x16, 0x96, 0xb9, 0xb5, 0x28, 0x31, 0x09, 0x59, 0x0e, 0x2b, 0xdd, 0x57, 0xe9, 0x13,
0x57, 0xba, 0xed, 0x90, 0xd2, 0xbd, 0x3e, 0x66, 0x70, 0x4a, 0xb1, 0x1b, 0x52, 0x93, 0x89, 0x93,
0x55, 0x93, 0xf7, 0x21, 0x3f, 0x18, 0x12, 0x12, 0xe3, 0x55, 0x98, 0xc6, 0x44, 0x49, 0x4d, 0x89,
0x65, 0x86, 0x07, 0xf6, 0x95, 0x65, 0x8b, 0xba, 0x4f, 0x2c, 0xbb, 0x35, 0x86, 0xb2, 0xa0, 0x85,
0xdf, 0x85, 0xc2, 0x9a, 0x4d, 0xeb, 0x2e, 0xc5, 0x2d, 0x93, 0x44, 0xba, 0x8e, 0x0a, 0x20, 0x58,
0xb4, 0xa8, 0x9a, 0x06, 0x2d, 0x02, 0x22, 0xb0, 0x09, 0x67, 0x43, 0x93, 0x61, 0x54, 0x37, 0x20,
0x8b, 0x69, 0xc0, 0x09, 0xcf, 0xc7, 0x4c, 0x68, 0x48, 0xac, 0xfe, 0x36, 0xcc, 0x6f, 0x50, 0x37,
0x14, 0xd9, 0x55, 0x00, 0x3f, 0xeb, 0x78, 0x6a, 0xf2, 0xbd, 0xc3, 0xc5, 0x19, 0x2f, 0xe9, 0xc6,
0x8c, 0x97, 0x73, 0xfd, 0x2e, 0x90, 0xe0, 0x14, 0xe3, 0xc5, 0xf3, 0x63, 0x0a, 0x0a, 0x42, 0xe5,
0xc6, 0x89, 0x89, 0xac, 0xc3, 0x69, 0x89, 0x1e, 0x41, 0xa0, 0xe7, 0xd0, 0x46, 0x6a, 0xf4, 0xf5,
0x3e, 0x8d, 0x1e, 0x3e, 0x43, 0xa1, 0x05, 0x8c, 0xb7, 0x23, 0xeb, 0x50, 0x10, 0xd2, 0x34, 0x56,
0x92, 0xfe, 0x05, 0x67, 0x43, 0xb3, 0xa0, 0xc6, 0xfd, 0x9e, 0x86, 0x05, 0xc6, 0x71, 0x1c, 0xf7,
0x64, 0xae, 0x16, 0x96, 0xb9, 0x95, 0x28, 0x31, 0x09, 0x59, 0x0e, 0x2a, 0xdd, 0x97, 0xe9, 0x63,
0x57, 0xba, 0xad, 0x90, 0xd2, 0xbd, 0x36, 0x62, 0x70, 0x4a, 0xb1, 0x1b, 0x50, 0x93, 0x89, 0xe3,
0x55, 0x93, 0xf7, 0xa0, 0xd0, 0x1f, 0x12, 0x12, 0xe3, 0x15, 0x98, 0xc6, 0x44, 0x49, 0x4d, 0x89,
0x65, 0x86, 0x07, 0xf6, 0x95, 0x65, 0x93, 0xba, 0x4f, 0x2c, 0xbb, 0x35, 0x82, 0xb2, 0xa0, 0x85,
0x4a, 0x59, 0xbc, 0xc9, 0x7c, 0xde, 0x76, 0xc4, 0x50, 0x1c, 0x6f, 0xa5, 0x95, 0xc4, 0xea, 0x8f,
0xb8, 0xb2, 0x84, 0x22, 0x23, 0x30, 0xc1, 0x76, 0x13, 0xf7, 0x8b, 0x3f, 0x33, 0x22, 0xa3, 0x0d,
0x23, 0x72, 0xda, 0x27, 0x32, 0xda, 0x32, 0x22, 0x23, 0xc0, 0x53, 0x9b, 0x13, 0x8a, 0xf1, 0x23,
0x79, 0xb6, 0x4e, 0x3c, 0x4c, 0xef, 0xbc, 0x85, 0x22, 0xf5, 0xce, 0x1b, 0x8e, 0x1f, 0xe1, 0xbc,
0x85, 0x2c, 0x5f, 0xae, 0xf3, 0x16, 0x11, 0xdc, 0x69, 0x9e, 0x37, 0x3f, 0x24, 0xff, 0xbc, 0x61,
0xa2, 0x62, 0xcf, 0x9b, 0xcc, 0x9c, 0x07, 0xc6, 0x1f, 0xcb, 0x8d, 0xf6, 0x81, 0xe3, 0x52, 0x3b,
0x23, 0x72, 0xda, 0x27, 0x32, 0xda, 0x32, 0x22, 0x23, 0xc0, 0x53, 0x9b, 0x63, 0x8a, 0xf1, 0x43,
0x79, 0xb6, 0x8e, 0x3d, 0x4c, 0xef, 0xbc, 0x85, 0x22, 0xf5, 0xce, 0x1b, 0x8e, 0x1f, 0xe1, 0xbc,
0x85, 0x2c, 0x5f, 0xae, 0xf3, 0x16, 0x11, 0xdc, 0x49, 0x9e, 0x37, 0x3f, 0x24, 0xff, 0xbc, 0x61,
0xa2, 0x62, 0xcf, 0x9b, 0xcc, 0x9c, 0x07, 0xc6, 0x1f, 0xcb, 0xb5, 0xf6, 0xbe, 0xe3, 0x52, 0x3b,
0xa0, 0xc3, 0x0d, 0x31, 0x12, 0xd2, 0x61, 0xc4, 0x31, 0x5e, 0x20, 0xc0, 0xa3, 0xaf, 0x37, 0x85,
0x4f, 0x5f, 0x84, 0xc4, 0xd1, 0x57, 0x5a, 0x49, 0xac, 0xc7, 0x25, 0xfc, 0x70, 0x04, 0x2e, 0x85,
0x2c, 0x5f, 0x2e, 0x2e, 0x45, 0x04, 0x77, 0x9a, 0x5c, 0xf2, 0x43, 0xf2, 0xb9, 0x84, 0xd9, 0x88,
0xe5, 0x92, 0x4c, 0x9d, 0x07, 0xd6, 0x0f, 0x60, 0xe1, 0x8e, 0x65, 0x76, 0x1e, 0x5a, 0x2d, 0xda,
0x31, 0x2c, 0xb7, 0xee, 0xb2, 0x82, 0xa3, 0x0c, 0x8b, 0x36, 0x7b, 0xa6, 0x3b, 0x8c, 0x70, 0xd4,
0xde, 0x71, 0xd9, 0x67, 0x1e, 0xe1, 0xb4, 0xb1, 0x20, 0x3e, 0x7d, 0xc8, 0xbf, 0x70, 0x3b, 0x72,
0x0d, 0xf2, 0x88, 0xdf, 0xaf, 0x77, 0xea, 0x7b, 0x9e, 0x81, 0xb8, 0xa3, 0x11, 0xf1, 0xed, 0xbe,
0xf8, 0xc4, 0x2d, 0xf4, 0xaf, 0xd3, 0xb2, 0xbe, 0x3a, 0x0e, 0x8d, 0x59, 0x7d, 0x25, 0xd1, 0xe3,
0xd4, 0x57, 0x68, 0x33, 0x46, 0x7d, 0x85, 0xde, 0xfd, 0xdf, 0x29, 0xb2, 0x09, 0xd3, 0x36, 0xee,
0x57, 0x61, 0x82, 0x1b, 0x5e, 0x56, 0x19, 0x0e, 0x6d, 0xee, 0xfa, 0xc4, 0xf3, 0xde, 0xf2, 0x19,
0xc3, 0x33, 0xf6, 0x0b, 0xb5, 0x13, 0x3a, 0x8d, 0x6f, 0xc0, 0x39, 0x5e, 0x07, 0x37, 0x6c, 0xea,
0xca, 0x5d, 0x5d, 0x85, 0x19, 0x87, 0x0f, 0xf8, 0x9b, 0x3a, 0xdb, 0xef, 0x2d, 0x4f, 0x0b, 0x54,
0xad, 0xca, 0x7e, 0xcc, 0xf9, 0x53, 0x53, 0xdf, 0xc4, 0x4a, 0x5c, 0x98, 0x63, 0x28, 0x15, 0x98,
0x12, 0x00, 0x8c, 0x44, 0x53, 0x17, 0x06, 0xdc, 0x06, 0x91, 0xfa, 0x6f, 0x69, 0x20, 0xa2, 0xce,
0x60, 0xaf, 0x9e, 0x28, 0xbc, 0x17, 0x16, 0x85, 0x72, 0x74, 0xcd, 0x14, 0x34, 0x1c, 0xd6, 0x84,
0x2f, 0x4f, 0x5e, 0x13, 0x8c, 0x90, 0x26, 0xdc, 0x1a, 0x2f, 0xb6, 0x53, 0x91, 0x84, 0xbb, 0xb2,
0x70, 0xc6, 0x88, 0x30, 0x65, 0xaf, 0xb0, 0x32, 0x9f, 0x0f, 0xa1, 0x20, 0xc4, 0xe5, 0x4c, 0x42,
0xf5, 0x1a, 0x2c, 0xca, 0x7b, 0x5d, 0x90, 0x3f, 0x95, 0x81, 0x4a, 0xae, 0x18, 0x3d, 0x53, 0xa0,
0x90, 0xbb, 0xe3, 0xdf, 0x37, 0x8f, 0xcd, 0xa5, 0xb7, 0x61, 0x51, 0x5e, 0x1b, 0x8e, 0x48, 0xeb,
0x7f, 0xf9, 0xd7, 0x97, 0x60, 0x34, 0x95, 0x1f, 0x96, 0x20, 0xbb, 0x21, 0x5a, 0xd2, 0xc4, 0x84,
0x2c, 0x76, 0x7b, 0x89, 0xae, 0x0a, 0x6a, 0xb0, 0x83, 0xac, 0x5d, 0x8a, 0xc5, 0x60, 0x9d, 0xb5,
0xf4, 0xd3, 0xf7, 0x7f, 0x7c, 0x93, 0x3e, 0x0b, 0x73, 0x1c, 0xf4, 0x3f, 0xd4, 0x47, 0x62, 0xc1,
0x8c, 0xd7, 0x36, 0x24, 0xff, 0x1d, 0xa5, 0xc9, 0xaa, 0x5d, 0x4e, 0x40, 0xc5, 0x3b, 0xb4, 0x01,
0xfc, 0xae, 0x1d, 0x51, 0xce, 0x35, 0xd4, 0x81, 0xd4, 0x56, 0x92, 0x60, 0x89, 0x3e, 0xfd, 0xae,
0x9c, 0xda, 0xe7, 0x50, 0x17, 0x50, 0xed, 0x53, 0xd1, 0xdc, 0x8b, 0xf0, 0x29, 0x72, 0xf8, 0xb0,
0xee, 0xb4, 0x22, 0x73, 0x18, 0xe8, 0xca, 0x45, 0xe6, 0x70, 0xa0, 0xff, 0x16, 0x9f, 0x43, 0xde,
0x95, 0x89, 0xce, 0x61, 0xb0, 0xc7, 0x15, 0x9d, 0xc3, 0x81, 0xd6, 0x4e, 0xe2, 0x7e, 0xf2, 0xe5,
0xc5, 0xec, 0x67, 0x70, 0x85, 0x2b, 0x49, 0xb0, 0x44, 0x9f, 0x7e, 0x57, 0x45, 0xed, 0x73, 0xa8,
0x71, 0xa3, 0xf6, 0x39, 0xdc, 0x9c, 0x89, 0xf2, 0xf9, 0x14, 0x66, 0x83, 0x17, 0x54, 0x72, 0x65,
0xc4, 0x5b, 0xb5, 0x56, 0x4a, 0x06, 0xc6, 0x7b, 0xfe, 0x0c, 0xe6, 0x06, 0xda, 0x5a, 0x44, 0x39,
0xa3, 0xaa, 0x8d, 0xa6, 0xad, 0x8e, 0x80, 0x4c, 0x74, 0x3e, 0xd0, 0xb1, 0x51, 0x3b, 0x57, 0x75,
0xa5, 0xd4, 0xce, 0x95, 0xed, 0x9f, 0x18, 0xe7, 0x03, 0x8d, 0x19, 0xb5, 0x73, 0x55, 0x07, 0x48,
0xed, 0x5c, 0xdd, 0xe5, 0x89, 0x25, 0x19, 0x5e, 0x74, 0x22, 0x49, 0x36, 0x78, 0x39, 0x8e, 0x24,
0x59, 0xf8, 0xa6, 0x1b, 0x4f, 0x32, 0x79, 0x2b, 0x8b, 0x26, 0x59, 0xe8, 0x2a, 0x19, 0x4d, 0xb2,
0xf0, 0x05, 0x2f, 0x91, 0x64, 0x72, 0xc1, 0x31, 0x24, 0x0b, 0xad, 0x79, 0x75, 0x04, 0xe4, 0x88,
0x79, 0x8e, 0x75, 0xae, 0xea, 0x46, 0xc4, 0xe5, 0x79, 0x44, 0xe7, 0x22, 0xcf, 0x58, 0xb1, 0x46,
0xe6, 0x79, 0xf0, 0x46, 0x10, 0x99, 0xe7, 0x50, 0xb9, 0x9c, 0x90, 0x67, 0x79, 0x63, 0x8a, 0xce,
0x73, 0xe8, 0x9a, 0x17, 0x9d, 0xe7, 0xf0, 0xe5, 0x2b, 0xf1, 0x3c, 0xcb, 0x05, 0xc7, 0x9c, 0xe7,
0xd0, 0x9a, 0x57, 0x47, 0x40, 0x26, 0xfe, 0x38, 0x79, 0x65, 0xbc, 0xfa, 0xc7, 0x29, 0x7c, 0x49,
0xd0, 0x2e, 0x27, 0xa0, 0xe2, 0x1d, 0x1e, 0x40, 0x2e, 0x50, 0x86, 0x92, 0x95, 0xd1, 0x2a, 0x67,
0xed, 0x4a, 0x22, 0x2e, 0x31, 0xbd, 0xc1, 0x2a, 0x53, 0x9d, 0x5e, 0x45, 0x49, 0xab, 0x95, 0x92,
0x81, 0x89, 0x9e, 0x83, 0x15, 0xa5, 0xda, 0xb3, 0xa2, 0x6a, 0xd5, 0x4a, 0xc9, 0xc0, 0x58, 0xcf,
0xeb, 0x17, 0x9e, 0xbf, 0x28, 0x9e, 0xf9, 0xe5, 0x45, 0xf1, 0xcc, 0x9f, 0x2f, 0x8a, 0xa9, 0xcf,
0xfb, 0xc5, 0xd4, 0xf3, 0x7e, 0x31, 0xf5, 0x73, 0xbf, 0x98, 0xfa, 0xb5, 0x5f, 0x4c, 0xed, 0x4e,
0xf1, 0xff, 0x78, 0xb8, 0xfe, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0xde, 0x36, 0x11, 0xa9, 0x6a,
0x21, 0x00, 0x00,
0x2c, 0x5f, 0x2e, 0x2e, 0x45, 0x04, 0x77, 0x92, 0x5c, 0xf2, 0x43, 0xf2, 0xb9, 0x84, 0xd9, 0x88,
0xe5, 0x92, 0x4c, 0x9d, 0x07, 0xd6, 0xf7, 0x61, 0xfe, 0x8e, 0x65, 0x76, 0x1e, 0x5a, 0x2d, 0xda,
0x31, 0x2c, 0xb7, 0xee, 0xb2, 0x82, 0xa3, 0x02, 0x0b, 0x36, 0x7b, 0xa6, 0xdb, 0x8c, 0x70, 0xd4,
0xde, 0x76, 0xd9, 0x67, 0x1e, 0xe1, 0xb4, 0x31, 0x2f, 0x3e, 0x7d, 0xc0, 0xbf, 0x70, 0x3b, 0x72,
0x0d, 0x0a, 0x88, 0xdf, 0xab, 0x77, 0xea, 0xbb, 0x9e, 0x81, 0xb8, 0xa3, 0x11, 0xf1, 0xed, 0xbe,
0xf8, 0xc4, 0x2d, 0xf4, 0xaf, 0xd2, 0xb2, 0xbe, 0x1a, 0x87, 0xc6, 0xac, 0xbe, 0x92, 0xe8, 0x51,
0xea, 0x2b, 0xb4, 0x19, 0xa1, 0xbe, 0x42, 0xef, 0xfe, 0xef, 0x14, 0xd9, 0x80, 0x69, 0x1b, 0xf7,
0xab, 0x38, 0xc1, 0x0d, 0x2f, 0xab, 0x0c, 0x07, 0x36, 0x77, 0x75, 0xe2, 0xf9, 0xe1, 0xe2, 0x29,
0xc3, 0x33, 0xf6, 0x0b, 0xb5, 0x63, 0x3a, 0x8d, 0xaf, 0xc3, 0x19, 0x5e, 0x07, 0x37, 0x6c, 0xea,
0xca, 0x5d, 0x5d, 0x86, 0x19, 0x87, 0x0f, 0xf8, 0x9b, 0x3a, 0xdb, 0x3b, 0x5c, 0x9c, 0x16, 0xa8,
0xda, 0x3a, 0xfb, 0x31, 0xe7, 0x4f, 0x4d, 0x7d, 0x03, 0x2b, 0x71, 0x61, 0x8e, 0xa1, 0x54, 0x61,
0x4a, 0x00, 0x30, 0x12, 0x4d, 0x5d, 0x18, 0x70, 0x1b, 0x44, 0xea, 0x3f, 0xa4, 0x60, 0x41, 0x56,
0xa0, 0x47, 0x8b, 0x85, 0xac, 0xc2, 0x1c, 0x42, 0x47, 0xc8, 0x6e, 0x5e, 0x98, 0xc8, 0xe4, 0x56,
0xfb, 0x92, 0x5b, 0x8a, 0x0e, 0x3c, 0x50, 0x83, 0xdc, 0xf1, 0x8b, 0xff, 0xb1, 0xb7, 0xe1, 0xb7,
0x34, 0x10, 0x51, 0x6e, 0xb1, 0x57, 0x4f, 0x1b, 0xdf, 0x0d, 0x6b, 0x63, 0x25, 0xba, 0x74, 0x0c,
0x1a, 0x0e, 0x4a, 0xe3, 0x17, 0xc7, 0x2f, 0x8d, 0x46, 0x48, 0x1a, 0x6f, 0x8d, 0x16, 0xdb, 0x89,
0x28, 0xe3, 0x5d, 0x79, 0x7f, 0xc0, 0x88, 0x30, 0x65, 0xff, 0x67, 0xb7, 0x1d, 0x3e, 0x84, 0xba,
0x18, 0x97, 0x33, 0x09, 0xd5, 0x6b, 0xb0, 0x20, 0xaf, 0xb7, 0x41, 0xea, 0x56, 0xfb, 0x0a, 0xda,
0xa1, 0xb9, 0xd4, 0x3f, 0xd5, 0x18, 0x5c, 0x7a, 0x0b, 0x16, 0xe4, 0xed, 0xe9, 0x88, 0xa7, 0xfb,
0x9c, 0x7f, 0x8b, 0x0b, 0x46, 0x53, 0xfd, 0xee, 0x1c, 0x64, 0xd7, 0x44, 0x67, 0x9e, 0x98, 0x90,
0xc5, 0xa6, 0x37, 0xd1, 0x55, 0x41, 0xf5, 0x37, 0xd2, 0xb5, 0x4b, 0xb1, 0x18, 0x2c, 0x37, 0xcf,
0xfe, 0xf4, 0xfd, 0x1f, 0x5f, 0xa7, 0x4f, 0x43, 0x9e, 0x83, 0xfe, 0x8b, 0x3f, 0x13, 0xc4, 0x82,
0x19, 0xaf, 0x7b, 0x4a, 0xfe, 0x33, 0x4c, 0xaf, 0x59, 0xbb, 0x9c, 0x80, 0x8a, 0x77, 0x68, 0x03,
0xf8, 0xcd, 0x4b, 0xa2, 0x9c, 0x6b, 0xa0, 0x11, 0xab, 0x2d, 0x25, 0xc1, 0x12, 0x7d, 0xfa, 0xcd,
0x49, 0xb5, 0xcf, 0x81, 0x66, 0xa8, 0xda, 0xa7, 0xa2, 0xc7, 0x19, 0xe1, 0x53, 0xe4, 0xf0, 0x61,
0xdd, 0x69, 0x45, 0xe6, 0x30, 0xd0, 0x9c, 0x8c, 0xcc, 0x61, 0x5f, 0x1b, 0x32, 0x3e, 0x87, 0xbc,
0x39, 0x15, 0x9d, 0xc3, 0x60, 0xab, 0x2f, 0x3a, 0x87, 0x7d, 0x1d, 0xae, 0xc4, 0xfd, 0xe4, 0xcb,
0x8b, 0xd9, 0xcf, 0xe0, 0x0a, 0x97, 0x92, 0x60, 0x89, 0x3e, 0xfd, 0xe6, 0x92, 0xda, 0xe7, 0x40,
0xff, 0x4a, 0xed, 0x73, 0xb0, 0x47, 0x15, 0xe5, 0xf3, 0x29, 0xcc, 0x06, 0xef, 0xe9, 0xe4, 0xca,
0x90, 0xcd, 0x05, 0xad, 0x9c, 0x0c, 0x8c, 0xf7, 0xfc, 0x29, 0xe4, 0xfb, 0xba, 0x7b, 0x44, 0x39,
0xa3, 0xaa, 0x9b, 0xa8, 0x2d, 0x0f, 0x81, 0x4c, 0x74, 0xde, 0xd7, 0xb8, 0x52, 0x3b, 0x57, 0x35,
0xe7, 0xd4, 0xce, 0x95, 0x5d, 0xb0, 0x18, 0xe7, 0x7d, 0xfd, 0x29, 0xb5, 0x73, 0x55, 0x23, 0x4c,
0xed, 0x5c, 0xdd, 0xec, 0x8a, 0x25, 0x19, 0xde, 0xf7, 0x22, 0x49, 0xd6, 0xdf, 0x23, 0x88, 0x24,
0x59, 0xf8, 0xc2, 0x1f, 0x4f, 0x32, 0x79, 0x39, 0x8d, 0x26, 0x59, 0xe8, 0x46, 0x1d, 0x4d, 0xb2,
0xf0, 0x3d, 0x37, 0x91, 0x64, 0x72, 0xc1, 0x31, 0x24, 0x0b, 0xad, 0x79, 0x79, 0x08, 0xe4, 0x90,
0x79, 0x8e, 0x75, 0xae, 0x6a, 0xca, 0xc4, 0xe5, 0x79, 0x48, 0xe7, 0x22, 0xcf, 0x58, 0xb8, 0x47,
0xe6, 0xb9, 0xff, 0x62, 0x14, 0x99, 0xe7, 0xd0, 0xad, 0x21, 0x21, 0xcf, 0xf2, 0xe2, 0x18, 0x9d,
0xe7, 0xd0, 0x6d, 0x37, 0x3a, 0xcf, 0xe1, 0x3b, 0x68, 0xe2, 0x79, 0x96, 0x0b, 0x8e, 0x39, 0xcf,
0xa1, 0x35, 0x2f, 0x0f, 0x81, 0x4c, 0xfc, 0x71, 0xf2, 0x6e, 0x33, 0xea, 0x1f, 0xa7, 0xf0, 0x5d,
0x49, 0xbb, 0x9c, 0x80, 0x4a, 0xdc, 0xe7, 0xe0, 0xd5, 0x41, 0xbd, 0xcf, 0x8a, 0x6b, 0x91, 0x56,
0x4e, 0x06, 0xc6, 0x7b, 0xde, 0x87, 0x5c, 0xa0, 0x00, 0x26, 0x4b, 0xc3, 0xd5, 0xec, 0xda, 0x95,
0x44, 0x5c, 0xe2, 0x82, 0x83, 0xf5, 0xad, 0x7a, 0xc1, 0x8a, 0x62, 0x5a, 0x2b, 0x27, 0x03, 0x13,
0x3d, 0x07, 0x6b, 0x59, 0xb5, 0x67, 0x45, 0xbd, 0xac, 0x95, 0x93, 0x81, 0xb1, 0x9e, 0x57, 0x2f,
0x3c, 0x7f, 0x51, 0x3a, 0xf5, 0xcb, 0x8b, 0xd2, 0xa9, 0x3f, 0x5f, 0x94, 0x52, 0x9f, 0xf5, 0x4a,
0xa9, 0xe7, 0xbd, 0x52, 0xea, 0xe7, 0x5e, 0x29, 0xf5, 0x6b, 0xaf, 0x94, 0xda, 0x99, 0xe2, 0xff,
0x72, 0x72, 0xfd, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x2a, 0x7c, 0x4c, 0x3e, 0xeb, 0x22, 0x00,
0x00,
}

View file

@ -83,6 +83,15 @@ service Control {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
}
// UpdateSecret returns a `UpdateSecretResponse` with a `Secret` with the same
// id as `GetSecretRequest.SecretID`
// - Returns `NotFound` if the Secret with the given id is not found.
// - Returns `InvalidArgument` if the `GetSecretRequest.SecretID` is empty.
// - Returns an error if updating fails.
rpc UpdateSecret(UpdateSecretRequest) returns (UpdateSecretResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
// ListSecrets returns a `ListSecretResponse` with a list all non-internal `Secret`s being
// managed, or all secrets matching any name in `ListSecretsRequest.Names`, any
// name prefix in `ListSecretsRequest.NamePrefixes`, any id in
@ -342,6 +351,23 @@ message GetSecretResponse {
Secret secret = 1;
}
message UpdateSecretRequest {
// SecretID is the secret ID to update.
string secret_id = 1 [(gogoproto.customname) = "SecretID"];
// SecretVersion is the version of the secret being updated.
Version secret_version = 2;
// Spec is the new spec to apply to the Secret
// Only some fields are allowed to be updated.
SecretSpec spec = 3;
}
message UpdateSecretResponse {
Secret secret = 1;
}
// ListSecretRequest is the request to list all non-internal secrets in the secret store,
// or all secrets filtered by (name or name prefix or id prefix) and labels.
message ListSecretsRequest {

View file

@ -1,3 +1,3 @@
package api
//go:generate protoc -I.:../protobuf:../vendor:../vendor/github.com/gogo/protobuf --gogoswarm_out=plugins=grpc+deepcopy+raftproxy+authenticatedwrapper,import_path=github.com/docker/swarmkit/api,Mgogoproto/gogo.proto=github.com/gogo/protobuf/gogoproto,Mtimestamp/timestamp.proto=github.com/docker/swarmkit/api/timestamp,Mduration/duration.proto=github.com/docker/swarmkit/api/duration,Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/protoc-gen-gogo/descriptor,Mplugin/plugin.proto=github.com/docker/swarmkit/protobuf/plugin:. types.proto specs.proto objects.proto control.proto dispatcher.proto ca.proto snapshot.proto raft.proto health.proto resource.proto
//go:generate protoc -I.:../protobuf:../vendor:../vendor/github.com/gogo/protobuf:../vendor/github.com/gogo/protobuf/protobuf --gogoswarm_out=plugins=grpc+deepcopy+raftproxy+authenticatedwrapper,import_path=github.com/docker/swarmkit/api,Mgogoproto/gogo.proto=github.com/gogo/protobuf/gogoproto,Mtimestamp/timestamp.proto=github.com/docker/swarmkit/api/timestamp,Mduration/duration.proto=github.com/docker/swarmkit/api/duration,Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/protoc-gen-gogo/descriptor,Mplugin/plugin.proto=github.com/docker/swarmkit/protobuf/plugin:. types.proto specs.proto objects.proto control.proto dispatcher.proto ca.proto snapshot.proto raft.proto health.proto resource.proto

View file

@ -0,0 +1,29 @@
// Package naming centralizes the naming of SwarmKit objects.
package naming
import (
"fmt"
"github.com/docker/swarmkit/api"
)
// Task returns the task name from Annotations.Name,
// and, in case Annotations.Name is missing, fallback
// to construct the name from othere information.
func Task(t *api.Task) string {
if t.Annotations.Name != "" {
// if set, use the container Annotations.Name field, set in the orchestrator.
return t.Annotations.Name
}
slot := fmt.Sprint(t.Slot)
if slot == "" || t.Slot == 0 {
// when no slot id is assigned, we assume that this is node-bound task.
slot = t.NodeID
}
// fallback to service.instance.id.
return fmt.Sprintf("%s.%s.%s", t.ServiceAnnotations.Name, slot, t.ID)
}
// TODO(stevvooe): Consolidate "Hostname" style validation here.

View file

@ -15,6 +15,7 @@ import github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto"
import sort "sort"
import strconv "strconv"
import reflect "reflect"
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
import io "io"
@ -227,9 +228,10 @@ type Cluster struct {
// and agents to unambiguously identify the older key to be deleted when
// a new key is allocated on key rotation.
EncryptionKeyLamportClock uint64 `protobuf:"varint,6,opt,name=encryption_key_lamport_clock,json=encryptionKeyLamportClock,proto3" json:"encryption_key_lamport_clock,omitempty"`
// RemovedNodes is the list of nodes that have been removed from the
// BlacklistedCertificates tracks certificates that should no longer
// be honored. It's a mapping from CN -> BlacklistedCertificate.
// swarm. Their certificates should effectively be blacklisted.
RemovedNodes []*RemovedNode `protobuf:"bytes,7,rep,name=removed_nodes,json=removedNodes" json:"removed_nodes,omitempty"`
BlacklistedCertificates map[string]*BlacklistedCertificate `protobuf:"bytes,8,rep,name=blacklisted_certificates,json=blacklistedCertificates" json:"blacklisted_certificates,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"`
}
func (m *Cluster) Reset() { *m = Cluster{} }
@ -451,10 +453,10 @@ func (m *Cluster) Copy() *Cluster {
}
}
if m.RemovedNodes != nil {
o.RemovedNodes = make([]*RemovedNode, 0, len(m.RemovedNodes))
for _, v := range m.RemovedNodes {
o.RemovedNodes = append(o.RemovedNodes, v.Copy())
if m.BlacklistedCertificates != nil {
o.BlacklistedCertificates = make(map[string]*BlacklistedCertificate)
for k, v := range m.BlacklistedCertificates {
o.BlacklistedCertificates[k] = v.Copy()
}
}
@ -641,8 +643,18 @@ func (this *Cluster) GoString() string {
s = append(s, "NetworkBootstrapKeys: "+fmt.Sprintf("%#v", this.NetworkBootstrapKeys)+",\n")
}
s = append(s, "EncryptionKeyLamportClock: "+fmt.Sprintf("%#v", this.EncryptionKeyLamportClock)+",\n")
if this.RemovedNodes != nil {
s = append(s, "RemovedNodes: "+fmt.Sprintf("%#v", this.RemovedNodes)+",\n")
keysForBlacklistedCertificates := make([]string, 0, len(this.BlacklistedCertificates))
for k, _ := range this.BlacklistedCertificates {
keysForBlacklistedCertificates = append(keysForBlacklistedCertificates, k)
}
github_com_gogo_protobuf_sortkeys.Strings(keysForBlacklistedCertificates)
mapStringForBlacklistedCertificates := "map[string]*BlacklistedCertificate{"
for _, k := range keysForBlacklistedCertificates {
mapStringForBlacklistedCertificates += fmt.Sprintf("%#v: %#v,", k, this.BlacklistedCertificates[k])
}
mapStringForBlacklistedCertificates += "}"
if this.BlacklistedCertificates != nil {
s = append(s, "BlacklistedCertificates: "+mapStringForBlacklistedCertificates+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
@ -1270,16 +1282,32 @@ func (m *Cluster) MarshalTo(data []byte) (int, error) {
i++
i = encodeVarintObjects(data, i, uint64(m.EncryptionKeyLamportClock))
}
if len(m.RemovedNodes) > 0 {
for _, msg := range m.RemovedNodes {
data[i] = 0x3a
if len(m.BlacklistedCertificates) > 0 {
for k, _ := range m.BlacklistedCertificates {
data[i] = 0x42
i++
i = encodeVarintObjects(data, i, uint64(msg.Size()))
n, err := msg.MarshalTo(data[i:])
if err != nil {
return 0, err
v := m.BlacklistedCertificates[k]
msgSize := 0
if v != nil {
msgSize = v.Size()
msgSize += 1 + sovObjects(uint64(msgSize))
}
mapSize := 1 + len(k) + sovObjects(uint64(len(k))) + msgSize
i = encodeVarintObjects(data, i, uint64(mapSize))
data[i] = 0xa
i++
i = encodeVarintObjects(data, i, uint64(len(k)))
i += copy(data[i:], k)
if v != nil {
data[i] = 0x12
i++
i = encodeVarintObjects(data, i, uint64(v.Size()))
n32, err := v.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n32
}
i += n
}
}
return i, nil
@ -1309,19 +1337,19 @@ func (m *Secret) MarshalTo(data []byte) (int, error) {
data[i] = 0x12
i++
i = encodeVarintObjects(data, i, uint64(m.Meta.Size()))
n32, err := m.Meta.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n32
data[i] = 0x1a
i++
i = encodeVarintObjects(data, i, uint64(m.Spec.Size()))
n33, err := m.Spec.MarshalTo(data[i:])
n33, err := m.Meta.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n33
data[i] = 0x1a
i++
i = encodeVarintObjects(data, i, uint64(m.Spec.Size()))
n34, err := m.Spec.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n34
if len(m.Digest) > 0 {
data[i] = 0x22
i++
@ -1596,10 +1624,17 @@ func (m *Cluster) Size() (n int) {
if m.EncryptionKeyLamportClock != 0 {
n += 1 + sovObjects(uint64(m.EncryptionKeyLamportClock))
}
if len(m.RemovedNodes) > 0 {
for _, e := range m.RemovedNodes {
l = e.Size()
n += 1 + l + sovObjects(uint64(l))
if len(m.BlacklistedCertificates) > 0 {
for k, v := range m.BlacklistedCertificates {
_ = k
_ = v
l = 0
if v != nil {
l = v.Size()
l += 1 + sovObjects(uint64(l))
}
mapEntrySize := 1 + len(k) + sovObjects(uint64(len(k))) + l
n += mapEntrySize + 1 + sovObjects(uint64(mapEntrySize))
}
}
return n
@ -1761,6 +1796,16 @@ func (this *Cluster) String() string {
if this == nil {
return "nil"
}
keysForBlacklistedCertificates := make([]string, 0, len(this.BlacklistedCertificates))
for k, _ := range this.BlacklistedCertificates {
keysForBlacklistedCertificates = append(keysForBlacklistedCertificates, k)
}
github_com_gogo_protobuf_sortkeys.Strings(keysForBlacklistedCertificates)
mapStringForBlacklistedCertificates := "map[string]*BlacklistedCertificate{"
for _, k := range keysForBlacklistedCertificates {
mapStringForBlacklistedCertificates += fmt.Sprintf("%v: %v,", k, this.BlacklistedCertificates[k])
}
mapStringForBlacklistedCertificates += "}"
s := strings.Join([]string{`&Cluster{`,
`ID:` + fmt.Sprintf("%v", this.ID) + `,`,
`Meta:` + strings.Replace(strings.Replace(this.Meta.String(), "Meta", "Meta", 1), `&`, ``, 1) + `,`,
@ -1768,7 +1813,7 @@ func (this *Cluster) String() string {
`RootCA:` + strings.Replace(strings.Replace(this.RootCA.String(), "RootCA", "RootCA", 1), `&`, ``, 1) + `,`,
`NetworkBootstrapKeys:` + strings.Replace(fmt.Sprintf("%v", this.NetworkBootstrapKeys), "EncryptionKey", "EncryptionKey", 1) + `,`,
`EncryptionKeyLamportClock:` + fmt.Sprintf("%v", this.EncryptionKeyLamportClock) + `,`,
`RemovedNodes:` + strings.Replace(fmt.Sprintf("%v", this.RemovedNodes), "RemovedNode", "RemovedNode", 1) + `,`,
`BlacklistedCertificates:` + mapStringForBlacklistedCertificates + `,`,
`}`,
}, "")
return s
@ -3697,9 +3742,9 @@ func (m *Cluster) Unmarshal(data []byte) error {
break
}
}
case 7:
case 8:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field RemovedNodes", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field BlacklistedCertificates", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
@ -3723,9 +3768,99 @@ func (m *Cluster) Unmarshal(data []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.RemovedNodes = append(m.RemovedNodes, &RemovedNode{})
if err := m.RemovedNodes[len(m.RemovedNodes)-1].Unmarshal(data[iNdEx:postIndex]); err != nil {
return err
var keykey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowObjects
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
keykey |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
var stringLenmapkey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowObjects
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
stringLenmapkey |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLenmapkey := int(stringLenmapkey)
if intStringLenmapkey < 0 {
return ErrInvalidLengthObjects
}
postStringIndexmapkey := iNdEx + intStringLenmapkey
if postStringIndexmapkey > l {
return io.ErrUnexpectedEOF
}
mapkey := string(data[iNdEx:postStringIndexmapkey])
iNdEx = postStringIndexmapkey
if m.BlacklistedCertificates == nil {
m.BlacklistedCertificates = make(map[string]*BlacklistedCertificate)
}
if iNdEx < postIndex {
var valuekey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowObjects
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
valuekey |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
var mapmsglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowObjects
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
mapmsglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if mapmsglen < 0 {
return ErrInvalidLengthObjects
}
postmsgIndex := iNdEx + mapmsglen
if mapmsglen < 0 {
return ErrInvalidLengthObjects
}
if postmsgIndex > l {
return io.ErrUnexpectedEOF
}
mapvalue := &BlacklistedCertificate{}
if err := mapvalue.Unmarshal(data[iNdEx:postmsgIndex]); err != nil {
return err
}
iNdEx = postmsgIndex
m.BlacklistedCertificates[mapkey] = mapvalue
} else {
var mapvalue *BlacklistedCertificate
m.BlacklistedCertificates[mapkey] = mapvalue
}
iNdEx = postIndex
default:
@ -4064,76 +4199,79 @@ var (
func init() { proto.RegisterFile("objects.proto", fileDescriptorObjects) }
var fileDescriptorObjects = []byte{
// 1126 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xbc, 0x57, 0x4d, 0x6f, 0x1b, 0xc5,
0x1b, 0xef, 0xda, 0x5b, 0xbf, 0x3c, 0xb6, 0x23, 0xfd, 0xe7, 0x5f, 0x45, 0xdb, 0x10, 0xec, 0xe0,
0x0a, 0xd4, 0x43, 0xe5, 0x8a, 0x52, 0x50, 0x2b, 0x5a, 0x21, 0xbf, 0x44, 0x60, 0x95, 0x40, 0x34,
0x29, 0xe9, 0x71, 0x35, 0xd9, 0x9d, 0x9a, 0xc5, 0xf6, 0xce, 0x6a, 0x66, 0xec, 0x2a, 0x3d, 0x21,
0x3e, 0x00, 0x1f, 0x81, 0x6f, 0xc1, 0x99, 0x6b, 0x0e, 0x1c, 0xb8, 0xc1, 0xc9, 0x22, 0x3e, 0x20,
0x71, 0xe3, 0x23, 0xa0, 0x79, 0x59, 0xdb, 0x91, 0xd7, 0x21, 0x95, 0xaa, 0xdc, 0xe6, 0xf1, 0xfc,
0x7e, 0xbf, 0x79, 0xde, 0xe6, 0x99, 0x35, 0xd4, 0xd8, 0xc9, 0x77, 0x34, 0x90, 0xa2, 0x95, 0x70,
0x26, 0x19, 0x42, 0x21, 0x0b, 0x86, 0x94, 0xb7, 0xc4, 0x2b, 0xc2, 0xc7, 0xc3, 0x48, 0xb6, 0xa6,
0x1f, 0xee, 0x54, 0xe4, 0x69, 0x42, 0x2d, 0x60, 0xa7, 0x22, 0x12, 0x1a, 0xa4, 0xc6, 0x6d, 0x19,
0x8d, 0xa9, 0x90, 0x64, 0x9c, 0xdc, 0x5f, 0xac, 0xec, 0xd6, 0xad, 0x01, 0x1b, 0x30, 0xbd, 0xbc,
0xaf, 0x56, 0xe6, 0xd7, 0xe6, 0x2f, 0x0e, 0xb8, 0x07, 0x54, 0x12, 0xf4, 0x29, 0x14, 0xa7, 0x94,
0x8b, 0x88, 0xc5, 0x9e, 0xb3, 0xe7, 0xdc, 0xad, 0x3c, 0x78, 0xa7, 0xb5, 0x7e, 0x72, 0xeb, 0xd8,
0x40, 0x3a, 0xee, 0xd9, 0xac, 0x71, 0x03, 0xa7, 0x0c, 0xf4, 0x04, 0x20, 0xe0, 0x94, 0x48, 0x1a,
0xfa, 0x44, 0x7a, 0x39, 0xcd, 0x7f, 0x37, 0x8b, 0xff, 0x3c, 0x75, 0x0a, 0x97, 0x2d, 0xa1, 0x2d,
0x15, 0x7b, 0x92, 0x84, 0x29, 0x3b, 0x7f, 0x25, 0xb6, 0x25, 0xb4, 0x65, 0xf3, 0xef, 0x3c, 0xb8,
0x5f, 0xb1, 0x90, 0xa2, 0x6d, 0xc8, 0x45, 0xa1, 0x76, 0xbe, 0xdc, 0x29, 0xcc, 0x67, 0x8d, 0x5c,
0xbf, 0x87, 0x73, 0x51, 0x88, 0x1e, 0x80, 0x3b, 0xa6, 0x92, 0x58, 0xb7, 0xbc, 0x2c, 0x61, 0x95,
0x01, 0x1b, 0x93, 0xc6, 0xa2, 0x4f, 0xc0, 0x55, 0x69, 0xb5, 0xce, 0xec, 0x66, 0x71, 0xd4, 0x99,
0x47, 0x09, 0x0d, 0x52, 0x9e, 0xc2, 0xa3, 0x7d, 0xa8, 0x84, 0x54, 0x04, 0x3c, 0x4a, 0xa4, 0xca,
0xa4, 0xab, 0xe9, 0x77, 0x36, 0xd1, 0x7b, 0x4b, 0x28, 0x5e, 0xe5, 0xa1, 0x27, 0x50, 0x10, 0x92,
0xc8, 0x89, 0xf0, 0x6e, 0x6a, 0x85, 0xfa, 0x46, 0x07, 0x34, 0xca, 0xba, 0x60, 0x39, 0xe8, 0x0b,
0xd8, 0x1a, 0x93, 0x98, 0x0c, 0x28, 0xf7, 0xad, 0x4a, 0x41, 0xab, 0xbc, 0x97, 0x19, 0xba, 0x41,
0x1a, 0x21, 0x5c, 0x1b, 0xaf, 0x9a, 0x68, 0x1f, 0x80, 0x48, 0x49, 0x82, 0x6f, 0xc7, 0x34, 0x96,
0x5e, 0x51, 0xab, 0xbc, 0x9f, 0xe9, 0x0b, 0x95, 0xaf, 0x18, 0x1f, 0xb6, 0x17, 0x60, 0xbc, 0x42,
0x44, 0x9f, 0x43, 0x25, 0xa0, 0x5c, 0x46, 0x2f, 0xa3, 0x80, 0x48, 0xea, 0x95, 0xb4, 0x4e, 0x23,
0x4b, 0xa7, 0xbb, 0x84, 0xd9, 0xa0, 0x56, 0x99, 0xcd, 0xdf, 0x73, 0x50, 0x3c, 0xa2, 0x7c, 0x1a,
0x05, 0x6f, 0xb7, 0xdc, 0x8f, 0x2f, 0x94, 0x3b, 0xd3, 0x33, 0x7b, 0xec, 0x5a, 0xc5, 0x1f, 0x41,
0x89, 0xc6, 0x61, 0xc2, 0xa2, 0x58, 0xda, 0x72, 0x67, 0x76, 0xcb, 0xbe, 0xc5, 0xe0, 0x05, 0x1a,
0xed, 0x43, 0xcd, 0x74, 0xb1, 0x7f, 0xa1, 0xd6, 0x7b, 0x59, 0xf4, 0x6f, 0x34, 0xd0, 0x16, 0xa9,
0x3a, 0x59, 0xb1, 0x50, 0x0f, 0x6a, 0x09, 0xa7, 0xd3, 0x88, 0x4d, 0x84, 0xaf, 0x83, 0x28, 0x5c,
0x29, 0x08, 0x5c, 0x4d, 0x59, 0xca, 0x6a, 0xfe, 0x94, 0x83, 0x52, 0xea, 0x23, 0x7a, 0x68, 0xd3,
0xe1, 0x6c, 0x76, 0x28, 0xc5, 0x6a, 0x29, 0x93, 0x89, 0x87, 0x70, 0x33, 0x61, 0x5c, 0x0a, 0x2f,
0xb7, 0x97, 0xdf, 0xd4, 0xb3, 0x87, 0x8c, 0xcb, 0x2e, 0x8b, 0x5f, 0x46, 0x03, 0x6c, 0xc0, 0xe8,
0x05, 0x54, 0xa6, 0x11, 0x97, 0x13, 0x32, 0xf2, 0xa3, 0x44, 0x78, 0x79, 0xcd, 0xfd, 0xe0, 0xb2,
0x23, 0x5b, 0xc7, 0x06, 0xdf, 0x3f, 0xec, 0x6c, 0xcd, 0x67, 0x0d, 0x58, 0x98, 0x02, 0x83, 0x95,
0xea, 0x27, 0x62, 0xe7, 0x00, 0xca, 0x8b, 0x1d, 0x74, 0x0f, 0x20, 0x36, 0x2d, 0xea, 0x2f, 0x9a,
0xa6, 0x36, 0x9f, 0x35, 0xca, 0xb6, 0x71, 0xfb, 0x3d, 0x5c, 0xb6, 0x80, 0x7e, 0x88, 0x10, 0xb8,
0x24, 0x0c, 0xb9, 0x6e, 0xa1, 0x32, 0xd6, 0xeb, 0xe6, 0xaf, 0x37, 0xc1, 0x7d, 0x4e, 0xc4, 0xf0,
0xba, 0xc7, 0x8c, 0x3a, 0x73, 0xad, 0xe9, 0xee, 0x01, 0x08, 0x53, 0x4a, 0x15, 0x8e, 0xbb, 0x0c,
0xc7, 0x16, 0x58, 0x85, 0x63, 0x01, 0x26, 0x1c, 0x31, 0x62, 0x52, 0xf7, 0x97, 0x8b, 0xf5, 0x1a,
0xdd, 0x81, 0x62, 0xcc, 0x42, 0x4d, 0x2f, 0x68, 0x3a, 0xcc, 0x67, 0x8d, 0x82, 0x1a, 0x29, 0xfd,
0x1e, 0x2e, 0xa8, 0xad, 0x7e, 0xa8, 0xee, 0x2d, 0x89, 0x63, 0x26, 0x89, 0x1a, 0x4a, 0xc2, 0xde,
0xff, 0xcc, 0xc6, 0x6a, 0x2f, 0x61, 0xe9, 0xbd, 0x5d, 0x61, 0xa2, 0x63, 0xf8, 0x7f, 0xea, 0xef,
0xaa, 0x60, 0xe9, 0x4d, 0x04, 0x91, 0x55, 0x58, 0xd9, 0x59, 0x99, 0x93, 0xe5, 0xcd, 0x73, 0x52,
0x67, 0x30, 0x6b, 0x4e, 0x76, 0xa0, 0x16, 0x52, 0x11, 0x71, 0x1a, 0xea, 0x1b, 0x48, 0x3d, 0xd8,
0x73, 0xee, 0x6e, 0x6d, 0x78, 0x7a, 0xac, 0x08, 0xc5, 0x55, 0xcb, 0xd1, 0x16, 0x6a, 0x43, 0xc9,
0xf6, 0x8d, 0xf0, 0x2a, 0xba, 0x77, 0xaf, 0x38, 0x1f, 0x17, 0xb4, 0x0b, 0x13, 0xa4, 0xfa, 0x46,
0x13, 0xe4, 0x31, 0xc0, 0x88, 0x0d, 0xfc, 0x90, 0x47, 0x53, 0xca, 0xbd, 0x9a, 0xe6, 0xee, 0x64,
0x71, 0x7b, 0x1a, 0x81, 0xcb, 0x23, 0x36, 0x30, 0xcb, 0xe6, 0x0f, 0x0e, 0xfc, 0x6f, 0xcd, 0x29,
0xf4, 0x31, 0x14, 0xad, 0x5b, 0x97, 0x7d, 0x04, 0x58, 0x1e, 0x4e, 0xb1, 0x68, 0x17, 0xca, 0xea,
0x8e, 0x50, 0x21, 0xa8, 0xb9, 0xfd, 0x65, 0xbc, 0xfc, 0x01, 0x79, 0x50, 0x24, 0xa3, 0x88, 0xa8,
0xbd, 0xbc, 0xde, 0x4b, 0xcd, 0xe6, 0x8f, 0x39, 0x28, 0x5a, 0xb1, 0xeb, 0x1e, 0xe7, 0xf6, 0xd8,
0xb5, 0x9b, 0xf5, 0x14, 0xaa, 0x26, 0x9d, 0xb6, 0x25, 0xdc, 0xff, 0x4c, 0x6a, 0xc5, 0xe0, 0x4d,
0x3b, 0x3c, 0x05, 0x37, 0x4a, 0xc8, 0xd8, 0x8e, 0xf2, 0xcc, 0x93, 0xfb, 0x87, 0xed, 0x83, 0xaf,
0x13, 0xd3, 0xd9, 0xa5, 0xf9, 0xac, 0xe1, 0xaa, 0x1f, 0xb0, 0xa6, 0x35, 0x7f, 0xce, 0x43, 0xb1,
0x3b, 0x9a, 0x08, 0x49, 0xf9, 0x75, 0x27, 0xc4, 0x1e, 0xbb, 0x96, 0x90, 0x2e, 0x14, 0x39, 0x63,
0xd2, 0x0f, 0xc8, 0x65, 0xb9, 0xc0, 0x8c, 0xc9, 0x6e, 0xbb, 0xb3, 0xa5, 0x88, 0x6a, 0x90, 0x18,
0x1b, 0x17, 0x14, 0xb5, 0x4b, 0xd0, 0x0b, 0xd8, 0x4e, 0xc7, 0xef, 0x09, 0x63, 0x52, 0x48, 0x4e,
0x12, 0x7f, 0x48, 0x4f, 0xd5, 0x9b, 0x97, 0xdf, 0xf4, 0x65, 0xb2, 0x1f, 0x07, 0xfc, 0x54, 0x27,
0xea, 0x19, 0x3d, 0xc5, 0xb7, 0xac, 0x40, 0x27, 0xe5, 0x3f, 0xa3, 0xa7, 0x02, 0x7d, 0x06, 0xbb,
0x74, 0x01, 0x53, 0x8a, 0xfe, 0x88, 0x8c, 0xd5, 0xc3, 0xe2, 0x07, 0x23, 0x16, 0x0c, 0xf5, 0x6c,
0x73, 0xf1, 0x6d, 0xba, 0x2a, 0xf5, 0xa5, 0x41, 0x74, 0x15, 0x40, 0xbd, 0x9e, 0x9c, 0x8e, 0xd9,
0x94, 0x86, 0xbe, 0x1a, 0x7a, 0x6a, 0xc8, 0xe5, 0x37, 0xa5, 0x08, 0x1b, 0xa0, 0x1a, 0x92, 0xb8,
0xca, 0x97, 0x86, 0x68, 0xfe, 0xe5, 0x40, 0xe1, 0x88, 0x06, 0x9c, 0xca, 0xb7, 0x5a, 0xb6, 0x47,
0x17, 0xca, 0x56, 0xcf, 0x7e, 0xd1, 0xd5, 0xa9, 0x6b, 0x55, 0xdb, 0x86, 0x42, 0x18, 0x0d, 0xa8,
0x30, 0xdf, 0x24, 0x65, 0x6c, 0x2d, 0xd4, 0x04, 0x57, 0x44, 0xaf, 0xa9, 0xee, 0xcf, 0xbc, 0x79,
0x3e, 0xad, 0x42, 0xf4, 0x9a, 0x62, 0xbd, 0x87, 0x76, 0xa0, 0x14, 0xc5, 0x92, 0xf2, 0x98, 0x8c,
0x74, 0xfe, 0x4a, 0x78, 0x61, 0x77, 0x76, 0xcf, 0xce, 0xeb, 0x37, 0xfe, 0x38, 0xaf, 0xdf, 0xf8,
0xe7, 0xbc, 0xee, 0x7c, 0x3f, 0xaf, 0x3b, 0x67, 0xf3, 0xba, 0xf3, 0xdb, 0xbc, 0xee, 0xfc, 0x39,
0xaf, 0x3b, 0x27, 0x05, 0xfd, 0x9f, 0xe2, 0xa3, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xf7, 0x71,
0xe0, 0xa4, 0xc3, 0x0c, 0x00, 0x00,
// 1174 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xbc, 0x57, 0x4d, 0x8f, 0x1b, 0x35,
0x18, 0xee, 0x24, 0xb3, 0xf9, 0x78, 0xb3, 0x59, 0x81, 0xa9, 0xca, 0x34, 0x2c, 0xc9, 0x92, 0x0a,
0x54, 0xa1, 0x2a, 0x15, 0xa5, 0xa0, 0x2d, 0xb4, 0x82, 0x7c, 0x09, 0xa2, 0x52, 0xa8, 0xdc, 0xd2,
0x1e, 0x23, 0xef, 0x8c, 0x1b, 0x86, 0x4c, 0xc6, 0x23, 0xdb, 0x49, 0x95, 0x9e, 0x10, 0x3f, 0x80,
0x9f, 0xc0, 0x5f, 0xe1, 0xba, 0x07, 0x0e, 0xdc, 0xe0, 0x80, 0x22, 0x36, 0x07, 0x24, 0x6e, 0xfc,
0x04, 0x64, 0x8f, 0x27, 0x99, 0x55, 0x26, 0xcb, 0x56, 0xaa, 0xf6, 0xe6, 0x37, 0x7e, 0x9e, 0xc7,
0xef, 0x97, 0xdf, 0x71, 0xa0, 0xca, 0x8e, 0xbe, 0xa7, 0xae, 0x14, 0xad, 0x88, 0x33, 0xc9, 0x10,
0xf2, 0x98, 0x3b, 0xa6, 0xbc, 0x25, 0x9e, 0x13, 0x3e, 0x19, 0xfb, 0xb2, 0x35, 0xfb, 0xa0, 0x56,
0x91, 0xf3, 0x88, 0x1a, 0x40, 0xad, 0x22, 0x22, 0xea, 0x26, 0xc6, 0x55, 0xe9, 0x4f, 0xa8, 0x90,
0x64, 0x12, 0xdd, 0x5c, 0xad, 0xcc, 0xd6, 0xe5, 0x11, 0x1b, 0x31, 0xbd, 0xbc, 0xa9, 0x56, 0xf1,
0xaf, 0xcd, 0x5f, 0x2c, 0xb0, 0x1f, 0x50, 0x49, 0xd0, 0xa7, 0x50, 0x9c, 0x51, 0x2e, 0x7c, 0x16,
0x3a, 0xd6, 0x81, 0x75, 0xbd, 0x72, 0xeb, 0xad, 0xd6, 0xe6, 0xc9, 0xad, 0x27, 0x31, 0xa4, 0x63,
0x1f, 0x2f, 0x1a, 0x97, 0x70, 0xc2, 0x40, 0x77, 0x01, 0x5c, 0x4e, 0x89, 0xa4, 0xde, 0x90, 0x48,
0x27, 0xa7, 0xf9, 0x6f, 0x67, 0xf1, 0x1f, 0x27, 0x4e, 0xe1, 0xb2, 0x21, 0xb4, 0xa5, 0x62, 0x4f,
0x23, 0x2f, 0x61, 0xe7, 0xcf, 0xc5, 0x36, 0x84, 0xb6, 0x6c, 0xfe, 0x93, 0x07, 0xfb, 0x6b, 0xe6,
0x51, 0x74, 0x05, 0x72, 0xbe, 0xa7, 0x9d, 0x2f, 0x77, 0x0a, 0xcb, 0x45, 0x23, 0x37, 0xe8, 0xe1,
0x9c, 0xef, 0xa1, 0x5b, 0x60, 0x4f, 0xa8, 0x24, 0xc6, 0x2d, 0x27, 0x4b, 0x58, 0x65, 0xc0, 0xc4,
0xa4, 0xb1, 0xe8, 0x63, 0xb0, 0x55, 0x5a, 0x8d, 0x33, 0xfb, 0x59, 0x1c, 0x75, 0xe6, 0xa3, 0x88,
0xba, 0x09, 0x4f, 0xe1, 0x51, 0x1f, 0x2a, 0x1e, 0x15, 0x2e, 0xf7, 0x23, 0xa9, 0x32, 0x69, 0x6b,
0xfa, 0xb5, 0x6d, 0xf4, 0xde, 0x1a, 0x8a, 0xd3, 0x3c, 0x74, 0x17, 0x0a, 0x42, 0x12, 0x39, 0x15,
0xce, 0x8e, 0x56, 0xa8, 0x6f, 0x75, 0x40, 0xa3, 0x8c, 0x0b, 0x86, 0x83, 0xbe, 0x84, 0xbd, 0x09,
0x09, 0xc9, 0x88, 0xf2, 0xa1, 0x51, 0x29, 0x68, 0x95, 0x77, 0x32, 0x43, 0x8f, 0x91, 0xb1, 0x10,
0xae, 0x4e, 0xd2, 0x26, 0xea, 0x03, 0x10, 0x29, 0x89, 0xfb, 0xdd, 0x84, 0x86, 0xd2, 0x29, 0x6a,
0x95, 0x77, 0x33, 0x7d, 0xa1, 0xf2, 0x39, 0xe3, 0xe3, 0xf6, 0x0a, 0x8c, 0x53, 0x44, 0xf4, 0x05,
0x54, 0x5c, 0xca, 0xa5, 0xff, 0xcc, 0x77, 0x89, 0xa4, 0x4e, 0x49, 0xeb, 0x34, 0xb2, 0x74, 0xba,
0x6b, 0x98, 0x09, 0x2a, 0xcd, 0x6c, 0xfe, 0x9e, 0x83, 0xe2, 0x23, 0xca, 0x67, 0xbe, 0xfb, 0x6a,
0xcb, 0x7d, 0xe7, 0x54, 0xb9, 0x33, 0x3d, 0x33, 0xc7, 0x6e, 0x54, 0xfc, 0x10, 0x4a, 0x34, 0xf4,
0x22, 0xe6, 0x87, 0xd2, 0x94, 0x3b, 0xb3, 0x5b, 0xfa, 0x06, 0x83, 0x57, 0x68, 0xd4, 0x87, 0x6a,
0xdc, 0xc5, 0xc3, 0x53, 0xb5, 0x3e, 0xc8, 0xa2, 0x7f, 0xab, 0x81, 0xa6, 0x48, 0xbb, 0xd3, 0x94,
0x85, 0x7a, 0x50, 0x8d, 0x38, 0x9d, 0xf9, 0x6c, 0x2a, 0x86, 0x3a, 0x88, 0xc2, 0xb9, 0x82, 0xc0,
0xbb, 0x09, 0x4b, 0x59, 0xcd, 0x9f, 0x73, 0x50, 0x4a, 0x7c, 0x44, 0xb7, 0x4d, 0x3a, 0xac, 0xed,
0x0e, 0x25, 0x58, 0x2d, 0x15, 0x67, 0xe2, 0x36, 0xec, 0x44, 0x8c, 0x4b, 0xe1, 0xe4, 0x0e, 0xf2,
0xdb, 0x7a, 0xf6, 0x21, 0xe3, 0xb2, 0xcb, 0xc2, 0x67, 0xfe, 0x08, 0xc7, 0x60, 0xf4, 0x14, 0x2a,
0x33, 0x9f, 0xcb, 0x29, 0x09, 0x86, 0x7e, 0x24, 0x9c, 0xbc, 0xe6, 0xbe, 0x77, 0xd6, 0x91, 0xad,
0x27, 0x31, 0x7e, 0xf0, 0xb0, 0xb3, 0xb7, 0x5c, 0x34, 0x60, 0x65, 0x0a, 0x0c, 0x46, 0x6a, 0x10,
0x89, 0xda, 0x03, 0x28, 0xaf, 0x76, 0xd0, 0x0d, 0x80, 0x30, 0x6e, 0xd1, 0xe1, 0xaa, 0x69, 0xaa,
0xcb, 0x45, 0xa3, 0x6c, 0x1a, 0x77, 0xd0, 0xc3, 0x65, 0x03, 0x18, 0x78, 0x08, 0x81, 0x4d, 0x3c,
0x8f, 0xeb, 0x16, 0x2a, 0x63, 0xbd, 0x6e, 0xfe, 0xba, 0x03, 0xf6, 0x63, 0x22, 0xc6, 0x17, 0x3d,
0x66, 0xd4, 0x99, 0x1b, 0x4d, 0x77, 0x03, 0x40, 0xc4, 0xa5, 0x54, 0xe1, 0xd8, 0xeb, 0x70, 0x4c,
0x81, 0x55, 0x38, 0x06, 0x10, 0x87, 0x23, 0x02, 0x26, 0x75, 0x7f, 0xd9, 0x58, 0xaf, 0xd1, 0x35,
0x28, 0x86, 0xcc, 0xd3, 0xf4, 0x82, 0xa6, 0xc3, 0x72, 0xd1, 0x28, 0xa8, 0x91, 0x32, 0xe8, 0xe1,
0x82, 0xda, 0x1a, 0x78, 0xea, 0xde, 0x92, 0x30, 0x64, 0x92, 0xa8, 0xa1, 0x24, 0xcc, 0xfd, 0xcf,
0x6c, 0xac, 0xf6, 0x1a, 0x96, 0xdc, 0xdb, 0x14, 0x13, 0x3d, 0x81, 0x37, 0x12, 0x7f, 0xd3, 0x82,
0xa5, 0x97, 0x11, 0x44, 0x46, 0x21, 0xb5, 0x93, 0x9a, 0x93, 0xe5, 0xed, 0x73, 0x52, 0x67, 0x30,
0x6b, 0x4e, 0x76, 0xa0, 0xea, 0x51, 0xe1, 0x73, 0xea, 0xe9, 0x1b, 0x48, 0x1d, 0x38, 0xb0, 0xae,
0xef, 0x6d, 0xf9, 0xf4, 0x18, 0x11, 0x8a, 0x77, 0x0d, 0x47, 0x5b, 0xa8, 0x0d, 0x25, 0xd3, 0x37,
0xc2, 0xa9, 0xe8, 0xde, 0x3d, 0xe7, 0x7c, 0x5c, 0xd1, 0x4e, 0x4d, 0x90, 0xdd, 0x97, 0x9a, 0x20,
0x77, 0x00, 0x02, 0x36, 0x1a, 0x7a, 0xdc, 0x9f, 0x51, 0xee, 0x54, 0x35, 0xb7, 0x96, 0xc5, 0xed,
0x69, 0x04, 0x2e, 0x07, 0x6c, 0x14, 0x2f, 0x9b, 0x3f, 0x5a, 0xf0, 0xfa, 0x86, 0x53, 0xe8, 0x23,
0x28, 0x1a, 0xb7, 0xce, 0x7a, 0x04, 0x18, 0x1e, 0x4e, 0xb0, 0x68, 0x1f, 0xca, 0xea, 0x8e, 0x50,
0x21, 0x68, 0x7c, 0xfb, 0xcb, 0x78, 0xfd, 0x03, 0x72, 0xa0, 0x48, 0x02, 0x9f, 0xa8, 0xbd, 0xbc,
0xde, 0x4b, 0xcc, 0xe6, 0x4f, 0x39, 0x28, 0x1a, 0xb1, 0x8b, 0x1e, 0xe7, 0xe6, 0xd8, 0x8d, 0x9b,
0x75, 0x0f, 0x76, 0xe3, 0x74, 0x9a, 0x96, 0xb0, 0xff, 0x37, 0xa9, 0x95, 0x18, 0x1f, 0xb7, 0xc3,
0x3d, 0xb0, 0xfd, 0x88, 0x4c, 0xcc, 0x28, 0xcf, 0x3c, 0x79, 0xf0, 0xb0, 0xfd, 0xe0, 0x9b, 0x28,
0xee, 0xec, 0xd2, 0x72, 0xd1, 0xb0, 0xd5, 0x0f, 0x58, 0xd3, 0x9a, 0x7f, 0xda, 0x50, 0xec, 0x06,
0x53, 0x21, 0x29, 0xbf, 0xe8, 0x84, 0x98, 0x63, 0x37, 0x12, 0xd2, 0x85, 0x22, 0x67, 0x4c, 0x0e,
0x5d, 0x72, 0x56, 0x2e, 0x30, 0x63, 0xb2, 0xdb, 0xee, 0xec, 0x29, 0xa2, 0x1a, 0x24, 0xb1, 0x8d,
0x0b, 0x8a, 0xda, 0x25, 0xe8, 0x29, 0x5c, 0x49, 0xc6, 0xef, 0x11, 0x63, 0x52, 0x48, 0x4e, 0xa2,
0xe1, 0x98, 0xce, 0xd5, 0x37, 0x2f, 0xbf, 0xed, 0x65, 0xd2, 0x0f, 0x5d, 0x3e, 0xd7, 0x89, 0xba,
0x4f, 0xe7, 0xf8, 0xb2, 0x11, 0xe8, 0x24, 0xfc, 0xfb, 0x74, 0x2e, 0xd0, 0x67, 0xb0, 0x4f, 0x57,
0x30, 0xa5, 0x38, 0x0c, 0xc8, 0x44, 0x7d, 0x58, 0x86, 0x6e, 0xc0, 0xdc, 0xb1, 0x9e, 0x6d, 0x36,
0xbe, 0x4a, 0xd3, 0x52, 0x5f, 0xc5, 0x88, 0xae, 0x02, 0x20, 0x01, 0xce, 0x51, 0x40, 0xdc, 0x71,
0xe0, 0x0b, 0xf5, 0xfe, 0x4c, 0x3d, 0x36, 0xd4, 0x78, 0x52, 0xbe, 0x1d, 0x9e, 0x91, 0xad, 0x56,
0x67, 0xcd, 0x4d, 0x3d, 0x5d, 0x44, 0x3f, 0x94, 0x7c, 0x8e, 0xdf, 0x3c, 0xca, 0xde, 0xad, 0xcd,
0x60, 0xff, 0x2c, 0x22, 0x7a, 0x0d, 0xf2, 0x63, 0x3a, 0x8f, 0x6b, 0x8f, 0xd5, 0x12, 0x7d, 0x0e,
0x3b, 0x33, 0x12, 0x4c, 0xa9, 0xa9, 0xfa, 0xfb, 0x59, 0x3e, 0x65, 0x4b, 0xe2, 0x98, 0xf8, 0x49,
0xee, 0xd0, 0x6a, 0xfe, 0x6d, 0x41, 0xe1, 0x11, 0x75, 0x39, 0x95, 0xaf, 0xb4, 0xbb, 0x0e, 0x4f,
0x75, 0x57, 0x3d, 0xfb, 0xe1, 0xa1, 0x4e, 0xdd, 0x68, 0xae, 0x2b, 0x50, 0xf0, 0xfc, 0x11, 0x15,
0xf1, 0xd3, 0xa9, 0x8c, 0x8d, 0x85, 0x9a, 0x60, 0x0b, 0xff, 0x05, 0xd5, 0xd7, 0x28, 0x1f, 0x7f,
0xe5, 0x8d, 0x82, 0xff, 0x82, 0x62, 0xbd, 0x87, 0x6a, 0x50, 0xf2, 0x43, 0x49, 0x79, 0x48, 0x02,
0x5d, 0xe6, 0x12, 0x5e, 0xd9, 0x9d, 0xfd, 0xe3, 0x93, 0xfa, 0xa5, 0x3f, 0x4e, 0xea, 0x97, 0xfe,
0x3d, 0xa9, 0x5b, 0x3f, 0x2c, 0xeb, 0xd6, 0xf1, 0xb2, 0x6e, 0xfd, 0xb6, 0xac, 0x5b, 0x7f, 0x2d,
0xeb, 0xd6, 0x51, 0x41, 0xff, 0xf5, 0xf9, 0xf0, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x40, 0xcf,
0x57, 0x63, 0x6a, 0x0d, 0x00, 0x00,
}

View file

@ -226,9 +226,10 @@ message Cluster {
// a new key is allocated on key rotation.
uint64 encryption_key_lamport_clock = 6;
// RemovedNodes is the list of nodes that have been removed from the
// BlacklistedCertificates tracks certificates that should no longer
// be honored. It's a mapping from CN -> BlacklistedCertificate.
// swarm. Their certificates should effectively be blacklisted.
repeated RemovedNode removed_nodes = 7;
map<string, BlacklistedCertificate> blacklisted_certificates = 8;
}
// Secret represents a secret that should be passed to a container or a node,

View file

@ -458,6 +458,9 @@ type ContainerSpec struct {
//
// If Command and Args are provided, Args will be appended to Command.
Args []string `protobuf:"bytes,4,rep,name=args" json:"args,omitempty"`
// Hostname specifies the hostname that will be set on containers created by docker swarm.
// All containers for a given service will have the same hostname
Hostname string `protobuf:"bytes,14,opt,name=hostname,proto3" json:"hostname,omitempty"`
// Env specifies the environment variables for the container in NAME=VALUE
// format. These must be compliant with [IEEE Std
// 1003.1-2001](http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html).
@ -472,7 +475,10 @@ type ContainerSpec struct {
User string `protobuf:"bytes,7,opt,name=user,proto3" json:"user,omitempty"`
// Groups specifies supplementary groups available to the user.
Groups []string `protobuf:"bytes,11,rep,name=groups" json:"groups,omitempty"`
Mounts []Mount `protobuf:"bytes,8,rep,name=mounts" json:"mounts"`
// TTY declares that a TTY should be attached to the standard streams,
// including stdin if it is still open.
TTY bool `protobuf:"varint,13,opt,name=tty,proto3" json:"tty,omitempty"`
Mounts []Mount `protobuf:"bytes,8,rep,name=mounts" json:"mounts"`
// StopGracePeriod the grace period for stopping the container before
// forcefully killing the container.
StopGracePeriod *docker_swarmkit_v11.Duration `protobuf:"bytes,9,opt,name=stop_grace_period,json=stopGracePeriod" json:"stop_grace_period,omitempty"`
@ -481,6 +487,8 @@ type ContainerSpec struct {
// SecretReference contains references to zero or more secrets that
// will be exposed to the container.
Secrets []*SecretReference `protobuf:"bytes,12,rep,name=secrets" json:"secrets,omitempty"`
// DNSConfig allows one to specify DNS related configuration in resolv.conf
DNSConfig *ContainerSpec_DNSConfig `protobuf:"bytes,15,opt,name=dns_config,json=dnsConfig" json:"dns_config,omitempty"`
}
func (m *ContainerSpec) Reset() { *m = ContainerSpec{} }
@ -502,6 +510,23 @@ func (*ContainerSpec_PullOptions) Descriptor() ([]byte, []int) {
return fileDescriptorSpecs, []int{6, 1}
}
// DNSConfig specifies DNS related configurations in resolver configuration file (resolv.conf)
// Detailed documentation is available in:
// http://man7.org/linux/man-pages/man5/resolv.conf.5.html
// TODO: domain is not supported yet
type ContainerSpec_DNSConfig struct {
// Nameservers specifies the IP addresses of the name servers
Nameservers []string `protobuf:"bytes,1,rep,name=nameservers" json:"nameservers,omitempty"`
// Search specifies the search list for host-name lookup
Search []string `protobuf:"bytes,2,rep,name=search" json:"search,omitempty"`
// Options allows certain internal resolver variables to be modified
Options []string `protobuf:"bytes,3,rep,name=options" json:"options,omitempty"`
}
func (m *ContainerSpec_DNSConfig) Reset() { *m = ContainerSpec_DNSConfig{} }
func (*ContainerSpec_DNSConfig) ProtoMessage() {}
func (*ContainerSpec_DNSConfig) Descriptor() ([]byte, []int) { return fileDescriptorSpecs, []int{6, 2} }
// EndpointSpec defines the properties that can be configured to
// access and loadbalance the service.
type EndpointSpec struct {
@ -583,6 +608,7 @@ func init() {
proto.RegisterType((*NetworkAttachmentSpec)(nil), "docker.swarmkit.v1.NetworkAttachmentSpec")
proto.RegisterType((*ContainerSpec)(nil), "docker.swarmkit.v1.ContainerSpec")
proto.RegisterType((*ContainerSpec_PullOptions)(nil), "docker.swarmkit.v1.ContainerSpec.PullOptions")
proto.RegisterType((*ContainerSpec_DNSConfig)(nil), "docker.swarmkit.v1.ContainerSpec.DNSConfig")
proto.RegisterType((*EndpointSpec)(nil), "docker.swarmkit.v1.EndpointSpec")
proto.RegisterType((*NetworkSpec)(nil), "docker.swarmkit.v1.NetworkSpec")
proto.RegisterType((*ClusterSpec)(nil), "docker.swarmkit.v1.ClusterSpec")
@ -723,10 +749,13 @@ func (m *ContainerSpec) Copy() *ContainerSpec {
o := &ContainerSpec{
Image: m.Image,
Hostname: m.Hostname,
Dir: m.Dir,
User: m.User,
TTY: m.TTY,
StopGracePeriod: m.StopGracePeriod.Copy(),
PullOptions: m.PullOptions.Copy(),
DNSConfig: m.DNSConfig.Copy(),
}
if m.Labels != nil {
@ -785,6 +814,31 @@ func (m *ContainerSpec_PullOptions) Copy() *ContainerSpec_PullOptions {
return o
}
func (m *ContainerSpec_DNSConfig) Copy() *ContainerSpec_DNSConfig {
if m == nil {
return nil
}
o := &ContainerSpec_DNSConfig{}
if m.Nameservers != nil {
o.Nameservers = make([]string, 0, len(m.Nameservers))
o.Nameservers = append(o.Nameservers, m.Nameservers...)
}
if m.Search != nil {
o.Search = make([]string, 0, len(m.Search))
o.Search = append(o.Search, m.Search...)
}
if m.Options != nil {
o.Options = make([]string, 0, len(m.Options))
o.Options = append(o.Options, m.Options...)
}
return o
}
func (m *EndpointSpec) Copy() *EndpointSpec {
if m == nil {
return nil
@ -981,7 +1035,7 @@ func (this *ContainerSpec) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 16)
s := make([]string, 0, 19)
s = append(s, "&api.ContainerSpec{")
s = append(s, "Image: "+fmt.Sprintf("%#v", this.Image)+",\n")
keysForLabels := make([]string, 0, len(this.Labels))
@ -999,10 +1053,12 @@ func (this *ContainerSpec) GoString() string {
}
s = append(s, "Command: "+fmt.Sprintf("%#v", this.Command)+",\n")
s = append(s, "Args: "+fmt.Sprintf("%#v", this.Args)+",\n")
s = append(s, "Hostname: "+fmt.Sprintf("%#v", this.Hostname)+",\n")
s = append(s, "Env: "+fmt.Sprintf("%#v", this.Env)+",\n")
s = append(s, "Dir: "+fmt.Sprintf("%#v", this.Dir)+",\n")
s = append(s, "User: "+fmt.Sprintf("%#v", this.User)+",\n")
s = append(s, "Groups: "+fmt.Sprintf("%#v", this.Groups)+",\n")
s = append(s, "TTY: "+fmt.Sprintf("%#v", this.TTY)+",\n")
if this.Mounts != nil {
s = append(s, "Mounts: "+fmt.Sprintf("%#v", this.Mounts)+",\n")
}
@ -1015,6 +1071,9 @@ func (this *ContainerSpec) GoString() string {
if this.Secrets != nil {
s = append(s, "Secrets: "+fmt.Sprintf("%#v", this.Secrets)+",\n")
}
if this.DNSConfig != nil {
s = append(s, "DNSConfig: "+fmt.Sprintf("%#v", this.DNSConfig)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
@ -1028,6 +1087,18 @@ func (this *ContainerSpec_PullOptions) GoString() string {
s = append(s, "}")
return strings.Join(s, "")
}
func (this *ContainerSpec_DNSConfig) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 7)
s = append(s, "&api.ContainerSpec_DNSConfig{")
s = append(s, "Nameservers: "+fmt.Sprintf("%#v", this.Nameservers)+",\n")
s = append(s, "Search: "+fmt.Sprintf("%#v", this.Search)+",\n")
s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
s = append(s, "}")
return strings.Join(s, "")
}
func (this *EndpointSpec) GoString() string {
if this == nil {
return "nil"
@ -1584,6 +1655,32 @@ func (m *ContainerSpec) MarshalTo(data []byte) (int, error) {
i += n
}
}
if m.TTY {
data[i] = 0x68
i++
if m.TTY {
data[i] = 1
} else {
data[i] = 0
}
i++
}
if len(m.Hostname) > 0 {
data[i] = 0x72
i++
i = encodeVarintSpecs(data, i, uint64(len(m.Hostname)))
i += copy(data[i:], m.Hostname)
}
if m.DNSConfig != nil {
data[i] = 0x7a
i++
i = encodeVarintSpecs(data, i, uint64(m.DNSConfig.Size()))
n18, err := m.DNSConfig.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n18
}
return i, nil
}
@ -1613,6 +1710,69 @@ func (m *ContainerSpec_PullOptions) MarshalTo(data []byte) (int, error) {
return i, nil
}
func (m *ContainerSpec_DNSConfig) Marshal() (data []byte, err error) {
size := m.Size()
data = make([]byte, size)
n, err := m.MarshalTo(data)
if err != nil {
return nil, err
}
return data[:n], nil
}
func (m *ContainerSpec_DNSConfig) MarshalTo(data []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if len(m.Nameservers) > 0 {
for _, s := range m.Nameservers {
data[i] = 0xa
i++
l = len(s)
for l >= 1<<7 {
data[i] = uint8(uint64(l)&0x7f | 0x80)
l >>= 7
i++
}
data[i] = uint8(l)
i++
i += copy(data[i:], s)
}
}
if len(m.Search) > 0 {
for _, s := range m.Search {
data[i] = 0x12
i++
l = len(s)
for l >= 1<<7 {
data[i] = uint8(uint64(l)&0x7f | 0x80)
l >>= 7
i++
}
data[i] = uint8(l)
i++
i += copy(data[i:], s)
}
}
if len(m.Options) > 0 {
for _, s := range m.Options {
data[i] = 0x1a
i++
l = len(s)
for l >= 1<<7 {
data[i] = uint8(uint64(l)&0x7f | 0x80)
l >>= 7
i++
}
data[i] = uint8(l)
i++
i += copy(data[i:], s)
}
}
return i, nil
}
func (m *EndpointSpec) Marshal() (data []byte, err error) {
size := m.Size()
data = make([]byte, size)
@ -1666,20 +1826,20 @@ func (m *NetworkSpec) MarshalTo(data []byte) (int, error) {
data[i] = 0xa
i++
i = encodeVarintSpecs(data, i, uint64(m.Annotations.Size()))
n18, err := m.Annotations.MarshalTo(data[i:])
n19, err := m.Annotations.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n18
i += n19
if m.DriverConfig != nil {
data[i] = 0x12
i++
i = encodeVarintSpecs(data, i, uint64(m.DriverConfig.Size()))
n19, err := m.DriverConfig.MarshalTo(data[i:])
n20, err := m.DriverConfig.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n19
i += n20
}
if m.Ipv6Enabled {
data[i] = 0x18
@ -1705,11 +1865,11 @@ func (m *NetworkSpec) MarshalTo(data []byte) (int, error) {
data[i] = 0x2a
i++
i = encodeVarintSpecs(data, i, uint64(m.IPAM.Size()))
n20, err := m.IPAM.MarshalTo(data[i:])
n21, err := m.IPAM.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n20
i += n21
}
if m.Attachable {
data[i] = 0x30
@ -1742,59 +1902,59 @@ func (m *ClusterSpec) MarshalTo(data []byte) (int, error) {
data[i] = 0xa
i++
i = encodeVarintSpecs(data, i, uint64(m.Annotations.Size()))
n21, err := m.Annotations.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n21
data[i] = 0x12
i++
i = encodeVarintSpecs(data, i, uint64(m.AcceptancePolicy.Size()))
n22, err := m.AcceptancePolicy.MarshalTo(data[i:])
n22, err := m.Annotations.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n22
data[i] = 0x1a
data[i] = 0x12
i++
i = encodeVarintSpecs(data, i, uint64(m.Orchestration.Size()))
n23, err := m.Orchestration.MarshalTo(data[i:])
i = encodeVarintSpecs(data, i, uint64(m.AcceptancePolicy.Size()))
n23, err := m.AcceptancePolicy.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n23
data[i] = 0x22
data[i] = 0x1a
i++
i = encodeVarintSpecs(data, i, uint64(m.Raft.Size()))
n24, err := m.Raft.MarshalTo(data[i:])
i = encodeVarintSpecs(data, i, uint64(m.Orchestration.Size()))
n24, err := m.Orchestration.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n24
data[i] = 0x2a
data[i] = 0x22
i++
i = encodeVarintSpecs(data, i, uint64(m.Dispatcher.Size()))
n25, err := m.Dispatcher.MarshalTo(data[i:])
i = encodeVarintSpecs(data, i, uint64(m.Raft.Size()))
n25, err := m.Raft.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n25
data[i] = 0x32
data[i] = 0x2a
i++
i = encodeVarintSpecs(data, i, uint64(m.CAConfig.Size()))
n26, err := m.CAConfig.MarshalTo(data[i:])
i = encodeVarintSpecs(data, i, uint64(m.Dispatcher.Size()))
n26, err := m.Dispatcher.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n26
data[i] = 0x3a
data[i] = 0x32
i++
i = encodeVarintSpecs(data, i, uint64(m.TaskDefaults.Size()))
n27, err := m.TaskDefaults.MarshalTo(data[i:])
i = encodeVarintSpecs(data, i, uint64(m.CAConfig.Size()))
n27, err := m.CAConfig.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n27
data[i] = 0x3a
i++
i = encodeVarintSpecs(data, i, uint64(m.TaskDefaults.Size()))
n28, err := m.TaskDefaults.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n28
return i, nil
}
@ -1816,11 +1976,11 @@ func (m *SecretSpec) MarshalTo(data []byte) (int, error) {
data[i] = 0xa
i++
i = encodeVarintSpecs(data, i, uint64(m.Annotations.Size()))
n28, err := m.Annotations.MarshalTo(data[i:])
n29, err := m.Annotations.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n28
i += n29
if len(m.Data) > 0 {
data[i] = 0x12
i++
@ -2064,6 +2224,17 @@ func (m *ContainerSpec) Size() (n int) {
n += 1 + l + sovSpecs(uint64(l))
}
}
if m.TTY {
n += 2
}
l = len(m.Hostname)
if l > 0 {
n += 1 + l + sovSpecs(uint64(l))
}
if m.DNSConfig != nil {
l = m.DNSConfig.Size()
n += 1 + l + sovSpecs(uint64(l))
}
return n
}
@ -2077,6 +2248,30 @@ func (m *ContainerSpec_PullOptions) Size() (n int) {
return n
}
func (m *ContainerSpec_DNSConfig) Size() (n int) {
var l int
_ = l
if len(m.Nameservers) > 0 {
for _, s := range m.Nameservers {
l = len(s)
n += 1 + l + sovSpecs(uint64(l))
}
}
if len(m.Search) > 0 {
for _, s := range m.Search {
l = len(s)
n += 1 + l + sovSpecs(uint64(l))
}
}
if len(m.Options) > 0 {
for _, s := range m.Options {
l = len(s)
n += 1 + l + sovSpecs(uint64(l))
}
}
return n
}
func (m *EndpointSpec) Size() (n int) {
var l int
_ = l
@ -2302,6 +2497,9 @@ func (this *ContainerSpec) String() string {
`PullOptions:` + strings.Replace(fmt.Sprintf("%v", this.PullOptions), "ContainerSpec_PullOptions", "ContainerSpec_PullOptions", 1) + `,`,
`Groups:` + fmt.Sprintf("%v", this.Groups) + `,`,
`Secrets:` + strings.Replace(fmt.Sprintf("%v", this.Secrets), "SecretReference", "SecretReference", 1) + `,`,
`TTY:` + fmt.Sprintf("%v", this.TTY) + `,`,
`Hostname:` + fmt.Sprintf("%v", this.Hostname) + `,`,
`DNSConfig:` + strings.Replace(fmt.Sprintf("%v", this.DNSConfig), "ContainerSpec_DNSConfig", "ContainerSpec_DNSConfig", 1) + `,`,
`}`,
}, "")
return s
@ -2316,6 +2514,18 @@ func (this *ContainerSpec_PullOptions) String() string {
}, "")
return s
}
func (this *ContainerSpec_DNSConfig) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&ContainerSpec_DNSConfig{`,
`Nameservers:` + fmt.Sprintf("%v", this.Nameservers) + `,`,
`Search:` + fmt.Sprintf("%v", this.Search) + `,`,
`Options:` + fmt.Sprintf("%v", this.Options) + `,`,
`}`,
}, "")
return s
}
func (this *EndpointSpec) String() string {
if this == nil {
return "nil"
@ -3755,6 +3965,88 @@ func (m *ContainerSpec) Unmarshal(data []byte) error {
return err
}
iNdEx = postIndex
case 13:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field TTY", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSpecs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
v |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.TTY = bool(v != 0)
case 14:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Hostname", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSpecs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthSpecs
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Hostname = string(data[iNdEx:postIndex])
iNdEx = postIndex
case 15:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field DNSConfig", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSpecs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthSpecs
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.DNSConfig == nil {
m.DNSConfig = &ContainerSpec_DNSConfig{}
}
if err := m.DNSConfig.Unmarshal(data[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipSpecs(data[iNdEx:])
@ -3855,6 +4147,143 @@ func (m *ContainerSpec_PullOptions) Unmarshal(data []byte) error {
}
return nil
}
func (m *ContainerSpec_DNSConfig) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSpecs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: DNSConfig: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: DNSConfig: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Nameservers", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSpecs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthSpecs
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Nameservers = append(m.Nameservers, string(data[iNdEx:postIndex]))
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Search", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSpecs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthSpecs
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Search = append(m.Search, string(data[iNdEx:postIndex]))
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSpecs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthSpecs
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Options = append(m.Options, string(data[iNdEx:postIndex]))
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipSpecs(data[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthSpecs
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *EndpointSpec) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
@ -4640,97 +5069,103 @@ var (
func init() { proto.RegisterFile("specs.proto", fileDescriptorSpecs) }
var fileDescriptorSpecs = []byte{
// 1457 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0x4d, 0x6f, 0x1b, 0xb9,
0x19, 0xd6, 0xd8, 0x63, 0x59, 0x7a, 0x47, 0x4e, 0x14, 0x22, 0x1f, 0x13, 0x25, 0x95, 0x15, 0x25,
0x4d, 0x9d, 0x16, 0xb5, 0x5b, 0xb5, 0x48, 0x93, 0xa6, 0x41, 0xab, 0xaf, 0x3a, 0xaa, 0x6b, 0x47,
0xa0, 0x93, 0x00, 0x3d, 0x09, 0xf4, 0x0c, 0x2d, 0x0f, 0x3c, 0x1a, 0x4e, 0x39, 0x1c, 0x05, 0xbe,
0xed, 0x31, 0xf0, 0x61, 0xff, 0x81, 0x4f, 0x0b, 0xec, 0x3f, 0xd8, 0xff, 0x90, 0xe3, 0x1e, 0xf7,
0x64, 0xac, 0x7d, 0x5f, 0x60, 0x81, 0xfd, 0x03, 0x0b, 0x72, 0x28, 0x69, 0xb4, 0x19, 0x27, 0x01,
0xd6, 0x37, 0xf2, 0xe5, 0xf3, 0xbc, 0xa4, 0xde, 0xf7, 0x99, 0x87, 0x14, 0x58, 0x51, 0x48, 0x9d,
0x68, 0x3d, 0xe4, 0x4c, 0x30, 0x84, 0x5c, 0xe6, 0x1c, 0x52, 0xbe, 0x1e, 0xbd, 0x25, 0x7c, 0x74,
0xe8, 0x89, 0xf5, 0xf1, 0x9f, 0x2b, 0x96, 0x38, 0x0a, 0xa9, 0x06, 0x54, 0xae, 0x0f, 0xd9, 0x90,
0xa9, 0xe1, 0x86, 0x1c, 0xe9, 0xe8, 0x2d, 0x37, 0xe6, 0x44, 0x78, 0x2c, 0xd8, 0x98, 0x0c, 0x92,
0x85, 0xfa, 0x97, 0x26, 0x14, 0x76, 0x98, 0x4b, 0x77, 0x43, 0xea, 0xa0, 0x4d, 0xb0, 0x48, 0x10,
0x30, 0xa1, 0x00, 0x91, 0x6d, 0xd4, 0x8c, 0x35, 0xab, 0xb1, 0xba, 0xfe, 0xe1, 0x96, 0xeb, 0xcd,
0x19, 0xac, 0x65, 0xbe, 0x3f, 0x5d, 0xcd, 0xe1, 0x34, 0x13, 0xfd, 0x09, 0x4c, 0xce, 0x7c, 0x6a,
0x2f, 0xd4, 0x8c, 0xb5, 0x2b, 0x8d, 0xbb, 0x59, 0x19, 0xe4, 0xa6, 0x98, 0xf9, 0x14, 0x2b, 0x24,
0xda, 0x04, 0x18, 0xd1, 0xd1, 0x1e, 0xe5, 0xd1, 0x81, 0x17, 0xda, 0x8b, 0x8a, 0xf7, 0xbb, 0x8b,
0x78, 0xf2, 0xb0, 0xeb, 0xdb, 0x53, 0x38, 0x4e, 0x51, 0xd1, 0x36, 0x94, 0xc8, 0x98, 0x78, 0x3e,
0xd9, 0xf3, 0x7c, 0x4f, 0x1c, 0xd9, 0xa6, 0x4a, 0xf5, 0xe8, 0xa3, 0xa9, 0x9a, 0x29, 0x02, 0x9e,
0xa3, 0xd7, 0x5d, 0x80, 0xd9, 0x46, 0xe8, 0x21, 0x2c, 0xf7, 0xbb, 0x3b, 0x9d, 0xde, 0xce, 0x66,
0x39, 0x57, 0xb9, 0x7d, 0x7c, 0x52, 0xbb, 0x21, 0x73, 0xcc, 0x00, 0x7d, 0x1a, 0xb8, 0x5e, 0x30,
0x44, 0x6b, 0x50, 0x68, 0xb6, 0xdb, 0xdd, 0xfe, 0xab, 0x6e, 0xa7, 0x6c, 0x54, 0x2a, 0xc7, 0x27,
0xb5, 0x9b, 0xf3, 0xc0, 0xa6, 0xe3, 0xd0, 0x50, 0x50, 0xb7, 0x62, 0xbe, 0xfb, 0xaa, 0x9a, 0xab,
0xbf, 0x33, 0xa0, 0x94, 0x3e, 0x04, 0x7a, 0x08, 0xf9, 0x66, 0xfb, 0x55, 0xef, 0x4d, 0xb7, 0x9c,
0x9b, 0xd1, 0xd3, 0x88, 0xa6, 0x23, 0xbc, 0x31, 0x45, 0x0f, 0x60, 0xa9, 0xdf, 0x7c, 0xbd, 0xdb,
0x2d, 0x1b, 0xb3, 0xe3, 0xa4, 0x61, 0x7d, 0x12, 0x47, 0x0a, 0xd5, 0xc1, 0xcd, 0xde, 0x4e, 0x79,
0x21, 0x1b, 0xd5, 0xe1, 0xc4, 0x0b, 0xf4, 0x51, 0xce, 0x16, 0xc1, 0xda, 0xa5, 0x7c, 0xec, 0x39,
0x97, 0xac, 0x89, 0xc7, 0x60, 0x0a, 0x12, 0x1d, 0x2a, 0x4d, 0x58, 0xd9, 0x9a, 0x78, 0x45, 0xa2,
0x43, 0xb9, 0xa9, 0xa6, 0x2b, 0xbc, 0x54, 0x06, 0xa7, 0xa1, 0xef, 0x39, 0x44, 0x50, 0x57, 0x29,
0xc3, 0x6a, 0xfc, 0x36, 0x8b, 0x8d, 0xa7, 0x28, 0x7d, 0xfe, 0x17, 0x39, 0x9c, 0xa2, 0xa2, 0x67,
0x90, 0x1f, 0xfa, 0x6c, 0x8f, 0xf8, 0x4a, 0x13, 0x56, 0xe3, 0x5e, 0x56, 0x92, 0x4d, 0x85, 0x98,
0x25, 0xd0, 0x14, 0xf4, 0x04, 0xf2, 0x71, 0xe8, 0x12, 0x41, 0xed, 0xbc, 0x22, 0xd7, 0xb2, 0xc8,
0xaf, 0x15, 0xa2, 0xcd, 0x82, 0x7d, 0x6f, 0x88, 0x35, 0x1e, 0x6d, 0x41, 0x21, 0xa0, 0xe2, 0x2d,
0xe3, 0x87, 0x91, 0xbd, 0x5c, 0x5b, 0x5c, 0xb3, 0x1a, 0x7f, 0xc8, 0x14, 0x63, 0x82, 0x69, 0x0a,
0x41, 0x9c, 0x83, 0x11, 0x0d, 0x44, 0x92, 0xa6, 0xb5, 0x60, 0x1b, 0x78, 0x9a, 0x00, 0xfd, 0x03,
0x0a, 0x34, 0x70, 0x43, 0xe6, 0x05, 0xc2, 0x2e, 0x5c, 0x7c, 0x90, 0xae, 0xc6, 0xc8, 0x62, 0xe2,
0x29, 0xa3, 0x95, 0x07, 0x73, 0xc4, 0x5c, 0x5a, 0xdf, 0x80, 0x6b, 0x1f, 0x14, 0x0b, 0x55, 0xa0,
0xa0, 0x8b, 0x95, 0x74, 0xd9, 0xc4, 0xd3, 0x79, 0xfd, 0x2a, 0xac, 0xcc, 0x15, 0x46, 0xd9, 0xc6,
0xa4, 0x5b, 0xa8, 0x09, 0x45, 0x87, 0x05, 0x82, 0x78, 0x01, 0xe5, 0x5a, 0x20, 0x99, 0xb5, 0x6d,
0x4f, 0x40, 0x92, 0xf5, 0x22, 0x87, 0x67, 0x2c, 0xf4, 0x6f, 0x28, 0x72, 0x1a, 0xb1, 0x98, 0x3b,
0x34, 0xd2, 0x0a, 0x59, 0xcb, 0xee, 0x71, 0x02, 0xc2, 0xf4, 0xff, 0xb1, 0xc7, 0xa9, 0xac, 0x53,
0x84, 0x67, 0x54, 0xf4, 0x0c, 0x96, 0x39, 0x8d, 0x04, 0xe1, 0xe2, 0x63, 0x4d, 0xc6, 0x09, 0xa4,
0xcf, 0x7c, 0xcf, 0x39, 0xc2, 0x13, 0x06, 0x7a, 0x06, 0xc5, 0xd0, 0x27, 0x8e, 0xca, 0x6a, 0x2f,
0x29, 0xfa, 0x6f, 0xb2, 0xe8, 0xfd, 0x09, 0x08, 0xcf, 0xf0, 0xe8, 0x29, 0x80, 0xcf, 0x86, 0x03,
0x97, 0x7b, 0x63, 0xca, 0xb5, 0x48, 0x2a, 0x59, 0xec, 0x8e, 0x42, 0xe0, 0xa2, 0xcf, 0x86, 0xc9,
0x10, 0x6d, 0xfe, 0x2a, 0x85, 0xa4, 0xd4, 0xb1, 0x05, 0x40, 0xa6, 0xab, 0x5a, 0x1f, 0x8f, 0x3e,
0x2b, 0x95, 0xee, 0x48, 0x8a, 0x8e, 0xee, 0x41, 0x69, 0x9f, 0x71, 0x87, 0x0e, 0xb4, 0xee, 0x8b,
0x4a, 0x13, 0x96, 0x8a, 0x25, 0x42, 0x6f, 0x15, 0x61, 0x99, 0xc7, 0x81, 0xf0, 0x46, 0xb4, 0xbe,
0x05, 0x37, 0x32, 0x93, 0xa2, 0x06, 0x94, 0xa6, 0x6d, 0x1e, 0x78, 0xae, 0xd2, 0x47, 0xb1, 0x75,
0xf5, 0xfc, 0x74, 0xd5, 0x9a, 0xea, 0xa1, 0xd7, 0xc1, 0xd6, 0x14, 0xd4, 0x73, 0xeb, 0x3f, 0x98,
0xb0, 0x32, 0x27, 0x16, 0x74, 0x1d, 0x96, 0xbc, 0x11, 0x19, 0xd2, 0x84, 0x8e, 0x93, 0x09, 0xea,
0x42, 0xde, 0x27, 0x7b, 0xd4, 0x97, 0x92, 0x91, 0x65, 0xfb, 0xe3, 0x27, 0x55, 0xb7, 0xfe, 0x5f,
0x85, 0xef, 0x06, 0x82, 0x1f, 0x61, 0x4d, 0x46, 0x36, 0x2c, 0x3b, 0x6c, 0x34, 0x22, 0x81, 0xb4,
0x97, 0xc5, 0xb5, 0x22, 0x9e, 0x4c, 0x11, 0x02, 0x93, 0xf0, 0x61, 0x64, 0x9b, 0x2a, 0xac, 0xc6,
0xa8, 0x0c, 0x8b, 0x34, 0x18, 0xdb, 0x4b, 0x2a, 0x24, 0x87, 0x32, 0xe2, 0x7a, 0x49, 0xcf, 0x8b,
0x58, 0x0e, 0x25, 0x2f, 0x8e, 0x28, 0xb7, 0x97, 0x55, 0x48, 0x8d, 0xd1, 0xdf, 0x20, 0x3f, 0x62,
0x71, 0x20, 0x22, 0xbb, 0xa0, 0x0e, 0x7b, 0x3b, 0xeb, 0xb0, 0xdb, 0x12, 0xa1, 0xed, 0x4f, 0xc3,
0xd1, 0x0b, 0xb8, 0x16, 0x09, 0x16, 0x0e, 0x86, 0x9c, 0x38, 0x74, 0x10, 0x52, 0xee, 0x31, 0x57,
0x75, 0xe3, 0x02, 0x17, 0xed, 0xe8, 0x1b, 0x1e, 0x5f, 0x95, 0xb4, 0x4d, 0xc9, 0xea, 0x2b, 0x12,
0xea, 0x43, 0x29, 0x8c, 0x7d, 0x7f, 0xc0, 0xc2, 0xc4, 0xcc, 0x41, 0x25, 0xf9, 0x8c, 0xaa, 0xf5,
0x63, 0xdf, 0x7f, 0x99, 0x90, 0xb0, 0x15, 0xce, 0x26, 0xe8, 0x26, 0xe4, 0x87, 0x9c, 0xc5, 0x61,
0x64, 0x5b, 0xaa, 0x1e, 0x7a, 0x86, 0x9e, 0xc3, 0x72, 0x44, 0x1d, 0x4e, 0x45, 0x64, 0x97, 0xd4,
0xaf, 0xbd, 0x9f, 0xb5, 0xc9, 0xae, 0x82, 0x60, 0xba, 0x4f, 0x39, 0x0d, 0x1c, 0x8a, 0x27, 0x9c,
0xca, 0x53, 0xb0, 0x52, 0x8d, 0x92, 0x05, 0x3e, 0xa4, 0x47, 0xba, 0xf7, 0x72, 0x28, 0xf5, 0x30,
0x26, 0x7e, 0x9c, 0xbc, 0x30, 0x8a, 0x38, 0x99, 0xfc, 0x7d, 0xe1, 0x89, 0x51, 0x69, 0x80, 0x95,
0x3a, 0x2d, 0xba, 0x0f, 0x2b, 0x9c, 0x0e, 0xbd, 0x48, 0xf0, 0xa3, 0x01, 0x89, 0xc5, 0x81, 0xfd,
0x2f, 0x45, 0x28, 0x4d, 0x82, 0xcd, 0x58, 0x1c, 0xd4, 0x7f, 0x32, 0xa0, 0x94, 0xb6, 0x4c, 0xd4,
0x4e, 0x8c, 0x52, 0xed, 0x78, 0xa5, 0xb1, 0xf1, 0x29, 0x8b, 0x55, 0xb6, 0xe4, 0xc7, 0x72, 0xc7,
0x6d, 0xf9, 0xac, 0x51, 0x64, 0xf4, 0x57, 0x58, 0x0a, 0x19, 0x17, 0x13, 0x71, 0x56, 0x33, 0xad,
0x84, 0xf1, 0xc9, 0x67, 0x9c, 0x80, 0xeb, 0x07, 0x70, 0x65, 0x3e, 0x1b, 0x7a, 0x00, 0x8b, 0x6f,
0x7a, 0xfd, 0x72, 0xae, 0x72, 0xe7, 0xf8, 0xa4, 0x76, 0x6b, 0x7e, 0xf1, 0x8d, 0xc7, 0x45, 0x4c,
0xfc, 0x5e, 0x1f, 0xfd, 0x1e, 0x96, 0x3a, 0x3b, 0xbb, 0x18, 0x97, 0x8d, 0xca, 0xea, 0xf1, 0x49,
0xed, 0xce, 0x3c, 0x4e, 0x2e, 0xb1, 0x38, 0x70, 0x31, 0xdb, 0x9b, 0xde, 0xf4, 0xdf, 0x2c, 0x80,
0xa5, 0xbf, 0xd9, 0xcb, 0xbd, 0xe9, 0xff, 0x09, 0x2b, 0x89, 0x0d, 0x0e, 0x1c, 0xf5, 0xd3, 0xb4,
0xa1, 0x7f, 0xcc, 0x0d, 0x4b, 0x09, 0x21, 0x29, 0x85, 0xb4, 0x1e, 0x2f, 0x1c, 0x3f, 0x1e, 0xd0,
0x80, 0xec, 0xf9, 0xfa, 0xd2, 0x2f, 0x60, 0x4b, 0xc6, 0xba, 0x49, 0x48, 0xde, 0x56, 0x5e, 0x20,
0x28, 0x0f, 0xf4, 0x75, 0x5e, 0xc0, 0xd3, 0x39, 0x7a, 0x0e, 0xa6, 0x17, 0x92, 0x91, 0xb6, 0xf0,
0xcc, 0x5f, 0xd0, 0xeb, 0x37, 0xb7, 0xb5, 0x44, 0x5a, 0x85, 0xf3, 0xd3, 0x55, 0x53, 0x06, 0xb0,
0xa2, 0xa1, 0xea, 0xc4, 0x45, 0xe5, 0x4e, 0xea, 0xab, 0x2e, 0xe0, 0x54, 0xa4, 0xfe, 0xb5, 0x09,
0x56, 0xdb, 0x8f, 0x23, 0xa1, 0xbd, 0xe9, 0xd2, 0xea, 0xf6, 0x3f, 0xb8, 0x46, 0xd4, 0xbb, 0x90,
0x04, 0xf2, 0x43, 0x57, 0xb7, 0x93, 0xae, 0xdd, 0x83, 0xcc, 0x74, 0x53, 0x70, 0x72, 0x93, 0xb5,
0xf2, 0x32, 0xa7, 0x6d, 0xe0, 0x32, 0xf9, 0xc5, 0x0a, 0xda, 0x85, 0x15, 0xc6, 0x9d, 0x03, 0x1a,
0x89, 0xc4, 0x1b, 0xf4, 0x3b, 0x2a, 0xf3, 0x85, 0xfd, 0x32, 0x0d, 0xd4, 0xaf, 0x90, 0xe4, 0xb4,
0xf3, 0x39, 0xd0, 0x13, 0x30, 0x39, 0xd9, 0x9f, 0xdc, 0xb4, 0x99, 0xfa, 0xc6, 0x64, 0x5f, 0xcc,
0xa5, 0x50, 0x0c, 0xf4, 0x1f, 0x00, 0xd7, 0x8b, 0x42, 0x22, 0x9c, 0x03, 0xca, 0x75, 0x9f, 0x32,
0x7f, 0x62, 0x67, 0x8a, 0x9a, 0xcb, 0x92, 0x62, 0xa3, 0x2d, 0x28, 0x3a, 0x64, 0xa2, 0xb4, 0xfc,
0xc5, 0xb6, 0xd8, 0x6e, 0xea, 0x14, 0x65, 0x99, 0xe2, 0xfc, 0x74, 0xb5, 0x30, 0x89, 0xe0, 0x82,
0x43, 0xb4, 0xf2, 0xb6, 0x60, 0x45, 0x3e, 0x3a, 0x07, 0x2e, 0xdd, 0x27, 0xb1, 0x2f, 0x22, 0xe5,
0xe0, 0x17, 0x3c, 0xb2, 0xe4, 0xfb, 0xa7, 0xa3, 0x71, 0xfa, 0x5c, 0x25, 0x91, 0x8a, 0xd5, 0x3d,
0x80, 0xc4, 0xe1, 0x2e, 0x57, 0x26, 0x08, 0x4c, 0x97, 0x08, 0xa2, 0x94, 0x51, 0xc2, 0x6a, 0xdc,
0xba, 0xfb, 0xfe, 0xac, 0x9a, 0xfb, 0xee, 0xac, 0x9a, 0xfb, 0xf1, 0xac, 0x6a, 0x7c, 0x71, 0x5e,
0x35, 0xde, 0x9f, 0x57, 0x8d, 0x6f, 0xcf, 0xab, 0xc6, 0xf7, 0xe7, 0x55, 0x63, 0x2f, 0xaf, 0xfe,
0xeb, 0xfd, 0xe5, 0xe7, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb6, 0x26, 0x4a, 0x64, 0x4a, 0x0e, 0x00,
0x00,
// 1563 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0xcd, 0x6e, 0x23, 0xc7,
0x11, 0xe6, 0x88, 0x14, 0x7f, 0x6a, 0xc8, 0x5d, 0x6e, 0xc3, 0x3f, 0xb3, 0xb4, 0x43, 0x72, 0xe9,
0x8d, 0x23, 0xc7, 0x88, 0x36, 0x61, 0x02, 0x67, 0x9d, 0x8d, 0x91, 0xf0, 0x2f, 0x5a, 0x46, 0x91,
0x4c, 0xb4, 0xe4, 0x05, 0xf6, 0x44, 0xb4, 0x66, 0x5a, 0xe4, 0x40, 0xc3, 0xe9, 0x49, 0x4f, 0x0f,
0x0d, 0xdd, 0x72, 0x34, 0xf6, 0x90, 0x37, 0xd0, 0x29, 0x40, 0xde, 0x20, 0xef, 0xb0, 0xc7, 0x1c,
0x73, 0x12, 0x2c, 0x3e, 0x41, 0x80, 0xbc, 0x40, 0xd0, 0x3d, 0x3d, 0xe4, 0x30, 0x1e, 0x59, 0x06,
0xa2, 0x5b, 0x77, 0xcd, 0xf7, 0x55, 0x77, 0x57, 0x7d, 0xac, 0x2a, 0x82, 0x19, 0x06, 0xd4, 0x0e,
0xf7, 0x03, 0xce, 0x04, 0x43, 0xc8, 0x61, 0xf6, 0x05, 0xe5, 0xfb, 0xe1, 0xd7, 0x84, 0x2f, 0x2e,
0x5c, 0xb1, 0xbf, 0xfc, 0x45, 0xc3, 0x14, 0x97, 0x01, 0xd5, 0x80, 0xc6, 0x3b, 0x33, 0x36, 0x63,
0x6a, 0xf9, 0x4c, 0xae, 0xb4, 0xf5, 0x7d, 0x27, 0xe2, 0x44, 0xb8, 0xcc, 0x7f, 0x96, 0x2c, 0xe2,
0x0f, 0x9d, 0xbf, 0x16, 0xa0, 0x7c, 0xcc, 0x1c, 0x7a, 0x12, 0x50, 0x1b, 0x1d, 0x80, 0x49, 0x7c,
0x9f, 0x09, 0x05, 0x08, 0x2d, 0xa3, 0x6d, 0xec, 0x99, 0xdd, 0xd6, 0xfe, 0x77, 0x8f, 0xdc, 0xef,
0x6d, 0x60, 0xfd, 0xc2, 0xdb, 0xeb, 0x56, 0x0e, 0xa7, 0x99, 0xe8, 0xe7, 0x50, 0xe0, 0xcc, 0xa3,
0xd6, 0x4e, 0xdb, 0xd8, 0x7b, 0xd0, 0xfd, 0x30, 0xcb, 0x83, 0x3c, 0x14, 0x33, 0x8f, 0x62, 0x85,
0x44, 0x07, 0x00, 0x0b, 0xba, 0x38, 0xa3, 0x3c, 0x9c, 0xbb, 0x81, 0x95, 0x57, 0xbc, 0x9f, 0xdc,
0xc6, 0x93, 0x97, 0xdd, 0x3f, 0x5a, 0xc3, 0x71, 0x8a, 0x8a, 0x8e, 0xa0, 0x4a, 0x96, 0xc4, 0xf5,
0xc8, 0x99, 0xeb, 0xb9, 0xe2, 0xd2, 0x2a, 0x28, 0x57, 0x9f, 0x7c, 0xaf, 0xab, 0x5e, 0x8a, 0x80,
0xb7, 0xe8, 0x1d, 0x07, 0x60, 0x73, 0x10, 0xfa, 0x18, 0x4a, 0x93, 0xd1, 0xf1, 0x70, 0x7c, 0x7c,
0x50, 0xcf, 0x35, 0x1e, 0xbf, 0xb9, 0x6a, 0xbf, 0x2b, 0x7d, 0x6c, 0x00, 0x13, 0xea, 0x3b, 0xae,
0x3f, 0x43, 0x7b, 0x50, 0xee, 0x0d, 0x06, 0xa3, 0xc9, 0xe9, 0x68, 0x58, 0x37, 0x1a, 0x8d, 0x37,
0x57, 0xed, 0xf7, 0xb6, 0x81, 0x3d, 0xdb, 0xa6, 0x81, 0xa0, 0x4e, 0xa3, 0xf0, 0xcd, 0xdf, 0x9a,
0xb9, 0xce, 0x37, 0x06, 0x54, 0xd3, 0x97, 0x40, 0x1f, 0x43, 0xb1, 0x37, 0x38, 0x1d, 0xbf, 0x1a,
0xd5, 0x73, 0x1b, 0x7a, 0x1a, 0xd1, 0xb3, 0x85, 0xbb, 0xa4, 0xe8, 0x29, 0xec, 0x4e, 0x7a, 0x5f,
0x9d, 0x8c, 0xea, 0xc6, 0xe6, 0x3a, 0x69, 0xd8, 0x84, 0x44, 0xa1, 0x42, 0x0d, 0x71, 0x6f, 0x7c,
0x5c, 0xdf, 0xc9, 0x46, 0x0d, 0x39, 0x71, 0x7d, 0x7d, 0x95, 0x9b, 0x3c, 0x98, 0x27, 0x94, 0x2f,
0x5d, 0xfb, 0x9e, 0x35, 0xf1, 0x19, 0x14, 0x04, 0x09, 0x2f, 0x94, 0x26, 0xcc, 0x6c, 0x4d, 0x9c,
0x92, 0xf0, 0x42, 0x1e, 0xaa, 0xe9, 0x0a, 0x2f, 0x95, 0xc1, 0x69, 0xe0, 0xb9, 0x36, 0x11, 0xd4,
0x51, 0xca, 0x30, 0xbb, 0x3f, 0xce, 0x62, 0xe3, 0x35, 0x4a, 0xdf, 0xff, 0x65, 0x0e, 0xa7, 0xa8,
0xe8, 0x05, 0x14, 0x67, 0x1e, 0x3b, 0x23, 0x9e, 0xd2, 0x84, 0xd9, 0x7d, 0x92, 0xe5, 0xe4, 0x40,
0x21, 0x36, 0x0e, 0x34, 0x05, 0x3d, 0x87, 0x62, 0x14, 0x38, 0x44, 0x50, 0xab, 0xa8, 0xc8, 0xed,
0x2c, 0xf2, 0x57, 0x0a, 0x31, 0x60, 0xfe, 0xb9, 0x3b, 0xc3, 0x1a, 0x8f, 0x0e, 0xa1, 0xec, 0x53,
0xf1, 0x35, 0xe3, 0x17, 0xa1, 0x55, 0x6a, 0xe7, 0xf7, 0xcc, 0xee, 0xa7, 0x99, 0x62, 0x8c, 0x31,
0x3d, 0x21, 0x88, 0x3d, 0x5f, 0x50, 0x5f, 0xc4, 0x6e, 0xfa, 0x3b, 0x96, 0x81, 0xd7, 0x0e, 0xd0,
0x6f, 0xa1, 0x4c, 0x7d, 0x27, 0x60, 0xae, 0x2f, 0xac, 0xf2, 0xed, 0x17, 0x19, 0x69, 0x8c, 0x0c,
0x26, 0x5e, 0x33, 0xfa, 0x45, 0x28, 0x2c, 0x98, 0x43, 0x3b, 0xcf, 0xe0, 0xd1, 0x77, 0x82, 0x85,
0x1a, 0x50, 0xd6, 0xc1, 0x8a, 0xb3, 0x5c, 0xc0, 0xeb, 0x7d, 0xe7, 0x21, 0xd4, 0xb6, 0x02, 0xa3,
0xca, 0x46, 0x92, 0x2d, 0xd4, 0x83, 0x8a, 0xcd, 0x7c, 0x41, 0x5c, 0x9f, 0x72, 0x2d, 0x90, 0xcc,
0xd8, 0x0e, 0x12, 0x90, 0x64, 0xbd, 0xcc, 0xe1, 0x0d, 0x0b, 0xfd, 0x01, 0x2a, 0x9c, 0x86, 0x2c,
0xe2, 0x36, 0x0d, 0xb5, 0x42, 0xf6, 0xb2, 0x73, 0x1c, 0x83, 0x30, 0xfd, 0x73, 0xe4, 0x72, 0x2a,
0xe3, 0x14, 0xe2, 0x0d, 0x15, 0xbd, 0x80, 0x12, 0xa7, 0xa1, 0x20, 0x5c, 0x7c, 0x5f, 0x92, 0x71,
0x0c, 0x99, 0x30, 0xcf, 0xb5, 0x2f, 0x71, 0xc2, 0x40, 0x2f, 0xa0, 0x12, 0x78, 0xc4, 0x56, 0x5e,
0xad, 0x5d, 0x45, 0xff, 0x51, 0x16, 0x7d, 0x92, 0x80, 0xf0, 0x06, 0x8f, 0x3e, 0x07, 0xf0, 0xd8,
0x6c, 0xea, 0x70, 0x77, 0x49, 0xb9, 0x16, 0x49, 0x23, 0x8b, 0x3d, 0x54, 0x08, 0x5c, 0xf1, 0xd8,
0x2c, 0x5e, 0xa2, 0x83, 0xff, 0x4b, 0x21, 0x29, 0x75, 0x1c, 0x02, 0x90, 0xf5, 0x57, 0xad, 0x8f,
0x4f, 0x7e, 0x90, 0x2b, 0x9d, 0x91, 0x14, 0x1d, 0x3d, 0x81, 0xea, 0x39, 0xe3, 0x36, 0x9d, 0x6a,
0xdd, 0x57, 0x94, 0x26, 0x4c, 0x65, 0x8b, 0x85, 0xde, 0xaf, 0x40, 0x89, 0x47, 0xbe, 0x70, 0x17,
0xb4, 0x73, 0x08, 0xef, 0x66, 0x3a, 0x45, 0x5d, 0xa8, 0xae, 0xd3, 0x3c, 0x75, 0x1d, 0xa5, 0x8f,
0x4a, 0xff, 0xe1, 0xea, 0xba, 0x65, 0xae, 0xf5, 0x30, 0x1e, 0x62, 0x73, 0x0d, 0x1a, 0x3b, 0x9d,
0x6f, 0x8b, 0x50, 0xdb, 0x12, 0x0b, 0x7a, 0x07, 0x76, 0xdd, 0x05, 0x99, 0xd1, 0x98, 0x8e, 0xe3,
0x0d, 0x1a, 0x41, 0xd1, 0x23, 0x67, 0xd4, 0x93, 0x92, 0x91, 0x61, 0xfb, 0xd9, 0x9d, 0xaa, 0xdb,
0xff, 0x93, 0xc2, 0x8f, 0x7c, 0xc1, 0x2f, 0xb1, 0x26, 0x23, 0x0b, 0x4a, 0x36, 0x5b, 0x2c, 0x88,
0x2f, 0xcb, 0x4b, 0x7e, 0xaf, 0x82, 0x93, 0x2d, 0x42, 0x50, 0x20, 0x7c, 0x16, 0x5a, 0x05, 0x65,
0x56, 0x6b, 0x54, 0x87, 0x3c, 0xf5, 0x97, 0xd6, 0xae, 0x32, 0xc9, 0xa5, 0xb4, 0x38, 0x6e, 0x9c,
0xf3, 0x0a, 0x96, 0x4b, 0xc9, 0x8b, 0x42, 0xca, 0xad, 0x92, 0x32, 0xa9, 0x35, 0xfa, 0x35, 0x14,
0x17, 0x2c, 0xf2, 0x45, 0x68, 0x95, 0xd5, 0x65, 0x1f, 0x67, 0x5d, 0xf6, 0x48, 0x22, 0x74, 0xf9,
0xd3, 0x70, 0xf4, 0x12, 0x1e, 0x85, 0x82, 0x05, 0xd3, 0x19, 0x27, 0x36, 0x9d, 0x06, 0x94, 0xbb,
0xcc, 0x51, 0xd9, 0xb8, 0xa5, 0x8a, 0x0e, 0x75, 0x87, 0xc7, 0x0f, 0x25, 0xed, 0x40, 0xb2, 0x26,
0x8a, 0x84, 0x26, 0x50, 0x0d, 0x22, 0xcf, 0x9b, 0xb2, 0x20, 0x2e, 0xe6, 0xa0, 0x9c, 0xfc, 0x80,
0xa8, 0x4d, 0x22, 0xcf, 0xfb, 0x32, 0x26, 0x61, 0x33, 0xd8, 0x6c, 0xd0, 0x7b, 0x50, 0x9c, 0x71,
0x16, 0x05, 0xa1, 0x65, 0xaa, 0x78, 0xe8, 0x1d, 0xfa, 0x02, 0x4a, 0x21, 0xb5, 0x39, 0x15, 0xa1,
0x55, 0x55, 0xaf, 0xfd, 0x28, 0xeb, 0x90, 0x13, 0x05, 0xc1, 0xf4, 0x9c, 0x72, 0xea, 0xdb, 0x14,
0x27, 0x1c, 0xf4, 0x18, 0xf2, 0x42, 0x5c, 0x5a, 0xb5, 0xb6, 0xb1, 0x57, 0xee, 0x97, 0x56, 0xd7,
0xad, 0xfc, 0xe9, 0xe9, 0x6b, 0x2c, 0x6d, 0xb2, 0x4c, 0xcd, 0x59, 0x28, 0x7c, 0xb2, 0xa0, 0xd6,
0x03, 0x15, 0xde, 0xf5, 0x1e, 0xbd, 0x06, 0x70, 0xfc, 0x70, 0x6a, 0xab, 0xdf, 0x85, 0xf5, 0x50,
0xbd, 0xee, 0xd3, 0xbb, 0x5f, 0x37, 0x3c, 0x3e, 0xd1, 0xc5, 0xb6, 0xb6, 0xba, 0x6e, 0x55, 0xd6,
0x5b, 0x5c, 0x71, 0xfc, 0x30, 0x5e, 0x36, 0x3e, 0x07, 0x33, 0x25, 0x1d, 0x99, 0xf2, 0x0b, 0x7a,
0xa9, 0xd5, 0x28, 0x97, 0x52, 0xa1, 0x4b, 0xe2, 0x45, 0xf1, 0xcc, 0x53, 0xc1, 0xf1, 0xe6, 0x37,
0x3b, 0xcf, 0x8d, 0x46, 0x17, 0xcc, 0x54, 0xfc, 0xd0, 0x47, 0x50, 0xe3, 0x74, 0xe6, 0x86, 0x82,
0x5f, 0x4e, 0x49, 0x24, 0xe6, 0xd6, 0xef, 0x15, 0xa1, 0x9a, 0x18, 0x7b, 0x91, 0x98, 0x37, 0xa6,
0xb0, 0xb9, 0x06, 0x6a, 0x83, 0x29, 0x9f, 0x17, 0x52, 0xbe, 0xa4, 0x5c, 0x16, 0x67, 0x19, 0xe9,
0xb4, 0x49, 0xa6, 0x21, 0xa4, 0x84, 0xdb, 0x73, 0xf5, 0x43, 0xa8, 0x60, 0xbd, 0x93, 0xca, 0x4e,
0x72, 0xad, 0x95, 0xad, 0xb7, 0x9d, 0xff, 0x18, 0x50, 0x4d, 0x77, 0x09, 0x34, 0x88, 0x7b, 0x83,
0x7a, 0xd2, 0x83, 0xee, 0xb3, 0xbb, 0xba, 0x8a, 0xaa, 0xc4, 0x5e, 0x24, 0x9d, 0x1d, 0xc9, 0x49,
0x4e, 0x91, 0xd1, 0xaf, 0x60, 0x37, 0x60, 0x5c, 0x24, 0xbf, 0xc7, 0x66, 0x66, 0xf5, 0x64, 0x3c,
0xa9, 0x5c, 0x31, 0xb8, 0x33, 0x87, 0x07, 0xdb, 0xde, 0xd0, 0x53, 0xc8, 0xbf, 0x1a, 0x4f, 0xea,
0xb9, 0xc6, 0x07, 0x6f, 0xae, 0xda, 0xef, 0x6f, 0x7f, 0x7c, 0xe5, 0x72, 0x11, 0x11, 0x6f, 0x3c,
0x41, 0x3f, 0x85, 0xdd, 0xe1, 0xf1, 0x09, 0xc6, 0x75, 0xa3, 0xd1, 0x7a, 0x73, 0xd5, 0xfe, 0x60,
0x1b, 0x27, 0x3f, 0xb1, 0xc8, 0x77, 0x30, 0x3b, 0x5b, 0x0f, 0x37, 0xff, 0xd8, 0x01, 0x53, 0x97,
0xa9, 0xfb, 0x1d, 0x6e, 0x7e, 0x07, 0xb5, 0xb8, 0xf2, 0x27, 0xe2, 0xdb, 0xb9, 0xb3, 0x01, 0x54,
0x63, 0x82, 0xce, 0xf1, 0x13, 0xa8, 0xba, 0xc1, 0xf2, 0xb3, 0x29, 0xf5, 0xc9, 0x99, 0xa7, 0xe7,
0x9c, 0x32, 0x36, 0xa5, 0x6d, 0x14, 0x9b, 0xa4, 0xf2, 0x5d, 0x5f, 0x50, 0xee, 0xeb, 0x09, 0xa6,
0x8c, 0xd7, 0x7b, 0xf4, 0x05, 0x14, 0xdc, 0x80, 0x2c, 0x74, 0xd7, 0xca, 0x7c, 0xc1, 0x78, 0xd2,
0x3b, 0xd2, 0x1a, 0xec, 0x97, 0x57, 0xd7, 0xad, 0x82, 0x34, 0x60, 0x45, 0x43, 0xcd, 0xa4, 0x71,
0xc8, 0x93, 0x54, 0x21, 0x2b, 0xe3, 0x94, 0xa5, 0xf3, 0xf7, 0x02, 0x98, 0x03, 0x2f, 0x0a, 0x85,
0x2e, 0xc7, 0xf7, 0x16, 0xb7, 0xd7, 0xf0, 0x88, 0xa8, 0x51, 0x98, 0xf8, 0xb2, 0xb6, 0xa9, 0x86,
0xac, 0x63, 0xf7, 0x34, 0xd3, 0xdd, 0x1a, 0x1c, 0x37, 0xef, 0x7e, 0x51, 0xfa, 0xb4, 0x0c, 0x5c,
0x27, 0xff, 0xf3, 0x05, 0x9d, 0x40, 0x8d, 0x71, 0x7b, 0x4e, 0x43, 0x11, 0x97, 0x43, 0x3d, 0x3a,
0x66, 0xfe, 0xa9, 0xf8, 0x32, 0x0d, 0xd4, 0xb5, 0x20, 0xbe, 0xed, 0xb6, 0x0f, 0xf4, 0x1c, 0x0a,
0x9c, 0x9c, 0x27, 0xc3, 0x45, 0xa6, 0xbe, 0x31, 0x39, 0x17, 0x5b, 0x2e, 0x14, 0x03, 0xfd, 0x11,
0xc0, 0x71, 0xc3, 0x80, 0x08, 0x7b, 0x4e, 0xb9, 0xce, 0x53, 0xe6, 0x13, 0x87, 0x6b, 0xd4, 0x96,
0x97, 0x14, 0x1b, 0x1d, 0x42, 0xc5, 0x26, 0x89, 0xd2, 0x8a, 0xb7, 0x77, 0x82, 0x41, 0x4f, 0xbb,
0xa8, 0x4b, 0x17, 0xab, 0xeb, 0x56, 0x39, 0xb1, 0xe0, 0xb2, 0x4d, 0xb4, 0xf2, 0x0e, 0xa1, 0x26,
0xe7, 0xec, 0xa9, 0x43, 0xcf, 0x49, 0xe4, 0x89, 0x50, 0x35, 0xad, 0x5b, 0xe6, 0x4a, 0x39, 0xf2,
0x0d, 0x35, 0x4e, 0xdf, 0xab, 0x2a, 0x52, 0xb6, 0x8e, 0x0b, 0x10, 0x17, 0xf5, 0xfb, 0x95, 0x09,
0x82, 0x82, 0x43, 0x04, 0x51, 0xca, 0xa8, 0x62, 0xb5, 0xee, 0x7f, 0xf8, 0xf6, 0xa6, 0x99, 0xfb,
0xd7, 0x4d, 0x33, 0xf7, 0xef, 0x9b, 0xa6, 0xf1, 0x97, 0x55, 0xd3, 0x78, 0xbb, 0x6a, 0x1a, 0xff,
0x5c, 0x35, 0x8d, 0x6f, 0x57, 0x4d, 0xe3, 0xac, 0xa8, 0xfe, 0xde, 0xfe, 0xf2, 0xbf, 0x01, 0x00,
0x00, 0xff, 0xff, 0x2a, 0x90, 0x7c, 0x40, 0x3d, 0x0f, 0x00, 0x00,
}

View file

@ -128,6 +128,7 @@ message NetworkAttachmentSpec {
string container_id = 1 [(gogoproto.customname) = "ContainerID"];
}
// Container specifies runtime parameters for a container.
message ContainerSpec {
// image defines the image reference, as specified in the
@ -159,6 +160,10 @@ message ContainerSpec {
// If Command and Args are provided, Args will be appended to Command.
repeated string args = 4;
// Hostname specifies the hostname that will be set on containers created by docker swarm.
// All containers for a given service will have the same hostname
string hostname = 14;
// Env specifies the environment variables for the container in NAME=VALUE
// format. These must be compliant with [IEEE Std
// 1003.1-2001](http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html).
@ -177,6 +182,10 @@ message ContainerSpec {
// Groups specifies supplementary groups available to the user.
repeated string groups = 11;
// TTY declares that a TTY should be attached to the standard streams,
// including stdin if it is still open.
bool tty = 13 [(gogoproto.customname) = "TTY"];
repeated Mount mounts = 8 [(gogoproto.nullable) = false];
// StopGracePeriod the grace period for stopping the container before
@ -198,6 +207,24 @@ message ContainerSpec {
// SecretReference contains references to zero or more secrets that
// will be exposed to the container.
repeated SecretReference secrets = 12;
// DNSConfig specifies DNS related configurations in resolver configuration file (resolv.conf)
// Detailed documentation is available in:
// http://man7.org/linux/man-pages/man5/resolv.conf.5.html
// TODO: domain is not supported yet
message DNSConfig {
// Nameservers specifies the IP addresses of the name servers
repeated string nameservers = 1;
// Search specifies the search list for host-name lookup
repeated string search = 2;
// Options allows certain internal resolver variables to be modified
repeated string options = 3;
}
// DNSConfig allows one to specify DNS related configuration in resolv.conf
DNSConfig dns_config = 15 [(gogoproto.customname) = "DNSConfig"];
}
// EndpointSpec defines the properties that can be configured to

View file

@ -57,7 +57,7 @@
EncryptionKey
ManagerStatus
SecretReference
RemovedNode
BlacklistedCertificate
NodeSpec
ServiceSpec
ReplicatedService
@ -119,6 +119,8 @@
UpdateClusterResponse
GetSecretRequest
GetSecretResponse
UpdateSecretRequest
UpdateSecretResponse
ListSecretsRequest
ListSecretsResponse
CreateSecretRequest
@ -202,8 +204,7 @@ type TaskState int32
const (
TaskStateNew TaskState = 0
TaskStateAllocated TaskState = 64
TaskStatePending TaskState = 128
TaskStatePending TaskState = 64
TaskStateAssigned TaskState = 192
TaskStateAccepted TaskState = 256
TaskStatePreparing TaskState = 320
@ -218,8 +219,7 @@ const (
var TaskState_name = map[int32]string{
0: "NEW",
64: "ALLOCATED",
128: "PENDING",
64: "PENDING",
192: "ASSIGNED",
256: "ACCEPTED",
320: "PREPARING",
@ -233,8 +233,7 @@ var TaskState_name = map[int32]string{
}
var TaskState_value = map[string]int32{
"NEW": 0,
"ALLOCATED": 64,
"PENDING": 128,
"PENDING": 64,
"ASSIGNED": 192,
"ACCEPTED": 256,
"PREPARING": 320,
@ -540,14 +539,50 @@ func (x PortConfig_Protocol) String() string {
}
func (PortConfig_Protocol) EnumDescriptor() ([]byte, []int) { return fileDescriptorTypes, []int{19, 0} }
// PublishMode controls how ports are published on the swarm.
type PortConfig_PublishMode int32
const (
// PublishModeIngress exposes the port across the cluster on all nodes.
PublishModeIngress PortConfig_PublishMode = 0
// PublishModeHost exposes the port on just the target host. If the
// published port is undefined, an ephemeral port will be allocated. If
// the published port is defined, the node will attempt to allocate it,
// erroring the task if it fails.
PublishModeHost PortConfig_PublishMode = 1
)
var PortConfig_PublishMode_name = map[int32]string{
0: "INGRESS",
1: "HOST",
}
var PortConfig_PublishMode_value = map[string]int32{
"INGRESS": 0,
"HOST": 1,
}
func (x PortConfig_PublishMode) String() string {
return proto.EnumName(PortConfig_PublishMode_name, int32(x))
}
func (PortConfig_PublishMode) EnumDescriptor() ([]byte, []int) {
return fileDescriptorTypes, []int{19, 1}
}
type IssuanceStatus_State int32
const (
IssuanceStateUnknown IssuanceStatus_State = 0
IssuanceStateRenew IssuanceStatus_State = 1
// A new certificate should be issued
IssuanceStateRenew IssuanceStatus_State = 1
// Certificate is pending acceptance
IssuanceStatePending IssuanceStatus_State = 2
IssuanceStateIssued IssuanceStatus_State = 3
IssuanceStateFailed IssuanceStatus_State = 4
// successful completion certificate issuance
IssuanceStateIssued IssuanceStatus_State = 3
// Certificate issuance failed
IssuanceStateFailed IssuanceStatus_State = 4
// Signals workers to renew their certificate. From the CA's perspective
// this is equivalent to IssuanceStateIssued: a noop.
IssuanceStateRotate IssuanceStatus_State = 5
)
var IssuanceStatus_State_name = map[int32]string{
@ -556,6 +591,7 @@ var IssuanceStatus_State_name = map[int32]string{
2: "PENDING",
3: "ISSUED",
4: "FAILED",
5: "ROTATE",
}
var IssuanceStatus_State_value = map[string]int32{
"UNKNOWN": 0,
@ -563,6 +599,7 @@ var IssuanceStatus_State_value = map[string]int32{
"PENDING": 2,
"ISSUED": 3,
"FAILED": 4,
"ROTATE": 5,
}
func (x IssuanceStatus_State) String() string {
@ -1106,11 +1143,12 @@ type PortConfig struct {
Protocol PortConfig_Protocol `protobuf:"varint,2,opt,name=protocol,proto3,enum=docker.swarmkit.v1.PortConfig_Protocol" json:"protocol,omitempty"`
// The port which the application is exposing and is bound to.
TargetPort uint32 `protobuf:"varint,3,opt,name=target_port,json=targetPort,proto3" json:"target_port,omitempty"`
// PublishedPort specifies the port on which the service is
// exposed. If specified, the port must be
// within the available range. If not specified, an available
// port is automatically assigned.
// PublishedPort specifies the port on which the service is exposed. If
// specified, the port must be within the available range. If not specified
// (value is zero), an available port is automatically assigned.
PublishedPort uint32 `protobuf:"varint,4,opt,name=published_port,json=publishedPort,proto3" json:"published_port,omitempty"`
// PublishMode controls how the port is published.
PublishMode PortConfig_PublishMode `protobuf:"varint,5,opt,name=publish_mode,json=publishMode,proto3,enum=docker.swarmkit.v1.PortConfig_PublishMode" json:"publish_mode,omitempty"`
}
func (m *PortConfig) Reset() { *m = PortConfig{} }
@ -1397,18 +1435,17 @@ func (m *SecretReference) Reset() { *m = SecretReference{} }
func (*SecretReference) ProtoMessage() {}
func (*SecretReference) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{38} }
// RemovedNode is a record for a node that has been removed from the swarm.
type RemovedNode struct {
// ID is the ID of the removed node.
ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
// BlacklistedCertificate is a record for a blacklisted certificate. It does not
// contain the certificate's CN, because these records are indexed by CN.
type BlacklistedCertificate struct {
// Expiry is the latest known expiration time of a certificate that
// was issued to this node.
Expiry *docker_swarmkit_v1.Timestamp `protobuf:"bytes,2,opt,name=expiry" json:"expiry,omitempty"`
// was issued for the given CN.
Expiry *docker_swarmkit_v1.Timestamp `protobuf:"bytes,1,opt,name=expiry" json:"expiry,omitempty"`
}
func (m *RemovedNode) Reset() { *m = RemovedNode{} }
func (*RemovedNode) ProtoMessage() {}
func (*RemovedNode) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{39} }
func (m *BlacklistedCertificate) Reset() { *m = BlacklistedCertificate{} }
func (*BlacklistedCertificate) ProtoMessage() {}
func (*BlacklistedCertificate) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{39} }
func init() {
proto.RegisterType((*Version)(nil), "docker.swarmkit.v1.Version")
@ -1455,7 +1492,7 @@ func init() {
proto.RegisterType((*EncryptionKey)(nil), "docker.swarmkit.v1.EncryptionKey")
proto.RegisterType((*ManagerStatus)(nil), "docker.swarmkit.v1.ManagerStatus")
proto.RegisterType((*SecretReference)(nil), "docker.swarmkit.v1.SecretReference")
proto.RegisterType((*RemovedNode)(nil), "docker.swarmkit.v1.RemovedNode")
proto.RegisterType((*BlacklistedCertificate)(nil), "docker.swarmkit.v1.BlacklistedCertificate")
proto.RegisterEnum("docker.swarmkit.v1.TaskState", TaskState_name, TaskState_value)
proto.RegisterEnum("docker.swarmkit.v1.NodeRole", NodeRole_name, NodeRole_value)
proto.RegisterEnum("docker.swarmkit.v1.RaftMemberStatus_Reachability", RaftMemberStatus_Reachability_name, RaftMemberStatus_Reachability_value)
@ -1467,6 +1504,7 @@ func init() {
proto.RegisterEnum("docker.swarmkit.v1.UpdateStatus_UpdateState", UpdateStatus_UpdateState_name, UpdateStatus_UpdateState_value)
proto.RegisterEnum("docker.swarmkit.v1.IPAMConfig_AddressFamily", IPAMConfig_AddressFamily_name, IPAMConfig_AddressFamily_value)
proto.RegisterEnum("docker.swarmkit.v1.PortConfig_Protocol", PortConfig_Protocol_name, PortConfig_Protocol_value)
proto.RegisterEnum("docker.swarmkit.v1.PortConfig_PublishMode", PortConfig_PublishMode_name, PortConfig_PublishMode_value)
proto.RegisterEnum("docker.swarmkit.v1.IssuanceStatus_State", IssuanceStatus_State_name, IssuanceStatus_State_value)
proto.RegisterEnum("docker.swarmkit.v1.ExternalCA_CAProtocol", ExternalCA_CAProtocol_name, ExternalCA_CAProtocol_value)
proto.RegisterEnum("docker.swarmkit.v1.EncryptionKey_Algorithm", EncryptionKey_Algorithm_name, EncryptionKey_Algorithm_value)
@ -1837,6 +1875,7 @@ func (m *PortConfig) Copy() *PortConfig {
Protocol: m.Protocol,
TargetPort: m.TargetPort,
PublishedPort: m.PublishedPort,
PublishMode: m.PublishMode,
}
return o
@ -2158,13 +2197,12 @@ func (m *SecretReference) Copy() *SecretReference {
return o
}
func (m *RemovedNode) Copy() *RemovedNode {
func (m *BlacklistedCertificate) Copy() *BlacklistedCertificate {
if m == nil {
return nil
}
o := &RemovedNode{
ID: m.ID,
o := &BlacklistedCertificate{
Expiry: m.Expiry.Copy(),
}
@ -2529,12 +2567,13 @@ func (this *PortConfig) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 8)
s := make([]string, 0, 9)
s = append(s, "&api.PortConfig{")
s = append(s, "Name: "+fmt.Sprintf("%#v", this.Name)+",\n")
s = append(s, "Protocol: "+fmt.Sprintf("%#v", this.Protocol)+",\n")
s = append(s, "TargetPort: "+fmt.Sprintf("%#v", this.TargetPort)+",\n")
s = append(s, "PublishedPort: "+fmt.Sprintf("%#v", this.PublishedPort)+",\n")
s = append(s, "PublishMode: "+fmt.Sprintf("%#v", this.PublishMode)+",\n")
s = append(s, "}")
return strings.Join(s, "")
}
@ -2822,13 +2861,12 @@ func (this *SecretReference) GoString() string {
s = append(s, "}")
return strings.Join(s, "")
}
func (this *RemovedNode) GoString() string {
func (this *BlacklistedCertificate) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 6)
s = append(s, "&api.RemovedNode{")
s = append(s, "ID: "+fmt.Sprintf("%#v", this.ID)+",\n")
s := make([]string, 0, 5)
s = append(s, "&api.BlacklistedCertificate{")
if this.Expiry != nil {
s = append(s, "Expiry: "+fmt.Sprintf("%#v", this.Expiry)+",\n")
}
@ -3827,6 +3865,11 @@ func (m *PortConfig) MarshalTo(data []byte) (int, error) {
i++
i = encodeVarintTypes(data, i, uint64(m.PublishedPort))
}
if m.PublishMode != 0 {
data[i] = 0x28
i++
i = encodeVarintTypes(data, i, uint64(m.PublishMode))
}
return i, nil
}
@ -4595,7 +4638,7 @@ func (m *SecretReference) MarshalTo(data []byte) (int, error) {
return i, nil
}
func (m *RemovedNode) Marshal() (data []byte, err error) {
func (m *BlacklistedCertificate) Marshal() (data []byte, err error) {
size := m.Size()
data = make([]byte, size)
n, err := m.MarshalTo(data)
@ -4605,19 +4648,13 @@ func (m *RemovedNode) Marshal() (data []byte, err error) {
return data[:n], nil
}
func (m *RemovedNode) MarshalTo(data []byte) (int, error) {
func (m *BlacklistedCertificate) MarshalTo(data []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if len(m.ID) > 0 {
data[i] = 0xa
i++
i = encodeVarintTypes(data, i, uint64(len(m.ID)))
i += copy(data[i:], m.ID)
}
if m.Expiry != nil {
data[i] = 0x12
data[i] = 0xa
i++
i = encodeVarintTypes(data, i, uint64(m.Expiry.Size()))
n27, err := m.Expiry.MarshalTo(data[i:])
@ -5075,6 +5112,9 @@ func (m *PortConfig) Size() (n int) {
if m.PublishedPort != 0 {
n += 1 + sovTypes(uint64(m.PublishedPort))
}
if m.PublishMode != 0 {
n += 1 + sovTypes(uint64(m.PublishMode))
}
return n
}
@ -5410,13 +5450,9 @@ func (m *SecretReference) Size() (n int) {
return n
}
func (m *RemovedNode) Size() (n int) {
func (m *BlacklistedCertificate) Size() (n int) {
var l int
_ = l
l = len(m.ID)
if l > 0 {
n += 1 + l + sovTypes(uint64(l))
}
if m.Expiry != nil {
l = m.Expiry.Size()
n += 1 + l + sovTypes(uint64(l))
@ -5760,6 +5796,7 @@ func (this *PortConfig) String() string {
`Protocol:` + fmt.Sprintf("%v", this.Protocol) + `,`,
`TargetPort:` + fmt.Sprintf("%v", this.TargetPort) + `,`,
`PublishedPort:` + fmt.Sprintf("%v", this.PublishedPort) + `,`,
`PublishMode:` + fmt.Sprintf("%v", this.PublishMode) + `,`,
`}`,
}, "")
return s
@ -6026,12 +6063,11 @@ func (this *SecretReference) String() string {
}, "")
return s
}
func (this *RemovedNode) String() string {
func (this *BlacklistedCertificate) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&RemovedNode{`,
`ID:` + fmt.Sprintf("%v", this.ID) + `,`,
s := strings.Join([]string{`&BlacklistedCertificate{`,
`Expiry:` + strings.Replace(fmt.Sprintf("%v", this.Expiry), "Timestamp", "docker_swarmkit_v1.Timestamp", 1) + `,`,
`}`,
}, "")
@ -9366,6 +9402,25 @@ func (m *PortConfig) Unmarshal(data []byte) error {
break
}
}
case 5:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field PublishMode", wireType)
}
m.PublishMode = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTypes
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
m.PublishMode |= (PortConfig_PublishMode(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipTypes(data[iNdEx:])
@ -12014,7 +12069,7 @@ func (m *SecretReference) Unmarshal(data []byte) error {
}
return nil
}
func (m *RemovedNode) Unmarshal(data []byte) error {
func (m *BlacklistedCertificate) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
@ -12037,42 +12092,13 @@ func (m *RemovedNode) Unmarshal(data []byte) error {
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: RemovedNode: wiretype end group for non-group")
return fmt.Errorf("proto: BlacklistedCertificate: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: RemovedNode: illegal tag %d (wire type %d)", fieldNum, wire)
return fmt.Errorf("proto: BlacklistedCertificate: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTypes
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthTypes
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.ID = string(data[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Expiry", wireType)
}
@ -12234,233 +12260,236 @@ var (
func init() { proto.RegisterFile("types.proto", fileDescriptorTypes) }
var fileDescriptorTypes = []byte{
// 3635 bytes of a gzipped FileDescriptorProto
// 3694 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x59, 0xcd, 0x6f, 0x23, 0x47,
0x76, 0x17, 0x3f, 0x45, 0x3e, 0x52, 0x52, 0x4f, 0xcd, 0xec, 0x58, 0x43, 0x8f, 0x25, 0xba, 0xc7,
0xb3, 0x1e, 0x7b, 0x1d, 0xda, 0x96, 0x77, 0x8d, 0x59, 0xcf, 0x66, 0xed, 0x16, 0x49, 0xcd, 0x70,
0x47, 0xa2, 0x88, 0x22, 0x39, 0x03, 0x23, 0x41, 0x88, 0x52, 0x77, 0x89, 0x6a, 0xab, 0xd9, 0xc5,
0xb3, 0x1e, 0xcf, 0x3a, 0xb4, 0x2d, 0xef, 0x1a, 0xb3, 0x9e, 0xcd, 0xda, 0x2d, 0x92, 0x1a, 0x71,
0x47, 0x22, 0x89, 0x22, 0x39, 0x03, 0x23, 0x40, 0x88, 0x52, 0x77, 0x89, 0x6a, 0xab, 0xd9, 0xcd,
0x74, 0x17, 0xa5, 0x61, 0x82, 0x00, 0x93, 0x1c, 0x92, 0x40, 0xa7, 0xdc, 0x03, 0x61, 0x11, 0x24,
0xc8, 0x2d, 0xe7, 0x00, 0x39, 0xf9, 0xe8, 0xe3, 0x06, 0x01, 0x82, 0xc5, 0x06, 0x19, 0xc4, 0xca,
0x3f, 0xb0, 0x40, 0x10, 0xec, 0x21, 0x39, 0x04, 0xf5, 0xd1, 0xcd, 0x8f, 0xe1, 0xc8, 0x72, 0xd6,
0x27, 0xb2, 0x5e, 0xfd, 0xde, 0xab, 0x57, 0x55, 0xaf, 0x5e, 0xfd, 0x5e, 0x35, 0x14, 0xf8, 0x78,
0x48, 0xc3, 0xca, 0x30, 0x60, 0x9c, 0x21, 0xe4, 0x30, 0xfb, 0x98, 0x06, 0x95, 0xf0, 0x94, 0x04,
0x83, 0x63, 0x97, 0x57, 0x4e, 0x3e, 0x2c, 0xdd, 0xe2, 0xee, 0x80, 0x86, 0x9c, 0x0c, 0x86, 0xef,
0xc7, 0xff, 0x14, 0xbc, 0xf4, 0x9a, 0x33, 0x0a, 0x08, 0x77, 0x99, 0xff, 0x7e, 0xf4, 0x47, 0x77,
0xdc, 0xe8, 0xb3, 0x3e, 0x93, 0x7f, 0xdf, 0x17, 0xff, 0x94, 0xd4, 0xdc, 0x84, 0xe5, 0x27, 0x34,
0x08, 0x5d, 0xe6, 0xa3, 0x1b, 0x90, 0x71, 0x7d, 0x87, 0x3e, 0x5b, 0x4f, 0x94, 0x13, 0xf7, 0xd2,
0x58, 0x35, 0xcc, 0xbf, 0x49, 0x40, 0xc1, 0xf2, 0x7d, 0xc6, 0xa5, 0xad, 0x10, 0x21, 0x48, 0xfb,
0x64, 0x40, 0x25, 0x28, 0x8f, 0xe5, 0x7f, 0x54, 0x85, 0xac, 0x47, 0x0e, 0xa8, 0x17, 0xae, 0x27,
0xcb, 0xa9, 0x7b, 0x85, 0xad, 0x1f, 0x54, 0x5e, 0xf6, 0xb9, 0x32, 0x65, 0xa4, 0xb2, 0x2b, 0xd1,
0x75, 0x9f, 0x07, 0x63, 0xac, 0x55, 0x4b, 0x3f, 0x86, 0xc2, 0x94, 0x18, 0x19, 0x90, 0x3a, 0xa6,
0x63, 0x3d, 0x8c, 0xf8, 0x2b, 0xfc, 0x3b, 0x21, 0xde, 0x88, 0xae, 0x27, 0xa5, 0x4c, 0x35, 0x3e,
0x49, 0xde, 0x4f, 0x98, 0x9f, 0x43, 0x1e, 0xd3, 0x90, 0x8d, 0x02, 0x9b, 0x86, 0xe8, 0x1d, 0xc8,
0xfb, 0xc4, 0x67, 0x3d, 0x7b, 0x38, 0x0a, 0xa5, 0x7a, 0x6a, 0xbb, 0x78, 0xf1, 0x62, 0x33, 0xd7,
0x24, 0x3e, 0xab, 0xb6, 0xba, 0x21, 0xce, 0x89, 0xee, 0xea, 0x70, 0x14, 0xa2, 0x37, 0xa1, 0x38,
0xa0, 0x03, 0x16, 0x8c, 0x7b, 0x07, 0x63, 0x4e, 0x43, 0x69, 0x38, 0x85, 0x0b, 0x4a, 0xb6, 0x2d,
0x44, 0xe6, 0x5f, 0x25, 0xe0, 0x46, 0x64, 0x1b, 0xd3, 0x3f, 0x1c, 0xb9, 0x01, 0x1d, 0x50, 0x9f,
0x87, 0xe8, 0x47, 0x90, 0xf5, 0xdc, 0x81, 0xcb, 0xd5, 0x18, 0x85, 0xad, 0x37, 0x16, 0xcd, 0x39,
0xf6, 0x0a, 0x6b, 0x30, 0xb2, 0xa0, 0x18, 0xd0, 0x90, 0x06, 0x27, 0x6a, 0x25, 0xe4, 0x90, 0xdf,
0xa8, 0x3c, 0xa3, 0x62, 0xee, 0x40, 0xae, 0xe5, 0x11, 0x7e, 0xc8, 0x82, 0x01, 0x32, 0xa1, 0x48,
0x02, 0xfb, 0xc8, 0xe5, 0xd4, 0xe6, 0xa3, 0x20, 0xda, 0x95, 0x19, 0x19, 0xba, 0x09, 0x49, 0xa6,
0x06, 0xca, 0x6f, 0x67, 0x2f, 0x5e, 0x6c, 0x26, 0xf7, 0xdb, 0x38, 0xc9, 0x42, 0xf3, 0x01, 0x5c,
0x6b, 0x79, 0xa3, 0xbe, 0xeb, 0xd7, 0x68, 0x68, 0x07, 0xee, 0x50, 0x58, 0x17, 0xdb, 0x2b, 0x82,
0x2f, 0xda, 0x5e, 0xf1, 0x3f, 0xde, 0xf2, 0xe4, 0x64, 0xcb, 0xcd, 0xbf, 0x48, 0xc2, 0xb5, 0xba,
0xdf, 0x77, 0x7d, 0x3a, 0xad, 0x7d, 0x17, 0x56, 0xa9, 0x14, 0xf6, 0x4e, 0x54, 0x50, 0x69, 0x3b,
0x2b, 0x4a, 0x1a, 0x45, 0x5a, 0x63, 0x2e, 0x5e, 0x3e, 0x5c, 0x34, 0xfd, 0x97, 0xac, 0x2f, 0x8a,
0x1a, 0x54, 0x87, 0xe5, 0xa1, 0x9c, 0x44, 0xb8, 0x9e, 0x92, 0xb6, 0xee, 0x2e, 0xb2, 0xf5, 0xd2,
0x3c, 0xb7, 0xd3, 0x5f, 0xbd, 0xd8, 0x5c, 0xc2, 0x91, 0xee, 0x6f, 0x13, 0x7c, 0xff, 0x99, 0x80,
0xb5, 0x26, 0x73, 0x66, 0xd6, 0xa1, 0x04, 0xb9, 0x23, 0x16, 0xf2, 0xa9, 0x83, 0x12, 0xb7, 0xd1,
0x7d, 0xc8, 0x0d, 0xf5, 0xf6, 0xe9, 0xdd, 0xbf, 0xbd, 0xd8, 0x65, 0x85, 0xc1, 0x31, 0x1a, 0x3d,
0x80, 0x7c, 0x10, 0xc5, 0xc4, 0x7a, 0xea, 0x2a, 0x81, 0x33, 0xc1, 0xa3, 0xdf, 0x85, 0xac, 0xda,
0x84, 0xf5, 0xb4, 0xd4, 0xbc, 0x7b, 0xa5, 0x35, 0xc7, 0x5a, 0xc9, 0xfc, 0x65, 0x02, 0x0c, 0x4c,
0x0e, 0xf9, 0x1e, 0x1d, 0x1c, 0xd0, 0xa0, 0xcd, 0x09, 0x1f, 0x85, 0xe8, 0x26, 0x64, 0x3d, 0x4a,
0x1c, 0x1a, 0xc8, 0x49, 0xe6, 0xb0, 0x6e, 0xa1, 0xae, 0x08, 0x72, 0x62, 0x1f, 0x91, 0x03, 0xd7,
0x73, 0xf9, 0x58, 0x4e, 0x73, 0x75, 0xf1, 0x2e, 0xcf, 0xdb, 0xac, 0xe0, 0x29, 0x45, 0x3c, 0x63,
0x06, 0xad, 0xc3, 0xf2, 0x80, 0x86, 0x21, 0xe9, 0x53, 0x39, 0xfb, 0x3c, 0x8e, 0x9a, 0xe6, 0x03,
0x28, 0x4e, 0xeb, 0xa1, 0x02, 0x2c, 0x77, 0x9b, 0x8f, 0x9b, 0xfb, 0x4f, 0x9b, 0xc6, 0x12, 0x5a,
0x83, 0x42, 0xb7, 0x89, 0xeb, 0x56, 0xf5, 0x91, 0xb5, 0xbd, 0x5b, 0x37, 0x12, 0x68, 0x05, 0xf2,
0x93, 0x66, 0xd2, 0xfc, 0x79, 0x02, 0x40, 0x6c, 0xa0, 0x9e, 0xd4, 0x27, 0x90, 0x09, 0x39, 0xe1,
0x6a, 0xe3, 0x56, 0xb7, 0xde, 0x5a, 0xe4, 0xf5, 0x04, 0x5e, 0x11, 0x3f, 0x14, 0x2b, 0x95, 0x69,
0x0f, 0x93, 0xf3, 0x1e, 0x66, 0x24, 0x72, 0xd6, 0xb5, 0x1c, 0xa4, 0x6b, 0xe2, 0x5f, 0x02, 0xe5,
0x21, 0x83, 0xeb, 0x56, 0xed, 0x73, 0x23, 0x89, 0x0c, 0x28, 0xd6, 0x1a, 0xed, 0xea, 0x7e, 0xb3,
0x59, 0xaf, 0x76, 0xea, 0x35, 0x23, 0x65, 0xde, 0x85, 0x4c, 0x63, 0x40, 0xfa, 0x14, 0xdd, 0x16,
0x11, 0x70, 0x48, 0x03, 0xea, 0xdb, 0x51, 0x60, 0x4d, 0x04, 0xe6, 0x2f, 0xf2, 0x90, 0xd9, 0x63,
0x23, 0x9f, 0xa3, 0xad, 0xa9, 0x53, 0xbc, 0xba, 0xb5, 0xb1, 0x68, 0x0a, 0x12, 0x58, 0xe9, 0x8c,
0x87, 0x54, 0x9f, 0xf2, 0x9b, 0x90, 0x55, 0xb1, 0xa2, 0x5d, 0xd7, 0x2d, 0x21, 0xe7, 0x24, 0xe8,
0x53, 0xae, 0x17, 0x5d, 0xb7, 0xd0, 0x3d, 0xc8, 0x05, 0x94, 0x38, 0xcc, 0xf7, 0xc6, 0x32, 0xa4,
0x72, 0x2a, 0xcd, 0x62, 0x4a, 0x9c, 0x7d, 0xdf, 0x1b, 0xe3, 0xb8, 0x17, 0x3d, 0x82, 0xe2, 0x81,
0xeb, 0x3b, 0x3d, 0x36, 0x54, 0x39, 0x2f, 0xf3, 0xea, 0x00, 0x54, 0x5e, 0x6d, 0xbb, 0xbe, 0xb3,
0xaf, 0xc0, 0xb8, 0x70, 0x30, 0x69, 0xa0, 0x26, 0xac, 0x9e, 0x30, 0x6f, 0x34, 0xa0, 0xb1, 0xad,
0xac, 0xb4, 0xf5, 0xf6, 0xab, 0x6d, 0x3d, 0x91, 0xf8, 0xc8, 0xda, 0xca, 0xc9, 0x74, 0x13, 0x3d,
0x86, 0x15, 0x3e, 0x18, 0x1e, 0x86, 0xb1, 0xb9, 0x65, 0x69, 0xee, 0xfb, 0x97, 0x2c, 0x98, 0x80,
0x47, 0xd6, 0x8a, 0x7c, 0xaa, 0x55, 0xfa, 0xb3, 0x14, 0x14, 0xa6, 0x3c, 0x47, 0x6d, 0x28, 0x0c,
0x03, 0x36, 0x24, 0x7d, 0x99, 0xb7, 0xf5, 0x5e, 0x7c, 0x78, 0xa5, 0x59, 0x57, 0x5a, 0x13, 0x45,
0x3c, 0x6d, 0xc5, 0x3c, 0x4f, 0x42, 0x61, 0xaa, 0x13, 0xbd, 0x0b, 0x39, 0xdc, 0xc2, 0x8d, 0x27,
0x56, 0xa7, 0x6e, 0x2c, 0x95, 0x6e, 0x9f, 0x9d, 0x97, 0xd7, 0xa5, 0xb5, 0x69, 0x03, 0xad, 0xc0,
0x3d, 0x11, 0xa1, 0x77, 0x0f, 0x96, 0x23, 0x68, 0xa2, 0xf4, 0xfa, 0xd9, 0x79, 0xf9, 0xb5, 0x79,
0xe8, 0x14, 0x12, 0xb7, 0x1f, 0x59, 0xb8, 0x5e, 0x33, 0x92, 0x8b, 0x91, 0xb8, 0x7d, 0x44, 0x02,
0xea, 0xa0, 0xef, 0x43, 0x56, 0x03, 0x53, 0xa5, 0xd2, 0xd9, 0x79, 0xf9, 0xe6, 0x3c, 0x70, 0x82,
0xc3, 0xed, 0x5d, 0xeb, 0x49, 0xdd, 0x48, 0x2f, 0xc6, 0xe1, 0xb6, 0x47, 0x4e, 0x28, 0x7a, 0x0b,
0x32, 0x0a, 0x96, 0x29, 0xdd, 0x3a, 0x3b, 0x2f, 0x7f, 0xef, 0x25, 0x73, 0x02, 0x55, 0x5a, 0xff,
0xcb, 0xbf, 0xdd, 0x58, 0xfa, 0xa7, 0xbf, 0xdb, 0x30, 0xe6, 0xbb, 0x4b, 0xff, 0x9b, 0x80, 0x95,
0x99, 0x2d, 0x47, 0x26, 0x64, 0x7d, 0x66, 0xb3, 0xa1, 0x4a, 0xe7, 0xb9, 0x6d, 0xb8, 0x78, 0xb1,
0x99, 0x6d, 0xb2, 0x2a, 0x1b, 0x8e, 0xb1, 0xee, 0x41, 0x8f, 0xe7, 0x2e, 0xa4, 0x8f, 0xae, 0x18,
0x4f, 0x0b, 0xaf, 0xa4, 0x4f, 0x61, 0xc5, 0x09, 0xdc, 0x13, 0x1a, 0xf4, 0x6c, 0xe6, 0x1f, 0xba,
0x7d, 0x9d, 0xaa, 0x4b, 0x8b, 0x6c, 0xd6, 0x24, 0x10, 0x17, 0x95, 0x42, 0x55, 0xe2, 0x7f, 0x8b,
0xcb, 0xa8, 0xf4, 0x04, 0x8a, 0xd3, 0x11, 0x8a, 0xde, 0x00, 0x08, 0xdd, 0x3f, 0xa2, 0x9a, 0xdf,
0x48, 0x36, 0x84, 0xf3, 0x42, 0x22, 0xd9, 0x0d, 0x7a, 0x1b, 0xd2, 0x03, 0xe6, 0x28, 0x3b, 0x99,
0xed, 0xeb, 0xe2, 0x4e, 0xfc, 0xd5, 0x8b, 0xcd, 0x02, 0x0b, 0x2b, 0x3b, 0xae, 0x47, 0xf7, 0x98,
0x43, 0xb1, 0x04, 0x98, 0x27, 0x90, 0x16, 0xa9, 0x02, 0xbd, 0x0e, 0xe9, 0xed, 0x46, 0xb3, 0x66,
0x2c, 0x95, 0xae, 0x9d, 0x9d, 0x97, 0x57, 0xe4, 0x92, 0x88, 0x0e, 0x11, 0xbb, 0x68, 0x13, 0xb2,
0x4f, 0xf6, 0x77, 0xbb, 0x7b, 0x22, 0xbc, 0xae, 0x9f, 0x9d, 0x97, 0xd7, 0xe2, 0x6e, 0xb5, 0x68,
0xe8, 0x0d, 0xc8, 0x74, 0xf6, 0x5a, 0x3b, 0x6d, 0x23, 0x59, 0x42, 0x67, 0xe7, 0xe5, 0xd5, 0xb8,
0x5f, 0xfa, 0x5c, 0xba, 0xa6, 0x77, 0x35, 0x1f, 0xcb, 0xcd, 0xff, 0x49, 0xc2, 0x0a, 0x16, 0xfc,
0x36, 0xe0, 0x2d, 0xe6, 0xb9, 0xf6, 0x18, 0xb5, 0x20, 0x6f, 0x33, 0xdf, 0x71, 0xa7, 0xce, 0xd4,
0xd6, 0x2b, 0x2e, 0xc1, 0x89, 0x56, 0xd4, 0xaa, 0x46, 0x9a, 0x78, 0x62, 0x04, 0x6d, 0x41, 0xc6,
0xa1, 0x1e, 0x19, 0x5f, 0x76, 0x1b, 0xd7, 0x34, 0x97, 0xc6, 0x0a, 0x2a, 0x99, 0x23, 0x79, 0xd6,
0x23, 0x9c, 0xd3, 0xc1, 0x90, 0xab, 0xdb, 0x38, 0x8d, 0x0b, 0x03, 0xf2, 0xcc, 0xd2, 0x22, 0xf4,
0x43, 0xc8, 0x9e, 0xba, 0xbe, 0xc3, 0x4e, 0xf5, 0x85, 0x7b, 0xb9, 0x5d, 0x8d, 0x35, 0xcf, 0xc4,
0x3d, 0x3b, 0xe7, 0xac, 0x58, 0xf5, 0xe6, 0x7e, 0xb3, 0x1e, 0xad, 0xba, 0xee, 0xdf, 0xf7, 0x9b,
0xcc, 0x17, 0x27, 0x06, 0xf6, 0x9b, 0xbd, 0x1d, 0xab, 0xb1, 0xdb, 0xc5, 0x62, 0xe5, 0x6f, 0x9c,
0x9d, 0x97, 0x8d, 0x18, 0xb2, 0x43, 0x5c, 0x4f, 0x90, 0xc0, 0x5b, 0x90, 0xb2, 0x9a, 0x9f, 0x1b,
0xc9, 0x92, 0x71, 0x76, 0x5e, 0x2e, 0xc6, 0xdd, 0x96, 0x3f, 0x9e, 0x1c, 0xa6, 0xf9, 0x71, 0xcd,
0x7f, 0x4f, 0x42, 0xb1, 0x3b, 0x74, 0x08, 0xa7, 0x2a, 0x32, 0x51, 0x19, 0x0a, 0x43, 0x12, 0x10,
0xcf, 0xa3, 0x9e, 0x1b, 0x0e, 0x74, 0xa1, 0x30, 0x2d, 0x42, 0xf7, 0xbf, 0xc5, 0x62, 0x6a, 0x12,
0xa6, 0x97, 0xb4, 0x0b, 0xab, 0x87, 0xca, 0xd9, 0x1e, 0xb1, 0xe5, 0xee, 0xa6, 0xe4, 0xee, 0x56,
0x16, 0x99, 0x98, 0xf6, 0xaa, 0xa2, 0xe7, 0x68, 0x49, 0x2d, 0xbc, 0x72, 0x38, 0xdd, 0x44, 0x1f,
0xc3, 0xf2, 0x80, 0xf9, 0x2e, 0x67, 0xc1, 0x95, 0xf6, 0x21, 0x02, 0xa3, 0x77, 0xe1, 0x9a, 0xd8,
0xe1, 0xc8, 0x25, 0xd9, 0x2d, 0x6f, 0xae, 0x24, 0x5e, 0x1b, 0x90, 0x67, 0x7a, 0x4c, 0x2c, 0xc4,
0xe6, 0xc7, 0xb0, 0x32, 0xe3, 0x83, 0xb8, 0xcd, 0x5b, 0x56, 0xb7, 0x5d, 0x37, 0x96, 0x50, 0x11,
0x72, 0xd5, 0xfd, 0x66, 0xa7, 0xd1, 0xec, 0x0a, 0xea, 0x51, 0x84, 0x1c, 0xde, 0xdf, 0xdd, 0xdd,
0xb6, 0xaa, 0x8f, 0x8d, 0xa4, 0xf9, 0xdf, 0xf1, 0xfa, 0x6a, 0xee, 0xb1, 0x3d, 0xcb, 0x3d, 0xde,
0x7b, 0xf5, 0xd4, 0x35, 0xfb, 0x98, 0x34, 0x62, 0x0e, 0xf2, 0x13, 0x00, 0xb9, 0x8d, 0xd4, 0xe9,
0x11, 0x7e, 0x59, 0x7d, 0xd1, 0x89, 0x2a, 0x47, 0x9c, 0xd7, 0x0a, 0x16, 0x47, 0x9f, 0x41, 0xd1,
0x66, 0x83, 0xa1, 0x47, 0xb5, 0x7e, 0xea, 0x2a, 0xfa, 0x85, 0x58, 0xc5, 0xe2, 0xd3, 0x1c, 0x28,
0x3d, 0xcb, 0x81, 0xfe, 0x3c, 0x01, 0x85, 0x29, 0x87, 0x67, 0xa9, 0x50, 0x11, 0x72, 0xdd, 0x56,
0xcd, 0xea, 0x34, 0x9a, 0x0f, 0x8d, 0x04, 0x02, 0xc8, 0xca, 0x05, 0xac, 0x19, 0x49, 0x41, 0xd7,
0xaa, 0xfb, 0x7b, 0xad, 0xdd, 0xba, 0x24, 0x43, 0xe8, 0x06, 0x18, 0xd1, 0x12, 0xf6, 0xda, 0x1d,
0x0b, 0x0b, 0x69, 0x1a, 0x5d, 0x87, 0xb5, 0x58, 0xaa, 0x35, 0x33, 0xe8, 0x26, 0xa0, 0x58, 0x38,
0x31, 0x91, 0x35, 0xff, 0x04, 0xd6, 0xaa, 0xcc, 0xe7, 0xc4, 0xf5, 0x63, 0x2a, 0xbb, 0x25, 0xe6,
0xad, 0x45, 0x3d, 0xd7, 0x51, 0xd9, 0x76, 0x7b, 0xed, 0xe2, 0xc5, 0x66, 0x21, 0x86, 0x36, 0x6a,
0x62, 0xa6, 0x51, 0xc3, 0x11, 0x67, 0x6a, 0xe8, 0x3a, 0x3a, 0x79, 0x2e, 0x5f, 0xbc, 0xd8, 0x4c,
0xb5, 0x1a, 0x35, 0x2c, 0x64, 0xe8, 0x75, 0xc8, 0xd3, 0x67, 0x2e, 0xef, 0xd9, 0x22, 0xbb, 0x8a,
0x35, 0xcc, 0xe0, 0x9c, 0x10, 0x54, 0x45, 0x32, 0xfd, 0xd3, 0x24, 0x40, 0x87, 0x84, 0xc7, 0x7a,
0xe8, 0x07, 0x90, 0x8f, 0x8b, 0xf8, 0xcb, 0x8a, 0xc9, 0xa9, 0xfd, 0x8a, 0xf1, 0xe8, 0xa3, 0x28,
0x62, 0x14, 0xc7, 0x5e, 0xac, 0xa8, 0xc7, 0x5a, 0x44, 0x53, 0x67, 0x89, 0xb4, 0xb8, 0x6b, 0x68,
0x10, 0xe8, 0x8d, 0x13, 0x7f, 0x51, 0x55, 0xe6, 0x5b, 0x35, 0x67, 0xcd, 0xdc, 0xee, 0x2c, 0x1a,
0x64, 0x6e, 0x41, 0x1f, 0x2d, 0xe1, 0x89, 0xde, 0xb6, 0x01, 0xab, 0xc1, 0xc8, 0x17, 0x5e, 0xf7,
0x42, 0xd9, 0x6d, 0xba, 0xf0, 0x5a, 0x93, 0xf2, 0x53, 0x16, 0x1c, 0x5b, 0x9c, 0x13, 0xfb, 0x48,
0x14, 0xd5, 0x3a, 0xc9, 0x4c, 0x08, 0x67, 0x62, 0x86, 0x70, 0xae, 0xc3, 0x32, 0xf1, 0x5c, 0x12,
0x52, 0x75, 0x4b, 0xe7, 0x71, 0xd4, 0x14, 0xb4, 0x98, 0x38, 0x4e, 0x40, 0xc3, 0x90, 0xaa, 0x32,
0x30, 0x8f, 0x27, 0x02, 0xf3, 0x5f, 0x92, 0x00, 0x8d, 0x96, 0xb5, 0xa7, 0xcd, 0xd7, 0x20, 0x7b,
0x48, 0x06, 0xae, 0x37, 0xbe, 0xec, 0x90, 0x4d, 0xf0, 0x15, 0x4b, 0x19, 0xda, 0x91, 0x3a, 0x58,
0xeb, 0x4a, 0xb6, 0x3c, 0x3a, 0xf0, 0x29, 0x8f, 0xd9, 0xb2, 0x6c, 0x89, 0xab, 0x39, 0x20, 0x7e,
0xbc, 0xb0, 0xaa, 0x21, 0x5c, 0xef, 0x13, 0x4e, 0x4f, 0xc9, 0x38, 0x3a, 0x13, 0xba, 0x89, 0x1e,
0x09, 0x16, 0x2d, 0x8a, 0x7b, 0xea, 0xac, 0x67, 0x24, 0xf7, 0xf8, 0x26, 0x7f, 0xb0, 0x86, 0x2b,
0xd2, 0x11, 0x6b, 0x97, 0x1e, 0xc8, 0x9b, 0x72, 0xd2, 0xf5, 0xad, 0x8a, 0xd8, 0x0f, 0x60, 0x65,
0x66, 0x9e, 0x2f, 0x95, 0x29, 0x8d, 0xd6, 0x93, 0x1f, 0x1a, 0x69, 0xfd, 0xef, 0x63, 0x23, 0x6b,
0xfe, 0x57, 0x02, 0xa0, 0xc5, 0x82, 0x68, 0xd3, 0x16, 0x3f, 0x0b, 0xe5, 0xe4, 0x23, 0x93, 0xcd,
0x3c, 0x1d, 0x9e, 0x0b, 0x79, 0xfa, 0xc4, 0x8a, 0xa0, 0xbd, 0x12, 0x8e, 0x63, 0x45, 0xb4, 0x09,
0x05, 0xb5, 0xff, 0xbd, 0x21, 0x0b, 0x54, 0x3e, 0x5a, 0xc1, 0xa0, 0x44, 0x42, 0x13, 0xdd, 0x85,
0xd5, 0xe1, 0xe8, 0xc0, 0x73, 0xc3, 0x23, 0xea, 0x28, 0x4c, 0x5a, 0x62, 0x56, 0x62, 0xa9, 0x80,
0x99, 0x35, 0xc8, 0x45, 0xd6, 0xd1, 0x3a, 0xa4, 0x3a, 0xd5, 0x96, 0xb1, 0x54, 0x5a, 0x3b, 0x3b,
0x2f, 0x17, 0x22, 0x71, 0xa7, 0xda, 0x12, 0x3d, 0xdd, 0x5a, 0xcb, 0x48, 0xcc, 0xf6, 0x74, 0x6b,
0xad, 0x52, 0x5a, 0xdc, 0x92, 0xe6, 0x5f, 0x27, 0x20, 0xab, 0x38, 0xdb, 0xc2, 0x19, 0x5b, 0xb0,
0x1c, 0x55, 0x12, 0x8a, 0x48, 0xbe, 0xfd, 0x6a, 0xd2, 0x57, 0xd1, 0x1c, 0x4d, 0xed, 0x63, 0xa4,
0x57, 0xfa, 0x04, 0x8a, 0xd3, 0x1d, 0xdf, 0x6a, 0x17, 0xff, 0x18, 0x0a, 0x22, 0x50, 0x22, 0xf2,
0xb7, 0x05, 0x59, 0xc5, 0x2b, 0x75, 0x56, 0xb9, 0x8c, 0x81, 0x6a, 0x24, 0xba, 0x0f, 0xcb, 0x8a,
0xb5, 0x46, 0xef, 0x29, 0x1b, 0x97, 0x87, 0x23, 0x8e, 0xe0, 0xe6, 0xa7, 0x90, 0x6e, 0x51, 0x1a,
0xa0, 0x3b, 0xb0, 0xec, 0x33, 0x87, 0x4e, 0x92, 0xa8, 0x26, 0xdc, 0x0e, 0x6d, 0xd4, 0x04, 0xe1,
0x76, 0x68, 0xc3, 0x11, 0x8b, 0x27, 0x0e, 0x68, 0xf4, 0xa4, 0x24, 0xfe, 0x9b, 0x1d, 0x28, 0x3e,
0xa5, 0x6e, 0xff, 0x88, 0x53, 0x47, 0x1a, 0x7a, 0x0f, 0xd2, 0x43, 0x1a, 0x3b, 0xbf, 0xbe, 0x30,
0x74, 0x28, 0x0d, 0xb0, 0x44, 0x89, 0x03, 0x79, 0x2a, 0xb5, 0xf5, 0x2b, 0x9e, 0x6e, 0x99, 0xff,
0x90, 0x84, 0xd5, 0x46, 0x18, 0x8e, 0x88, 0x6f, 0x47, 0xb7, 0xec, 0x4f, 0x67, 0x6f, 0xd9, 0x7b,
0x0b, 0x67, 0x38, 0xa3, 0x32, 0x5b, 0xe5, 0xeb, 0x24, 0x99, 0x8c, 0x93, 0xa4, 0xf9, 0x55, 0x22,
0x2a, 0xef, 0xef, 0x4e, 0x9d, 0x9b, 0xd2, 0xfa, 0xd9, 0x79, 0xf9, 0xc6, 0xb4, 0x25, 0xda, 0xf5,
0x8f, 0x7d, 0x76, 0xea, 0xa3, 0x37, 0x45, 0xb9, 0xdf, 0xac, 0x3f, 0x35, 0x12, 0xa5, 0x9b, 0x67,
0xe7, 0x65, 0x34, 0x03, 0xc2, 0xd4, 0xa7, 0xa7, 0xc2, 0x52, 0xab, 0xde, 0xac, 0x89, 0xfb, 0x30,
0xb9, 0xc0, 0x52, 0x8b, 0xfa, 0x8e, 0xeb, 0xf7, 0xd1, 0x1d, 0xc8, 0x36, 0xda, 0xed, 0xae, 0x2c,
0xc0, 0x5e, 0x3b, 0x3b, 0x2f, 0x5f, 0x9f, 0x41, 0x89, 0x06, 0x75, 0x04, 0x48, 0x10, 0x44, 0x71,
0x53, 0x2e, 0x00, 0x09, 0xee, 0x42, 0x1d, 0x1d, 0xe1, 0xff, 0x96, 0x04, 0xc3, 0xb2, 0x6d, 0x3a,
0xe4, 0xa2, 0x5f, 0x93, 0xee, 0x0e, 0xe4, 0x86, 0xe2, 0x9f, 0x2b, 0x8b, 0x08, 0x11, 0x16, 0xf7,
0x17, 0x3e, 0xf1, 0xce, 0xe9, 0x55, 0x30, 0xf3, 0xa8, 0xe5, 0x0c, 0xdc, 0x30, 0x14, 0xc5, 0xa5,
0x94, 0xe1, 0xd8, 0x52, 0xe9, 0xd7, 0x09, 0xb8, 0xbe, 0x00, 0x81, 0x3e, 0x80, 0x74, 0xc0, 0xbc,
0x68, 0x7b, 0x6e, 0xbf, 0xea, 0x01, 0x46, 0xa8, 0x62, 0x89, 0x44, 0x1b, 0x00, 0x64, 0xc4, 0x19,
0x91, 0xe3, 0xcb, 0x8d, 0xc9, 0xe1, 0x29, 0x09, 0x7a, 0x0a, 0xd9, 0x90, 0xda, 0x01, 0x8d, 0xf8,
0xcc, 0xa7, 0xff, 0x5f, 0xef, 0x2b, 0x6d, 0x69, 0x06, 0x6b, 0x73, 0xa5, 0x0a, 0x64, 0x95, 0x44,
0x44, 0xb4, 0x43, 0x38, 0x91, 0x4e, 0x17, 0xb1, 0xfc, 0x2f, 0x02, 0x85, 0x78, 0xfd, 0x28, 0x50,
0x88, 0xd7, 0x37, 0x7f, 0x9e, 0x04, 0xa8, 0x3f, 0xe3, 0x34, 0xf0, 0x89, 0x57, 0xb5, 0x50, 0x7d,
0x2a, 0x43, 0xaa, 0xd9, 0xbe, 0xb3, 0xf0, 0x59, 0x2e, 0xd6, 0xa8, 0x54, 0xad, 0x05, 0x39, 0xf2,
0x16, 0xa4, 0x46, 0x81, 0xa7, 0x9f, 0x78, 0x25, 0x11, 0xe9, 0xe2, 0x5d, 0x2c, 0x64, 0xa8, 0x3e,
0xc9, 0x48, 0xa9, 0x57, 0xbf, 0xcd, 0x4f, 0x0d, 0xf0, 0xdd, 0x67, 0xa5, 0xf7, 0x00, 0x26, 0x5e,
0xa3, 0x0d, 0xc8, 0x54, 0x77, 0xda, 0xed, 0x5d, 0x63, 0x49, 0xd5, 0x88, 0x93, 0x2e, 0x29, 0x36,
0xff, 0x3e, 0x01, 0xb9, 0xaa, 0xa5, 0x6f, 0x95, 0x1d, 0x30, 0x64, 0x2e, 0xb1, 0x69, 0xc0, 0x7b,
0xf4, 0xd9, 0xd0, 0x0d, 0xc6, 0x3a, 0x1d, 0x5c, 0xce, 0xe2, 0x57, 0x85, 0x56, 0x95, 0x06, 0xbc,
0x2e, 0x75, 0x10, 0x86, 0x22, 0xd5, 0x53, 0xec, 0xd9, 0x24, 0x4a, 0xce, 0x1b, 0x97, 0x2f, 0x85,
0x62, 0x7f, 0x93, 0x76, 0x88, 0x0b, 0x91, 0x91, 0x2a, 0x09, 0xcd, 0x27, 0x70, 0x7d, 0x3f, 0xb0,
0x8f, 0x68, 0xc8, 0xd5, 0xa0, 0xda, 0xe5, 0x4f, 0xe1, 0x36, 0x27, 0xe1, 0x71, 0xef, 0xc8, 0x0d,
0x39, 0x0b, 0xc6, 0xbd, 0x80, 0x72, 0xea, 0x8b, 0xfe, 0x9e, 0xfc, 0x02, 0xa0, 0x6b, 0xf0, 0x5b,
0x02, 0xf3, 0x48, 0x41, 0x70, 0x84, 0xd8, 0x15, 0x00, 0xb3, 0x01, 0x45, 0x41, 0xd8, 0x6a, 0xf4,
0x90, 0x8c, 0x3c, 0x1e, 0xa2, 0x1f, 0x03, 0x78, 0xac, 0xdf, 0xbb, 0x72, 0x26, 0xcf, 0x7b, 0xac,
0xaf, 0xfe, 0x9a, 0xbf, 0x07, 0x46, 0xcd, 0x0d, 0x87, 0x84, 0xdb, 0x47, 0xd1, 0xe3, 0x02, 0x7a,
0x08, 0xc6, 0x11, 0x25, 0x01, 0x3f, 0xa0, 0x84, 0xf7, 0x86, 0x34, 0x70, 0x99, 0x73, 0xa5, 0x25,
0x5d, 0x8b, 0xb5, 0x5a, 0x52, 0xc9, 0xfc, 0x4d, 0x02, 0x00, 0x93, 0xc3, 0x88, 0x00, 0xfc, 0x00,
0xae, 0x85, 0x3e, 0x19, 0x86, 0x47, 0x8c, 0xf7, 0x5c, 0x9f, 0xd3, 0xe0, 0x84, 0x78, 0xba, 0x40,
0x34, 0xa2, 0x8e, 0x86, 0x96, 0xa3, 0xf7, 0x00, 0x1d, 0x53, 0x3a, 0xec, 0x31, 0xcf, 0xe9, 0x45,
0x9d, 0xea, 0x13, 0x45, 0x1a, 0x1b, 0xa2, 0x67, 0xdf, 0x73, 0xda, 0x91, 0x1c, 0x6d, 0xc3, 0x86,
0x58, 0x01, 0xea, 0xf3, 0xc0, 0xa5, 0x61, 0xef, 0x90, 0x05, 0xbd, 0xd0, 0x63, 0xa7, 0xbd, 0x43,
0xe6, 0x79, 0xec, 0x94, 0x06, 0x51, 0xf9, 0x5d, 0xf2, 0x58, 0xbf, 0xae, 0x40, 0x3b, 0x2c, 0x68,
0x7b, 0xec, 0x74, 0x27, 0x42, 0x08, 0x96, 0x30, 0x99, 0x36, 0x77, 0xed, 0xe3, 0x88, 0x25, 0xc4,
0xd2, 0x8e, 0x6b, 0x1f, 0xa3, 0x3b, 0xb0, 0x42, 0x3d, 0x2a, 0x8b, 0x38, 0x85, 0xca, 0x48, 0x54,
0x31, 0x12, 0x0a, 0x90, 0xf9, 0x3b, 0x90, 0x6f, 0x79, 0xc4, 0x96, 0x1f, 0x82, 0x44, 0x49, 0x6c,
0x33, 0x5f, 0x04, 0x81, 0xeb, 0x73, 0x95, 0x1d, 0xf3, 0x78, 0x5a, 0x64, 0xfe, 0x14, 0xe0, 0x67,
0xcc, 0xf5, 0x3b, 0xec, 0x98, 0xfa, 0xf2, 0xcd, 0x5c, 0xb0, 0x5e, 0xbd, 0x95, 0x79, 0xac, 0x5b,
0x92, 0x93, 0x13, 0x9f, 0xf4, 0x69, 0x10, 0x3f, 0x1d, 0xab, 0xa6, 0xb8, 0x5c, 0xb2, 0x98, 0x31,
0x5e, 0xb5, 0x50, 0x19, 0xb2, 0x36, 0xe9, 0x45, 0x27, 0xaf, 0xb8, 0x9d, 0xbf, 0x78, 0xb1, 0x99,
0xa9, 0x5a, 0x8f, 0xe9, 0x18, 0x67, 0x6c, 0xf2, 0x98, 0x8e, 0xc5, 0xed, 0x6b, 0x13, 0x79, 0x5e,
0xa4, 0x99, 0xa2, 0xba, 0x7d, 0xab, 0x96, 0x38, 0x0c, 0x38, 0x6b, 0x13, 0xf1, 0x8b, 0x3e, 0x80,
0xa2, 0x06, 0xf5, 0x8e, 0x48, 0x78, 0xa4, 0xb8, 0xea, 0xf6, 0xea, 0xc5, 0x8b, 0x4d, 0x50, 0xc8,
0x47, 0x24, 0x3c, 0xc2, 0xa0, 0xd0, 0xe2, 0x3f, 0xaa, 0x43, 0xe1, 0x0b, 0xe6, 0xfa, 0x3d, 0x2e,
0x27, 0xa1, 0x2b, 0xe9, 0x85, 0xe7, 0x67, 0x32, 0x55, 0x5d, 0xde, 0xc3, 0x17, 0xb1, 0xc4, 0xfc,
0xd7, 0x04, 0x14, 0x84, 0x4d, 0xf7, 0xd0, 0xb5, 0xc5, 0x6d, 0xf9, 0xed, 0x33, 0xfd, 0x2d, 0x48,
0xd9, 0x61, 0xa0, 0xe7, 0x26, 0x53, 0x5d, 0xb5, 0x8d, 0xb1, 0x90, 0xa1, 0xcf, 0x20, 0xab, 0x8a,
0x0b, 0x9d, 0xe4, 0xcd, 0x6f, 0xbe, 0xd7, 0xb5, 0x8b, 0x5a, 0x4f, 0xee, 0xe5, 0xc4, 0x3b, 0x39,
0xcb, 0x22, 0x9e, 0x16, 0xa1, 0x9b, 0x90, 0xb4, 0x7d, 0x19, 0x14, 0xfa, 0x5b, 0x5a, 0xb5, 0x89,
0x93, 0xb6, 0x6f, 0xfe, 0x73, 0x02, 0x56, 0xea, 0xbe, 0x1d, 0x8c, 0x65, 0x92, 0x14, 0x1b, 0x71,
0x1b, 0xf2, 0xe1, 0xe8, 0x20, 0x1c, 0x87, 0x9c, 0x0e, 0xa2, 0xa7, 0xfa, 0x58, 0x80, 0x1a, 0x90,
0x27, 0x5e, 0x9f, 0x05, 0x2e, 0x3f, 0x1a, 0x68, 0x6e, 0xbc, 0x38, 0x31, 0x4f, 0xdb, 0xac, 0x58,
0x91, 0x0a, 0x9e, 0x68, 0x47, 0xa9, 0x38, 0x25, 0x9d, 0x95, 0xa9, 0xf8, 0x4d, 0x28, 0x7a, 0x64,
0x20, 0xa8, 0x70, 0x4f, 0x94, 0x5c, 0x72, 0x1e, 0x69, 0x5c, 0xd0, 0x32, 0x51, 0x46, 0x9a, 0x26,
0xe4, 0x63, 0x63, 0x68, 0x0d, 0x0a, 0x56, 0xbd, 0xdd, 0xfb, 0x70, 0xeb, 0x7e, 0xef, 0x61, 0x75,
0xcf, 0x58, 0xd2, 0x4c, 0xe0, 0x1f, 0x13, 0xb0, 0xb2, 0xa7, 0x62, 0x50, 0x13, 0xa7, 0x3b, 0xb0,
0x1c, 0x90, 0x43, 0x1e, 0x51, 0xbb, 0xb4, 0x0a, 0x2e, 0x91, 0x04, 0x04, 0xb5, 0x13, 0x5d, 0x8b,
0xa9, 0xdd, 0xd4, 0x87, 0xa2, 0xd4, 0xa5, 0x1f, 0x8a, 0xd2, 0xdf, 0xc9, 0x87, 0x22, 0xf3, 0x57,
0x09, 0x58, 0xd3, 0x17, 0x75, 0xf4, 0x71, 0x04, 0xbd, 0x03, 0x79, 0x75, 0x67, 0x4f, 0x88, 0xa9,
0xfc, 0x5e, 0xa1, 0x70, 0x8d, 0x1a, 0xce, 0xa9, 0xee, 0x86, 0x83, 0x7e, 0x32, 0xf5, 0x2a, 0xfa,
0x0a, 0x7a, 0x38, 0x67, 0xbd, 0x32, 0x79, 0x2a, 0x7d, 0xe5, 0xf7, 0x92, 0x4d, 0x28, 0x68, 0x07,
0x64, 0xd9, 0xa0, 0xea, 0x40, 0x50, 0xa2, 0x26, 0x19, 0x50, 0xf3, 0x2e, 0xa4, 0x85, 0x19, 0x04,
0x90, 0x6d, 0x7f, 0xde, 0xee, 0xd4, 0xf7, 0x54, 0xe5, 0xb5, 0xd3, 0x90, 0x1f, 0xad, 0x96, 0x21,
0x55, 0x6f, 0x3e, 0x31, 0x92, 0xe6, 0xef, 0x43, 0x01, 0xd3, 0x01, 0x3b, 0xa1, 0x4e, 0x53, 0x0d,
0x97, 0x8c, 0x27, 0x24, 0x23, 0xb2, 0x51, 0xc3, 0x49, 0xd7, 0x41, 0x3f, 0x82, 0xac, 0xbe, 0x30,
0xaf, 0xf4, 0x04, 0xa4, 0xc1, 0xef, 0xfe, 0x26, 0x05, 0xf9, 0xf8, 0xbd, 0x40, 0x9c, 0x36, 0x41,
0x52, 0x97, 0xd4, 0xab, 0x61, 0x2c, 0x6f, 0x4a, 0x7a, 0x9a, 0xb7, 0x76, 0x77, 0xf7, 0xab, 0x56,
0xa7, 0x5e, 0x33, 0x3e, 0x53, 0x2c, 0x36, 0x06, 0x58, 0x9e, 0xc7, 0xc4, 0x79, 0x71, 0x90, 0x39,
0x61, 0xb1, 0xcf, 0xf5, 0xdb, 0x64, 0x8c, 0x8a, 0x28, 0xec, 0x5b, 0x90, 0xb3, 0xda, 0xed, 0xc6,
0xc3, 0x66, 0xbd, 0x66, 0x7c, 0x99, 0x28, 0x7d, 0xef, 0xec, 0xbc, 0x7c, 0x6d, 0x62, 0x2a, 0x0c,
0xdd, 0xbe, 0x4f, 0x1d, 0x89, 0xaa, 0x56, 0xeb, 0x2d, 0x31, 0xde, 0xf3, 0xe4, 0x3c, 0x4a, 0x72,
0x37, 0xf9, 0x9d, 0x21, 0xdf, 0xc2, 0xf5, 0x96, 0x85, 0xc5, 0x88, 0x5f, 0x26, 0xe7, 0xfc, 0x6a,
0x05, 0x74, 0x48, 0x02, 0x31, 0xe6, 0x46, 0xf4, 0xbd, 0xed, 0x79, 0x4a, 0xbd, 0x45, 0x4f, 0x1e,
0x49, 0x28, 0x71, 0xc6, 0x62, 0x34, 0xf9, 0xb8, 0x24, 0xcd, 0xa4, 0xe6, 0x46, 0x6b, 0x73, 0x12,
0x70, 0x61, 0xc5, 0x84, 0x65, 0xdc, 0x6d, 0x36, 0xe5, 0xec, 0xd2, 0x73, 0xb3, 0xc3, 0x23, 0xdf,
0x17, 0x98, 0xbb, 0x90, 0x8b, 0xde, 0x9e, 0x8c, 0x2f, 0xd3, 0x73, 0x0e, 0x55, 0xa3, 0x87, 0x33,
0x39, 0xe0, 0xa3, 0x6e, 0x47, 0x7e, 0x0e, 0x7c, 0x9e, 0x99, 0x1f, 0xf0, 0x68, 0xc4, 0x1d, 0x51,
0x37, 0x94, 0x63, 0x22, 0xff, 0x65, 0x46, 0xf1, 0xa7, 0x18, 0xa3, 0x58, 0xbc, 0xb0, 0x83, 0xeb,
0x3f, 0x53, 0x5f, 0x0e, 0x9f, 0x67, 0xe7, 0xec, 0x60, 0xfa, 0x05, 0xb5, 0x39, 0x75, 0x26, 0x4f,
0xed, 0x71, 0xd7, 0xbb, 0x7f, 0x00, 0xb9, 0x28, 0xd7, 0xa2, 0x0d, 0xc8, 0x3e, 0xdd, 0xc7, 0x8f,
0xeb, 0xd8, 0x58, 0x52, 0xab, 0x13, 0xf5, 0x3c, 0x55, 0x97, 0x55, 0x19, 0x96, 0xf7, 0xac, 0xa6,
0xf5, 0xb0, 0x8e, 0xa3, 0xa7, 0xfe, 0x08, 0xa0, 0x13, 0x46, 0xc9, 0xd0, 0x03, 0xc4, 0x36, 0xb7,
0x6f, 0x7f, 0xf5, 0xf5, 0xc6, 0xd2, 0x2f, 0xbf, 0xde, 0x58, 0xfa, 0xf5, 0xd7, 0x1b, 0x89, 0xe7,
0x17, 0x1b, 0x89, 0xaf, 0x2e, 0x36, 0x12, 0xbf, 0xb8, 0xd8, 0x48, 0xfc, 0xc7, 0xc5, 0x46, 0xe2,
0x20, 0x2b, 0xc9, 0xec, 0x47, 0xff, 0x17, 0x00, 0x00, 0xff, 0xff, 0x1f, 0x9b, 0xee, 0x67, 0xfb,
0x22, 0x00, 0x00,
0xc8, 0x21, 0xff, 0x40, 0x80, 0x9c, 0x7c, 0xf4, 0x2d, 0x9b, 0x04, 0x08, 0x16, 0x1b, 0x64, 0x10,
0x2b, 0xe7, 0x00, 0x7b, 0x09, 0x72, 0x48, 0x0e, 0x41, 0x7d, 0x74, 0xb3, 0xc9, 0xa1, 0x34, 0xe3,
0xac, 0x2f, 0x64, 0xd7, 0xab, 0xdf, 0x7b, 0xf5, 0xaa, 0xea, 0xd5, 0xab, 0x5f, 0x55, 0x41, 0x81,
0x4d, 0x46, 0x34, 0xa8, 0x8c, 0x7c, 0x8f, 0x79, 0x08, 0x59, 0x9e, 0x79, 0x4c, 0xfd, 0x4a, 0x70,
0x4a, 0xfc, 0xe1, 0xb1, 0xcd, 0x2a, 0x27, 0x1f, 0x95, 0x6e, 0x31, 0x7b, 0x48, 0x03, 0x46, 0x86,
0xa3, 0x0f, 0xa2, 0x2f, 0x09, 0x2f, 0xbd, 0x61, 0x8d, 0x7d, 0xc2, 0x6c, 0xcf, 0xfd, 0x20, 0xfc,
0x50, 0x15, 0x37, 0x06, 0xde, 0xc0, 0x13, 0x9f, 0x1f, 0xf0, 0x2f, 0x29, 0xd5, 0x37, 0x61, 0xf9,
0x09, 0xf5, 0x03, 0xdb, 0x73, 0xd1, 0x0d, 0xc8, 0xd8, 0xae, 0x45, 0x9f, 0xad, 0x27, 0xca, 0x89,
0x7b, 0x69, 0x2c, 0x0b, 0xfa, 0x5f, 0x26, 0xa0, 0x60, 0xb8, 0xae, 0xc7, 0x84, 0xad, 0x00, 0x21,
0x48, 0xbb, 0x64, 0x48, 0x05, 0x28, 0x8f, 0xc5, 0x37, 0xaa, 0x42, 0xd6, 0x21, 0x07, 0xd4, 0x09,
0xd6, 0x93, 0xe5, 0xd4, 0xbd, 0xc2, 0xd6, 0x0f, 0x2a, 0x2f, 0xfb, 0x5c, 0x89, 0x19, 0xa9, 0xec,
0x09, 0x74, 0xdd, 0x65, 0xfe, 0x04, 0x2b, 0xd5, 0xd2, 0x8f, 0xa1, 0x10, 0x13, 0x23, 0x0d, 0x52,
0xc7, 0x74, 0xa2, 0x9a, 0xe1, 0x9f, 0xdc, 0xbf, 0x13, 0xe2, 0x8c, 0xe9, 0x7a, 0x52, 0xc8, 0x64,
0xe1, 0xd3, 0xe4, 0x83, 0x84, 0xfe, 0x05, 0xe4, 0x31, 0x0d, 0xbc, 0xb1, 0x6f, 0xd2, 0x00, 0xbd,
0x07, 0x79, 0x97, 0xb8, 0x5e, 0xdf, 0x1c, 0x8d, 0x03, 0xa1, 0x9e, 0xda, 0x2e, 0x5e, 0xbc, 0xd8,
0xcc, 0x35, 0x89, 0xeb, 0x55, 0xdb, 0xbd, 0x00, 0xe7, 0x78, 0x75, 0x75, 0x34, 0x0e, 0xd0, 0xdb,
0x50, 0x1c, 0xd2, 0xa1, 0xe7, 0x4f, 0xfa, 0x07, 0x13, 0x46, 0x03, 0x61, 0x38, 0x85, 0x0b, 0x52,
0xb6, 0xcd, 0x45, 0xfa, 0x9f, 0x27, 0xe0, 0x46, 0x68, 0x1b, 0xd3, 0xdf, 0x1b, 0xdb, 0x3e, 0x1d,
0x52, 0x97, 0x05, 0xe8, 0x47, 0x90, 0x75, 0xec, 0xa1, 0xcd, 0x64, 0x1b, 0x85, 0xad, 0xb7, 0x16,
0xf5, 0x39, 0xf2, 0x0a, 0x2b, 0x30, 0x32, 0xa0, 0xe8, 0xd3, 0x80, 0xfa, 0x27, 0x72, 0x24, 0x44,
0x93, 0xaf, 0x54, 0x9e, 0x51, 0xd1, 0x77, 0x20, 0xd7, 0x76, 0x08, 0x3b, 0xf4, 0xfc, 0x21, 0xd2,
0xa1, 0x48, 0x7c, 0xf3, 0xc8, 0x66, 0xd4, 0x64, 0x63, 0x3f, 0x9c, 0x95, 0x19, 0x19, 0xba, 0x09,
0x49, 0x4f, 0x36, 0x94, 0xdf, 0xce, 0x5e, 0xbc, 0xd8, 0x4c, 0xb6, 0x3a, 0x38, 0xe9, 0x05, 0xfa,
0x43, 0xb8, 0xd6, 0x76, 0xc6, 0x03, 0xdb, 0xad, 0xd1, 0xc0, 0xf4, 0xed, 0x11, 0xb7, 0xce, 0xa7,
0x97, 0x07, 0x5f, 0x38, 0xbd, 0xfc, 0x3b, 0x9a, 0xf2, 0xe4, 0x74, 0xca, 0xf5, 0x3f, 0x4d, 0xc2,
0xb5, 0xba, 0x3b, 0xb0, 0x5d, 0x1a, 0xd7, 0xbe, 0x0b, 0xab, 0x54, 0x08, 0xfb, 0x27, 0x32, 0xa8,
0x94, 0x9d, 0x15, 0x29, 0x0d, 0x23, 0xad, 0x31, 0x17, 0x2f, 0x1f, 0x2d, 0xea, 0xfe, 0x4b, 0xd6,
0x17, 0x45, 0x0d, 0xaa, 0xc3, 0xf2, 0x48, 0x74, 0x22, 0x58, 0x4f, 0x09, 0x5b, 0x77, 0x17, 0xd9,
0x7a, 0xa9, 0x9f, 0xdb, 0xe9, 0xaf, 0x5f, 0x6c, 0x2e, 0xe1, 0x50, 0xf7, 0x37, 0x09, 0xbe, 0xff,
0x48, 0xc0, 0x5a, 0xd3, 0xb3, 0x66, 0xc6, 0xa1, 0x04, 0xb9, 0x23, 0x2f, 0x60, 0xb1, 0x85, 0x12,
0x95, 0xd1, 0x03, 0xc8, 0x8d, 0xd4, 0xf4, 0xa9, 0xd9, 0xbf, 0xbd, 0xd8, 0x65, 0x89, 0xc1, 0x11,
0x1a, 0x3d, 0x84, 0xbc, 0x1f, 0xc6, 0xc4, 0x7a, 0xea, 0x75, 0x02, 0x67, 0x8a, 0x47, 0xbf, 0x0d,
0x59, 0x39, 0x09, 0xeb, 0x69, 0xa1, 0x79, 0xf7, 0xb5, 0xc6, 0x1c, 0x2b, 0x25, 0xfd, 0x97, 0x09,
0xd0, 0x30, 0x39, 0x64, 0xfb, 0x74, 0x78, 0x40, 0xfd, 0x0e, 0x23, 0x6c, 0x1c, 0xa0, 0x9b, 0x90,
0x75, 0x28, 0xb1, 0xa8, 0x2f, 0x3a, 0x99, 0xc3, 0xaa, 0x84, 0x7a, 0x3c, 0xc8, 0x89, 0x79, 0x44,
0x0e, 0x6c, 0xc7, 0x66, 0x13, 0xd1, 0xcd, 0xd5, 0xc5, 0xb3, 0x3c, 0x6f, 0xb3, 0x82, 0x63, 0x8a,
0x78, 0xc6, 0x0c, 0x5a, 0x87, 0xe5, 0x21, 0x0d, 0x02, 0x32, 0xa0, 0xa2, 0xf7, 0x79, 0x1c, 0x16,
0xf5, 0x87, 0x50, 0x8c, 0xeb, 0xa1, 0x02, 0x2c, 0xf7, 0x9a, 0x8f, 0x9b, 0xad, 0xa7, 0x4d, 0x6d,
0x09, 0xad, 0x41, 0xa1, 0xd7, 0xc4, 0x75, 0xa3, 0xba, 0x6b, 0x6c, 0xef, 0xd5, 0xb5, 0x04, 0x5a,
0x81, 0xfc, 0xb4, 0x98, 0xd4, 0x7f, 0x9e, 0x00, 0xe0, 0x13, 0xa8, 0x3a, 0xf5, 0x29, 0x64, 0x02,
0x46, 0x98, 0x9c, 0xb8, 0xd5, 0xad, 0x77, 0x16, 0x79, 0x3d, 0x85, 0x57, 0xf8, 0x1f, 0xc5, 0x52,
0x25, 0xee, 0x61, 0x72, 0xde, 0xc3, 0x8c, 0x40, 0xce, 0xba, 0x96, 0x83, 0x74, 0x8d, 0x7f, 0x25,
0x50, 0x1e, 0x32, 0xb8, 0x6e, 0xd4, 0xbe, 0xd0, 0x92, 0x48, 0x83, 0x62, 0xad, 0xd1, 0xa9, 0xb6,
0x9a, 0xcd, 0x7a, 0xb5, 0x5b, 0xaf, 0x69, 0x29, 0xfd, 0x2e, 0x64, 0x1a, 0x43, 0x32, 0xa0, 0xe8,
0x36, 0x8f, 0x80, 0x43, 0xea, 0x53, 0xd7, 0x0c, 0x03, 0x6b, 0x2a, 0xd0, 0x7f, 0x91, 0x87, 0xcc,
0xbe, 0x37, 0x76, 0x19, 0xda, 0x8a, 0xad, 0xe2, 0xd5, 0xad, 0x8d, 0x45, 0x5d, 0x10, 0xc0, 0x4a,
0x77, 0x32, 0xa2, 0x6a, 0x95, 0xdf, 0x84, 0xac, 0x8c, 0x15, 0xe5, 0xba, 0x2a, 0x71, 0x39, 0x23,
0xfe, 0x80, 0x32, 0x35, 0xe8, 0xaa, 0x84, 0xee, 0x41, 0xce, 0xa7, 0xc4, 0xf2, 0x5c, 0x67, 0x22,
0x42, 0x2a, 0x27, 0xd3, 0x2c, 0xa6, 0xc4, 0x6a, 0xb9, 0xce, 0x04, 0x47, 0xb5, 0x68, 0x17, 0x8a,
0x07, 0xb6, 0x6b, 0xf5, 0xbd, 0x91, 0xcc, 0x79, 0x99, 0xcb, 0x03, 0x50, 0x7a, 0xb5, 0x6d, 0xbb,
0x56, 0x4b, 0x82, 0x71, 0xe1, 0x60, 0x5a, 0x40, 0x4d, 0x58, 0x3d, 0xf1, 0x9c, 0xf1, 0x90, 0x46,
0xb6, 0xb2, 0xc2, 0xd6, 0xbb, 0x97, 0xdb, 0x7a, 0x22, 0xf0, 0xa1, 0xb5, 0x95, 0x93, 0x78, 0x11,
0x3d, 0x86, 0x15, 0x36, 0x1c, 0x1d, 0x06, 0x91, 0xb9, 0x65, 0x61, 0xee, 0xfb, 0x57, 0x0c, 0x18,
0x87, 0x87, 0xd6, 0x8a, 0x2c, 0x56, 0x2a, 0xfd, 0x71, 0x0a, 0x0a, 0x31, 0xcf, 0x51, 0x07, 0x0a,
0x23, 0xdf, 0x1b, 0x91, 0x81, 0xc8, 0xdb, 0x6a, 0x2e, 0x3e, 0x7a, 0xad, 0x5e, 0x57, 0xda, 0x53,
0x45, 0x1c, 0xb7, 0xa2, 0x9f, 0x27, 0xa1, 0x10, 0xab, 0x44, 0xf7, 0x21, 0x87, 0xdb, 0xb8, 0xf1,
0xc4, 0xe8, 0xd6, 0xb5, 0xa5, 0xd2, 0xed, 0xb3, 0xf3, 0xf2, 0xba, 0xb0, 0x16, 0x37, 0xd0, 0xf6,
0xed, 0x13, 0x1e, 0x7a, 0xf7, 0x60, 0x39, 0x84, 0x26, 0x4a, 0x6f, 0x9e, 0x9d, 0x97, 0xdf, 0x98,
0x87, 0xc6, 0x90, 0xb8, 0xb3, 0x6b, 0xe0, 0x7a, 0x4d, 0x4b, 0x2e, 0x46, 0xe2, 0xce, 0x11, 0xf1,
0xa9, 0x85, 0xbe, 0x0f, 0x59, 0x05, 0x4c, 0x95, 0x4a, 0x67, 0xe7, 0xe5, 0x9b, 0xf3, 0xc0, 0x29,
0x0e, 0x77, 0xf6, 0x8c, 0x27, 0x75, 0x2d, 0xbd, 0x18, 0x87, 0x3b, 0x0e, 0x39, 0xa1, 0xe8, 0x1d,
0xc8, 0x48, 0x58, 0xa6, 0x74, 0xeb, 0xec, 0xbc, 0xfc, 0xbd, 0x97, 0xcc, 0x71, 0x54, 0x69, 0xfd,
0xcf, 0xfe, 0x6a, 0x63, 0xe9, 0xef, 0xff, 0x7a, 0x43, 0x9b, 0xaf, 0x2e, 0xfd, 0x6f, 0x02, 0x56,
0x66, 0xa6, 0x1c, 0xe9, 0x90, 0x75, 0x3d, 0xd3, 0x1b, 0xc9, 0x74, 0x9e, 0xdb, 0x86, 0x8b, 0x17,
0x9b, 0xd9, 0xa6, 0x57, 0xf5, 0x46, 0x13, 0xac, 0x6a, 0xd0, 0xe3, 0xb9, 0x0d, 0xe9, 0xe3, 0xd7,
0x8c, 0xa7, 0x85, 0x5b, 0xd2, 0x67, 0xb0, 0x62, 0xf9, 0xf6, 0x09, 0xf5, 0xfb, 0xa6, 0xe7, 0x1e,
0xda, 0x03, 0x95, 0xaa, 0x4b, 0x8b, 0x6c, 0xd6, 0x04, 0x10, 0x17, 0xa5, 0x42, 0x55, 0xe0, 0x7f,
0x83, 0xcd, 0xa8, 0xf4, 0x04, 0x8a, 0xf1, 0x08, 0x45, 0x6f, 0x01, 0x04, 0xf6, 0xef, 0x53, 0xc5,
0x6f, 0x04, 0x1b, 0xc2, 0x79, 0x2e, 0x11, 0xec, 0x06, 0xbd, 0x0b, 0xe9, 0xa1, 0x67, 0x49, 0x3b,
0x99, 0xed, 0xeb, 0x7c, 0x4f, 0xfc, 0xd5, 0x8b, 0xcd, 0x82, 0x17, 0x54, 0x76, 0x6c, 0x87, 0xee,
0x7b, 0x16, 0xc5, 0x02, 0xa0, 0x9f, 0x40, 0x9a, 0xa7, 0x0a, 0xf4, 0x26, 0xa4, 0xb7, 0x1b, 0xcd,
0x9a, 0xb6, 0x54, 0xba, 0x76, 0x76, 0x5e, 0x5e, 0x11, 0x43, 0xc2, 0x2b, 0x78, 0xec, 0xa2, 0x4d,
0xc8, 0x3e, 0x69, 0xed, 0xf5, 0xf6, 0x79, 0x78, 0x5d, 0x3f, 0x3b, 0x2f, 0xaf, 0x45, 0xd5, 0x72,
0xd0, 0xd0, 0x5b, 0x90, 0xe9, 0xee, 0xb7, 0x77, 0x3a, 0x5a, 0xb2, 0x84, 0xce, 0xce, 0xcb, 0xab,
0x51, 0xbd, 0xf0, 0xb9, 0x74, 0x4d, 0xcd, 0x6a, 0x3e, 0x92, 0xeb, 0xff, 0x93, 0x84, 0x15, 0xcc,
0xf9, 0xad, 0xcf, 0xda, 0x9e, 0x63, 0x9b, 0x13, 0xd4, 0x86, 0xbc, 0xe9, 0xb9, 0x96, 0x1d, 0x5b,
0x53, 0x5b, 0x97, 0x6c, 0x82, 0x53, 0xad, 0xb0, 0x54, 0x0d, 0x35, 0xf1, 0xd4, 0x08, 0xda, 0x82,
0x8c, 0x45, 0x1d, 0x32, 0xb9, 0x6a, 0x37, 0xae, 0x29, 0x2e, 0x8d, 0x25, 0x54, 0x30, 0x47, 0xf2,
0xac, 0x4f, 0x18, 0xa3, 0xc3, 0x11, 0x93, 0xbb, 0x71, 0x1a, 0x17, 0x86, 0xe4, 0x99, 0xa1, 0x44,
0xe8, 0x87, 0x90, 0x3d, 0xb5, 0x5d, 0xcb, 0x3b, 0x55, 0x1b, 0xee, 0xd5, 0x76, 0x15, 0x56, 0x3f,
0xe3, 0xfb, 0xec, 0x9c, 0xb3, 0x7c, 0xd4, 0x9b, 0xad, 0x66, 0x3d, 0x1c, 0x75, 0x55, 0xdf, 0x72,
0x9b, 0x9e, 0xcb, 0x57, 0x0c, 0xb4, 0x9a, 0xfd, 0x1d, 0xa3, 0xb1, 0xd7, 0xc3, 0x7c, 0xe4, 0x6f,
0x9c, 0x9d, 0x97, 0xb5, 0x08, 0xb2, 0x43, 0x6c, 0x87, 0x93, 0xc0, 0x5b, 0x90, 0x32, 0x9a, 0x5f,
0x68, 0xc9, 0x92, 0x76, 0x76, 0x5e, 0x2e, 0x46, 0xd5, 0x86, 0x3b, 0x99, 0x2e, 0xa6, 0xf9, 0x76,
0xf5, 0x7f, 0x4b, 0x42, 0xb1, 0x37, 0xb2, 0x08, 0xa3, 0x32, 0x32, 0x51, 0x19, 0x0a, 0x23, 0xe2,
0x13, 0xc7, 0xa1, 0x8e, 0x1d, 0x0c, 0xd5, 0x41, 0x21, 0x2e, 0x42, 0x0f, 0xbe, 0xc5, 0x60, 0x2a,
0x12, 0xa6, 0x86, 0xb4, 0x07, 0xab, 0x87, 0xd2, 0xd9, 0x3e, 0x31, 0xc5, 0xec, 0xa6, 0xc4, 0xec,
0x56, 0x16, 0x99, 0x88, 0x7b, 0x55, 0x51, 0x7d, 0x34, 0x84, 0x16, 0x5e, 0x39, 0x8c, 0x17, 0xd1,
0x27, 0xb0, 0x3c, 0xf4, 0x5c, 0x9b, 0x79, 0xfe, 0x6b, 0xcd, 0x43, 0x08, 0x46, 0xf7, 0xe1, 0x1a,
0x9f, 0xe1, 0xd0, 0x25, 0x51, 0x2d, 0x76, 0xae, 0x24, 0x5e, 0x1b, 0x92, 0x67, 0xaa, 0x4d, 0xcc,
0xc5, 0xfa, 0x27, 0xb0, 0x32, 0xe3, 0x03, 0xdf, 0xcd, 0xdb, 0x46, 0xaf, 0x53, 0xd7, 0x96, 0x50,
0x11, 0x72, 0xd5, 0x56, 0xb3, 0xdb, 0x68, 0xf6, 0x38, 0xf5, 0x28, 0x42, 0x0e, 0xb7, 0xf6, 0xf6,
0xb6, 0x8d, 0xea, 0x63, 0x2d, 0xa9, 0xff, 0x57, 0x34, 0xbe, 0x8a, 0x7b, 0x6c, 0xcf, 0x72, 0x8f,
0xf7, 0x2f, 0xef, 0xba, 0x62, 0x1f, 0xd3, 0x42, 0xc4, 0x41, 0x7e, 0x02, 0x20, 0xa6, 0x91, 0x5a,
0x7d, 0xc2, 0xae, 0x3a, 0x5f, 0x74, 0xc3, 0x93, 0x23, 0xce, 0x2b, 0x05, 0x83, 0xa1, 0xcf, 0xa1,
0x68, 0x7a, 0xc3, 0x91, 0x43, 0x95, 0x7e, 0xea, 0x75, 0xf4, 0x0b, 0x91, 0x8a, 0xc1, 0xe2, 0x1c,
0x28, 0x3d, 0xcb, 0x81, 0xfe, 0x24, 0x01, 0x85, 0x98, 0xc3, 0xb3, 0x54, 0xa8, 0x08, 0xb9, 0x5e,
0xbb, 0x66, 0x74, 0x1b, 0xcd, 0x47, 0x5a, 0x02, 0x01, 0x64, 0xc5, 0x00, 0xd6, 0xb4, 0x24, 0xa7,
0x6b, 0xd5, 0xd6, 0x7e, 0x7b, 0xaf, 0x2e, 0xc8, 0x10, 0xba, 0x01, 0x5a, 0x38, 0x84, 0xfd, 0x4e,
0xd7, 0xc0, 0x5c, 0x9a, 0x46, 0xd7, 0x61, 0x2d, 0x92, 0x2a, 0xcd, 0x0c, 0xba, 0x09, 0x28, 0x12,
0x4e, 0x4d, 0x64, 0xf5, 0x3f, 0x84, 0xb5, 0xaa, 0xe7, 0x32, 0x62, 0xbb, 0x11, 0x95, 0xdd, 0xe2,
0xfd, 0x56, 0xa2, 0xbe, 0x6d, 0xc9, 0x6c, 0xbb, 0xbd, 0x76, 0xf1, 0x62, 0xb3, 0x10, 0x41, 0x1b,
0x35, 0xde, 0xd3, 0xb0, 0x60, 0xf1, 0x35, 0x35, 0xb2, 0x2d, 0x95, 0x3c, 0x97, 0x2f, 0x5e, 0x6c,
0xa6, 0xda, 0x8d, 0x1a, 0xe6, 0x32, 0xf4, 0x26, 0xe4, 0xe9, 0x33, 0x9b, 0xf5, 0x4d, 0x9e, 0x5d,
0xf9, 0x18, 0x66, 0x70, 0x8e, 0x0b, 0xaa, 0x3c, 0x99, 0xfe, 0x51, 0x12, 0xa0, 0x4b, 0x82, 0x63,
0xd5, 0xf4, 0x43, 0xc8, 0x47, 0x87, 0xf8, 0xab, 0x0e, 0x93, 0xb1, 0xf9, 0x8a, 0xf0, 0xe8, 0xe3,
0x30, 0x62, 0x24, 0xc7, 0x5e, 0xac, 0xa8, 0xda, 0x5a, 0x44, 0x53, 0x67, 0x89, 0x34, 0xdf, 0x6b,
0xa8, 0xef, 0xab, 0x89, 0xe3, 0x9f, 0xa8, 0x2a, 0xf2, 0xad, 0xec, 0xb3, 0x62, 0x6e, 0x77, 0x16,
0x35, 0x32, 0x37, 0xa0, 0xbb, 0x4b, 0x78, 0xaa, 0xb7, 0xad, 0xc1, 0xaa, 0x3f, 0x76, 0xb9, 0xd7,
0xfd, 0x40, 0x54, 0xeb, 0x36, 0xbc, 0xd1, 0xa4, 0xec, 0xd4, 0xf3, 0x8f, 0x0d, 0xc6, 0x88, 0x79,
0xc4, 0x0f, 0xd5, 0x2a, 0xc9, 0x4c, 0x09, 0x67, 0x62, 0x86, 0x70, 0xae, 0xc3, 0x32, 0x71, 0x6c,
0x12, 0x50, 0xb9, 0x4b, 0xe7, 0x71, 0x58, 0xe4, 0xb4, 0x98, 0x58, 0x96, 0x4f, 0x83, 0x80, 0xca,
0x63, 0x60, 0x1e, 0x4f, 0x05, 0xfa, 0x3f, 0x27, 0x01, 0x1a, 0x6d, 0x63, 0x5f, 0x99, 0xaf, 0x41,
0xf6, 0x90, 0x0c, 0x6d, 0x67, 0x72, 0xd5, 0x22, 0x9b, 0xe2, 0x2b, 0x86, 0x34, 0xb4, 0x23, 0x74,
0xb0, 0xd2, 0x15, 0x6c, 0x79, 0x7c, 0xe0, 0x52, 0x16, 0xb1, 0x65, 0x51, 0xe2, 0x5b, 0xb3, 0x4f,
0xdc, 0x68, 0x60, 0x65, 0x81, 0xbb, 0x3e, 0x20, 0x8c, 0x9e, 0x92, 0x49, 0xb8, 0x26, 0x54, 0x11,
0xed, 0x72, 0x16, 0xcd, 0x0f, 0xf7, 0xd4, 0x5a, 0xcf, 0x08, 0xee, 0xf1, 0x2a, 0x7f, 0xb0, 0x82,
0x4b, 0xd2, 0x11, 0x69, 0x97, 0x1e, 0x8a, 0x9d, 0x72, 0x5a, 0xf5, 0xad, 0x0e, 0xb1, 0x1f, 0xc2,
0xca, 0x4c, 0x3f, 0x5f, 0x3a, 0xa6, 0x34, 0xda, 0x4f, 0x7e, 0xa8, 0xa5, 0xd5, 0xd7, 0x27, 0x5a,
0x56, 0xff, 0xdb, 0x14, 0x40, 0xdb, 0xf3, 0xc3, 0x49, 0x5b, 0x7c, 0x2d, 0x94, 0x13, 0x97, 0x4c,
0xa6, 0xe7, 0xa8, 0xf0, 0x5c, 0xc8, 0xd3, 0xa7, 0x56, 0x38, 0xed, 0x15, 0x70, 0x1c, 0x29, 0xa2,
0x4d, 0x28, 0xc8, 0xf9, 0xef, 0x8f, 0x3c, 0x5f, 0xe6, 0xa3, 0x15, 0x0c, 0x52, 0xc4, 0x35, 0xd1,
0x5d, 0x58, 0x1d, 0x8d, 0x0f, 0x1c, 0x3b, 0x38, 0xa2, 0x96, 0xc4, 0xa4, 0x05, 0x66, 0x25, 0x92,
0x0a, 0xd8, 0x3e, 0x14, 0x95, 0xa0, 0x2f, 0x28, 0x4f, 0x46, 0x38, 0x74, 0xff, 0x55, 0x0e, 0x49,
0x15, 0xc1, 0x84, 0x0a, 0xa3, 0x69, 0x41, 0xaf, 0x41, 0x2e, 0x74, 0x16, 0xad, 0x43, 0xaa, 0x5b,
0x6d, 0x6b, 0x4b, 0xa5, 0xb5, 0xb3, 0xf3, 0x72, 0x21, 0x14, 0x77, 0xab, 0x6d, 0x5e, 0xd3, 0xab,
0xb5, 0xb5, 0xc4, 0x6c, 0x4d, 0xaf, 0xd6, 0x2e, 0xa5, 0xf9, 0xa6, 0xab, 0x1f, 0x42, 0x21, 0xd6,
0x02, 0xba, 0x03, 0xcb, 0x8d, 0xe6, 0x23, 0x5c, 0xef, 0x74, 0xb4, 0xa5, 0xd2, 0xcd, 0xb3, 0xf3,
0x32, 0x8a, 0xd5, 0x36, 0xdc, 0x01, 0x9f, 0x1f, 0xf4, 0x16, 0xa4, 0x77, 0x5b, 0x9d, 0x6e, 0xc8,
0xb1, 0x62, 0x88, 0x5d, 0x2f, 0x60, 0xa5, 0xeb, 0x6a, 0x37, 0x8f, 0x1b, 0xd6, 0xff, 0x22, 0x01,
0x59, 0x49, 0x35, 0x17, 0x4e, 0x94, 0x01, 0xcb, 0xe1, 0x01, 0x48, 0xf2, 0xdf, 0x77, 0x2f, 0xe7,
0xaa, 0x15, 0x45, 0x2d, 0x65, 0xf8, 0x85, 0x7a, 0xa5, 0x4f, 0xa1, 0x18, 0xaf, 0xf8, 0x56, 0xc1,
0xf7, 0x07, 0x50, 0xe0, 0xf1, 0x1d, 0x72, 0xd6, 0x2d, 0xc8, 0x4a, 0x3a, 0xac, 0x92, 0xe1, 0x55,
0xc4, 0x59, 0x21, 0xd1, 0x03, 0x58, 0x96, 0x64, 0x3b, 0xbc, 0x06, 0xda, 0xb8, 0x7a, 0x15, 0xe1,
0x10, 0xae, 0x7f, 0x06, 0xe9, 0x36, 0xa5, 0x3e, 0x1f, 0x7b, 0xd7, 0xb3, 0xe8, 0x34, 0xf7, 0xab,
0x73, 0x82, 0x45, 0x1b, 0x35, 0x7e, 0x4e, 0xb0, 0x68, 0xc3, 0xe2, 0x83, 0xc7, 0xf3, 0x4a, 0x78,
0x13, 0xc6, 0xbf, 0xf5, 0x2e, 0x14, 0x9f, 0x52, 0x7b, 0x70, 0xc4, 0xa8, 0x25, 0x0c, 0xbd, 0x0f,
0xe9, 0x11, 0x8d, 0x9c, 0x5f, 0x5f, 0x18, 0x60, 0x94, 0xfa, 0x58, 0xa0, 0x78, 0x1e, 0x39, 0x15,
0xda, 0xea, 0xf2, 0x51, 0x95, 0xf4, 0x7f, 0x4a, 0xc2, 0x6a, 0x23, 0x08, 0xc6, 0xc4, 0x35, 0x43,
0x72, 0xf0, 0xd3, 0x59, 0x72, 0x70, 0x6f, 0x61, 0x0f, 0x67, 0x54, 0x66, 0x2f, 0x27, 0x54, 0x6e,
0x4f, 0x46, 0xb9, 0x5d, 0xff, 0xcf, 0x44, 0x78, 0x2b, 0x71, 0x37, 0xb6, 0xdc, 0x4b, 0xeb, 0x67,
0xe7, 0xe5, 0x1b, 0x71, 0x4b, 0xb4, 0xe7, 0x1e, 0xbb, 0xde, 0xa9, 0x8b, 0xde, 0x86, 0x0c, 0xae,
0x37, 0xeb, 0x4f, 0xb5, 0x84, 0x0c, 0xcf, 0x19, 0x10, 0xa6, 0x2e, 0x3d, 0xe5, 0x96, 0xda, 0xf5,
0x66, 0x8d, 0x6f, 0xe3, 0xc9, 0x05, 0x96, 0xda, 0xd4, 0xb5, 0x6c, 0x77, 0x80, 0xee, 0x40, 0xb6,
0xd1, 0xe9, 0xf4, 0xc4, 0xb9, 0xf1, 0x8d, 0xb3, 0xf3, 0xf2, 0xf5, 0x19, 0x14, 0x2f, 0x50, 0x8b,
0x83, 0x38, 0xaf, 0xe5, 0x1b, 0xfc, 0x02, 0x10, 0xa7, 0x5c, 0x12, 0x84, 0x5b, 0x5d, 0x7e, 0xa8,
0xcd, 0x2c, 0x00, 0x61, 0x8f, 0xff, 0xaa, 0xe5, 0xf6, 0xaf, 0x49, 0xd0, 0x0c, 0xd3, 0xa4, 0x23,
0xc6, 0xeb, 0xd5, 0x81, 0xa2, 0x0b, 0xb9, 0x11, 0xff, 0xb2, 0xc5, 0x01, 0x89, 0xc7, 0xce, 0x83,
0x85, 0xd7, 0xd7, 0x73, 0x7a, 0x15, 0xec, 0x39, 0xd4, 0xb0, 0x86, 0x76, 0x10, 0xf0, 0x83, 0xb3,
0x90, 0xe1, 0xc8, 0x52, 0xe9, 0xd7, 0x09, 0xb8, 0xbe, 0x00, 0x81, 0x3e, 0x84, 0xb4, 0xef, 0x39,
0xe1, 0x1c, 0xde, 0xbe, 0xec, 0x72, 0x89, 0xab, 0x62, 0x81, 0x44, 0x1b, 0x00, 0x64, 0xcc, 0x3c,
0x22, 0xda, 0x17, 0xb3, 0x97, 0xc3, 0x31, 0x09, 0x7a, 0x0a, 0xd9, 0x80, 0x9a, 0x3e, 0x0d, 0xb9,
0xda, 0x67, 0xff, 0x5f, 0xef, 0x2b, 0x1d, 0x61, 0x06, 0x2b, 0x73, 0xa5, 0x0a, 0x64, 0xa5, 0x84,
0x87, 0xbd, 0x45, 0x18, 0x11, 0x4e, 0x17, 0xb1, 0xf8, 0xe6, 0xd1, 0x44, 0x9c, 0x41, 0x18, 0x4d,
0xc4, 0x19, 0xe8, 0x3f, 0x4f, 0x02, 0xd4, 0x9f, 0x31, 0xea, 0xbb, 0xc4, 0xa9, 0x1a, 0xa8, 0x1e,
0xcb, 0xfe, 0xb2, 0xb7, 0xef, 0x2d, 0xbc, 0x72, 0x8c, 0x34, 0x2a, 0x55, 0x63, 0x41, 0xfe, 0xbf,
0x05, 0xa9, 0xb1, 0xef, 0xa8, 0xeb, 0x6b, 0x41, 0xb2, 0x7a, 0x78, 0x0f, 0x73, 0x19, 0xaa, 0x4f,
0xd3, 0x56, 0xea, 0xf2, 0x77, 0x87, 0x58, 0x03, 0xdf, 0x7d, 0xea, 0x7a, 0x1f, 0x60, 0xea, 0x35,
0xda, 0x80, 0x4c, 0x75, 0xa7, 0xd3, 0xd9, 0xd3, 0x96, 0x64, 0x6e, 0x9e, 0x56, 0x09, 0xb1, 0xfe,
0x37, 0x09, 0xc8, 0x55, 0x0d, 0xb5, 0x63, 0xee, 0x80, 0x26, 0x12, 0x8e, 0x49, 0x7d, 0xd6, 0xa7,
0xcf, 0x46, 0xb6, 0x3f, 0x51, 0x39, 0xe3, 0xea, 0x13, 0xca, 0x2a, 0xd7, 0xaa, 0x52, 0x9f, 0xd5,
0x85, 0x0e, 0xc2, 0x50, 0xa4, 0xaa, 0x8b, 0x7d, 0x93, 0x84, 0x19, 0x7c, 0xe3, 0xea, 0xa1, 0x90,
0xcc, 0x76, 0x5a, 0x0e, 0x70, 0x21, 0x34, 0x52, 0x25, 0x81, 0xfe, 0x04, 0xae, 0xb7, 0x7c, 0xf3,
0x88, 0x06, 0x4c, 0x36, 0xaa, 0x5c, 0xfe, 0x0c, 0x6e, 0x33, 0x12, 0x1c, 0xf7, 0x8f, 0xec, 0x80,
0x79, 0xfe, 0xa4, 0xef, 0x53, 0x46, 0x5d, 0x5e, 0xdf, 0x17, 0xaf, 0x1b, 0xea, 0x7e, 0xe1, 0x16,
0xc7, 0xec, 0x4a, 0x08, 0x0e, 0x11, 0x7b, 0x1c, 0xa0, 0x37, 0xa0, 0xc8, 0xc9, 0x68, 0x8d, 0x1e,
0x92, 0xb1, 0xc3, 0x02, 0xf4, 0x63, 0x00, 0xc7, 0x1b, 0xf4, 0x5f, 0x3b, 0xdd, 0xe7, 0x1d, 0x6f,
0x20, 0x3f, 0xf5, 0xdf, 0x01, 0xad, 0x66, 0x07, 0x23, 0xc2, 0xcc, 0xa3, 0xf0, 0xe2, 0x04, 0x3d,
0x02, 0xed, 0x88, 0x12, 0x9f, 0x1d, 0x50, 0xc2, 0xfa, 0x23, 0xea, 0xdb, 0x9e, 0xf5, 0x5a, 0x43,
0xba, 0x16, 0x69, 0xb5, 0x85, 0x92, 0xfe, 0xdf, 0x09, 0x00, 0x4c, 0x0e, 0x43, 0x72, 0xf3, 0x03,
0xb8, 0x16, 0xb8, 0x64, 0x14, 0x1c, 0x79, 0xac, 0x6f, 0xbb, 0x8c, 0xfa, 0x27, 0xc4, 0x51, 0x87,
0x5f, 0x2d, 0xac, 0x68, 0x28, 0x39, 0x7a, 0x1f, 0xd0, 0x31, 0xa5, 0xa3, 0xbe, 0xe7, 0x58, 0xfd,
0xb0, 0x52, 0x3e, 0xbf, 0xa4, 0xb1, 0xc6, 0x6b, 0x5a, 0x8e, 0xd5, 0x09, 0xe5, 0x68, 0x1b, 0x36,
0xf8, 0x08, 0x50, 0x97, 0xf9, 0x36, 0x0d, 0xfa, 0x87, 0x9e, 0xdf, 0x0f, 0x1c, 0xef, 0xb4, 0x7f,
0xe8, 0x39, 0x8e, 0x77, 0x4a, 0xfd, 0xf0, 0x6a, 0xa1, 0xe4, 0x78, 0x83, 0xba, 0x04, 0xed, 0x78,
0x7e, 0xc7, 0xf1, 0x4e, 0x77, 0x42, 0x04, 0x67, 0x40, 0xd3, 0x6e, 0x33, 0xdb, 0x3c, 0x0e, 0x19,
0x50, 0x24, 0xed, 0xda, 0xe6, 0x31, 0xba, 0x03, 0x2b, 0xd4, 0xa1, 0xe2, 0x80, 0x2a, 0x51, 0x19,
0x81, 0x2a, 0x86, 0x42, 0x0e, 0xd2, 0x7f, 0x0b, 0xf2, 0x6d, 0x87, 0x98, 0xe2, 0x91, 0x8b, 0x1f,
0xf7, 0x4d, 0xcf, 0xe5, 0x41, 0x60, 0xbb, 0x4c, 0x66, 0xc7, 0x3c, 0x8e, 0x8b, 0xf4, 0x9f, 0x02,
0xfc, 0xcc, 0xb3, 0xdd, 0xae, 0x77, 0x4c, 0x5d, 0xf1, 0x1e, 0xc0, 0x19, 0xbd, 0x9a, 0xca, 0x3c,
0x56, 0x25, 0x71, 0xde, 0x20, 0x2e, 0x19, 0x50, 0x3f, 0xba, 0x16, 0x97, 0x45, 0xfd, 0xeb, 0x04,
0x64, 0xb1, 0xe7, 0xb1, 0xaa, 0x81, 0xca, 0x90, 0x35, 0x49, 0x3f, 0x5c, 0x79, 0xc5, 0xed, 0xfc,
0xc5, 0x8b, 0xcd, 0x4c, 0xd5, 0x78, 0x4c, 0x27, 0x38, 0x63, 0x92, 0xc7, 0x74, 0xc2, 0xb7, 0x68,
0x93, 0x88, 0xf5, 0x22, 0xcc, 0x14, 0xe5, 0x16, 0x5d, 0x35, 0xf8, 0x62, 0xc0, 0x59, 0x93, 0xf0,
0x7f, 0xf4, 0x21, 0x14, 0x15, 0xa8, 0x7f, 0x44, 0x82, 0x23, 0xc9, 0xc3, 0xb7, 0x57, 0x2f, 0x5e,
0x6c, 0x82, 0x44, 0xee, 0x92, 0xe0, 0x08, 0x83, 0x44, 0xf3, 0x6f, 0x54, 0x87, 0xc2, 0x97, 0x9e,
0xed, 0xf6, 0x99, 0xe8, 0x84, 0xba, 0x25, 0x58, 0xb8, 0x7e, 0xa6, 0x5d, 0x55, 0x57, 0x17, 0xf0,
0x65, 0x24, 0xd1, 0xff, 0x25, 0x01, 0x05, 0x6e, 0xd3, 0x3e, 0xb4, 0x4d, 0xbe, 0xa5, 0x7e, 0xfb,
0x4c, 0x7f, 0x0b, 0x52, 0x66, 0xe0, 0xab, 0xbe, 0x89, 0x54, 0x57, 0xed, 0x60, 0xcc, 0x65, 0xe8,
0x73, 0xc8, 0xca, 0x83, 0x93, 0x4a, 0xf2, 0xfa, 0xab, 0x37, 0x7f, 0xe5, 0xa2, 0xd2, 0x13, 0x73,
0x39, 0xf5, 0x4e, 0xf4, 0xb2, 0x88, 0xe3, 0x22, 0x74, 0x13, 0x92, 0xa6, 0x2b, 0x82, 0x42, 0xbd,
0x13, 0x56, 0x9b, 0x38, 0x69, 0xba, 0xfa, 0x3f, 0x26, 0x60, 0xa5, 0xee, 0x9a, 0xfe, 0x44, 0x24,
0x49, 0x3e, 0x11, 0xb7, 0x21, 0x1f, 0x8c, 0x0f, 0x82, 0x49, 0xc0, 0xe8, 0x30, 0x7c, 0x86, 0x88,
0x04, 0xa8, 0x01, 0x79, 0xe2, 0x0c, 0x3c, 0xdf, 0x66, 0x47, 0x43, 0xc5, 0xfb, 0x17, 0x27, 0xe6,
0xb8, 0xcd, 0x8a, 0x11, 0xaa, 0xe0, 0xa9, 0x76, 0x98, 0x8a, 0x53, 0xc2, 0x59, 0x91, 0x8a, 0xdf,
0x86, 0xa2, 0x43, 0x86, 0x9c, 0xe6, 0xf7, 0xf9, 0x71, 0x52, 0xf4, 0x23, 0x8d, 0x0b, 0x4a, 0xc6,
0x8f, 0xc8, 0xba, 0x0e, 0xf9, 0xc8, 0x18, 0x5a, 0x83, 0x82, 0x51, 0xef, 0xf4, 0x3f, 0xda, 0x7a,
0xd0, 0x7f, 0x54, 0xdd, 0xd7, 0x96, 0x14, 0x13, 0xf8, 0xbb, 0x04, 0xac, 0xec, 0xcb, 0x18, 0x54,
0xec, 0xea, 0x0e, 0x2c, 0xfb, 0xe4, 0x90, 0x85, 0xfc, 0x2f, 0x2d, 0x83, 0x8b, 0x27, 0x01, 0xce,
0xff, 0x78, 0xd5, 0x62, 0xfe, 0x17, 0x7b, 0x04, 0x4b, 0x5d, 0xf9, 0x08, 0x96, 0xfe, 0x4e, 0x1e,
0xc1, 0xf4, 0x5f, 0x25, 0x60, 0x4d, 0x6d, 0xd4, 0xe1, 0xc3, 0x0f, 0x7a, 0x0f, 0xf2, 0x72, 0xcf,
0x9e, 0xb2, 0x57, 0xf1, 0x16, 0x23, 0x71, 0x8d, 0x1a, 0xce, 0xc9, 0xea, 0x86, 0x85, 0x7e, 0x12,
0xbb, 0xf1, 0xbd, 0x84, 0x43, 0xce, 0x59, 0xaf, 0x4c, 0xaf, 0x81, 0x2f, 0x7d, 0x0b, 0xda, 0x84,
0x82, 0x72, 0x40, 0x9c, 0x2d, 0xe4, 0x19, 0x17, 0xa4, 0xa8, 0x49, 0x86, 0x54, 0xbf, 0x0b, 0x69,
0x71, 0xc2, 0x01, 0xc8, 0x76, 0xbe, 0xe8, 0x74, 0xeb, 0xfb, 0xf2, 0x54, 0xb9, 0xd3, 0x10, 0x0f,
0x72, 0xcb, 0x90, 0xaa, 0x37, 0x9f, 0x68, 0x49, 0xbd, 0x05, 0x37, 0xb7, 0x1d, 0x62, 0x1e, 0x3b,
0x76, 0xc0, 0xa8, 0x15, 0x5f, 0x4d, 0x3f, 0x82, 0xec, 0xcc, 0x1e, 0xf9, 0x8a, 0x1b, 0x12, 0x05,
0xbe, 0xff, 0x0f, 0x29, 0xc8, 0x47, 0xd7, 0x1f, 0x7c, 0x81, 0x71, 0xf2, 0xba, 0x24, 0x2f, 0x41,
0x23, 0x79, 0x93, 0x9e, 0xa2, 0xb7, 0xa7, 0xb4, 0xf5, 0x73, 0x79, 0x85, 0x1a, 0x55, 0x87, 0x94,
0xf5, 0x1d, 0xc8, 0x19, 0x9d, 0x4e, 0xe3, 0x51, 0xb3, 0x5e, 0xd3, 0xbe, 0x4a, 0x94, 0xbe, 0x77,
0x76, 0x5e, 0xbe, 0x16, 0x81, 0x8c, 0x20, 0xb0, 0x07, 0x2e, 0xb5, 0x04, 0xaa, 0x5a, 0xad, 0xb7,
0xbb, 0xf5, 0x9a, 0xf6, 0x3c, 0x39, 0x8f, 0x12, 0x34, 0x4c, 0x3c, 0x87, 0xe4, 0xdb, 0xb8, 0xde,
0x36, 0x30, 0x6f, 0xf0, 0xab, 0xa4, 0x64, 0xd3, 0xd3, 0x16, 0x7d, 0x3a, 0x22, 0x3e, 0x6f, 0x73,
0x23, 0x7c, 0x16, 0x7c, 0x9e, 0x92, 0x57, 0xe6, 0xd3, 0xbb, 0x1c, 0x4a, 0xac, 0x09, 0x6f, 0x4d,
0xdc, 0x81, 0x09, 0x33, 0xa9, 0xb9, 0xd6, 0x3a, 0x8c, 0xf8, 0x8c, 0x5b, 0xd1, 0x61, 0x19, 0xf7,
0x9a, 0x4d, 0x0e, 0x7a, 0x9e, 0x9e, 0xeb, 0x1d, 0x1e, 0xbb, 0x2e, 0xc7, 0xdc, 0x85, 0x5c, 0x78,
0x45, 0xa6, 0x7d, 0x95, 0x9e, 0x73, 0xa8, 0x1a, 0xde, 0xef, 0x89, 0x06, 0x77, 0x7b, 0x5d, 0xf1,
0x6a, 0xf9, 0x3c, 0x33, 0xdf, 0xe0, 0xd1, 0x98, 0x59, 0xfc, 0x9c, 0x50, 0x8e, 0x88, 0xfb, 0x57,
0x19, 0x49, 0x85, 0x22, 0x8c, 0x62, 0xed, 0xef, 0x40, 0x0e, 0xd7, 0x7f, 0x26, 0x1f, 0x38, 0x9f,
0x67, 0xe7, 0xec, 0x60, 0xfa, 0x25, 0x35, 0x19, 0xb5, 0xa6, 0x2f, 0x02, 0x51, 0xd5, 0xfd, 0xdf,
0x85, 0x5c, 0x98, 0x36, 0xd1, 0x06, 0x64, 0x9f, 0xb6, 0xf0, 0xe3, 0x3a, 0xd6, 0x96, 0xe4, 0xe8,
0x84, 0x35, 0x4f, 0xe5, 0xbe, 0x53, 0x86, 0xe5, 0x7d, 0xa3, 0x69, 0x3c, 0xaa, 0xe3, 0xf0, 0xb4,
0x1c, 0x02, 0xd4, 0xda, 0x2f, 0x69, 0xaa, 0x81, 0xc8, 0xe6, 0xf6, 0xed, 0xaf, 0xbf, 0xd9, 0x58,
0xfa, 0xe5, 0x37, 0x1b, 0x4b, 0xbf, 0xfe, 0x66, 0x23, 0xf1, 0xfc, 0x62, 0x23, 0xf1, 0xf5, 0xc5,
0x46, 0xe2, 0x17, 0x17, 0x1b, 0x89, 0x7f, 0xbf, 0xd8, 0x48, 0x1c, 0x64, 0x05, 0x2f, 0xfd, 0xf8,
0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0xb4, 0x2d, 0x4d, 0x67, 0xa2, 0x23, 0x00, 0x00,
}

View file

@ -371,8 +371,7 @@ enum TaskState {
option (gogoproto.goproto_enum_prefix) = false;
option (gogoproto.enum_customname) = "TaskState";
NEW = 0 [(gogoproto.enumvalue_customname)="TaskStateNew"];
ALLOCATED = 64 [(gogoproto.enumvalue_customname)="TaskStateAllocated"]; // successful allocation of resources that the task needs
PENDING = 128 [(gogoproto.enumvalue_customname) = "TaskStatePending"]; // observed by scheduler but unassigned.
PENDING = 64 [(gogoproto.enumvalue_customname)="TaskStatePending"]; // waiting for scheduling decision
ASSIGNED = 192 [(gogoproto.enumvalue_customname)="TaskStateAssigned"];
ACCEPTED = 256 [(gogoproto.enumvalue_customname)="TaskStateAccepted"]; // task has been accepted by an agent.
PREPARING = 320 [(gogoproto.enumvalue_customname)="TaskStatePreparing"];
@ -506,6 +505,21 @@ message PortConfig {
UDP = 1 [(gogoproto.enumvalue_customname) = "ProtocolUDP"];
}
// PublishMode controls how ports are published on the swarm.
enum PublishMode {
option (gogoproto.enum_customname) = "PublishMode";
option (gogoproto.goproto_enum_prefix) = false;
// PublishModeIngress exposes the port across the cluster on all nodes.
INGRESS = 0 [(gogoproto.enumvalue_customname) = "PublishModeIngress"];
// PublishModeHost exposes the port on just the target host. If the
// published port is undefined, an ephemeral port will be allocated. If
// the published port is defined, the node will attempt to allocate it,
// erroring the task if it fails.
HOST = 1 [(gogoproto.enumvalue_customname) = "PublishModeHost"];
}
// Name for the port. If provided the port information can
// be queried using the name as in a DNS SRV query.
string name = 1;
@ -516,11 +530,13 @@ message PortConfig {
// The port which the application is exposing and is bound to.
uint32 target_port = 3;
// PublishedPort specifies the port on which the service is
// exposed. If specified, the port must be
// within the available range. If not specified, an available
// port is automatically assigned.
// PublishedPort specifies the port on which the service is exposed. If
// specified, the port must be within the available range. If not specified
// (value is zero), an available port is automatically assigned.
uint32 published_port = 4;
// PublishMode controls how the port is published.
PublishMode publish_mode = 5;
}
// Driver is a generic driver type to be used throughout the API. For now, a
@ -556,10 +572,17 @@ message IssuanceStatus {
option (gogoproto.goproto_enum_prefix) = false;
UNKNOWN = 0 [(gogoproto.enumvalue_customname) = "IssuanceStateUnknown"];
RENEW = 1 [(gogoproto.enumvalue_customname)="IssuanceStateRenew"]; // Certificate should be issued
PENDING = 2 [(gogoproto.enumvalue_customname)="IssuanceStatePending"]; // Certificate is pending acceptance
ISSUED = 3 [(gogoproto.enumvalue_customname)="IssuanceStateIssued"]; // successful completion certificate issuance
FAILED = 4 [(gogoproto.enumvalue_customname)="IssuanceStateFailed"]; // Certificate issuance failed
// A new certificate should be issued
RENEW = 1 [(gogoproto.enumvalue_customname)="IssuanceStateRenew"];
// Certificate is pending acceptance
PENDING = 2 [(gogoproto.enumvalue_customname)="IssuanceStatePending"];
// successful completion certificate issuance
ISSUED = 3 [(gogoproto.enumvalue_customname)="IssuanceStateIssued"];
// Certificate issuance failed
FAILED = 4 [(gogoproto.enumvalue_customname)="IssuanceStateFailed"];
// Signals workers to renew their certificate. From the CA's perspective
// this is equivalent to IssuanceStateIssued: a noop.
ROTATE = 5 [(gogoproto.enumvalue_customname)="IssuanceStateRotate"];
}
State state = 1;
@ -777,12 +800,10 @@ message SecretReference {
string secret_name = 4;
}
// RemovedNode is a record for a node that has been removed from the swarm.
message RemovedNode {
// ID is the ID of the removed node.
string id = 1 [(gogoproto.customname) = "ID"];
// BlacklistedCertificate is a record for a blacklisted certificate. It does not
// contain the certificate's CN, because these records are indexed by CN.
message BlacklistedCertificate {
// Expiry is the latest known expiration time of a certificate that
// was issued to this node.
Timestamp expiry = 2;
// was issued for the given CN.
Timestamp expiry = 1;
}

View file

@ -80,7 +80,7 @@ func certSubjectFromContext(ctx context.Context) (pkix.Name, error) {
// AuthorizeOrgAndRole takes in a context and a list of roles, and returns
// the Node ID of the node.
func AuthorizeOrgAndRole(ctx context.Context, org string, removedNodes []*api.RemovedNode, ou ...string) (string, error) {
func AuthorizeOrgAndRole(ctx context.Context, org string, blacklistedCerts map[string]*api.BlacklistedCertificate, ou ...string) (string, error) {
certSubj, err := certSubjectFromContext(ctx)
if err != nil {
return "", err
@ -88,7 +88,7 @@ func AuthorizeOrgAndRole(ctx context.Context, org string, removedNodes []*api.Re
// Check if the current certificate has an OU that authorizes
// access to this method
if intersectArrays(certSubj.OrganizationalUnit, ou) {
return authorizeOrg(certSubj, org, removedNodes)
return authorizeOrg(certSubj, org, blacklistedCerts)
}
return "", grpc.Errorf(codes.PermissionDenied, "Permission denied: remote certificate not part of OUs: %v", ou)
@ -96,11 +96,9 @@ func AuthorizeOrgAndRole(ctx context.Context, org string, removedNodes []*api.Re
// authorizeOrg takes in a certificate subject and an organization, and returns
// the Node ID of the node.
func authorizeOrg(certSubj pkix.Name, org string, removedNodes []*api.RemovedNode) (string, error) {
for _, removedNode := range removedNodes {
if removedNode.ID == certSubj.CommonName {
return "", grpc.Errorf(codes.PermissionDenied, "Permission denied: node %s was removed from swarm", certSubj.CommonName)
}
func authorizeOrg(certSubj pkix.Name, org string, blacklistedCerts map[string]*api.BlacklistedCertificate) (string, error) {
if _, ok := blacklistedCerts[certSubj.CommonName]; ok {
return "", grpc.Errorf(codes.PermissionDenied, "Permission denied: node %s was removed from swarm", certSubj.CommonName)
}
if len(certSubj.Organization) > 0 && certSubj.Organization[0] == org {
@ -114,9 +112,9 @@ func authorizeOrg(certSubj pkix.Name, org string, removedNodes []*api.RemovedNod
// been proxied by a manager, in which case the manager is authenticated and
// so is the certificate information that it forwarded. It returns the node ID
// of the original client.
func AuthorizeForwardedRoleAndOrg(ctx context.Context, authorizedRoles, forwarderRoles []string, org string, removedNodes []*api.RemovedNode) (string, error) {
func AuthorizeForwardedRoleAndOrg(ctx context.Context, authorizedRoles, forwarderRoles []string, org string, blacklistedCerts map[string]*api.BlacklistedCertificate) (string, error) {
if isForwardedRequest(ctx) {
_, err := AuthorizeOrgAndRole(ctx, org, removedNodes, forwarderRoles...)
_, err := AuthorizeOrgAndRole(ctx, org, blacklistedCerts, forwarderRoles...)
if err != nil {
return "", grpc.Errorf(codes.PermissionDenied, "Permission denied: unauthorized forwarder role: %v", err)
}
@ -142,7 +140,7 @@ func AuthorizeForwardedRoleAndOrg(ctx context.Context, authorizedRoles, forwarde
}
// There wasn't any node being forwarded, check if this is a direct call by the expected role
nodeID, err := AuthorizeOrgAndRole(ctx, org, removedNodes, authorizedRoles...)
nodeID, err := AuthorizeOrgAndRole(ctx, org, blacklistedCerts, authorizedRoles...)
if err == nil {
return nodeID, nil
}

View file

@ -168,9 +168,9 @@ func (s *Server) IssueNodeCertificate(ctx context.Context, request *api.IssueNod
defer s.doneTask()
var (
removedNodes []*api.RemovedNode
clusters []*api.Cluster
err error
blacklistedCerts map[string]*api.BlacklistedCertificate
clusters []*api.Cluster
err error
)
s.store.View(func(readTx store.ReadTx) {
@ -181,19 +181,19 @@ func (s *Server) IssueNodeCertificate(ctx context.Context, request *api.IssueNod
// Not having a cluster object yet means we can't check
// the blacklist.
if err == nil && len(clusters) == 1 {
removedNodes = clusters[0].RemovedNodes
blacklistedCerts = clusters[0].BlacklistedCertificates
}
// If the remote node is a worker (either forwarded by a manager, or calling directly),
// issue a renew worker certificate entry with the correct ID
nodeID, err := AuthorizeForwardedRoleAndOrg(ctx, []string{WorkerRole}, []string{ManagerRole}, s.securityConfig.ClientTLSCreds.Organization(), removedNodes)
nodeID, err := AuthorizeForwardedRoleAndOrg(ctx, []string{WorkerRole}, []string{ManagerRole}, s.securityConfig.ClientTLSCreds.Organization(), blacklistedCerts)
if err == nil {
return s.issueRenewCertificate(ctx, nodeID, request.CSR)
}
// If the remote node is a manager (either forwarded by another manager, or calling directly),
// issue a renew certificate entry with the correct ID
nodeID, err = AuthorizeForwardedRoleAndOrg(ctx, []string{ManagerRole}, []string{ManagerRole}, s.securityConfig.ClientTLSCreds.Organization(), removedNodes)
nodeID, err = AuthorizeForwardedRoleAndOrg(ctx, []string{ManagerRole}, []string{ManagerRole}, s.securityConfig.ClientTLSCreds.Organization(), blacklistedCerts)
if err == nil {
return s.issueRenewCertificate(ctx, nodeID, request.CSR)
}
@ -542,18 +542,20 @@ func (s *Server) updateCluster(ctx context.Context, cluster *api.Cluster) {
func (s *Server) evaluateAndSignNodeCert(ctx context.Context, node *api.Node) error {
// If the desired membership and actual state are in sync, there's
// nothing to do.
if node.Spec.Membership == api.NodeMembershipAccepted && node.Certificate.Status.State == api.IssuanceStateIssued {
certState := node.Certificate.Status.State
if node.Spec.Membership == api.NodeMembershipAccepted &&
(certState == api.IssuanceStateIssued || certState == api.IssuanceStateRotate) {
return nil
}
// If the certificate state is renew, then it is a server-sided accepted cert (cert renewals)
if node.Certificate.Status.State == api.IssuanceStateRenew {
if certState == api.IssuanceStateRenew {
return s.signNodeCert(ctx, node)
}
// Sign this certificate if a user explicitly changed it to Accepted, and
// the certificate is in pending state
if node.Spec.Membership == api.NodeMembershipAccepted && node.Certificate.Status.State == api.IssuanceStatePending {
if node.Spec.Membership == api.NodeMembershipAccepted && certState == api.IssuanceStatePending {
return s.signNodeCert(ctx, node)
}
@ -688,7 +690,8 @@ func (s *Server) reconcileNodeCertificates(ctx context.Context, nodes []*api.Nod
// A successfully issued certificate and a failed certificate are our current final states
func isFinalState(status api.IssuanceStatus) bool {
if status.State == api.IssuanceStateIssued || status.State == api.IssuanceStateFailed {
if status.State == api.IssuanceStateIssued || status.State == api.IssuanceStateFailed ||
status.State == api.IssuanceStateRotate {
return true
}

View file

@ -22,8 +22,12 @@ const (
ingressNetworkName = "ingress"
ingressSubnet = "10.255.0.0/16"
allocatedStatusMessage = "pending task scheduling"
)
var errNoChanges = errors.New("task unchanged")
func newIngressNetwork() *api.Network {
return &api.Network{
Spec: api.NetworkSpec{
@ -134,17 +138,13 @@ func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
if !na.IsAllocated(nc.ingressNetwork) {
if err := a.allocateNetwork(ctx, nc.ingressNetwork); err != nil {
log.G(ctx).WithError(err).Error("failed allocating ingress network during init")
}
// Update store after allocation
if err := a.store.Update(func(tx store.Tx) error {
if err := store.UpdateNetwork(tx, nc.ingressNetwork); err != nil {
return err
} else if _, err := a.store.Batch(func(batch *store.Batch) error {
if err := a.commitAllocatedNetwork(ctx, batch, nc.ingressNetwork); err != nil {
log.G(ctx).WithError(err).Error("failed committing allocation of ingress network during init")
}
return nil
}); err != nil {
return errors.Wrap(err, "failed to create ingress network")
log.G(ctx).WithError(err).Error("failed committing allocation of ingress network during init")
}
}
@ -157,6 +157,7 @@ func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
return errors.Wrap(err, "error listing all networks in store while trying to allocate during init")
}
var allocatedNetworks []*api.Network
for _, n := range networks {
if na.IsAllocated(n) {
continue
@ -164,7 +165,20 @@ func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
if err := a.allocateNetwork(ctx, n); err != nil {
log.G(ctx).WithError(err).Errorf("failed allocating network %s during init", n.ID)
continue
}
allocatedNetworks = append(allocatedNetworks, n)
}
if _, err := a.store.Batch(func(batch *store.Batch) error {
for _, n := range allocatedNetworks {
if err := a.commitAllocatedNetwork(ctx, batch, n); err != nil {
log.G(ctx).WithError(err).Errorf("failed committing allocation of network %s during init", n.ID)
}
}
return nil
}); err != nil {
log.G(ctx).WithError(err).Error("failed committing allocation of networks during init")
}
// Allocate nodes in the store so far before we process watched events.
@ -176,6 +190,7 @@ func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
return errors.Wrap(err, "error listing all nodes in store while trying to allocate during init")
}
var allocatedNodes []*api.Node
for _, node := range nodes {
if na.IsNodeAllocated(node) {
continue
@ -188,7 +203,21 @@ func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
node.Attachment.Network = nc.ingressNetwork.Copy()
if err := a.allocateNode(ctx, node); err != nil {
log.G(ctx).WithError(err).Errorf("Failed to allocate network resources for node %s during init", node.ID)
continue
}
allocatedNodes = append(allocatedNodes, node)
}
if _, err := a.store.Batch(func(batch *store.Batch) error {
for _, node := range allocatedNodes {
if err := a.commitAllocatedNode(ctx, batch, node); err != nil {
log.G(ctx).WithError(err).Errorf("Failed to commit allocation of network resources for node %s during init", node.ID)
}
}
return nil
}); err != nil {
log.G(ctx).WithError(err).Error("Failed to commit allocation of network resources for nodes during init")
}
// Allocate services in the store so far before we process watched events.
@ -200,6 +229,7 @@ func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
return errors.Wrap(err, "error listing all services in store while trying to allocate during init")
}
var allocatedServices []*api.Service
for _, s := range services {
if nc.nwkAllocator.IsServiceAllocated(s) {
continue
@ -207,11 +237,27 @@ func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
if err := a.allocateService(ctx, s); err != nil {
log.G(ctx).WithError(err).Errorf("failed allocating service %s during init", s.ID)
continue
}
allocatedServices = append(allocatedServices, s)
}
if _, err := a.store.Batch(func(batch *store.Batch) error {
for _, s := range allocatedServices {
if err := a.commitAllocatedService(ctx, batch, s); err != nil {
log.G(ctx).WithError(err).Errorf("failed committing allocation of service %s during init", s.ID)
}
}
return nil
}); err != nil {
log.G(ctx).WithError(err).Error("failed committing allocation of services during init")
}
// Allocate tasks in the store so far before we started watching.
var tasks []*api.Task
var (
tasks []*api.Task
allocatedTasks []*api.Task
)
a.store.View(func(tx store.ReadTx) {
tasks, err = store.FindTasks(tx, store.All)
})
@ -219,66 +265,56 @@ func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
return errors.Wrap(err, "error listing all tasks in store while trying to allocate during init")
}
if _, err := a.store.Batch(func(batch *store.Batch) error {
for _, t := range tasks {
if taskDead(t) {
continue
}
for _, t := range tasks {
if taskDead(t) {
continue
}
var s *api.Service
if t.ServiceID != "" {
a.store.View(func(tx store.ReadTx) {
s = store.GetService(tx, t.ServiceID)
})
}
// Populate network attachments in the task
// based on service spec.
a.taskCreateNetworkAttachments(t, s)
if taskReadyForNetworkVote(t, s, nc) {
if t.Status.State >= api.TaskStateAllocated {
continue
}
if a.taskAllocateVote(networkVoter, t.ID) {
// If the task is not attached to any network, network
// allocators job is done. Immediately cast a vote so
// that the task can be moved to ALLOCATED state as
// soon as possible.
if err := batch.Update(func(tx store.Tx) error {
storeT := store.GetTask(tx, t.ID)
if storeT == nil {
return fmt.Errorf("task %s not found while trying to update state", t.ID)
}
updateTaskStatus(storeT, api.TaskStateAllocated, "allocated")
if err := store.UpdateTask(tx, storeT); err != nil {
return errors.Wrapf(err, "failed updating state in store transaction for task %s", storeT.ID)
}
return nil
}); err != nil {
log.G(ctx).WithError(err).Error("error updating task network")
}
}
continue
}
err := batch.Update(func(tx store.Tx) error {
_, err := a.allocateTask(ctx, tx, t)
return err
var s *api.Service
if t.ServiceID != "" {
a.store.View(func(tx store.ReadTx) {
s = store.GetService(tx, t.ServiceID)
})
if err != nil {
log.G(ctx).WithError(err).Errorf("failed allocating task %s during init", t.ID)
nc.unallocatedTasks[t.ID] = t
}
// Populate network attachments in the task
// based on service spec.
a.taskCreateNetworkAttachments(t, s)
if taskReadyForNetworkVote(t, s, nc) {
if t.Status.State >= api.TaskStatePending {
continue
}
if a.taskAllocateVote(networkVoter, t.ID) {
// If the task is not attached to any network, network
// allocators job is done. Immediately cast a vote so
// that the task can be moved to ALLOCATED state as
// soon as possible.
allocatedTasks = append(allocatedTasks, t)
}
continue
}
err := a.allocateTask(ctx, t)
if err == nil {
allocatedTasks = append(allocatedTasks, t)
} else if err != errNoChanges {
log.G(ctx).WithError(err).Errorf("failed allocating task %s during init", t.ID)
nc.unallocatedTasks[t.ID] = t
}
}
if _, err := a.store.Batch(func(batch *store.Batch) error {
for _, t := range allocatedTasks {
if err := a.commitAllocatedTask(ctx, batch, t); err != nil {
log.G(ctx).WithError(err).Errorf("failed committing allocation of task %s during init", t.ID)
}
}
return nil
}); err != nil {
return err
log.G(ctx).WithError(err).Error("failed committing allocation of tasks during init")
}
return nil
@ -298,6 +334,12 @@ func (a *Allocator) doNetworkAlloc(ctx context.Context, ev events.Event) {
log.G(ctx).WithError(err).Errorf("Failed allocation for network %s", n.ID)
break
}
if _, err := a.store.Batch(func(batch *store.Batch) error {
return a.commitAllocatedNetwork(ctx, batch, n)
}); err != nil {
log.G(ctx).WithError(err).Errorf("Failed to commit allocation for network %s", n.ID)
}
case state.EventDeleteNetwork:
n := v.Network.Copy()
@ -319,6 +361,12 @@ func (a *Allocator) doNetworkAlloc(ctx context.Context, ev events.Event) {
log.G(ctx).WithError(err).Errorf("Failed allocation for service %s", s.ID)
break
}
if _, err := a.store.Batch(func(batch *store.Batch) error {
return a.commitAllocatedService(ctx, batch, s)
}); err != nil {
log.G(ctx).WithError(err).Errorf("Failed to commit allocation for service %s", s.ID)
}
case state.EventUpdateService:
s := v.Service.Copy()
@ -330,6 +378,12 @@ func (a *Allocator) doNetworkAlloc(ctx context.Context, ev events.Event) {
log.G(ctx).WithError(err).Errorf("Failed allocation during update of service %s", s.ID)
break
}
if _, err := a.store.Batch(func(batch *store.Batch) error {
return a.commitAllocatedService(ctx, batch, s)
}); err != nil {
log.G(ctx).WithError(err).Errorf("Failed to commit allocation during update for service %s", s.ID)
}
case state.EventDeleteService:
s := v.Service.Copy()
@ -387,6 +441,13 @@ func (a *Allocator) doNodeAlloc(ctx context.Context, ev events.Event) {
node.Attachment.Network = nc.ingressNetwork.Copy()
if err := a.allocateNode(ctx, node); err != nil {
log.G(ctx).WithError(err).Errorf("Failed to allocate network resources for node %s", node.ID)
return
}
if _, err := a.store.Batch(func(batch *store.Batch) error {
return a.commitAllocatedNode(ctx, batch, node)
}); err != nil {
log.G(ctx).WithError(err).Errorf("Failed to commit allocation of network resources for node %s", node.ID)
}
}
}
@ -503,7 +564,7 @@ func (a *Allocator) doTaskAlloc(ctx context.Context, ev events.Event) {
// If we are already in allocated state, there is
// absolutely nothing else to do.
if t.Status.State >= api.TaskStateAllocated {
if t.Status.State >= api.TaskStatePending {
delete(nc.unallocatedTasks, t.ID)
return
}
@ -537,31 +598,22 @@ func (a *Allocator) doTaskAlloc(ctx context.Context, ev events.Event) {
}
func (a *Allocator) allocateNode(ctx context.Context, node *api.Node) error {
nc := a.netCtx
return a.netCtx.nwkAllocator.AllocateNode(node)
}
if err := nc.nwkAllocator.AllocateNode(node); err != nil {
return err
}
func (a *Allocator) commitAllocatedNode(ctx context.Context, batch *store.Batch, node *api.Node) error {
if err := batch.Update(func(tx store.Tx) error {
err := store.UpdateNode(tx, node)
if err := a.store.Update(func(tx store.Tx) error {
for {
err := store.UpdateNode(tx, node)
if err != nil && err != store.ErrSequenceConflict {
return errors.Wrapf(err, "failed updating state in store transaction for node %s", node.ID)
}
if err == store.ErrSequenceConflict {
storeNode := store.GetNode(tx, node.ID)
storeNode.Attachment = node.Attachment.Copy()
node = storeNode
continue
}
break
if err == store.ErrSequenceConflict {
storeNode := store.GetNode(tx, node.ID)
storeNode.Attachment = node.Attachment.Copy()
err = store.UpdateNode(tx, storeNode)
}
return nil
return errors.Wrapf(err, "failed updating state in store transaction for node %s", node.ID)
}); err != nil {
if err := nc.nwkAllocator.DeallocateNode(node); err != nil {
if err := a.netCtx.nwkAllocator.DeallocateNode(node); err != nil {
log.G(ctx).WithError(err).Errorf("failed rolling back allocation of node %s", node.ID)
}
@ -628,27 +680,22 @@ func (a *Allocator) allocateService(ctx context.Context, s *api.Service) error {
}
}
}
return nil
}
if err := a.store.Update(func(tx store.Tx) error {
for {
err := store.UpdateService(tx, s)
func (a *Allocator) commitAllocatedService(ctx context.Context, batch *store.Batch, s *api.Service) error {
if err := batch.Update(func(tx store.Tx) error {
err := store.UpdateService(tx, s)
if err != nil && err != store.ErrSequenceConflict {
return errors.Wrapf(err, "failed updating state in store transaction for service %s", s.ID)
}
if err == store.ErrSequenceConflict {
storeService := store.GetService(tx, s.ID)
storeService.Endpoint = s.Endpoint
s = storeService
continue
}
break
if err == store.ErrSequenceConflict {
storeService := store.GetService(tx, s.ID)
storeService.Endpoint = s.Endpoint
err = store.UpdateService(tx, storeService)
}
return nil
return errors.Wrapf(err, "failed updating state in store transaction for service %s", s.ID)
}); err != nil {
if err := nc.nwkAllocator.ServiceDeallocate(s); err != nil {
if err := a.netCtx.nwkAllocator.ServiceDeallocate(s); err != nil {
log.G(ctx).WithError(err).Errorf("failed rolling back allocation of service %s", s.ID)
}
@ -666,13 +713,17 @@ func (a *Allocator) allocateNetwork(ctx context.Context, n *api.Network) error {
return errors.Wrapf(err, "failed during network allocation for network %s", n.ID)
}
if err := a.store.Update(func(tx store.Tx) error {
return nil
}
func (a *Allocator) commitAllocatedNetwork(ctx context.Context, batch *store.Batch, n *api.Network) error {
if err := batch.Update(func(tx store.Tx) error {
if err := store.UpdateNetwork(tx, n); err != nil {
return errors.Wrapf(err, "failed updating state in store transaction for network %s", n.ID)
}
return nil
}); err != nil {
if err := nc.nwkAllocator.Deallocate(n); err != nil {
if err := a.netCtx.nwkAllocator.Deallocate(n); err != nil {
log.G(ctx).WithError(err).Errorf("failed rolling back allocation of network %s", n.ID)
}
@ -682,15 +733,8 @@ func (a *Allocator) allocateNetwork(ctx context.Context, n *api.Network) error {
return nil
}
func (a *Allocator) allocateTask(ctx context.Context, tx store.Tx, t *api.Task) (*api.Task, error) {
func (a *Allocator) allocateTask(ctx context.Context, t *api.Task) (err error) {
taskUpdated := false
// Get the latest task state from the store before updating.
storeT := store.GetTask(tx, t.ID)
if storeT == nil {
return nil, fmt.Errorf("could not find task %s while trying to update network allocation", t.ID)
}
nc := a.netCtx
// We might be here even if a task allocation has already
@ -698,107 +742,180 @@ func (a *Allocator) allocateTask(ctx context.Context, tx store.Tx, t *api.Task)
// cases skip allocation and go straight ahead to updating the
// store.
if !nc.nwkAllocator.IsTaskAllocated(t) {
if t.ServiceID != "" {
s := store.GetService(tx, t.ServiceID)
if s == nil {
return nil, fmt.Errorf("could not find service %s", t.ServiceID)
a.store.View(func(tx store.ReadTx) {
if t.ServiceID != "" {
s := store.GetService(tx, t.ServiceID)
if s == nil {
err = fmt.Errorf("could not find service %s", t.ServiceID)
return
}
if !nc.nwkAllocator.IsServiceAllocated(s) {
err = fmt.Errorf("service %s to which this task %s belongs has pending allocations", s.ID, t.ID)
return
}
taskUpdateEndpoint(t, s.Endpoint)
}
if !nc.nwkAllocator.IsServiceAllocated(s) {
return nil, fmt.Errorf("service %s to which this task %s belongs has pending allocations", s.ID, t.ID)
for _, na := range t.Networks {
n := store.GetNetwork(tx, na.Network.ID)
if n == nil {
err = fmt.Errorf("failed to retrieve network %s while allocating task %s", na.Network.ID, t.ID)
return
}
if !nc.nwkAllocator.IsAllocated(n) {
err = fmt.Errorf("network %s attached to task %s not allocated yet", n.ID, t.ID)
return
}
na.Network = n
}
taskUpdateEndpoint(t, s.Endpoint)
}
for _, na := range t.Networks {
n := store.GetNetwork(tx, na.Network.ID)
if n == nil {
return nil, fmt.Errorf("failed to retrieve network %s while allocating task %s", na.Network.ID, t.ID)
if err = nc.nwkAllocator.AllocateTask(t); err != nil {
err = errors.Wrapf(err, "failed during networktask allocation for task %s", t.ID)
return
}
if !nc.nwkAllocator.IsAllocated(n) {
return nil, fmt.Errorf("network %s attached to task %s not allocated yet", n.ID, t.ID)
if nc.nwkAllocator.IsTaskAllocated(t) {
taskUpdated = true
}
na.Network = n
}
if err := nc.nwkAllocator.AllocateTask(t); err != nil {
return nil, errors.Wrapf(err, "failed during networktask allocation for task %s", t.ID)
}
if nc.nwkAllocator.IsTaskAllocated(t) {
taskUpdateNetworks(storeT, t.Networks)
taskUpdateEndpoint(storeT, t.Endpoint)
taskUpdated = true
})
if err != nil {
return err
}
}
// Update the network allocations and moving to
// ALLOCATED state on top of the latest store state.
// PENDING state on top of the latest store state.
if a.taskAllocateVote(networkVoter, t.ID) {
if storeT.Status.State < api.TaskStateAllocated {
updateTaskStatus(storeT, api.TaskStateAllocated, "allocated")
if t.Status.State < api.TaskStatePending {
updateTaskStatus(t, api.TaskStatePending, allocatedStatusMessage)
taskUpdated = true
}
}
if taskUpdated {
if err := store.UpdateTask(tx, storeT); err != nil {
return nil, errors.Wrapf(err, "failed updating state in store transaction for task %s", storeT.ID)
}
if !taskUpdated {
return errNoChanges
}
return storeT, nil
return nil
}
func (a *Allocator) commitAllocatedTask(ctx context.Context, batch *store.Batch, t *api.Task) error {
return batch.Update(func(tx store.Tx) error {
err := store.UpdateTask(tx, t)
if err == store.ErrSequenceConflict {
storeTask := store.GetTask(tx, t.ID)
taskUpdateNetworks(storeTask, t.Networks)
taskUpdateEndpoint(storeTask, t.Endpoint)
if storeTask.Status.State < api.TaskStatePending {
storeTask.Status = t.Status
}
err = store.UpdateTask(tx, storeTask)
}
return errors.Wrapf(err, "failed updating state in store transaction for task %s", t.ID)
})
}
func (a *Allocator) procUnallocatedNetworks(ctx context.Context) {
nc := a.netCtx
var allocatedNetworks []*api.Network
for _, n := range nc.unallocatedNetworks {
if !nc.nwkAllocator.IsAllocated(n) {
if err := a.allocateNetwork(ctx, n); err != nil {
log.G(ctx).Debugf("Failed allocation of unallocated network %s: %v", n.ID, err)
log.G(ctx).WithError(err).Debugf("Failed allocation of unallocated network %s", n.ID)
continue
}
allocatedNetworks = append(allocatedNetworks, n)
}
}
if len(allocatedNetworks) == 0 {
return
}
committed, err := a.store.Batch(func(batch *store.Batch) error {
for _, n := range allocatedNetworks {
if err := a.commitAllocatedNetwork(ctx, batch, n); err != nil {
log.G(ctx).WithError(err).Debugf("Failed to commit allocation of unallocated network %s", n.ID)
continue
}
}
return nil
})
if err != nil {
log.G(ctx).WithError(err).Error("Failed to commit allocation of unallocated networks")
}
for _, n := range allocatedNetworks[:committed] {
delete(nc.unallocatedNetworks, n.ID)
}
}
func (a *Allocator) procUnallocatedServices(ctx context.Context) {
nc := a.netCtx
var allocatedServices []*api.Service
for _, s := range nc.unallocatedServices {
if !nc.nwkAllocator.IsServiceAllocated(s) {
if err := a.allocateService(ctx, s); err != nil {
log.G(ctx).Debugf("Failed allocation of unallocated service %s: %v", s.ID, err)
log.G(ctx).WithError(err).Debugf("Failed allocation of unallocated service %s", s.ID)
continue
}
allocatedServices = append(allocatedServices, s)
}
}
if len(allocatedServices) == 0 {
return
}
committed, err := a.store.Batch(func(batch *store.Batch) error {
for _, s := range allocatedServices {
if err := a.commitAllocatedService(ctx, batch, s); err != nil {
log.G(ctx).WithError(err).Debugf("Failed to commit allocation of unallocated service %s", s.ID)
continue
}
}
return nil
})
if err != nil {
log.G(ctx).WithError(err).Error("Failed to commit allocation of unallocated services")
}
for _, s := range allocatedServices[:committed] {
delete(nc.unallocatedServices, s.ID)
}
}
func (a *Allocator) procUnallocatedTasksNetwork(ctx context.Context) {
nc := a.netCtx
tasks := make([]*api.Task, 0, len(nc.unallocatedTasks))
allocatedTasks := make([]*api.Task, 0, len(nc.unallocatedTasks))
for _, t := range nc.unallocatedTasks {
if err := a.allocateTask(ctx, t); err == nil {
allocatedTasks = append(allocatedTasks, t)
} else if err != errNoChanges {
log.G(ctx).WithError(err).Error("task allocation failure")
}
}
if len(allocatedTasks) == 0 {
return
}
committed, err := a.store.Batch(func(batch *store.Batch) error {
for _, t := range nc.unallocatedTasks {
var allocatedT *api.Task
err := batch.Update(func(tx store.Tx) error {
var err error
allocatedT, err = a.allocateTask(ctx, tx, t)
return err
})
for _, t := range allocatedTasks {
err := a.commitAllocatedTask(ctx, batch, t)
if err != nil {
log.G(ctx).WithError(err).Error("task allocation failure")
log.G(ctx).WithError(err).Error("task allocation commit failure")
continue
}
tasks = append(tasks, allocatedT)
}
return nil
@ -808,53 +925,8 @@ func (a *Allocator) procUnallocatedTasksNetwork(ctx context.Context) {
log.G(ctx).WithError(err).Error("failed a store batch operation while processing unallocated tasks")
}
var retryCnt int
for len(tasks) != 0 {
var err error
for _, t := range tasks[:committed] {
delete(nc.unallocatedTasks, t.ID)
}
tasks = tasks[committed:]
if len(tasks) == 0 {
break
}
updatedTasks := make([]*api.Task, 0, len(tasks))
committed, err = a.store.Batch(func(batch *store.Batch) error {
for _, t := range tasks {
err := batch.Update(func(tx store.Tx) error {
return store.UpdateTask(tx, t)
})
if err != nil {
log.G(ctx).WithError(err).Error("allocated task store update failure")
continue
}
updatedTasks = append(updatedTasks, t)
}
return nil
})
if err != nil {
log.G(ctx).WithError(err).Error("failed a store batch operation while processing unallocated tasks")
}
tasks = updatedTasks
select {
case <-ctx.Done():
return
default:
}
retryCnt++
if retryCnt >= 3 {
log.G(ctx).Error("failed to complete batch update of allocated tasks after 3 retries")
break
}
for _, t := range allocatedTasks[:committed] {
delete(nc.unallocatedTasks, t.ID)
}
}

View file

@ -125,6 +125,26 @@ func NodeMatches(constraints []Constraint, n *api.Node) bool {
if !constraint.Match(n.Spec.Role.String()) {
return false
}
case strings.EqualFold(constraint.key, "node.platform.os"):
if n.Description == nil || n.Description.Platform == nil {
if !constraint.Match("") {
return false
}
continue
}
if !constraint.Match(n.Description.Platform.OS) {
return false
}
case strings.EqualFold(constraint.key, "node.platform.arch"):
if n.Description == nil || n.Description.Platform == nil {
if !constraint.Match("") {
return false
}
continue
}
if !constraint.Match(n.Description.Platform.Architecture) {
return false
}
// node labels constraint in form like 'node.labels.key==value'
case len(constraint.key) > len(nodeLabelPrefix) && strings.EqualFold(constraint.key[:len(nodeLabelPrefix)], nodeLabelPrefix):

View file

@ -2,6 +2,7 @@ package controlapi
import (
"strings"
"time"
"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/ca"
@ -12,6 +13,12 @@ import (
"google.golang.org/grpc/codes"
)
const (
// expiredCertGrace is the amount of time to keep a node in the
// blacklist beyond its certificate expiration timestamp.
expiredCertGrace = 24 * time.Hour * 7
)
func validateClusterSpec(spec *api.ClusterSpec) error {
if spec == nil {
return grpc.Errorf(codes.InvalidArgument, errInvalidArgument.Error())
@ -98,6 +105,8 @@ func (s *Server) UpdateCluster(ctx context.Context, request *api.UpdateClusterRe
cluster.Meta.Version = *request.ClusterVersion
cluster.Spec = *request.Spec.Copy()
expireBlacklistedCerts(cluster)
if request.Rotation.RotateWorkerToken {
cluster.RootCA.JoinTokens.Worker = ca.GenerateJoinToken(s.rootCA)
}
@ -202,7 +211,7 @@ func redactClusters(clusters []*api.Cluster) []*api.Cluster {
CACertHash: cluster.RootCA.CACertHash,
JoinTokens: cluster.RootCA.JoinTokens,
},
RemovedNodes: cluster.RemovedNodes,
BlacklistedCertificates: cluster.BlacklistedCertificates,
}
redactedClusters = append(redactedClusters, newCluster)
@ -210,3 +219,18 @@ func redactClusters(clusters []*api.Cluster) []*api.Cluster {
return redactedClusters
}
func expireBlacklistedCerts(cluster *api.Cluster) {
nowMinusGrace := time.Now().Add(-expiredCertGrace)
for cn, blacklistedCert := range cluster.BlacklistedCertificates {
if blacklistedCert.Expiry == nil {
continue
}
expiry, err := ptypes.Timestamp(blacklistedCert.Expiry)
if err == nil && nowMinusGrace.After(expiry) {
delete(cluster.BlacklistedCertificates, cn)
}
}
}

View file

@ -301,7 +301,7 @@ func (s *Server) RemoveNode(ctx context.Context, request *api.RemoveNodeRequest)
}
cluster := clusters[0]
removedNode := &api.RemovedNode{ID: node.ID}
blacklistedCert := &api.BlacklistedCertificate{}
// Set an expiry time for this RemovedNode if a certificate
// exists and can be parsed.
@ -312,13 +312,18 @@ func (s *Server) RemoveNode(ctx context.Context, request *api.RemoveNodeRequest)
if err == nil && !X509Cert.NotAfter.IsZero() {
expiry, err := ptypes.TimestampProto(X509Cert.NotAfter)
if err == nil {
removedNode.Expiry = expiry
blacklistedCert.Expiry = expiry
}
}
}
}
cluster.RemovedNodes = append(cluster.RemovedNodes, removedNode)
if cluster.BlacklistedCertificates == nil {
cluster.BlacklistedCertificates = make(map[string]*api.BlacklistedCertificate)
}
cluster.BlacklistedCertificates[node.ID] = blacklistedCert
expireBlacklistedCerts(cluster)
if err := store.UpdateCluster(tx, cluster); err != nil {
return err

View file

@ -48,9 +48,50 @@ func (s *Server) GetSecret(ctx context.Context, request *api.GetSecretRequest) (
return nil, grpc.Errorf(codes.NotFound, "secret %s not found", request.SecretID)
}
secret.Spec.Data = nil // clean the actual secret data so it's never returned
return &api.GetSecretResponse{Secret: secret}, nil
}
// UpdateSecret updates a Secret referenced by SecretID with the given SecretSpec.
// - Returns `NotFound` if the Secret is not found.
// - Returns `InvalidArgument` if the SecretSpec is malformed or anything other than Labels is changed
// - Returns an error if the update fails.
func (s *Server) UpdateSecret(ctx context.Context, request *api.UpdateSecretRequest) (*api.UpdateSecretResponse, error) {
if request.SecretID == "" || request.SecretVersion == nil {
return nil, grpc.Errorf(codes.InvalidArgument, errInvalidArgument.Error())
}
var secret *api.Secret
err := s.store.Update(func(tx store.Tx) error {
secret = store.GetSecret(tx, request.SecretID)
if secret == nil {
return nil
}
if secret.Spec.Annotations.Name != request.Spec.Annotations.Name || request.Spec.Data != nil {
return grpc.Errorf(codes.InvalidArgument, "only updates to Labels are allowed")
}
// We only allow updating Labels
secret.Meta.Version = *request.SecretVersion
secret.Spec.Annotations.Labels = request.Spec.Annotations.Labels
return store.UpdateSecret(tx, secret)
})
if err != nil {
return nil, err
}
if secret == nil {
return nil, grpc.Errorf(codes.NotFound, "secret %s not found", request.SecretID)
}
// WARN: we should never return the actual secret data here. We need to redact the private fields first.
secret.Spec.Data = nil
return &api.UpdateSecretResponse{
Secret: secret,
}, nil
}
// ListSecrets returns a `ListSecretResponse` with a list all non-internal `Secret`s being
// managed, or all secrets matching any name in `ListSecretsRequest.Names`, any
// name prefix in `ListSecretsRequest.NamePrefixes`, any id in

View file

@ -3,6 +3,7 @@ package controlapi
import (
"errors"
"reflect"
"regexp"
"strconv"
"github.com/docker/distribution/reference"
@ -18,9 +19,13 @@ import (
var (
errNetworkUpdateNotSupported = errors.New("changing network in service is not supported")
errRenameNotSupported = errors.New("renaming services is not supported")
errModeChangeNotAllowed = errors.New("service mode change is not allowed")
)
// Regexp pattern for hostname to conform RFC 1123
var hostnamePattern = regexp.MustCompile("^(([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])\\.)*([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])$")
func validateResources(r *api.Resources) error {
if r == nil {
return nil
@ -102,6 +107,43 @@ func validateUpdate(uc *api.UpdateConfig) error {
return nil
}
func validateContainerSpec(container *api.ContainerSpec) error {
if container == nil {
return grpc.Errorf(codes.InvalidArgument, "ContainerSpec: missing in service spec")
}
if err := validateHostname(container.Hostname); err != nil {
return err
}
if container.Image == "" {
return grpc.Errorf(codes.InvalidArgument, "ContainerSpec: image reference must be provided")
}
if _, err := reference.ParseNamed(container.Image); err != nil {
return grpc.Errorf(codes.InvalidArgument, "ContainerSpec: %q is not a valid repository/tag", container.Image)
}
mountMap := make(map[string]bool)
for _, mount := range container.Mounts {
if _, exists := mountMap[mount.Target]; exists {
return grpc.Errorf(codes.InvalidArgument, "ContainerSpec: duplicate mount point: %s", mount.Target)
}
mountMap[mount.Target] = true
}
return nil
}
func validateHostname(hostname string) error {
if hostname != "" {
if len(hostname) > 63 || !hostnamePattern.MatchString(hostname) {
return grpc.Errorf(codes.InvalidArgument, "ContainerSpec: %s is not valid hostname", hostname)
}
}
return nil
}
func validateTask(taskSpec api.TaskSpec) error {
if err := validateResourceRequirements(taskSpec.Resources); err != nil {
return err
@ -124,25 +166,8 @@ func validateTask(taskSpec api.TaskSpec) error {
return grpc.Errorf(codes.Unimplemented, "RuntimeSpec: unimplemented runtime in service spec")
}
container := taskSpec.GetContainer()
if container == nil {
return grpc.Errorf(codes.InvalidArgument, "ContainerSpec: missing in service spec")
}
if container.Image == "" {
return grpc.Errorf(codes.InvalidArgument, "ContainerSpec: image reference must be provided")
}
if _, err := reference.ParseNamed(container.Image); err != nil {
return grpc.Errorf(codes.InvalidArgument, "ContainerSpec: %q is not a valid repository/tag", container.Image)
}
mountMap := make(map[string]bool)
for _, mount := range container.Mounts {
if _, exists := mountMap[mount.Target]; exists {
return grpc.Errorf(codes.InvalidArgument, "ContainerSpec: duplicate mount point: %s", mount.Target)
}
mountMap[mount.Target] = true
if err := validateContainerSpec(taskSpec.GetContainer()); err != nil {
return err
}
return nil
@ -279,6 +304,25 @@ func (s *Server) checkPortConflicts(spec *api.ServiceSpec, serviceID string) err
return nil
}
// checkSecretConflicts finds if the passed in spec has secrets with conflicting targets.
func (s *Server) checkSecretConflicts(spec *api.ServiceSpec) error {
container := spec.Task.GetContainer()
if container == nil {
return nil
}
existingTargets := make(map[string]string)
for _, secretRef := range container.Secrets {
if prevSecretName, ok := existingTargets[secretRef.Target]; ok {
return grpc.Errorf(codes.InvalidArgument, "secret references '%s' and '%s' have a conflicting target: '%s'", prevSecretName, secretRef.SecretName, secretRef.Target)
}
existingTargets[secretRef.Target] = secretRef.SecretName
}
return nil
}
// CreateService creates and return a Service based on the provided ServiceSpec.
// - Returns `InvalidArgument` if the ServiceSpec is malformed.
// - Returns `Unimplemented` if the ServiceSpec references unimplemented features.
@ -297,6 +341,10 @@ func (s *Server) CreateService(ctx context.Context, request *api.CreateServiceRe
return nil, err
}
if err := s.checkSecretConflicts(request.Spec); err != nil {
return nil, err
}
// TODO(aluzzardi): Consider using `Name` as a primary key to handle
// duplicate creations. See #65
service := &api.Service{
@ -364,6 +412,10 @@ func (s *Server) UpdateService(ctx context.Context, request *api.UpdateServiceRe
}
}
if err := s.checkSecretConflicts(request.Spec); err != nil {
return nil, err
}
err := s.store.Update(func(tx store.Tx) error {
service = store.GetService(tx, request.ServiceID)
if service == nil {
@ -390,6 +442,11 @@ func (s *Server) UpdateService(ctx context.Context, request *api.UpdateServiceRe
if reflect.TypeOf(service.Spec.Mode) != reflect.TypeOf(request.Spec.Mode) {
return errModeChangeNotAllowed
}
if service.Spec.Annotations.Name != request.Spec.Annotations.Name {
return errRenameNotSupported
}
service.Meta.Version = *request.ServiceVersion
service.PreviousSpec = service.Spec.Copy()
service.Spec = *request.Spec.Copy()

View file

@ -2,6 +2,7 @@ package controlapi
import (
"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/api/naming"
"github.com/docker/swarmkit/manager/state/store"
"golang.org/x/net/context"
"google.golang.org/grpc"
@ -104,10 +105,10 @@ func (s *Server) ListTasks(ctx context.Context, request *api.ListTasksRequest) (
if request.Filters != nil {
tasks = filterTasks(tasks,
func(e *api.Task) bool {
return filterContains(store.TaskName(e), request.Filters.Names)
return filterContains(naming.Task(e), request.Filters.Names)
},
func(e *api.Task) bool {
return filterContainsPrefix(store.TaskName(e), request.Filters.NamePrefixes)
return filterContainsPrefix(naming.Task(e), request.Filters.NamePrefixes)
},
func(e *api.Task) bool {
return filterContainsPrefix(e.ID, request.Filters.IDPrefixes)

View file

@ -21,7 +21,10 @@ import (
"github.com/docker/swarmkit/manager/dispatcher"
"github.com/docker/swarmkit/manager/health"
"github.com/docker/swarmkit/manager/keymanager"
"github.com/docker/swarmkit/manager/orchestrator"
"github.com/docker/swarmkit/manager/orchestrator/constraintenforcer"
"github.com/docker/swarmkit/manager/orchestrator/global"
"github.com/docker/swarmkit/manager/orchestrator/replicated"
"github.com/docker/swarmkit/manager/orchestrator/taskreaper"
"github.com/docker/swarmkit/manager/resourceapi"
"github.com/docker/swarmkit/manager/scheduler"
"github.com/docker/swarmkit/manager/state/raft"
@ -82,10 +85,10 @@ type Manager struct {
caserver *ca.Server
dispatcher *dispatcher.Dispatcher
replicatedOrchestrator *orchestrator.ReplicatedOrchestrator
globalOrchestrator *orchestrator.GlobalOrchestrator
taskReaper *orchestrator.TaskReaper
constraintEnforcer *orchestrator.ConstraintEnforcer
replicatedOrchestrator *replicated.Orchestrator
globalOrchestrator *global.Orchestrator
taskReaper *taskreaper.TaskReaper
constraintEnforcer *constraintenforcer.ConstraintEnforcer
scheduler *scheduler.Scheduler
allocator *allocator.Allocator
keyManager *keymanager.KeyManager
@ -263,9 +266,9 @@ func (m *Manager) Run(parent context.Context) error {
authorize := func(ctx context.Context, roles []string) error {
var (
removedNodes []*api.RemovedNode
clusters []*api.Cluster
err error
blacklistedCerts map[string]*api.BlacklistedCertificate
clusters []*api.Cluster
err error
)
m.raftNode.MemoryStore().View(func(readTx store.ReadTx) {
@ -276,11 +279,11 @@ func (m *Manager) Run(parent context.Context) error {
// Not having a cluster object yet means we can't check
// the blacklist.
if err == nil && len(clusters) == 1 {
removedNodes = clusters[0].RemovedNodes
blacklistedCerts = clusters[0].BlacklistedCertificates
}
// Authorize the remote roles, ensure they can only be forwarded by managers
_, err = ca.AuthorizeForwardedRoleAndOrg(ctx, roles, []string{ca.ManagerRole}, m.config.SecurityConfig.ClientTLSCreds.Organization(), removedNodes)
_, err = ca.AuthorizeForwardedRoleAndOrg(ctx, roles, []string{ca.ManagerRole}, m.config.SecurityConfig.ClientTLSCreds.Organization(), blacklistedCerts)
return err
}
@ -651,10 +654,10 @@ func (m *Manager) becomeLeader(ctx context.Context) {
log.G(ctx).WithError(err).Error("root key-encrypting-key rotation failed")
}
m.replicatedOrchestrator = orchestrator.NewReplicatedOrchestrator(s)
m.constraintEnforcer = orchestrator.NewConstraintEnforcer(s)
m.globalOrchestrator = orchestrator.NewGlobalOrchestrator(s)
m.taskReaper = orchestrator.NewTaskReaper(s)
m.replicatedOrchestrator = replicated.NewReplicatedOrchestrator(s)
m.constraintEnforcer = constraintenforcer.New(s)
m.globalOrchestrator = global.NewGlobalOrchestrator(s)
m.taskReaper = taskreaper.New(s)
m.scheduler = scheduler.New(s)
m.keyManager = keymanager.New(s, keymanager.DefaultConfig())
@ -706,21 +709,21 @@ func (m *Manager) becomeLeader(ctx context.Context) {
}
}(m.scheduler)
go func(constraintEnforcer *orchestrator.ConstraintEnforcer) {
go func(constraintEnforcer *constraintenforcer.ConstraintEnforcer) {
constraintEnforcer.Run()
}(m.constraintEnforcer)
go func(taskReaper *orchestrator.TaskReaper) {
go func(taskReaper *taskreaper.TaskReaper) {
taskReaper.Run()
}(m.taskReaper)
go func(orchestrator *orchestrator.ReplicatedOrchestrator) {
go func(orchestrator *replicated.Orchestrator) {
if err := orchestrator.Run(ctx); err != nil {
log.G(ctx).WithError(err).Error("replicated orchestrator exited with an error")
}
}(m.replicatedOrchestrator)
go func(globalOrchestrator *orchestrator.GlobalOrchestrator) {
go func(globalOrchestrator *global.Orchestrator) {
if err := globalOrchestrator.Run(ctx); err != nil {
log.G(ctx).WithError(err).Error("global orchestrator exited with an error")
}

View file

@ -1,4 +1,4 @@
package orchestrator
package constraintenforcer
import (
"github.com/docker/swarmkit/api"
@ -16,8 +16,8 @@ type ConstraintEnforcer struct {
doneChan chan struct{}
}
// NewConstraintEnforcer creates a new ConstraintEnforcer.
func NewConstraintEnforcer(store *store.MemoryStore) *ConstraintEnforcer {
// New creates a new ConstraintEnforcer.
func New(store *store.MemoryStore) *ConstraintEnforcer {
return &ConstraintEnforcer{
store: store,
stopChan: make(chan struct{}),

View file

@ -1,9 +1,12 @@
package orchestrator
package global
import (
"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/log"
"github.com/docker/swarmkit/manager/constraint"
"github.com/docker/swarmkit/manager/orchestrator"
"github.com/docker/swarmkit/manager/orchestrator/restart"
"github.com/docker/swarmkit/manager/orchestrator/update"
"github.com/docker/swarmkit/manager/state"
"github.com/docker/swarmkit/manager/state/store"
"golang.org/x/net/context"
@ -16,9 +19,9 @@ type globalService struct {
constraints []constraint.Constraint
}
// GlobalOrchestrator runs a reconciliation loop to create and destroy
// tasks as necessary for global services.
type GlobalOrchestrator struct {
// Orchestrator runs a reconciliation loop to create and destroy tasks as
// necessary for global services.
type Orchestrator struct {
store *store.MemoryStore
// nodes is the set of non-drained nodes in the cluster, indexed by node ID
nodes map[string]*api.Node
@ -30,17 +33,17 @@ type GlobalOrchestrator struct {
// doneChan is closed when the state machine terminates.
doneChan chan struct{}
updater *UpdateSupervisor
restarts *RestartSupervisor
updater *update.Supervisor
restarts *restart.Supervisor
cluster *api.Cluster // local instance of the cluster
}
// NewGlobalOrchestrator creates a new GlobalOrchestrator
func NewGlobalOrchestrator(store *store.MemoryStore) *GlobalOrchestrator {
restartSupervisor := NewRestartSupervisor(store)
updater := NewUpdateSupervisor(store, restartSupervisor)
return &GlobalOrchestrator{
// NewGlobalOrchestrator creates a new global Orchestrator
func NewGlobalOrchestrator(store *store.MemoryStore) *Orchestrator {
restartSupervisor := restart.NewSupervisor(store)
updater := update.NewSupervisor(store, restartSupervisor)
return &Orchestrator{
store: store,
nodes: make(map[string]*api.Node),
globalServices: make(map[string]globalService),
@ -51,8 +54,8 @@ func NewGlobalOrchestrator(store *store.MemoryStore) *GlobalOrchestrator {
}
}
// Run contains the GlobalOrchestrator event loop
func (g *GlobalOrchestrator) Run(ctx context.Context) error {
// Run contains the global orchestrator event loop
func (g *Orchestrator) Run(ctx context.Context) error {
defer close(g.doneChan)
// Watch changes to services and tasks
@ -98,7 +101,7 @@ func (g *GlobalOrchestrator) Run(ctx context.Context) error {
var reconcileServiceIDs []string
for _, s := range existingServices {
if isGlobalService(s) {
if orchestrator.IsGlobalService(s) {
g.updateService(s)
reconcileServiceIDs = append(reconcileServiceIDs, s.ID)
}
@ -113,22 +116,22 @@ func (g *GlobalOrchestrator) Run(ctx context.Context) error {
case state.EventUpdateCluster:
g.cluster = v.Cluster
case state.EventCreateService:
if !isGlobalService(v.Service) {
if !orchestrator.IsGlobalService(v.Service) {
continue
}
g.updateService(v.Service)
g.reconcileServices(ctx, []string{v.Service.ID})
case state.EventUpdateService:
if !isGlobalService(v.Service) {
if !orchestrator.IsGlobalService(v.Service) {
continue
}
g.updateService(v.Service)
g.reconcileServices(ctx, []string{v.Service.ID})
case state.EventDeleteService:
if !isGlobalService(v.Service) {
if !orchestrator.IsGlobalService(v.Service) {
continue
}
deleteServiceTasks(ctx, g.store, v.Service)
orchestrator.DeleteServiceTasks(ctx, g.store, v.Service)
// delete the service from service map
delete(g.globalServices, v.Service.ID)
g.restarts.ClearServiceHistory(v.Service.ID)
@ -172,14 +175,14 @@ func (g *GlobalOrchestrator) Run(ctx context.Context) error {
}
// Stop stops the orchestrator.
func (g *GlobalOrchestrator) Stop() {
func (g *Orchestrator) Stop() {
close(g.stopChan)
<-g.doneChan
g.updater.CancelAll()
g.restarts.CancelAll()
}
func (g *GlobalOrchestrator) removeTasksFromNode(ctx context.Context, node *api.Node) {
func (g *Orchestrator) removeTasksFromNode(ctx context.Context, node *api.Node) {
var (
tasks []*api.Task
err error
@ -194,7 +197,7 @@ func (g *GlobalOrchestrator) removeTasksFromNode(ctx context.Context, node *api.
_, err = g.store.Batch(func(batch *store.Batch) error {
for _, t := range tasks {
// GlobalOrchestrator only removes tasks from globalServices
// Global orchestrator only removes tasks from globalServices
if _, exists := g.globalServices[t.ServiceID]; exists {
g.removeTask(ctx, batch, t)
}
@ -206,7 +209,7 @@ func (g *GlobalOrchestrator) removeTasksFromNode(ctx context.Context, node *api.
}
}
func (g *GlobalOrchestrator) reconcileServices(ctx context.Context, serviceIDs []string) {
func (g *Orchestrator) reconcileServices(ctx context.Context, serviceIDs []string) {
nodeCompleted := make(map[string]map[string]struct{})
nodeTasks := make(map[string]map[string][]*api.Task)
@ -229,7 +232,7 @@ func (g *GlobalOrchestrator) reconcileServices(ctx context.Context, serviceIDs [
nodeTasks[serviceID][t.NodeID] = append(nodeTasks[serviceID][t.NodeID], t)
} else {
// for finished tasks, check restartPolicy
if isTaskCompleted(t, restartCondition(t)) {
if isTaskCompleted(t, orchestrator.RestartCondition(t)) {
nodeCompleted[serviceID][t.NodeID] = struct{}{}
}
}
@ -238,7 +241,7 @@ func (g *GlobalOrchestrator) reconcileServices(ctx context.Context, serviceIDs [
})
_, err := g.store.Batch(func(batch *store.Batch) error {
var updateTasks []slot
var updateTasks []orchestrator.Slot
for _, serviceID := range serviceIDs {
if _, exists := nodeTasks[serviceID]; !exists {
continue
@ -290,7 +293,7 @@ func (g *GlobalOrchestrator) reconcileServices(ctx context.Context, serviceIDs [
}
// updateNode updates g.nodes based on the current node value
func (g *GlobalOrchestrator) updateNode(node *api.Node) {
func (g *Orchestrator) updateNode(node *api.Node) {
if node.Spec.Availability == api.NodeAvailabilityDrain {
delete(g.nodes, node.ID)
} else {
@ -299,7 +302,7 @@ func (g *GlobalOrchestrator) updateNode(node *api.Node) {
}
// updateService updates g.globalServices based on the current service value
func (g *GlobalOrchestrator) updateService(service *api.Service) {
func (g *Orchestrator) updateService(service *api.Service) {
var constraints []constraint.Constraint
if service.Spec.Task.Placement != nil && len(service.Spec.Task.Placement.Constraints) != 0 {
@ -313,7 +316,7 @@ func (g *GlobalOrchestrator) updateService(service *api.Service) {
}
// reconcileOneNode checks all global services on one node
func (g *GlobalOrchestrator) reconcileOneNode(ctx context.Context, node *api.Node) {
func (g *Orchestrator) reconcileOneNode(ctx context.Context, node *api.Node) {
if node.Spec.Availability == api.NodeAvailabilityDrain {
log.G(ctx).Debugf("global orchestrator: node %s in drain state, removing tasks from it", node.ID)
g.removeTasksFromNode(ctx, node)
@ -328,7 +331,7 @@ func (g *GlobalOrchestrator) reconcileOneNode(ctx context.Context, node *api.Nod
}
// reconcileServicesOneNode checks the specified services on one node
func (g *GlobalOrchestrator) reconcileServicesOneNode(ctx context.Context, serviceIDs []string, nodeID string) {
func (g *Orchestrator) reconcileServicesOneNode(ctx context.Context, serviceIDs []string, nodeID string) {
node, exists := g.nodes[nodeID]
if !exists {
return
@ -360,7 +363,7 @@ func (g *GlobalOrchestrator) reconcileServicesOneNode(ctx context.Context, servi
if isTaskRunning(t) {
tasks[serviceID] = append(tasks[serviceID], t)
} else {
if isTaskCompleted(t, restartCondition(t)) {
if isTaskCompleted(t, orchestrator.RestartCondition(t)) {
completed[serviceID] = true
}
}
@ -413,7 +416,7 @@ func (g *GlobalOrchestrator) reconcileServicesOneNode(ctx context.Context, servi
)
for _, t := range tasks[serviceID] {
if isTaskDirty(service.Service, t) {
if orchestrator.IsTaskDirty(service.Service, t) {
dirtyTasks = append(dirtyTasks, t)
} else {
cleanTasks = append(cleanTasks, t)
@ -438,7 +441,7 @@ func (g *GlobalOrchestrator) reconcileServicesOneNode(ctx context.Context, servi
// restartTask calls the restart supervisor's Restart function, which
// sets a task's desired state to shutdown and restarts it if the restart
// policy calls for it to be restarted.
func (g *GlobalOrchestrator) restartTask(ctx context.Context, taskID string, serviceID string) {
func (g *Orchestrator) restartTask(ctx context.Context, taskID string, serviceID string) {
err := g.store.Update(func(tx store.Tx) error {
t := store.GetTask(tx, taskID)
if t == nil || t.DesiredState > api.TaskStateRunning {
@ -455,7 +458,7 @@ func (g *GlobalOrchestrator) restartTask(ctx context.Context, taskID string, ser
}
}
func (g *GlobalOrchestrator) removeTask(ctx context.Context, batch *store.Batch, t *api.Task) {
func (g *Orchestrator) removeTask(ctx context.Context, batch *store.Batch, t *api.Task) {
// set existing task DesiredState to TaskStateShutdown
// TODO(aaronl): optimistic update?
err := batch.Update(func(tx store.Tx) error {
@ -471,8 +474,8 @@ func (g *GlobalOrchestrator) removeTask(ctx context.Context, batch *store.Batch,
}
}
func (g *GlobalOrchestrator) addTask(ctx context.Context, batch *store.Batch, service *api.Service, nodeID string) {
task := newTask(g.cluster, service, 0, nodeID)
func (g *Orchestrator) addTask(ctx context.Context, batch *store.Batch, service *api.Service, nodeID string) {
task := orchestrator.NewTask(g.cluster, service, 0, nodeID)
err := batch.Update(func(tx store.Tx) error {
return store.CreateTask(tx, task)
@ -482,7 +485,7 @@ func (g *GlobalOrchestrator) addTask(ctx context.Context, batch *store.Batch, se
}
}
func (g *GlobalOrchestrator) removeTasks(ctx context.Context, batch *store.Batch, tasks []*api.Task) {
func (g *Orchestrator) removeTasks(ctx context.Context, batch *store.Batch, tasks []*api.Task) {
for _, t := range tasks {
g.removeTask(ctx, batch, t)
}
@ -503,11 +506,3 @@ func isTaskCompleted(t *api.Task, restartPolicy api.RestartPolicy_RestartConditi
func isTaskTerminated(t *api.Task) bool {
return t != nil && t.Status.State > api.TaskStateRunning
}
func isGlobalService(service *api.Service) bool {
if service == nil {
return false
}
_, ok := service.Spec.GetMode().(*api.ServiceSpec_Global)
return ok
}

View file

@ -1,203 +0,0 @@
package orchestrator
import (
"time"
"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/identity"
"github.com/docker/swarmkit/log"
"github.com/docker/swarmkit/manager/state"
"github.com/docker/swarmkit/manager/state/store"
"github.com/docker/swarmkit/protobuf/ptypes"
"golang.org/x/net/context"
)
// A ReplicatedOrchestrator runs a reconciliation loop to create and destroy
// tasks as necessary for the replicated services.
type ReplicatedOrchestrator struct {
store *store.MemoryStore
reconcileServices map[string]*api.Service
restartTasks map[string]struct{}
// stopChan signals to the state machine to stop running.
stopChan chan struct{}
// doneChan is closed when the state machine terminates.
doneChan chan struct{}
updater *UpdateSupervisor
restarts *RestartSupervisor
cluster *api.Cluster // local cluster instance
}
// NewReplicatedOrchestrator creates a new ReplicatedOrchestrator.
func NewReplicatedOrchestrator(store *store.MemoryStore) *ReplicatedOrchestrator {
restartSupervisor := NewRestartSupervisor(store)
updater := NewUpdateSupervisor(store, restartSupervisor)
return &ReplicatedOrchestrator{
store: store,
stopChan: make(chan struct{}),
doneChan: make(chan struct{}),
reconcileServices: make(map[string]*api.Service),
restartTasks: make(map[string]struct{}),
updater: updater,
restarts: restartSupervisor,
}
}
// Run contains the orchestrator event loop. It runs until Stop is called.
func (r *ReplicatedOrchestrator) Run(ctx context.Context) error {
defer close(r.doneChan)
// Watch changes to services and tasks
queue := r.store.WatchQueue()
watcher, cancel := queue.Watch()
defer cancel()
// Balance existing services and drain initial tasks attached to invalid
// nodes
var err error
r.store.View(func(readTx store.ReadTx) {
if err = r.initTasks(ctx, readTx); err != nil {
return
}
if err = r.initServices(readTx); err != nil {
return
}
if err = r.initCluster(readTx); err != nil {
return
}
})
if err != nil {
return err
}
r.tick(ctx)
for {
select {
case event := <-watcher:
// TODO(stevvooe): Use ctx to limit running time of operation.
r.handleTaskEvent(ctx, event)
r.handleServiceEvent(ctx, event)
switch v := event.(type) {
case state.EventCommit:
r.tick(ctx)
case state.EventUpdateCluster:
r.cluster = v.Cluster
}
case <-r.stopChan:
return nil
}
}
}
// Stop stops the orchestrator.
func (r *ReplicatedOrchestrator) Stop() {
close(r.stopChan)
<-r.doneChan
r.updater.CancelAll()
r.restarts.CancelAll()
}
func (r *ReplicatedOrchestrator) tick(ctx context.Context) {
// tickTasks must be called first, so we respond to task-level changes
// before performing service reconcillation.
r.tickTasks(ctx)
r.tickServices(ctx)
}
func newTask(cluster *api.Cluster, service *api.Service, slot uint64, nodeID string) *api.Task {
var logDriver *api.Driver
if service.Spec.Task.LogDriver != nil {
// use the log driver specific to the task, if we have it.
logDriver = service.Spec.Task.LogDriver
} else if cluster != nil {
// pick up the cluster default, if available.
logDriver = cluster.Spec.TaskDefaults.LogDriver // nil is okay here.
}
taskID := identity.NewID()
task := api.Task{
ID: taskID,
ServiceAnnotations: service.Spec.Annotations,
Spec: service.Spec.Task,
ServiceID: service.ID,
Slot: slot,
Status: api.TaskStatus{
State: api.TaskStateNew,
Timestamp: ptypes.MustTimestampProto(time.Now()),
Message: "created",
},
Endpoint: &api.Endpoint{
Spec: service.Spec.Endpoint.Copy(),
},
DesiredState: api.TaskStateRunning,
LogDriver: logDriver,
}
// In global mode we also set the NodeID
if nodeID != "" {
task.NodeID = nodeID
}
// Assign name based on task name schema
name := store.TaskName(&task)
task.Annotations = api.Annotations{Name: name}
return &task
}
// isReplicatedService checks if a service is a replicated service
func isReplicatedService(service *api.Service) bool {
// service nil validation is required as there are scenarios
// where service is removed from store
if service == nil {
return false
}
_, ok := service.Spec.GetMode().(*api.ServiceSpec_Replicated)
return ok
}
func deleteServiceTasks(ctx context.Context, s *store.MemoryStore, service *api.Service) {
var (
tasks []*api.Task
err error
)
s.View(func(tx store.ReadTx) {
tasks, err = store.FindTasks(tx, store.ByServiceID(service.ID))
})
if err != nil {
log.G(ctx).WithError(err).Errorf("failed to list tasks")
return
}
_, err = s.Batch(func(batch *store.Batch) error {
for _, t := range tasks {
err := batch.Update(func(tx store.Tx) error {
if err := store.DeleteTask(tx, t.ID); err != nil {
log.G(ctx).WithError(err).Errorf("failed to delete task")
}
return nil
})
if err != nil {
return err
}
}
return nil
})
if err != nil {
log.G(ctx).WithError(err).Errorf("task search transaction failed")
}
}
func restartCondition(task *api.Task) api.RestartPolicy_RestartCondition {
restartCondition := api.RestartOnAny
if task.Spec.Restart != nil {
restartCondition = task.Spec.Restart.Condition
}
return restartCondition
}

View file

@ -0,0 +1,108 @@
package replicated
import (
"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/manager/orchestrator/restart"
"github.com/docker/swarmkit/manager/orchestrator/update"
"github.com/docker/swarmkit/manager/state"
"github.com/docker/swarmkit/manager/state/store"
"golang.org/x/net/context"
)
// An Orchestrator runs a reconciliation loop to create and destroy
// tasks as necessary for the replicated services.
type Orchestrator struct {
store *store.MemoryStore
reconcileServices map[string]*api.Service
restartTasks map[string]struct{}
// stopChan signals to the state machine to stop running.
stopChan chan struct{}
// doneChan is closed when the state machine terminates.
doneChan chan struct{}
updater *update.Supervisor
restarts *restart.Supervisor
cluster *api.Cluster // local cluster instance
}
// NewReplicatedOrchestrator creates a new replicated Orchestrator.
func NewReplicatedOrchestrator(store *store.MemoryStore) *Orchestrator {
restartSupervisor := restart.NewSupervisor(store)
updater := update.NewSupervisor(store, restartSupervisor)
return &Orchestrator{
store: store,
stopChan: make(chan struct{}),
doneChan: make(chan struct{}),
reconcileServices: make(map[string]*api.Service),
restartTasks: make(map[string]struct{}),
updater: updater,
restarts: restartSupervisor,
}
}
// Run contains the orchestrator event loop. It runs until Stop is called.
func (r *Orchestrator) Run(ctx context.Context) error {
defer close(r.doneChan)
// Watch changes to services and tasks
queue := r.store.WatchQueue()
watcher, cancel := queue.Watch()
defer cancel()
// Balance existing services and drain initial tasks attached to invalid
// nodes
var err error
r.store.View(func(readTx store.ReadTx) {
if err = r.initTasks(ctx, readTx); err != nil {
return
}
if err = r.initServices(readTx); err != nil {
return
}
if err = r.initCluster(readTx); err != nil {
return
}
})
if err != nil {
return err
}
r.tick(ctx)
for {
select {
case event := <-watcher:
// TODO(stevvooe): Use ctx to limit running time of operation.
r.handleTaskEvent(ctx, event)
r.handleServiceEvent(ctx, event)
switch v := event.(type) {
case state.EventCommit:
r.tick(ctx)
case state.EventUpdateCluster:
r.cluster = v.Cluster
}
case <-r.stopChan:
return nil
}
}
}
// Stop stops the orchestrator.
func (r *Orchestrator) Stop() {
close(r.stopChan)
<-r.doneChan
r.updater.CancelAll()
r.restarts.CancelAll()
}
func (r *Orchestrator) tick(ctx context.Context) {
// tickTasks must be called first, so we respond to task-level changes
// before performing service reconcillation.
r.tickTasks(ctx)
r.tickServices(ctx)
}

View file

@ -1,4 +1,4 @@
package orchestrator
package replicated
import (
"sort"
@ -6,6 +6,7 @@ import (
"github.com/docker/go-events"
"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/log"
"github.com/docker/swarmkit/manager/orchestrator"
"github.com/docker/swarmkit/manager/state"
"github.com/docker/swarmkit/manager/state/store"
"golang.org/x/net/context"
@ -16,7 +17,7 @@ import (
// specifications. This is different from task-level orchestration, which
// responds to changes in individual tasks (or nodes which run them).
func (r *ReplicatedOrchestrator) initCluster(readTx store.ReadTx) error {
func (r *Orchestrator) initCluster(readTx store.ReadTx) error {
clusters, err := store.FindClusters(readTx, store.ByName("default"))
if err != nil {
return err
@ -31,41 +32,41 @@ func (r *ReplicatedOrchestrator) initCluster(readTx store.ReadTx) error {
return nil
}
func (r *ReplicatedOrchestrator) initServices(readTx store.ReadTx) error {
func (r *Orchestrator) initServices(readTx store.ReadTx) error {
services, err := store.FindServices(readTx, store.All)
if err != nil {
return err
}
for _, s := range services {
if isReplicatedService(s) {
if orchestrator.IsReplicatedService(s) {
r.reconcileServices[s.ID] = s
}
}
return nil
}
func (r *ReplicatedOrchestrator) handleServiceEvent(ctx context.Context, event events.Event) {
func (r *Orchestrator) handleServiceEvent(ctx context.Context, event events.Event) {
switch v := event.(type) {
case state.EventDeleteService:
if !isReplicatedService(v.Service) {
if !orchestrator.IsReplicatedService(v.Service) {
return
}
deleteServiceTasks(ctx, r.store, v.Service)
orchestrator.DeleteServiceTasks(ctx, r.store, v.Service)
r.restarts.ClearServiceHistory(v.Service.ID)
case state.EventCreateService:
if !isReplicatedService(v.Service) {
if !orchestrator.IsReplicatedService(v.Service) {
return
}
r.reconcileServices[v.Service.ID] = v.Service
case state.EventUpdateService:
if !isReplicatedService(v.Service) {
if !orchestrator.IsReplicatedService(v.Service) {
return
}
r.reconcileServices[v.Service.ID] = v.Service
}
}
func (r *ReplicatedOrchestrator) tickServices(ctx context.Context) {
func (r *Orchestrator) tickServices(ctx context.Context) {
if len(r.reconcileServices) > 0 {
for _, s := range r.reconcileServices {
r.reconcile(ctx, s)
@ -74,7 +75,7 @@ func (r *ReplicatedOrchestrator) tickServices(ctx context.Context) {
}
}
func (r *ReplicatedOrchestrator) resolveService(ctx context.Context, task *api.Task) *api.Service {
func (r *Orchestrator) resolveService(ctx context.Context, task *api.Task) *api.Service {
if task.ServiceID == "" {
return nil
}
@ -85,8 +86,8 @@ func (r *ReplicatedOrchestrator) resolveService(ctx context.Context, task *api.T
return service
}
func (r *ReplicatedOrchestrator) reconcile(ctx context.Context, service *api.Service) {
runningSlots, deadSlots, err := getRunnableAndDeadSlots(r.store, service.ID)
func (r *Orchestrator) reconcile(ctx context.Context, service *api.Service) {
runningSlots, deadSlots, err := orchestrator.GetRunnableAndDeadSlots(r.store, service.ID)
if err != nil {
log.G(ctx).WithError(err).Errorf("reconcile failed finding tasks")
return
@ -94,7 +95,7 @@ func (r *ReplicatedOrchestrator) reconcile(ctx context.Context, service *api.Ser
numSlots := len(runningSlots)
slotsSlice := make([]slot, 0, numSlots)
slotsSlice := make([]orchestrator.Slot, 0, numSlots)
for _, slot := range runningSlots {
slotsSlice = append(slotsSlice, slot)
}
@ -148,7 +149,7 @@ func (r *ReplicatedOrchestrator) reconcile(ctx context.Context, service *api.Ser
sort.Sort(slotsWithIndices)
sortedSlots := make([]slot, 0, numSlots)
sortedSlots := make([]orchestrator.Slot, 0, numSlots)
for _, slot := range slotsWithIndices {
sortedSlots = append(sortedSlots, slot.slot)
}
@ -176,7 +177,7 @@ func (r *ReplicatedOrchestrator) reconcile(ctx context.Context, service *api.Ser
}
}
func (r *ReplicatedOrchestrator) addTasks(ctx context.Context, batch *store.Batch, service *api.Service, runningSlots map[uint64]slot, deadSlots map[uint64]slot, count int) {
func (r *Orchestrator) addTasks(ctx context.Context, batch *store.Batch, service *api.Service, runningSlots map[uint64]orchestrator.Slot, deadSlots map[uint64]orchestrator.Slot, count int) {
slot := uint64(0)
for i := 0; i < count; i++ {
// Find an slot number that is missing a running task
@ -189,7 +190,7 @@ func (r *ReplicatedOrchestrator) addTasks(ctx context.Context, batch *store.Batc
delete(deadSlots, slot)
err := batch.Update(func(tx store.Tx) error {
return store.CreateTask(tx, newTask(r.cluster, service, slot, ""))
return store.CreateTask(tx, orchestrator.NewTask(r.cluster, service, slot, ""))
})
if err != nil {
log.G(ctx).Errorf("Failed to create task: %v", err)
@ -197,7 +198,7 @@ func (r *ReplicatedOrchestrator) addTasks(ctx context.Context, batch *store.Batc
}
}
func (r *ReplicatedOrchestrator) deleteTasks(ctx context.Context, batch *store.Batch, slots []slot) {
func (r *Orchestrator) deleteTasks(ctx context.Context, batch *store.Batch, slots []orchestrator.Slot) {
for _, slot := range slots {
for _, t := range slot {
r.deleteTask(ctx, batch, t)
@ -205,7 +206,7 @@ func (r *ReplicatedOrchestrator) deleteTasks(ctx context.Context, batch *store.B
}
}
func (r *ReplicatedOrchestrator) deleteTasksMap(ctx context.Context, batch *store.Batch, slots map[uint64]slot) {
func (r *Orchestrator) deleteTasksMap(ctx context.Context, batch *store.Batch, slots map[uint64]orchestrator.Slot) {
for _, slot := range slots {
for _, t := range slot {
r.deleteTask(ctx, batch, t)
@ -213,7 +214,7 @@ func (r *ReplicatedOrchestrator) deleteTasksMap(ctx context.Context, batch *stor
}
}
func (r *ReplicatedOrchestrator) deleteTask(ctx context.Context, batch *store.Batch, t *api.Task) {
func (r *Orchestrator) deleteTask(ctx context.Context, batch *store.Batch, t *api.Task) {
err := batch.Update(func(tx store.Tx) error {
return store.DeleteTask(tx, t.ID)
})
@ -221,36 +222,3 @@ func (r *ReplicatedOrchestrator) deleteTask(ctx context.Context, batch *store.Ba
log.G(ctx).WithError(err).Errorf("deleting task %s failed", t.ID)
}
}
// getRunnableAndDeadSlots returns two maps of slots. The first contains slots
// that have at least one task with a desired state above NEW and lesser or
// equal to RUNNING. The second is for slots that only contain tasks with a
// desired state above RUNNING.
func getRunnableAndDeadSlots(s *store.MemoryStore, serviceID string) (map[uint64]slot, map[uint64]slot, error) {
var (
tasks []*api.Task
err error
)
s.View(func(tx store.ReadTx) {
tasks, err = store.FindTasks(tx, store.ByServiceID(serviceID))
})
if err != nil {
return nil, nil, err
}
runningSlots := make(map[uint64]slot)
for _, t := range tasks {
if t.DesiredState <= api.TaskStateRunning {
runningSlots[t.Slot] = append(runningSlots[t.Slot], t)
}
}
deadSlots := make(map[uint64]slot)
for _, t := range tasks {
if _, exists := runningSlots[t.Slot]; !exists {
deadSlots[t.Slot] = append(deadSlots[t.Slot], t)
}
}
return runningSlots, deadSlots, nil
}

View file

@ -0,0 +1,55 @@
package replicated
import (
"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/manager/orchestrator"
)
type slotsByRunningState []orchestrator.Slot
func (is slotsByRunningState) Len() int { return len(is) }
func (is slotsByRunningState) Swap(i, j int) { is[i], is[j] = is[j], is[i] }
func (is slotsByRunningState) Less(i, j int) bool {
iRunning := false
jRunning := false
for _, ii := range is[i] {
if ii.Status.State == api.TaskStateRunning {
iRunning = true
break
}
}
for _, ij := range is[j] {
if ij.Status.State == api.TaskStateRunning {
jRunning = true
break
}
}
return iRunning && !jRunning
}
type slotWithIndex struct {
slot orchestrator.Slot
// index is a counter that counts this task as the nth instance of
// the service on its node. This is used for sorting the tasks so that
// when scaling down we leave tasks more evenly balanced.
index int
}
type slotsByIndex []slotWithIndex
func (is slotsByIndex) Len() int { return len(is) }
func (is slotsByIndex) Swap(i, j int) { is[i], is[j] = is[j], is[i] }
func (is slotsByIndex) Less(i, j int) bool {
if is[i].index < 0 && is[j].index >= 0 {
return false
}
if is[j].index < 0 && is[i].index >= 0 {
return true
}
return is[i].index < is[j].index
}

View file

@ -1,4 +1,4 @@
package orchestrator
package replicated
import (
"time"
@ -6,6 +6,7 @@ import (
"github.com/docker/go-events"
"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/log"
"github.com/docker/swarmkit/manager/orchestrator"
"github.com/docker/swarmkit/manager/state"
"github.com/docker/swarmkit/manager/state/store"
"github.com/docker/swarmkit/protobuf/ptypes"
@ -23,7 +24,7 @@ func invalidNode(n *api.Node) bool {
n.Spec.Availability == api.NodeAvailabilityDrain
}
func (r *ReplicatedOrchestrator) initTasks(ctx context.Context, readTx store.ReadTx) error {
func (r *Orchestrator) initTasks(ctx context.Context, readTx store.ReadTx) error {
tasks, err := store.FindTasks(readTx, store.All)
if err != nil {
return err
@ -56,16 +57,16 @@ func (r *ReplicatedOrchestrator) initTasks(ctx context.Context, readTx store.Rea
continue
}
// TODO(aluzzardi): This is shady. We should have a more generic condition.
if t.DesiredState != api.TaskStateReady || !isReplicatedService(service) {
if t.DesiredState != api.TaskStateReady || !orchestrator.IsReplicatedService(service) {
continue
}
restartDelay := defaultRestartDelay
restartDelay := orchestrator.DefaultRestartDelay
if t.Spec.Restart != nil && t.Spec.Restart.Delay != nil {
var err error
restartDelay, err = ptypes.Duration(t.Spec.Restart.Delay)
if err != nil {
log.G(ctx).WithError(err).Error("invalid restart delay")
restartDelay = defaultRestartDelay
restartDelay = orchestrator.DefaultRestartDelay
}
}
if restartDelay != 0 {
@ -107,7 +108,7 @@ func (r *ReplicatedOrchestrator) initTasks(ctx context.Context, readTx store.Rea
return err
}
func (r *ReplicatedOrchestrator) handleTaskEvent(ctx context.Context, event events.Event) {
func (r *Orchestrator) handleTaskEvent(ctx context.Context, event events.Event) {
switch v := event.(type) {
case state.EventDeleteNode:
r.restartTasksByNodeID(ctx, v.Node.ID)
@ -118,7 +119,7 @@ func (r *ReplicatedOrchestrator) handleTaskEvent(ctx context.Context, event even
case state.EventDeleteTask:
if v.Task.DesiredState <= api.TaskStateRunning {
service := r.resolveService(ctx, v.Task)
if !isReplicatedService(service) {
if !orchestrator.IsReplicatedService(service) {
return
}
r.reconcileServices[service.ID] = service
@ -131,7 +132,7 @@ func (r *ReplicatedOrchestrator) handleTaskEvent(ctx context.Context, event even
}
}
func (r *ReplicatedOrchestrator) tickTasks(ctx context.Context) {
func (r *Orchestrator) tickTasks(ctx context.Context) {
if len(r.restartTasks) > 0 {
_, err := r.store.Batch(func(batch *store.Batch) error {
for taskID := range r.restartTasks {
@ -144,7 +145,7 @@ func (r *ReplicatedOrchestrator) tickTasks(ctx context.Context) {
}
service := store.GetService(tx, t.ServiceID)
if !isReplicatedService(service) {
if !orchestrator.IsReplicatedService(service) {
return nil
}
@ -156,7 +157,7 @@ func (r *ReplicatedOrchestrator) tickTasks(ctx context.Context) {
return nil
})
if err != nil {
log.G(ctx).WithError(err).Errorf("ReplicatedOrchestrator task reaping transaction failed")
log.G(ctx).WithError(err).Errorf("Orchestrator task reaping transaction failed")
}
}
return nil
@ -170,7 +171,7 @@ func (r *ReplicatedOrchestrator) tickTasks(ctx context.Context) {
}
}
func (r *ReplicatedOrchestrator) restartTasksByNodeID(ctx context.Context, nodeID string) {
func (r *Orchestrator) restartTasksByNodeID(ctx context.Context, nodeID string) {
var err error
r.store.View(func(tx store.ReadTx) {
var tasks []*api.Task
@ -184,7 +185,7 @@ func (r *ReplicatedOrchestrator) restartTasksByNodeID(ctx context.Context, nodeI
continue
}
service := store.GetService(tx, t.ServiceID)
if isReplicatedService(service) {
if orchestrator.IsReplicatedService(service) {
r.restartTasks[t.ID] = struct{}{}
}
}
@ -194,7 +195,7 @@ func (r *ReplicatedOrchestrator) restartTasksByNodeID(ctx context.Context, nodeI
}
}
func (r *ReplicatedOrchestrator) handleNodeChange(ctx context.Context, n *api.Node) {
func (r *Orchestrator) handleNodeChange(ctx context.Context, n *api.Node) {
if !invalidNode(n) {
return
}
@ -202,7 +203,7 @@ func (r *ReplicatedOrchestrator) handleNodeChange(ctx context.Context, n *api.No
r.restartTasksByNodeID(ctx, n.ID)
}
func (r *ReplicatedOrchestrator) handleTaskChange(ctx context.Context, t *api.Task) {
func (r *Orchestrator) handleTaskChange(ctx context.Context, t *api.Task) {
// If we already set the desired state past TaskStateRunning, there is no
// further action necessary.
if t.DesiredState > api.TaskStateRunning {
@ -222,7 +223,7 @@ func (r *ReplicatedOrchestrator) handleTaskChange(ctx context.Context, t *api.Ta
}
})
if !isReplicatedService(service) {
if !orchestrator.IsReplicatedService(service) {
return
}

View file

@ -1,4 +1,4 @@
package orchestrator
package restart
import (
"container/list"
@ -9,6 +9,7 @@ import (
"github.com/docker/go-events"
"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/log"
"github.com/docker/swarmkit/manager/orchestrator"
"github.com/docker/swarmkit/manager/state"
"github.com/docker/swarmkit/manager/state/store"
"github.com/docker/swarmkit/protobuf/ptypes"
@ -16,7 +17,6 @@ import (
)
const defaultOldTaskTimeout = time.Minute
const defaultRestartDelay = 5 * time.Second
type restartedInstance struct {
timestamp time.Time
@ -41,29 +41,35 @@ type delayedStart struct {
waiter bool
}
// RestartSupervisor initiates and manages restarts. It's responsible for
type instanceTuple struct {
instance uint64 // unset for global tasks
serviceID string
nodeID string // unset for replicated tasks
}
// Supervisor initiates and manages restarts. It's responsible for
// delaying restarts when applicable.
type RestartSupervisor struct {
type Supervisor struct {
mu sync.Mutex
store *store.MemoryStore
delays map[string]*delayedStart
history map[instanceTuple]*instanceRestartInfo
historyByService map[string]map[instanceTuple]struct{}
taskTimeout time.Duration
TaskTimeout time.Duration
}
// NewRestartSupervisor creates a new RestartSupervisor.
func NewRestartSupervisor(store *store.MemoryStore) *RestartSupervisor {
return &RestartSupervisor{
// NewSupervisor creates a new RestartSupervisor.
func NewSupervisor(store *store.MemoryStore) *Supervisor {
return &Supervisor{
store: store,
delays: make(map[string]*delayedStart),
history: make(map[instanceTuple]*instanceRestartInfo),
historyByService: make(map[string]map[instanceTuple]struct{}),
taskTimeout: defaultOldTaskTimeout,
TaskTimeout: defaultOldTaskTimeout,
}
}
func (r *RestartSupervisor) waitRestart(ctx context.Context, oldDelay *delayedStart, cluster *api.Cluster, taskID string) {
func (r *Supervisor) waitRestart(ctx context.Context, oldDelay *delayedStart, cluster *api.Cluster, taskID string) {
// Wait for the last restart delay to elapse.
select {
case <-oldDelay.doneCh:
@ -94,7 +100,7 @@ func (r *RestartSupervisor) waitRestart(ctx context.Context, oldDelay *delayedSt
// Restart initiates a new task to replace t if appropriate under the service's
// restart policy.
func (r *RestartSupervisor) Restart(ctx context.Context, tx store.Tx, cluster *api.Cluster, service *api.Service, t api.Task) error {
func (r *Supervisor) Restart(ctx context.Context, tx store.Tx, cluster *api.Cluster, service *api.Service, t api.Task) error {
// TODO(aluzzardi): This function should not depend on `service`.
// Is the old task still in the process of restarting? If so, wait for
@ -132,10 +138,10 @@ func (r *RestartSupervisor) Restart(ctx context.Context, tx store.Tx, cluster *a
var restartTask *api.Task
if isReplicatedService(service) {
restartTask = newTask(cluster, service, t.Slot, "")
} else if isGlobalService(service) {
restartTask = newTask(cluster, service, 0, t.NodeID)
if orchestrator.IsReplicatedService(service) {
restartTask = orchestrator.NewTask(cluster, service, t.Slot, "")
} else if orchestrator.IsGlobalService(service) {
restartTask = orchestrator.NewTask(cluster, service, 0, t.NodeID)
} else {
log.G(ctx).Error("service not supported by restart supervisor")
return nil
@ -153,10 +159,10 @@ func (r *RestartSupervisor) Restart(ctx context.Context, tx store.Tx, cluster *a
restartDelay, err = ptypes.Duration(t.Spec.Restart.Delay)
if err != nil {
log.G(ctx).WithError(err).Error("invalid restart delay; using default")
restartDelay = defaultRestartDelay
restartDelay = orchestrator.DefaultRestartDelay
}
} else {
restartDelay = defaultRestartDelay
restartDelay = orchestrator.DefaultRestartDelay
}
}
@ -179,10 +185,10 @@ func (r *RestartSupervisor) Restart(ctx context.Context, tx store.Tx, cluster *a
return nil
}
func (r *RestartSupervisor) shouldRestart(ctx context.Context, t *api.Task, service *api.Service) bool {
func (r *Supervisor) shouldRestart(ctx context.Context, t *api.Task, service *api.Service) bool {
// TODO(aluzzardi): This function should not depend on `service`.
condition := restartCondition(t)
condition := orchestrator.RestartCondition(t)
if condition != api.RestartOnAny &&
(condition != api.RestartOnFailure || t.Status.State == api.TaskStateCompleted) {
@ -200,7 +206,7 @@ func (r *RestartSupervisor) shouldRestart(ctx context.Context, t *api.Task, serv
// Instance is not meaningful for "global" tasks, so they need to be
// indexed by NodeID.
if isGlobalService(service) {
if orchestrator.IsGlobalService(service) {
instanceTuple.nodeID = t.NodeID
}
@ -246,7 +252,7 @@ func (r *RestartSupervisor) shouldRestart(ctx context.Context, t *api.Task, serv
return numRestarts < t.Spec.Restart.MaxAttempts
}
func (r *RestartSupervisor) recordRestartHistory(restartTask *api.Task) {
func (r *Supervisor) recordRestartHistory(restartTask *api.Task) {
if restartTask.Spec.Restart == nil || restartTask.Spec.Restart.MaxAttempts == 0 {
// No limit on the number of restarts, so no need to record
// history.
@ -292,7 +298,7 @@ func (r *RestartSupervisor) recordRestartHistory(restartTask *api.Task) {
// It must be called during an Update transaction to ensure that it does not
// miss events. The purpose of the store.Tx argument is to avoid accidental
// calls outside an Update transaction.
func (r *RestartSupervisor) DelayStart(ctx context.Context, _ store.Tx, oldTask *api.Task, newTaskID string, delay time.Duration, waitStop bool) <-chan struct{} {
func (r *Supervisor) DelayStart(ctx context.Context, _ store.Tx, oldTask *api.Task, newTaskID string, delay time.Duration, waitStop bool) <-chan struct{} {
ctx, cancel := context.WithCancel(context.Background())
doneCh := make(chan struct{})
@ -345,7 +351,7 @@ func (r *RestartSupervisor) DelayStart(ctx context.Context, _ store.Tx, oldTask
close(doneCh)
}()
oldTaskTimer := time.NewTimer(r.taskTimeout)
oldTaskTimer := time.NewTimer(r.TaskTimeout)
defer oldTaskTimer.Stop()
// Wait for the delay to elapse, if one is specified.
@ -383,7 +389,7 @@ func (r *RestartSupervisor) DelayStart(ctx context.Context, _ store.Tx, oldTask
// StartNow moves the task into the RUNNING state so it will proceed to start
// up.
func (r *RestartSupervisor) StartNow(tx store.Tx, taskID string) error {
func (r *Supervisor) StartNow(tx store.Tx, taskID string) error {
t := store.GetTask(tx, taskID)
if t == nil || t.DesiredState >= api.TaskStateRunning {
return nil
@ -393,7 +399,7 @@ func (r *RestartSupervisor) StartNow(tx store.Tx, taskID string) error {
}
// Cancel cancels a pending restart.
func (r *RestartSupervisor) Cancel(taskID string) {
func (r *Supervisor) Cancel(taskID string) {
r.mu.Lock()
delay, ok := r.delays[taskID]
r.mu.Unlock()
@ -408,7 +414,7 @@ func (r *RestartSupervisor) Cancel(taskID string) {
// CancelAll aborts all pending restarts and waits for any instances of
// StartNow that have already triggered to complete.
func (r *RestartSupervisor) CancelAll() {
func (r *Supervisor) CancelAll() {
var cancelled []delayedStart
r.mu.Lock()
@ -423,7 +429,7 @@ func (r *RestartSupervisor) CancelAll() {
}
// ClearServiceHistory forgets restart history related to a given service ID.
func (r *RestartSupervisor) ClearServiceHistory(serviceID string) {
func (r *Supervisor) ClearServiceHistory(serviceID string) {
r.mu.Lock()
defer r.mu.Unlock()

View file

@ -0,0 +1,61 @@
package orchestrator
import (
"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/log"
"github.com/docker/swarmkit/manager/state/store"
"golang.org/x/net/context"
)
// IsReplicatedService checks if a service is a replicated service.
func IsReplicatedService(service *api.Service) bool {
// service nil validation is required as there are scenarios
// where service is removed from store
if service == nil {
return false
}
_, ok := service.Spec.GetMode().(*api.ServiceSpec_Replicated)
return ok
}
// IsGlobalService checks if the service is a global service.
func IsGlobalService(service *api.Service) bool {
if service == nil {
return false
}
_, ok := service.Spec.GetMode().(*api.ServiceSpec_Global)
return ok
}
// DeleteServiceTasks deletes the tasks associated with a service.
func DeleteServiceTasks(ctx context.Context, s *store.MemoryStore, service *api.Service) {
var (
tasks []*api.Task
err error
)
s.View(func(tx store.ReadTx) {
tasks, err = store.FindTasks(tx, store.ByServiceID(service.ID))
})
if err != nil {
log.G(ctx).WithError(err).Errorf("failed to list tasks")
return
}
_, err = s.Batch(func(batch *store.Batch) error {
for _, t := range tasks {
err := batch.Update(func(tx store.Tx) error {
if err := store.DeleteTask(tx, t.ID); err != nil {
log.G(ctx).WithError(err).Errorf("failed to delete task")
}
return nil
})
if err != nil {
return err
}
}
return nil
})
if err != nil {
log.G(ctx).WithError(err).Errorf("task search transaction failed")
}
}

View file

@ -2,60 +2,45 @@ package orchestrator
import (
"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/manager/state/store"
)
// slot is a list of the running tasks occupying a certain slot. Generally this
// Slot is a list of the running tasks occupying a certain slot. Generally this
// will only be one task, but some rolling update situations involve
// temporarily having two running tasks in the same slot. Note that this use of
// "slot" is more generic than the Slot number for replicated services - a node
// is also considered a slot for global services.
type slot []*api.Task
type Slot []*api.Task
type slotsByRunningState []slot
func (is slotsByRunningState) Len() int { return len(is) }
func (is slotsByRunningState) Swap(i, j int) { is[i], is[j] = is[j], is[i] }
func (is slotsByRunningState) Less(i, j int) bool {
iRunning := false
jRunning := false
for _, ii := range is[i] {
if ii.Status.State == api.TaskStateRunning {
iRunning = true
break
}
// GetRunnableAndDeadSlots returns two maps of slots. The first contains slots
// that have at least one task with a desired state above NEW and lesser or
// equal to RUNNING. The second is for slots that only contain tasks with a
// desired state above RUNNING.
func GetRunnableAndDeadSlots(s *store.MemoryStore, serviceID string) (map[uint64]Slot, map[uint64]Slot, error) {
var (
tasks []*api.Task
err error
)
s.View(func(tx store.ReadTx) {
tasks, err = store.FindTasks(tx, store.ByServiceID(serviceID))
})
if err != nil {
return nil, nil, err
}
for _, ij := range is[j] {
if ij.Status.State == api.TaskStateRunning {
jRunning = true
break
runningSlots := make(map[uint64]Slot)
for _, t := range tasks {
if t.DesiredState <= api.TaskStateRunning {
runningSlots[t.Slot] = append(runningSlots[t.Slot], t)
}
}
return iRunning && !jRunning
}
type slotWithIndex struct {
slot slot
// index is a counter that counts this task as the nth instance of
// the service on its node. This is used for sorting the tasks so that
// when scaling down we leave tasks more evenly balanced.
index int
}
type slotsByIndex []slotWithIndex
func (is slotsByIndex) Len() int { return len(is) }
func (is slotsByIndex) Swap(i, j int) { is[i], is[j] = is[j], is[i] }
func (is slotsByIndex) Less(i, j int) bool {
if is[i].index < 0 && is[j].index >= 0 {
return false
deadSlots := make(map[uint64]Slot)
for _, t := range tasks {
if _, exists := runningSlots[t.Slot]; !exists {
deadSlots[t.Slot] = append(deadSlots[t.Slot], t)
}
}
if is[j].index < 0 && is[i].index >= 0 {
return true
}
return is[i].index < is[j].index
return runningSlots, deadSlots, nil
}

View file

@ -0,0 +1,67 @@
package orchestrator
import (
"reflect"
"time"
"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/identity"
"github.com/docker/swarmkit/protobuf/ptypes"
)
// DefaultRestartDelay is the restart delay value to use when none is
// specified.
const DefaultRestartDelay = 5 * time.Second
// NewTask creates a new task.
func NewTask(cluster *api.Cluster, service *api.Service, slot uint64, nodeID string) *api.Task {
var logDriver *api.Driver
if service.Spec.Task.LogDriver != nil {
// use the log driver specific to the task, if we have it.
logDriver = service.Spec.Task.LogDriver
} else if cluster != nil {
// pick up the cluster default, if available.
logDriver = cluster.Spec.TaskDefaults.LogDriver // nil is okay here.
}
taskID := identity.NewID()
task := api.Task{
ID: taskID,
ServiceAnnotations: service.Spec.Annotations,
Spec: service.Spec.Task,
ServiceID: service.ID,
Slot: slot,
Status: api.TaskStatus{
State: api.TaskStateNew,
Timestamp: ptypes.MustTimestampProto(time.Now()),
Message: "created",
},
Endpoint: &api.Endpoint{
Spec: service.Spec.Endpoint.Copy(),
},
DesiredState: api.TaskStateRunning,
LogDriver: logDriver,
}
// In global mode we also set the NodeID
if nodeID != "" {
task.NodeID = nodeID
}
return &task
}
// RestartCondition returns the restart condition to apply to this task.
func RestartCondition(task *api.Task) api.RestartPolicy_RestartCondition {
restartCondition := api.RestartOnAny
if task.Spec.Restart != nil {
restartCondition = task.Spec.Restart.Condition
}
return restartCondition
}
// IsTaskDirty determines whether a task matches the given service's spec.
func IsTaskDirty(s *api.Service, t *api.Task) bool {
return !reflect.DeepEqual(s.Spec.Task, t.Spec) ||
(t.Endpoint != nil && !reflect.DeepEqual(s.Spec.Endpoint, t.Endpoint.Spec))
}

View file

@ -1,4 +1,4 @@
package orchestrator
package taskreaper
import (
"sort"
@ -36,8 +36,8 @@ type TaskReaper struct {
doneChan chan struct{}
}
// NewTaskReaper creates a new TaskReaper.
func NewTaskReaper(store *store.MemoryStore) *TaskReaper {
// New creates a new TaskReaper.
func New(store *store.MemoryStore) *TaskReaper {
watcher, cancel := state.Watch(store.WatchQueue(), state.EventCreateTask{}, state.EventUpdateCluster{})
return &TaskReaper{

View file

@ -1,4 +1,4 @@
package orchestrator
package update
import (
"errors"
@ -12,6 +12,8 @@ import (
"github.com/docker/go-events"
"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/log"
"github.com/docker/swarmkit/manager/orchestrator"
"github.com/docker/swarmkit/manager/orchestrator/restart"
"github.com/docker/swarmkit/manager/state"
"github.com/docker/swarmkit/manager/state/store"
"github.com/docker/swarmkit/manager/state/watch"
@ -20,18 +22,18 @@ import (
const defaultMonitor = 30 * time.Second
// UpdateSupervisor supervises a set of updates. It's responsible for keeping track of updates,
// Supervisor supervises a set of updates. It's responsible for keeping track of updates,
// shutting them down and replacing them.
type UpdateSupervisor struct {
type Supervisor struct {
store *store.MemoryStore
restarts *RestartSupervisor
restarts *restart.Supervisor
updates map[string]*Updater
l sync.Mutex
}
// NewUpdateSupervisor creates a new UpdateSupervisor.
func NewUpdateSupervisor(store *store.MemoryStore, restartSupervisor *RestartSupervisor) *UpdateSupervisor {
return &UpdateSupervisor{
// NewSupervisor creates a new UpdateSupervisor.
func NewSupervisor(store *store.MemoryStore, restartSupervisor *restart.Supervisor) *Supervisor {
return &Supervisor{
store: store,
updates: make(map[string]*Updater),
restarts: restartSupervisor,
@ -45,7 +47,7 @@ func NewUpdateSupervisor(store *store.MemoryStore, restartSupervisor *RestartSup
// and the new task was started before the old one was shut down. If an update
// for that service was already in progress, it will be cancelled before the
// new one starts.
func (u *UpdateSupervisor) Update(ctx context.Context, cluster *api.Cluster, service *api.Service, slots []slot) {
func (u *Supervisor) Update(ctx context.Context, cluster *api.Cluster, service *api.Service, slots []orchestrator.Slot) {
u.l.Lock()
defer u.l.Unlock()
@ -72,7 +74,7 @@ func (u *UpdateSupervisor) Update(ctx context.Context, cluster *api.Cluster, ser
}
// CancelAll cancels all current updates.
func (u *UpdateSupervisor) CancelAll() {
func (u *Supervisor) CancelAll() {
u.l.Lock()
defer u.l.Unlock()
@ -85,7 +87,7 @@ func (u *UpdateSupervisor) CancelAll() {
type Updater struct {
store *store.MemoryStore
watchQueue *watch.Queue
restarts *RestartSupervisor
restarts *restart.Supervisor
cluster *api.Cluster
newService *api.Service
@ -100,7 +102,7 @@ type Updater struct {
}
// NewUpdater creates a new Updater.
func NewUpdater(store *store.MemoryStore, restartSupervisor *RestartSupervisor, cluster *api.Cluster, newService *api.Service) *Updater {
func NewUpdater(store *store.MemoryStore, restartSupervisor *restart.Supervisor, cluster *api.Cluster, newService *api.Service) *Updater {
return &Updater{
store: store,
watchQueue: store.WatchQueue(),
@ -120,7 +122,7 @@ func (u *Updater) Cancel() {
}
// Run starts the update and returns only once its complete or cancelled.
func (u *Updater) Run(ctx context.Context, slots []slot) {
func (u *Updater) Run(ctx context.Context, slots []orchestrator.Slot) {
defer close(u.doneChan)
service := u.newService
@ -132,7 +134,7 @@ func (u *Updater) Run(ctx context.Context, slots []slot) {
return
}
var dirtySlots []slot
var dirtySlots []orchestrator.Slot
for _, slot := range slots {
if u.isSlotDirty(slot) {
dirtySlots = append(dirtySlots, slot)
@ -164,7 +166,7 @@ func (u *Updater) Run(ctx context.Context, slots []slot) {
}
// Start the workers.
slotQueue := make(chan slot)
slotQueue := make(chan orchestrator.Slot)
wg := sync.WaitGroup{}
wg.Add(parallelism)
for i := 0; i < parallelism; i++ {
@ -300,7 +302,7 @@ slotsLoop:
}
}
func (u *Updater) worker(ctx context.Context, queue <-chan slot) {
func (u *Updater) worker(ctx context.Context, queue <-chan orchestrator.Slot) {
for slot := range queue {
// Do we have a task with the new spec in desired state = RUNNING?
// If so, all we have to do to complete the update is remove the
@ -331,9 +333,9 @@ func (u *Updater) worker(ctx context.Context, queue <-chan slot) {
log.G(ctx).WithError(err).Error("update failed")
}
} else {
updated := newTask(u.cluster, u.newService, slot[0].Slot, "")
if isGlobalService(u.newService) {
updated = newTask(u.cluster, u.newService, slot[0].Slot, slot[0].NodeID)
updated := orchestrator.NewTask(u.cluster, u.newService, slot[0].Slot, "")
if orchestrator.IsGlobalService(u.newService) {
updated = orchestrator.NewTask(u.cluster, u.newService, slot[0].Slot, slot[0].NodeID)
}
updated.DesiredState = api.TaskStateReady
@ -357,7 +359,7 @@ func (u *Updater) worker(ctx context.Context, queue <-chan slot) {
}
}
func (u *Updater) updateTask(ctx context.Context, slot slot, updated *api.Task) error {
func (u *Updater) updateTask(ctx context.Context, slot orchestrator.Slot, updated *api.Task) error {
// Kick off the watch before even creating the updated task. This is in order to avoid missing any event.
taskUpdates, cancel := state.Watch(u.watchQueue, state.EventUpdateTask{
Task: &api.Task{ID: updated.ID},
@ -421,7 +423,7 @@ func (u *Updater) updateTask(ctx context.Context, slot slot, updated *api.Task)
}
}
func (u *Updater) useExistingTask(ctx context.Context, slot slot, existing *api.Task) error {
func (u *Updater) useExistingTask(ctx context.Context, slot orchestrator.Slot, existing *api.Task) error {
var removeTasks []*api.Task
for _, t := range slot {
if t != existing {
@ -489,16 +491,11 @@ func (u *Updater) removeOldTasks(ctx context.Context, batch *store.Batch, remove
return removedTask, nil
}
func isTaskDirty(s *api.Service, t *api.Task) bool {
return !reflect.DeepEqual(s.Spec.Task, t.Spec) ||
(t.Endpoint != nil && !reflect.DeepEqual(s.Spec.Endpoint, t.Endpoint.Spec))
}
func (u *Updater) isTaskDirty(t *api.Task) bool {
return isTaskDirty(u.newService, t)
return orchestrator.IsTaskDirty(u.newService, t)
}
func (u *Updater) isSlotDirty(slot slot) bool {
func (u *Updater) isSlotDirty(slot orchestrator.Slot) bool {
return len(slot) > 1 || (len(slot) == 1 && u.isTaskDirty(slot[0]))
}

View file

@ -1,6 +1,12 @@
package scheduler
import "github.com/docker/swarmkit/api"
import (
"time"
"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/log"
"golang.org/x/net/context"
)
// NodeInfo contains a node and some additional metadata.
type NodeInfo struct {
@ -9,6 +15,13 @@ type NodeInfo struct {
DesiredRunningTasksCount int
DesiredRunningTasksCountByService map[string]int
AvailableResources api.Resources
// recentFailures is a map from service ID to the timestamps of the
// most recent failures the node has experienced from replicas of that
// service.
// TODO(aaronl): When spec versioning is supported, this should track
// the version of the spec that failed.
recentFailures map[string][]time.Time
}
func newNodeInfo(n *api.Node, tasks map[string]*api.Task, availableResources api.Resources) NodeInfo {
@ -17,6 +30,7 @@ func newNodeInfo(n *api.Node, tasks map[string]*api.Task, availableResources api
Tasks: make(map[string]*api.Task),
DesiredRunningTasksCountByService: make(map[string]int),
AvailableResources: availableResources,
recentFailures: make(map[string][]time.Time),
}
for _, t := range tasks {
@ -28,9 +42,6 @@ func newNodeInfo(n *api.Node, tasks map[string]*api.Task, availableResources api
// addTask removes a task from nodeInfo if it's tracked there, and returns true
// if nodeInfo was modified.
func (nodeInfo *NodeInfo) removeTask(t *api.Task) bool {
if nodeInfo.Tasks == nil {
return false
}
oldTask, ok := nodeInfo.Tasks[t.ID]
if !ok {
return false
@ -52,13 +63,6 @@ func (nodeInfo *NodeInfo) removeTask(t *api.Task) bool {
// addTask adds or updates a task on nodeInfo, and returns true if nodeInfo was
// modified.
func (nodeInfo *NodeInfo) addTask(t *api.Task) bool {
if nodeInfo.Tasks == nil {
nodeInfo.Tasks = make(map[string]*api.Task)
}
if nodeInfo.DesiredRunningTasksCountByService == nil {
nodeInfo.DesiredRunningTasksCountByService = make(map[string]int)
}
oldTask, ok := nodeInfo.Tasks[t.ID]
if ok {
if t.DesiredState == api.TaskStateRunning && oldTask.DesiredState != api.TaskStateRunning {
@ -94,3 +98,35 @@ func taskReservations(spec api.TaskSpec) (reservations api.Resources) {
}
return
}
// taskFailed records a task failure from a given service.
func (nodeInfo *NodeInfo) taskFailed(ctx context.Context, serviceID string) {
expired := 0
now := time.Now()
for _, timestamp := range nodeInfo.recentFailures[serviceID] {
if now.Sub(timestamp) < monitorFailures {
break
}
expired++
}
if len(nodeInfo.recentFailures[serviceID])-expired == maxFailures-1 {
log.G(ctx).Warnf("underweighting node %s for service %s because it experienced %d failures or rejections within %s", nodeInfo.ID, serviceID, maxFailures, monitorFailures.String())
}
nodeInfo.recentFailures[serviceID] = append(nodeInfo.recentFailures[serviceID][expired:], now)
}
// countRecentFailures returns the number of times the service has failed on
// this node within the lookback window monitorFailures.
func (nodeInfo *NodeInfo) countRecentFailures(now time.Time, serviceID string) int {
recentFailureCount := len(nodeInfo.recentFailures[serviceID])
for i := recentFailureCount - 1; i >= 0; i-- {
if now.Sub(nodeInfo.recentFailures[serviceID][i]) > monitorFailures {
recentFailureCount -= i + 1
break
}
}
return recentFailureCount
}

View file

@ -3,6 +3,9 @@ package scheduler
import (
"container/heap"
"errors"
"time"
"github.com/docker/swarmkit/api"
)
var errNodeNotFound = errors.New("node not found in scheduler dataset")
@ -27,6 +30,16 @@ func (ns *nodeSet) nodeInfo(nodeID string) (NodeInfo, error) {
// addOrUpdateNode sets the number of tasks for a given node. It adds the node
// to the set if it wasn't already tracked.
func (ns *nodeSet) addOrUpdateNode(n NodeInfo) {
if n.Tasks == nil {
n.Tasks = make(map[string]*api.Task)
}
if n.DesiredRunningTasksCountByService == nil {
n.DesiredRunningTasksCountByService = make(map[string]int)
}
if n.recentFailures == nil {
n.recentFailures = make(map[string][]time.Time)
}
ns.nodes[n.ID] = n
}

View file

@ -12,6 +12,16 @@ import (
"golang.org/x/net/context"
)
const (
// monitorFailures is the lookback period for counting failures of
// a task to determine if a node is faulty for a particular service.
monitorFailures = 5 * time.Minute
// maxFailures is the number of failures within monitorFailures that
// triggers downweighting of a node in the sorting function.
maxFailures = 5
)
type schedulingDecision struct {
old *api.Task
new *api.Task
@ -54,9 +64,9 @@ func (s *Scheduler) setupTasksList(tx store.ReadTx) error {
tasksByNode := make(map[string]map[string]*api.Task)
for _, t := range tasks {
// Ignore all tasks that have not reached ALLOCATED
// Ignore all tasks that have not reached PENDING
// state and tasks that no longer consume resources.
if t.Status.State < api.TaskStateAllocated || t.Status.State > api.TaskStateRunning {
if t.Status.State < api.TaskStatePending || t.Status.State > api.TaskStateRunning {
continue
}
@ -66,7 +76,7 @@ func (s *Scheduler) setupTasksList(tx store.ReadTx) error {
continue
}
// preassigned tasks need to validate resource requirement on corresponding node
if t.Status.State == api.TaskStateAllocated {
if t.Status.State == api.TaskStatePending {
s.preassignedTasks[t.ID] = t
continue
}
@ -185,9 +195,9 @@ func (s *Scheduler) enqueue(t *api.Task) {
}
func (s *Scheduler) createTask(ctx context.Context, t *api.Task) int {
// Ignore all tasks that have not reached ALLOCATED
// Ignore all tasks that have not reached PENDING
// state, and tasks that no longer consume resources.
if t.Status.State < api.TaskStateAllocated || t.Status.State > api.TaskStateRunning {
if t.Status.State < api.TaskStatePending || t.Status.State > api.TaskStateRunning {
return 0
}
@ -198,7 +208,7 @@ func (s *Scheduler) createTask(ctx context.Context, t *api.Task) int {
return 1
}
if t.Status.State == api.TaskStateAllocated {
if t.Status.State == api.TaskStatePending {
s.preassignedTasks[t.ID] = t
// preassigned tasks do not contribute to running tasks count
return 0
@ -213,9 +223,9 @@ func (s *Scheduler) createTask(ctx context.Context, t *api.Task) int {
}
func (s *Scheduler) updateTask(ctx context.Context, t *api.Task) int {
// Ignore all tasks that have not reached ALLOCATED
// Ignore all tasks that have not reached PENDING
// state.
if t.Status.State < api.TaskStateAllocated {
if t.Status.State < api.TaskStatePending {
return 0
}
@ -224,8 +234,17 @@ func (s *Scheduler) updateTask(ctx context.Context, t *api.Task) int {
// Ignore all tasks that have not reached ALLOCATED
// state, and tasks that no longer consume resources.
if t.Status.State > api.TaskStateRunning {
if oldTask != nil {
s.deleteTask(ctx, oldTask)
if oldTask == nil {
return 1
}
s.deleteTask(ctx, oldTask)
if t.Status.State != oldTask.Status.State &&
(t.Status.State == api.TaskStateFailed || t.Status.State == api.TaskStateRejected) {
nodeInfo, err := s.nodeSet.nodeInfo(t.NodeID)
if err == nil {
nodeInfo.taskFailed(ctx, t.ServiceID)
s.nodeSet.updateNode(nodeInfo)
}
}
return 1
}
@ -240,7 +259,7 @@ func (s *Scheduler) updateTask(ctx context.Context, t *api.Task) int {
return 1
}
if t.Status.State == api.TaskStateAllocated {
if t.Status.State == api.TaskStatePending {
if oldTask != nil {
s.deleteTask(ctx, oldTask)
}
@ -481,7 +500,23 @@ func (s *Scheduler) scheduleTaskGroup(ctx context.Context, taskGroup map[string]
s.pipeline.SetTask(t)
now := time.Now()
nodeLess := func(a *NodeInfo, b *NodeInfo) bool {
// If either node has at least maxFailures recent failures,
// that's the deciding factor.
recentFailuresA := a.countRecentFailures(now, t.ServiceID)
recentFailuresB := b.countRecentFailures(now, t.ServiceID)
if recentFailuresA >= maxFailures || recentFailuresB >= maxFailures {
if recentFailuresA > recentFailuresB {
return false
}
if recentFailuresB > recentFailuresA {
return true
}
}
tasksByServiceA := a.DesiredRunningTasksCountByService[t.ServiceID]
tasksByServiceB := b.DesiredRunningTasksCountByService[t.ServiceID]

View file

@ -755,6 +755,9 @@ func (n *Node) Leave(ctx context.Context, req *api.LeaveRequest) (*api.LeaveResp
return nil, err
}
ctx, cancel := n.WithContext(ctx)
defer cancel()
fields := logrus.Fields{
"node.id": nodeInfo.NodeID,
"method": "(*Node).Leave",
@ -765,20 +768,7 @@ func (n *Node) Leave(ctx context.Context, req *api.LeaveRequest) (*api.LeaveResp
}
log.G(ctx).WithFields(fields).Debug("")
// can't stop the raft node while an async RPC is in progress
n.stopMu.RLock()
defer n.stopMu.RUnlock()
if !n.IsMember() {
return nil, ErrNoRaftMember
}
if !n.isLeader() {
return nil, ErrLostLeadership
}
err = n.RemoveMember(ctx, req.Node.RaftID)
if err != nil {
if err := n.removeMember(ctx, req.Node.RaftID); err != nil {
return nil, err
}
@ -791,12 +781,21 @@ func (n *Node) CanRemoveMember(id uint64) bool {
return n.cluster.CanRemoveMember(n.Config.ID, id)
}
// RemoveMember submits a configuration change to remove a member from the raft cluster
// after checking if the operation would not result in a loss of quorum.
func (n *Node) RemoveMember(ctx context.Context, id uint64) error {
func (n *Node) removeMember(ctx context.Context, id uint64) error {
// can't stop the raft node while an async RPC is in progress
n.stopMu.RLock()
defer n.stopMu.RUnlock()
if !n.IsMember() {
return ErrNoRaftMember
}
if !n.isLeader() {
return ErrLostLeadership
}
n.membershipLock.Lock()
defer n.membershipLock.Unlock()
if n.cluster.CanRemoveMember(n.Config.ID, id) {
cc := raftpb.ConfChange{
ID: id,
@ -804,15 +803,21 @@ func (n *Node) RemoveMember(ctx context.Context, id uint64) error {
NodeID: id,
Context: []byte(""),
}
ctx, cancel := n.WithContext(ctx)
err := n.configure(ctx, cc)
cancel()
return err
}
return ErrCannotRemoveMember
}
// RemoveMember submits a configuration change to remove a member from the raft cluster
// after checking if the operation would not result in a loss of quorum.
func (n *Node) RemoveMember(ctx context.Context, id uint64) error {
ctx, cancel := n.WithContext(ctx)
defer cancel()
return n.removeMember(ctx, id)
}
// ProcessRaftMessage calls 'Step' which advances the
// raft state machine with the provided message on the
// receiving node

View file

@ -240,7 +240,7 @@ func (s *MemoryStore) update(proposer state.Proposer, cb func(Tx) error) error {
sa, err = tx.changelistStoreActions()
if err == nil {
if sa != nil {
if len(sa) != 0 {
err = proposer.ProposeValue(context.Background(), sa, func() {
memDBTx.Commit()
})
@ -350,7 +350,7 @@ func (batch *Batch) commit() error {
sa, batch.err = batch.tx.changelistStoreActions()
if batch.err == nil {
if sa != nil {
if len(sa) != 0 {
batch.err = batch.store.proposer.ProposeValue(context.Background(), sa, func() {
batch.tx.memDBTx.Commit()
})

View file

@ -1,11 +1,11 @@
package store
import (
"fmt"
"strconv"
"strings"
"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/api/naming"
"github.com/docker/swarmkit/manager/state"
memdb "github.com/hashicorp/go-memdb"
)
@ -112,26 +112,6 @@ func init() {
})
}
// TaskName returns the task name from Annotations.Name,
// and, in case Annotations.Name is missing, fallback
// to construct the name from othere information.
func TaskName(t *api.Task) string {
name := t.Annotations.Name
if name == "" {
// If Task name is not assigned then calculated name is used like before.
// This might be removed in the future.
// We use the following scheme for Task name:
// Name := <ServiceAnnotations.Name>.<Slot>.<TaskID> (replicated mode)
// := <ServiceAnnotations.Name>.<NodeID>.<TaskID> (global mode)
if t.Slot != 0 {
name = fmt.Sprintf("%v.%v.%v", t.ServiceAnnotations.Name, t.Slot, t.ID)
} else {
name = fmt.Sprintf("%v.%v.%v", t.ServiceAnnotations.Name, t.NodeID, t.ID)
}
}
return name
}
type taskEntry struct {
*api.Task
}
@ -245,7 +225,7 @@ func (ti taskIndexerByName) FromObject(obj interface{}) (bool, []byte, error) {
panic("unexpected type passed to FromObject")
}
name := TaskName(t.Task)
name := naming.Task(t.Task)
// Add the null character as a terminator
return true, []byte(strings.ToLower(name) + "\x00"), nil

View file

@ -563,12 +563,17 @@ func Watch(queue *watch.Queue, specifiers ...Event) (eventq chan events.Event, c
if len(specifiers) == 0 {
return queue.Watch()
}
return queue.CallbackWatch(events.MatcherFunc(func(event events.Event) bool {
return queue.CallbackWatch(Matcher(specifiers...))
}
// Matcher returns an events.Matcher that matches the specifiers with OR logic.
func Matcher(specifiers ...Event) events.MatcherFunc {
return events.MatcherFunc(func(event events.Event) bool {
for _, s := range specifiers {
if s.matches(event) {
return true
}
}
return false
}))
})
}

View file

@ -104,7 +104,7 @@ type Node struct {
err error
agent *agent.Agent
manager *manager.Manager
roleChangeReq chan api.NodeRole // used to send role updates from the dispatcher api on promotion/demotion
notifyNodeChange chan *api.Node // used to send role updates from the dispatcher api on promotion/demotion
}
// RemoteAPIAddr returns address on which remote manager api listens.
@ -148,7 +148,7 @@ func New(c *Config) (*Node, error) {
closed: make(chan struct{}),
ready: make(chan struct{}),
certificateRequested: make(chan struct{}),
roleChangeReq: make(chan api.NodeRole, 1),
notifyNodeChange: make(chan *api.Node, 1),
}
n.roleCond = sync.NewCond(n.RLocker())
n.connCond = sync.NewCond(n.RLocker())
@ -248,16 +248,29 @@ func (n *Node) run(ctx context.Context) (err error) {
}
forceCertRenewal := make(chan struct{})
renewCert := func() {
select {
case forceCertRenewal <- struct{}{}:
case <-ctx.Done():
}
}
go func() {
for {
select {
case <-ctx.Done():
return
case apirole := <-n.roleChangeReq:
case node := <-n.notifyNodeChange:
// If the server is sending us a ForceRenewal State, renew
if node.Certificate.Status.State == api.IssuanceStateRotate {
renewCert()
continue
}
n.Lock()
// If we got a role change, renew
lastRole := n.role
role := ca.WorkerRole
if apirole == api.NodeRoleManager {
if node.Spec.Role == api.NodeRoleManager {
role = ca.ManagerRole
}
if lastRole == role {
@ -270,11 +283,7 @@ func (n *Node) run(ctx context.Context) (err error) {
n.roleCond.Broadcast()
}
n.Unlock()
select {
case forceCertRenewal <- struct{}{}:
case <-ctx.Done():
return
}
renewCert()
}
}
}()
@ -380,7 +389,7 @@ func (n *Node) runAgent(ctx context.Context, db *bolt.DB, creds credentials.Tran
Managers: n.remotes,
Executor: n.config.Executor,
DB: db,
NotifyRoleChange: n.roleChangeReq,
NotifyNodeChange: n.notifyNodeChange,
Credentials: creds,
})
if err != nil {

View file

@ -1,3 +1,3 @@
package plugin
//go:generate protoc -I.:/usr/local --gogoswarm_out=import_path=github.com/docker/swarmkit/protobuf/plugin,Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/protoc-gen-gogo/descriptor:. plugin.proto
//go:generate protoc -I.:../../vendor/github.com/gogo/protobuf/protobuf --gogoswarm_out=import_path=github.com/docker/swarmkit/protobuf/plugin,Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/protoc-gen-gogo/descriptor:. plugin.proto