From e1affcf1a816b624f26776a2ae68ad4c43deb90e Mon Sep 17 00:00:00 2001 From: Aaron Lehmann Date: Tue, 13 Dec 2016 17:19:53 -0800 Subject: [PATCH 1/4] Revendor swarmkit Signed-off-by: Aaron Lehmann Upstream-commit: 423ba6f223ac167fd84b96eebd94679e4ec8e52c Component: engine --- components/engine/vendor.conf | 2 +- .../github.com/docker/swarmkit/api/ca.pb.go | 137 ++++++------------ .../github.com/docker/swarmkit/api/ca.proto | 1 - .../docker/swarmkit/ca/certificates.go | 108 ++++++-------- .../github.com/docker/swarmkit/ca/config.go | 13 +- .../github.com/docker/swarmkit/ca/server.go | 10 +- .../networkallocator/networkallocator.go | 2 +- .../swarmkit/manager/scheduler/filter.go | 39 +++-- .../swarmkit/manager/scheduler/pipeline.go | 7 +- .../swarmkit/manager/state/raft/raft.go | 2 - 10 files changed, 127 insertions(+), 194 deletions(-) diff --git a/components/engine/vendor.conf b/components/engine/vendor.conf index 42ea2e9361..412d7a824e 100644 --- a/components/engine/vendor.conf +++ b/components/engine/vendor.conf @@ -100,7 +100,7 @@ github.com/docker/containerd 03e5862ec0d8d3b3f750e19fca3ee367e13c090e github.com/tonistiigi/fifo 1405643975692217d6720f8b54aeee1bf2cd5cf4 # cluster -github.com/docker/swarmkit 5a6df4b07d83e6dbd72e39e354c325dc9b91850f +github.com/docker/swarmkit 9e4bd71a1690cd27400714fcd98c329b752b5c4c github.com/golang/mock bd3c8e81be01eef76d4b503f5e687d2d1354d2d9 github.com/gogo/protobuf v0.3 github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a diff --git a/components/engine/vendor/github.com/docker/swarmkit/api/ca.pb.go b/components/engine/vendor/github.com/docker/swarmkit/api/ca.pb.go index d1c13f2c45..619421b3b0 100644 --- a/components/engine/vendor/github.com/docker/swarmkit/api/ca.pb.go +++ b/components/engine/vendor/github.com/docker/swarmkit/api/ca.pb.go @@ -43,9 +43,8 @@ func (*NodeCertificateStatusRequest) ProtoMessage() {} func (*NodeCertificateStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorCa, []int{0} } type NodeCertificateStatusResponse struct { - Status *IssuanceStatus `protobuf:"bytes,1,opt,name=status" json:"status,omitempty"` - Certificate *Certificate `protobuf:"bytes,2,opt,name=certificate" json:"certificate,omitempty"` - RootCABundle []byte `protobuf:"bytes,3,opt,name=root_ca_bundle,json=rootCaBundle,proto3" json:"root_ca_bundle,omitempty"` + Status *IssuanceStatus `protobuf:"bytes,1,opt,name=status" json:"status,omitempty"` + Certificate *Certificate `protobuf:"bytes,2,opt,name=certificate" json:"certificate,omitempty"` } func (m *NodeCertificateStatusResponse) Reset() { *m = NodeCertificateStatusResponse{} } @@ -184,9 +183,8 @@ func (m *NodeCertificateStatusResponse) Copy() *NodeCertificateStatusResponse { } o := &NodeCertificateStatusResponse{ - Status: m.Status.Copy(), - Certificate: m.Certificate.Copy(), - RootCABundle: m.RootCABundle, + Status: m.Status.Copy(), + Certificate: m.Certificate.Copy(), } return o @@ -279,7 +277,7 @@ func (this *NodeCertificateStatusResponse) GoString() string { if this == nil { return "nil" } - s := make([]string, 0, 7) + s := make([]string, 0, 6) s = append(s, "&api.NodeCertificateStatusResponse{") if this.Status != nil { s = append(s, "Status: "+fmt.Sprintf("%#v", this.Status)+",\n") @@ -287,7 +285,6 @@ func (this *NodeCertificateStatusResponse) GoString() string { if this.Certificate != nil { s = append(s, "Certificate: "+fmt.Sprintf("%#v", this.Certificate)+",\n") } - s = append(s, "RootCABundle: "+fmt.Sprintf("%#v", this.RootCABundle)+",\n") s = append(s, "}") return strings.Join(s, "") } @@ -646,12 +643,6 @@ func (m *NodeCertificateStatusResponse) MarshalTo(data []byte) (int, error) { } i += n2 } - if len(m.RootCABundle) > 0 { - data[i] = 0x1a - i++ - i = encodeVarintCa(data, i, uint64(len(m.RootCABundle))) - i += copy(data[i:], m.RootCABundle) - } return i, nil } @@ -1121,10 +1112,6 @@ func (m *NodeCertificateStatusResponse) Size() (n int) { l = m.Certificate.Size() n += 1 + l + sovCa(uint64(l)) } - l = len(m.RootCABundle) - if l > 0 { - n += 1 + l + sovCa(uint64(l)) - } return n } @@ -1225,7 +1212,6 @@ func (this *NodeCertificateStatusResponse) String() string { s := strings.Join([]string{`&NodeCertificateStatusResponse{`, `Status:` + strings.Replace(fmt.Sprintf("%v", this.Status), "IssuanceStatus", "IssuanceStatus", 1) + `,`, `Certificate:` + strings.Replace(fmt.Sprintf("%v", this.Certificate), "Certificate", "Certificate", 1) + `,`, - `RootCABundle:` + fmt.Sprintf("%v", this.RootCABundle) + `,`, `}`, }, "") return s @@ -1475,37 +1461,6 @@ func (m *NodeCertificateStatusResponse) Unmarshal(data []byte) error { return err } iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field RootCABundle", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCa - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - byteLen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthCa - } - postIndex := iNdEx + byteLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.RootCABundle = append(m.RootCABundle[:0], data[iNdEx:postIndex]...) - if m.RootCABundle == nil { - m.RootCABundle = []byte{} - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipCa(data[iNdEx:]) @@ -2173,46 +2128,44 @@ var ( func init() { proto.RegisterFile("ca.proto", fileDescriptorCa) } var fileDescriptorCa = []byte{ - // 651 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x54, 0xc1, 0x6e, 0xd3, 0x4a, - 0x14, 0xed, 0xb8, 0x7d, 0x69, 0x7b, 0xe3, 0x97, 0x56, 0xd3, 0x56, 0x0a, 0x69, 0xea, 0x54, 0x66, - 0xd1, 0xb2, 0x20, 0x6d, 0x03, 0x62, 0x01, 0x1b, 0xe2, 0x20, 0x55, 0x15, 0x2a, 0x42, 0x53, 0xc1, - 0x36, 0x9a, 0x38, 0x43, 0xb0, 0xe2, 0x78, 0x8c, 0x67, 0x5c, 0xc8, 0x0e, 0x09, 0xc4, 0x1f, 0x20, - 0xf8, 0x0a, 0xbe, 0xa3, 0x62, 0x85, 0x84, 0x84, 0x58, 0x45, 0xd4, 0x1f, 0x80, 0xf8, 0x04, 0xe4, - 0xb1, 0x43, 0x93, 0xc6, 0x09, 0x65, 0x15, 0xcf, 0xf5, 0x39, 0xe7, 0xde, 0x73, 0x7c, 0x33, 0xb0, - 0x64, 0xd3, 0xaa, 0x1f, 0x70, 0xc9, 0x31, 0x6e, 0x73, 0xbb, 0xcb, 0x82, 0xaa, 0x78, 0x49, 0x83, - 0x5e, 0xd7, 0x91, 0xd5, 0xd3, 0x83, 0x52, 0x5e, 0xf6, 0x7d, 0x26, 0x12, 0x40, 0x29, 0x2f, 0x7c, - 0x66, 0x0f, 0x0f, 0xeb, 0x1d, 0xde, 0xe1, 0xea, 0x71, 0x2f, 0x7e, 0x4a, 0xab, 0x6b, 0xbe, 0x1b, - 0x76, 0x1c, 0x6f, 0x2f, 0xf9, 0x49, 0x8a, 0x66, 0x03, 0xca, 0x8f, 0x78, 0x9b, 0x35, 0x58, 0x20, - 0x9d, 0x67, 0x8e, 0x4d, 0x25, 0x3b, 0x91, 0x54, 0x86, 0x82, 0xb0, 0x17, 0x21, 0x13, 0x12, 0x5f, - 0x87, 0x45, 0x8f, 0xb7, 0x59, 0xd3, 0x69, 0x17, 0xd1, 0x36, 0xda, 0x5d, 0xb6, 0x20, 0x1a, 0x54, - 0x72, 0x31, 0xe5, 0xe8, 0x01, 0xc9, 0xc5, 0xaf, 0x8e, 0xda, 0xe6, 0x37, 0x04, 0x5b, 0x53, 0x54, - 0x84, 0xcf, 0x3d, 0xc1, 0xf0, 0x5d, 0xc8, 0x09, 0x55, 0x51, 0x2a, 0xf9, 0x9a, 0x59, 0x9d, 0x34, - 0x54, 0x3d, 0x12, 0x22, 0xa4, 0x9e, 0x3d, 0xe4, 0xa6, 0x0c, 0x5c, 0x87, 0xbc, 0x7d, 0x21, 0x5c, - 0xd4, 0x94, 0x40, 0x25, 0x4b, 0x60, 0xa4, 0x3f, 0x19, 0xe5, 0xe0, 0x3b, 0x50, 0x08, 0x38, 0x97, - 0x4d, 0x9b, 0x36, 0x5b, 0xa1, 0xd7, 0x76, 0x59, 0x71, 0x7e, 0x1b, 0xed, 0xea, 0xd6, 0x6a, 0x34, - 0xa8, 0xe8, 0x84, 0x73, 0xd9, 0xa8, 0x5b, 0xaa, 0x4e, 0xf4, 0x18, 0xd7, 0xa0, 0xc9, 0xc9, 0xfc, - 0x8a, 0x60, 0x33, 0x9e, 0x8a, 0x5d, 0x72, 0x37, 0x4c, 0xe7, 0x36, 0x2c, 0x04, 0xdc, 0x65, 0xca, - 0x54, 0xa1, 0x56, 0xce, 0x9a, 0x29, 0x66, 0x12, 0xee, 0x32, 0x4b, 0x2b, 0x22, 0xa2, 0xd0, 0xf8, - 0x1a, 0xcc, 0xdb, 0x22, 0x50, 0x46, 0x74, 0x6b, 0x31, 0x1a, 0x54, 0xe6, 0x1b, 0x27, 0x84, 0xc4, - 0x35, 0xbc, 0x0e, 0xff, 0x49, 0xde, 0x65, 0x9e, 0x9a, 0x6f, 0x99, 0x24, 0x07, 0x7c, 0x0c, 0x3a, - 0x3d, 0xa5, 0x8e, 0x4b, 0x5b, 0x8e, 0xeb, 0xc8, 0x7e, 0x71, 0x41, 0xb5, 0xbb, 0x31, 0xad, 0xdd, - 0x89, 0xcf, 0xec, 0x6a, 0x7d, 0x84, 0x40, 0xc6, 0xe8, 0xe6, 0x7b, 0x04, 0xe5, 0x6c, 0x57, 0xe9, - 0xd7, 0xba, 0xca, 0x47, 0xc7, 0x8f, 0x61, 0x45, 0x81, 0x7a, 0xac, 0xd7, 0x62, 0x81, 0x78, 0xee, - 0xf8, 0xca, 0x51, 0xa1, 0xb6, 0x33, 0x73, 0xae, 0xe3, 0x3f, 0x70, 0x52, 0x88, 0xf9, 0x17, 0x67, - 0x73, 0x0b, 0x36, 0x0f, 0x99, 0x4c, 0x3e, 0xc7, 0x64, 0xd8, 0xe6, 0x7d, 0x28, 0x67, 0xbf, 0x4e, - 0xa7, 0xde, 0x1e, 0xdf, 0x93, 0x78, 0x72, 0x7d, 0x6c, 0x0d, 0xcc, 0x0d, 0x58, 0x3b, 0x64, 0xf2, - 0x89, 0xe7, 0x72, 0xbb, 0xfb, 0x90, 0xf5, 0x87, 0xc2, 0x01, 0xac, 0x8f, 0x97, 0x53, 0xc1, 0x2d, - 0x80, 0x50, 0x15, 0x9b, 0x5d, 0xd6, 0x4f, 0xf5, 0x96, 0xc3, 0x21, 0x0c, 0xdf, 0x83, 0xc5, 0x53, - 0x16, 0x08, 0x87, 0x7b, 0xe9, 0x4e, 0x6e, 0x66, 0x19, 0x7f, 0x9a, 0x40, 0xac, 0x85, 0xb3, 0x41, - 0x65, 0x8e, 0x0c, 0x19, 0xb5, 0xb7, 0x1a, 0x68, 0x8d, 0x3a, 0x7e, 0x83, 0x54, 0xef, 0x09, 0x53, - 0x78, 0x2f, 0x4b, 0x6b, 0x46, 0x3a, 0xa5, 0xfd, 0xab, 0x13, 0x12, 0x7b, 0xe6, 0xd2, 0xe7, 0x4f, - 0x3f, 0x3f, 0x6a, 0xda, 0x2a, 0xc2, 0xaf, 0x40, 0x1f, 0x0d, 0x00, 0xef, 0x4c, 0xd1, 0xba, 0x9c, - 0x5c, 0x69, 0xf7, 0xef, 0xc0, 0xb4, 0xd9, 0x86, 0x6a, 0xb6, 0x02, 0xff, 0x2b, 0xe4, 0xcd, 0x1e, - 0xf5, 0x68, 0x87, 0x05, 0xb5, 0x0f, 0x1a, 0xa8, 0xbd, 0x4a, 0xa3, 0xc8, 0xda, 0xca, 0xec, 0x28, - 0x66, 0xfc, 0x2b, 0xb3, 0xa3, 0x98, 0xb5, 0xf0, 0x23, 0x51, 0xbc, 0x43, 0xb0, 0x91, 0x79, 0x95, - 0xe1, 0xfd, 0x69, 0x6b, 0x3d, 0xed, 0xee, 0x2c, 0x1d, 0xfc, 0x03, 0xe3, 0xf2, 0x20, 0x56, 0xf9, - 0xec, 0xdc, 0x98, 0xfb, 0x7e, 0x6e, 0xcc, 0xfd, 0x3a, 0x37, 0xd0, 0xeb, 0xc8, 0x40, 0x67, 0x91, - 0x81, 0xbe, 0x44, 0x06, 0xfa, 0x11, 0x19, 0xa8, 0x95, 0x53, 0xb7, 0xf7, 0xad, 0xdf, 0x01, 0x00, - 0x00, 0xff, 0xff, 0x69, 0xb6, 0x7e, 0x90, 0x22, 0x06, 0x00, 0x00, + // 615 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x54, 0xcd, 0x6e, 0xd3, 0x4c, + 0x14, 0xed, 0xb8, 0xfd, 0xd2, 0xf6, 0x26, 0x5f, 0x8b, 0xa6, 0xad, 0x14, 0xd2, 0xd4, 0xa9, 0xcc, + 0xa2, 0x65, 0x81, 0xd3, 0x06, 0x56, 0xb0, 0x21, 0x09, 0x52, 0x15, 0xa1, 0x22, 0x34, 0x11, 0x6c, + 0x2b, 0xc7, 0x19, 0x82, 0x15, 0xc7, 0x63, 0x3c, 0xe3, 0x40, 0x76, 0x48, 0x20, 0xde, 0x00, 0xc1, + 0x8a, 0x47, 0xe0, 0x39, 0x22, 0x56, 0x48, 0x6c, 0x58, 0x45, 0xc4, 0x0f, 0x80, 0x78, 0x04, 0xe4, + 0xb1, 0x4d, 0xf3, 0xe3, 0x84, 0xb2, 0xf2, 0xcc, 0x9d, 0x73, 0xce, 0xbd, 0xf7, 0xcc, 0xf5, 0xc0, + 0x86, 0x69, 0xe8, 0xae, 0xc7, 0x04, 0xc3, 0xb8, 0xcd, 0xcc, 0x2e, 0xf5, 0x74, 0xfe, 0xd2, 0xf0, + 0x7a, 0x5d, 0x4b, 0xe8, 0xfd, 0xd3, 0x42, 0x56, 0x0c, 0x5c, 0xca, 0x23, 0x40, 0x21, 0xcb, 0x5d, + 0x6a, 0x26, 0x9b, 0xdd, 0x0e, 0xeb, 0x30, 0xb9, 0x2c, 0x87, 0xab, 0x38, 0xba, 0xe3, 0xda, 0x7e, + 0xc7, 0x72, 0xca, 0xd1, 0x27, 0x0a, 0x6a, 0x75, 0x28, 0x3e, 0x62, 0x6d, 0x5a, 0xa7, 0x9e, 0xb0, + 0x9e, 0x59, 0xa6, 0x21, 0x68, 0x53, 0x18, 0xc2, 0xe7, 0x84, 0xbe, 0xf0, 0x29, 0x17, 0xf8, 0x06, + 0xac, 0x3b, 0xac, 0x4d, 0x2f, 0xac, 0x76, 0x1e, 0x1d, 0xa2, 0xe3, 0xcd, 0x1a, 0x04, 0xa3, 0x52, + 0x26, 0xa4, 0x34, 0x1e, 0x90, 0x4c, 0x78, 0xd4, 0x68, 0x6b, 0x9f, 0x10, 0x1c, 0x2c, 0x50, 0xe1, + 0x2e, 0x73, 0x38, 0xc5, 0x77, 0x21, 0xc3, 0x65, 0x44, 0xaa, 0x64, 0x2b, 0x9a, 0x3e, 0xdf, 0x90, + 0xde, 0xe0, 0xdc, 0x37, 0x1c, 0x33, 0xe1, 0xc6, 0x0c, 0x5c, 0x85, 0xac, 0x79, 0x29, 0x9c, 0x57, + 0xa4, 0x40, 0x29, 0x4d, 0x60, 0x22, 0x3f, 0x99, 0xe4, 0x68, 0xdf, 0x10, 0xec, 0x87, 0xea, 0x74, + 0xa6, 0xca, 0xa4, 0xcb, 0x3b, 0xb0, 0xe6, 0x31, 0x9b, 0xca, 0xe2, 0xb6, 0x2a, 0xc5, 0x34, 0xed, + 0x90, 0x49, 0x98, 0x4d, 0x6b, 0x4a, 0x1e, 0x11, 0x89, 0xc6, 0xd7, 0x61, 0xd5, 0xe4, 0x9e, 0x2c, + 0x28, 0x57, 0x5b, 0x0f, 0x46, 0xa5, 0xd5, 0x7a, 0x93, 0x90, 0x30, 0x86, 0x77, 0xe1, 0x3f, 0xc1, + 0xba, 0xd4, 0xc9, 0xaf, 0x86, 0xa6, 0x91, 0x68, 0x83, 0xcf, 0x21, 0x67, 0xf4, 0x0d, 0xcb, 0x36, + 0x5a, 0x96, 0x6d, 0x89, 0x41, 0x7e, 0x4d, 0xa6, 0xbb, 0xb9, 0x28, 0x5d, 0xd3, 0xa5, 0xa6, 0x5e, + 0x9d, 0x20, 0x90, 0x29, 0xba, 0xf6, 0x1e, 0x41, 0x31, 0xbd, 0xab, 0xd8, 0xf5, 0xab, 0x5c, 0x1e, + 0x7e, 0x0c, 0xdb, 0x12, 0xd4, 0xa3, 0xbd, 0x16, 0xf5, 0xf8, 0x73, 0xcb, 0x95, 0x1d, 0x6d, 0x55, + 0x8e, 0x96, 0xd6, 0x75, 0xfe, 0x07, 0x4e, 0xb6, 0x42, 0xfe, 0xe5, 0x5e, 0x3b, 0x80, 0xfd, 0x33, + 0x2a, 0x08, 0x63, 0xa2, 0x5e, 0x9d, 0x37, 0x5b, 0xbb, 0x0f, 0xc5, 0xf4, 0xe3, 0xb8, 0xea, 0xc3, + 0xe9, 0xfb, 0x0e, 0x2b, 0xcf, 0x4d, 0x5f, 0xe7, 0x1e, 0xec, 0x9c, 0x51, 0xf1, 0xc4, 0xb1, 0x99, + 0xd9, 0x7d, 0x48, 0x07, 0x89, 0xb0, 0x07, 0xbb, 0xd3, 0xe1, 0x58, 0xf0, 0x00, 0xc0, 0x97, 0xc1, + 0x8b, 0x2e, 0x1d, 0xc4, 0x7a, 0x9b, 0x7e, 0x02, 0xc3, 0xf7, 0x60, 0xbd, 0x4f, 0x3d, 0x6e, 0x31, + 0x27, 0x9e, 0xad, 0xfd, 0xb4, 0xc6, 0x9f, 0x46, 0x90, 0xda, 0xda, 0x70, 0x54, 0x5a, 0x21, 0x09, + 0xa3, 0xf2, 0x56, 0x01, 0xa5, 0x5e, 0xc5, 0x6f, 0x90, 0xcc, 0x3d, 0xd7, 0x14, 0x2e, 0xa7, 0x69, + 0x2d, 0x71, 0xa7, 0x70, 0x72, 0x75, 0x42, 0xd4, 0x9e, 0xb6, 0xf1, 0xe5, 0xf3, 0xcf, 0x8f, 0x8a, + 0x72, 0x0d, 0xe1, 0x57, 0x90, 0x9b, 0x34, 0x00, 0x1f, 0x2d, 0xd0, 0x9a, 0x75, 0xae, 0x70, 0xfc, + 0x77, 0x60, 0x9c, 0x6c, 0x4f, 0x26, 0xdb, 0x86, 0xff, 0x25, 0xf2, 0x56, 0xcf, 0x70, 0x8c, 0x0e, + 0xf5, 0x2a, 0x1f, 0x14, 0x90, 0x73, 0x15, 0x5b, 0x91, 0x36, 0x95, 0xe9, 0x56, 0x2c, 0xf9, 0x2b, + 0xd3, 0xad, 0x58, 0x36, 0xf0, 0x13, 0x56, 0xbc, 0x43, 0xb0, 0x97, 0xfa, 0x24, 0xe1, 0x93, 0x45, + 0x63, 0xbd, 0xe8, 0x0d, 0x2c, 0x9c, 0xfe, 0x03, 0x63, 0xb6, 0x90, 0x5a, 0x71, 0x38, 0x56, 0x57, + 0xbe, 0x8f, 0xd5, 0x95, 0x5f, 0x63, 0x15, 0xbd, 0x0e, 0x54, 0x34, 0x0c, 0x54, 0xf4, 0x35, 0x50, + 0xd1, 0x8f, 0x40, 0x45, 0xad, 0x8c, 0x7c, 0x85, 0x6f, 0xff, 0x0e, 0x00, 0x00, 0xff, 0xff, 0xcf, + 0xc4, 0x68, 0xc2, 0xea, 0x05, 0x00, 0x00, } diff --git a/components/engine/vendor/github.com/docker/swarmkit/api/ca.proto b/components/engine/vendor/github.com/docker/swarmkit/api/ca.proto index 1d1cfa2193..be4b4a58c9 100644 --- a/components/engine/vendor/github.com/docker/swarmkit/api/ca.proto +++ b/components/engine/vendor/github.com/docker/swarmkit/api/ca.proto @@ -36,7 +36,6 @@ message NodeCertificateStatusRequest { message NodeCertificateStatusResponse { IssuanceStatus status = 1; Certificate certificate = 2; - bytes root_ca_bundle = 3 [(gogoproto.customname) = "RootCABundle"]; } message IssueNodeCertificateRequest { diff --git a/components/engine/vendor/github.com/docker/swarmkit/ca/certificates.go b/components/engine/vendor/github.com/docker/swarmkit/ca/certificates.go index 75b604a69e..6eb6e4dd74 100644 --- a/components/engine/vendor/github.com/docker/swarmkit/ca/certificates.go +++ b/components/engine/vendor/github.com/docker/swarmkit/ca/certificates.go @@ -102,15 +102,13 @@ type RootCA struct { // Key will only be used by the original manager to put the private // key-material in raft, no signing operations depend on it. Key []byte - // Cert includes the PEM encoded Certificate bundle for the Root CA + // Cert includes the PEM encoded Certificate for the Root CA Cert []byte Pool *x509.CertPool // Digest of the serialized bytes of the certificate Digest digest.Digest // This signer will be nil if the node doesn't have the appropriate key material Signer cfsigner.Signer - // Path stores the location on disk where the RootCA lives - Path CertPaths } // CanSign ensures that the signer has all three necessary elements needed to operate @@ -165,9 +163,9 @@ func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, kw KeyWrit // Get the remote manager to issue a CA signed certificate for this node // Retry up to 5 times in case the manager we first try to contact isn't // responding properly (for example, it may have just been demoted). - var response *api.NodeCertificateStatusResponse + var signedCert []byte for i := 0; i != 5; i++ { - response, err = GetRemoteSignedCertificate(ctx, csr, rca.Pool, config) + signedCert, err = GetRemoteSignedCertificate(ctx, csr, rca.Pool, config) if err == nil { break } @@ -179,7 +177,7 @@ func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, kw KeyWrit // Доверяй, но проверяй. // Before we overwrite our local key + certificate, let's make sure the server gave us one that is valid // Create an X509Cert so we can .Verify() - certBlock, _ := pem.Decode(response.Certificate.Certificate) + certBlock, _ := pem.Decode(signedCert) if certBlock == nil { return nil, errors.New("failed to parse certificate PEM") } @@ -187,34 +185,17 @@ func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, kw KeyWrit if err != nil { return nil, err } - // We retrieve the certificate with the current root pool, so we know this was issued by a legitimate manager. - // However, there might have been a server-side root rotation, so we verify this cert with a new pool. - // If we got a valid response.RootCABundle, turn it into a Pool, and verify the newly minted certificate using it. - var ( - newRootErr error - newRootCA RootCA - ) - rootCAPool := rca.Pool - if response.RootCABundle != nil { - newRootCA, newRootErr = NewRootCA(response.RootCABundle, nil, rca.Path, time.Minute) - if newRootErr == nil { - // The response.RootCABundle we got from the remote server seems to be good, use it - rootCAPool = newRootCA.Pool - } - } - - // Create VerifyOptions with either the new certificate bundle, or the old pool + // Include our current root pool opts := x509.VerifyOptions{ - Roots: rootCAPool, + Roots: rca.Pool, } - - // Check to see if this certificate was signed by one of the CAs, and isn't expired + // Check to see if this certificate was signed by our CA, and isn't expired if _, err := X509Cert.Verify(opts); err != nil { return nil, err } // Create a valid TLSKeyPair out of the PEM encoded private key and certificate - tlsKeyPair, err := tls.X509KeyPair(response.Certificate.Certificate, key) + tlsKeyPair, err := tls.X509KeyPair(signedCert, key) if err != nil { return nil, err } @@ -230,16 +211,7 @@ func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, kw KeyWrit return nil, err } - // If a CA certificate bundle exists it has been validated before. If it's different, let's write it to disk. - // Root rotation should always happen by appending a new CA cert, and later removing the old one, - // so it's safer to do it in this order of operations (write root, write certificate) - if newRootErr == nil && !bytes.Equal(rca.Cert, response.RootCABundle) { - if err := newRootCA.saveCertificate(); err != nil { - return nil, err - } - } - - if err := kw.Write(response.Certificate.Certificate, key, kekUpdate); err != nil { + if err := kw.Write(signedCert, key, kekUpdate); err != nil { return nil, err } @@ -344,28 +316,10 @@ func (rca *RootCA) AppendFirstRootPEM(cert []byte) ([]byte, error) { return certChain, nil } -func (rca *RootCA) saveCertificate() error { - if rca.Cert == nil { - return errors.New("no valid certificate bundle found") - - } - if rca.Path.Cert == "" { - return errors.New("no path found for this root CA") - } - - // Make sure the necessary dirs exist and they are writable - err := os.MkdirAll(filepath.Dir(rca.Path.Cert), 0755) - if err != nil { - return err - } - - return ioutils.AtomicWriteFile(rca.Path.Cert, rca.Cert, 0644) -} - // NewRootCA creates a new RootCA object from unparsed PEM cert bundle and key byte // slices. key may be nil, and in this case NewRootCA will return a RootCA // without a signer. -func NewRootCA(certBytes, keyBytes []byte, paths CertPaths, certExpiry time.Duration) (RootCA, error) { +func NewRootCA(certBytes, keyBytes []byte, certExpiry time.Duration) (RootCA, error) { // Parse all the certificates in the cert bundle parsedCerts, err := helpers.ParseCertificatesPEM(certBytes) if err != nil { @@ -391,7 +345,7 @@ func NewRootCA(certBytes, keyBytes []byte, paths CertPaths, certExpiry time.Dura if len(keyBytes) == 0 { // This RootCA does not have a valid signer. - return RootCA{Cert: certBytes, Digest: digest, Pool: pool, Path: paths}, nil + return RootCA{Cert: certBytes, Digest: digest, Pool: pool}, nil } var ( @@ -433,7 +387,7 @@ func NewRootCA(certBytes, keyBytes []byte, paths CertPaths, certExpiry time.Dura keyBlock, _ := pem.Decode(keyBytes) if keyBlock == nil { // This RootCA does not have a valid signer. - return RootCA{Cert: certBytes, Digest: digest, Pool: pool, Path: paths}, nil + return RootCA{Cert: certBytes, Digest: digest, Pool: pool}, nil } if passphraseStr != "" && !x509.IsEncryptedPEMBlock(keyBlock) { keyBytes, err = EncryptECPrivateKey(keyBytes, passphraseStr) @@ -442,7 +396,7 @@ func NewRootCA(certBytes, keyBytes []byte, paths CertPaths, certExpiry time.Dura } } - return RootCA{Signer: signer, Key: keyBytes, Digest: digest, Cert: certBytes, Pool: pool, Path: paths}, nil + return RootCA{Signer: signer, Key: keyBytes, Digest: digest, Cert: certBytes, Pool: pool}, nil } func ensureCertKeyMatch(cert *x509.Certificate, key crypto.PublicKey) error { @@ -460,7 +414,8 @@ func ensureCertKeyMatch(cert *x509.Certificate, key crypto.PublicKey) error { return errors.New("certificate key mismatch") } -// GetLocalRootCA returns the PEM-encoded root CA Certificate if it exists +// GetLocalRootCA validates if the contents of the file are a valid self-signed +// CA certificate, and returns the PEM-encoded Certificate if so func GetLocalRootCA(paths CertPaths) (RootCA, error) { // Check if we have a Certificate file cert, err := ioutil.ReadFile(paths.Cert) @@ -472,7 +427,17 @@ func GetLocalRootCA(paths CertPaths) (RootCA, error) { return RootCA{}, err } - return NewRootCA(cert, nil, paths, DefaultNodeCertExpiration) + key, err := ioutil.ReadFile(paths.Key) + if err != nil { + if !os.IsNotExist(err) { + return RootCA{}, err + } + // There may not be a local key. It's okay to pass in a nil + // key. We'll get a root CA without a signer. + key = nil + } + + return NewRootCA(cert, key, DefaultNodeCertExpiration) } func getGRPCConnection(creds credentials.TransportCredentials, r remotes.Remotes) (*grpc.ClientConn, api.Peer, error) { @@ -565,13 +530,13 @@ func CreateRootCA(rootCN string, paths CertPaths) (RootCA, error) { return RootCA{}, err } - rootCA, err := NewRootCA(cert, key, paths, DefaultNodeCertExpiration) + rootCA, err := NewRootCA(cert, key, DefaultNodeCertExpiration) if err != nil { return RootCA{}, err } // save the cert to disk - if err := rootCA.saveCertificate(); err != nil { + if err := saveRootCA(rootCA, paths); err != nil { return RootCA{}, err } @@ -580,7 +545,7 @@ func CreateRootCA(rootCN string, paths CertPaths) (RootCA, error) { // GetRemoteSignedCertificate submits a CSR to a remote CA server address, // and that is part of a CA identified by a specific certificate pool. -func GetRemoteSignedCertificate(ctx context.Context, csr []byte, rootCAPool *x509.CertPool, config CertificateRequestConfig) (*api.NodeCertificateStatusResponse, error) { +func GetRemoteSignedCertificate(ctx context.Context, csr []byte, rootCAPool *x509.CertPool, config CertificateRequestConfig) ([]byte, error) { if rootCAPool == nil { return nil, errors.New("valid root CA pool required") } @@ -629,7 +594,7 @@ func GetRemoteSignedCertificate(ctx context.Context, csr []byte, rootCAPool *x50 } // If the certificate was issued, return - if statusResponse.Status != nil && statusResponse.Status.State == api.IssuanceStateIssued { + if statusResponse.Status.State == api.IssuanceStateIssued { if statusResponse.Certificate == nil { return nil, errors.New("no certificate in CertificateStatus response") } @@ -641,7 +606,7 @@ func GetRemoteSignedCertificate(ctx context.Context, csr []byte, rootCAPool *x50 // current request. if bytes.Equal(statusResponse.Certificate.CSR, csr) { config.Remotes.Observe(peer, remotes.DefaultObservationWeight) - return statusResponse, nil + return statusResponse.Certificate.Certificate, nil } } @@ -675,6 +640,17 @@ func readCertValidity(kr KeyReader) (time.Time, time.Time, error) { } +func saveRootCA(rootCA RootCA, paths CertPaths) error { + // Make sure the necessary dirs exist and they are writable + err := os.MkdirAll(filepath.Dir(paths.Cert), 0755) + if err != nil { + return err + } + + // If the root certificate got returned successfully, save the rootCA to disk. + return ioutils.AtomicWriteFile(paths.Cert, rootCA.Cert, 0644) +} + // GenerateNewCSR returns a newly generated key and CSR signed with said key func GenerateNewCSR() (csr, key []byte, err error) { req := &cfcsr.CertificateRequest{ diff --git a/components/engine/vendor/github.com/docker/swarmkit/ca/config.go b/components/engine/vendor/github.com/docker/swarmkit/ca/config.go index db5ba02236..e15454b5b4 100644 --- a/components/engine/vendor/github.com/docker/swarmkit/ca/config.go +++ b/components/engine/vendor/github.com/docker/swarmkit/ca/config.go @@ -120,15 +120,8 @@ func (s *SecurityConfig) UpdateRootCA(cert, key []byte, certExpiry time.Duration s.mu.Lock() defer s.mu.Unlock() - // Create a new RootCA, keeping the path of the old RootCA - rootCA, err := NewRootCA(cert, key, s.rootCA.Path, certExpiry) - if err != nil { - return err - } - // Attempt to write the new certificate to disk - err = rootCA.saveCertificate() + rootCA, err := NewRootCA(cert, key, certExpiry) if err == nil { - // No errors, save the current rootCA s.rootCA = &rootCA } @@ -239,8 +232,7 @@ func DownloadRootCA(ctx context.Context, paths CertPaths, token string, r remote } // Save root CA certificate to disk - rootCA.Path = paths - if err = rootCA.saveCertificate(); err != nil { + if err = saveRootCA(rootCA, paths); err != nil { return RootCA{}, err } @@ -462,6 +454,7 @@ func RenewTLSConfig(ctx context.Context, s *SecurityConfig, remotes remotes.Remo // Since the expiration of the certificate is managed remotely we should update our // retry timer on every iteration of this loop. + // Retrieve the current certificate expiration information. validFrom, validUntil, err := readCertValidity(s.KeyReader()) if err != nil { // We failed to read the expiration, let's stick with the starting default diff --git a/components/engine/vendor/github.com/docker/swarmkit/ca/server.go b/components/engine/vendor/github.com/docker/swarmkit/ca/server.go index 51f78f4512..fa55d38534 100644 --- a/components/engine/vendor/github.com/docker/swarmkit/ca/server.go +++ b/components/engine/vendor/github.com/docker/swarmkit/ca/server.go @@ -142,9 +142,8 @@ func (s *Server) NodeCertificateStatus(ctx context.Context, request *api.NodeCer // If this certificate has a final state, return it immediately (both pending and renew are transition states) if isFinalState(node.Certificate.Status) { return &api.NodeCertificateStatusResponse{ - Status: &node.Certificate.Status, - Certificate: &node.Certificate, - RootCABundle: s.securityConfig.RootCA().Cert, + Status: &node.Certificate.Status, + Certificate: &node.Certificate, }, nil } @@ -165,9 +164,8 @@ func (s *Server) NodeCertificateStatus(ctx context.Context, request *api.NodeCer if isFinalState(v.Node.Certificate.Status) { cert := v.Node.Certificate.Copy() return &api.NodeCertificateStatusResponse{ - Status: &cert.Status, - Certificate: cert, - RootCABundle: s.securityConfig.RootCA().Cert, + Status: &cert.Status, + Certificate: cert, }, nil } } diff --git a/components/engine/vendor/github.com/docker/swarmkit/manager/allocator/networkallocator/networkallocator.go b/components/engine/vendor/github.com/docker/swarmkit/manager/allocator/networkallocator/networkallocator.go index 62751b290a..f16b0d4175 100644 --- a/components/engine/vendor/github.com/docker/swarmkit/manager/allocator/networkallocator/networkallocator.go +++ b/components/engine/vendor/github.com/docker/swarmkit/manager/allocator/networkallocator/networkallocator.go @@ -746,7 +746,7 @@ func (na *NetworkAllocator) allocatePools(n *api.Network) (map[string]string, er } for i, ic := range ipamConfigs { - poolID, poolIP, _, err := ipam.RequestPool(asName, ic.Subnet, ic.Range, nil, false) + poolID, poolIP, _, err := ipam.RequestPool(asName, ic.Subnet, ic.Range, dOptions, false) if err != nil { // Rollback by releasing all the resources allocated so far. releasePools(ipam, ipamConfigs[:i], pools) diff --git a/components/engine/vendor/github.com/docker/swarmkit/manager/scheduler/filter.go b/components/engine/vendor/github.com/docker/swarmkit/manager/scheduler/filter.go index 1ecbb7d08a..b2b64578b4 100644 --- a/components/engine/vendor/github.com/docker/swarmkit/manager/scheduler/filter.go +++ b/components/engine/vendor/github.com/docker/swarmkit/manager/scheduler/filter.go @@ -2,6 +2,7 @@ package scheduler import ( "fmt" + "strings" "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/manager/constraint" @@ -93,6 +94,15 @@ type PluginFilter struct { t *api.Task } +func referencesVolumePlugin(mount api.Mount) bool { + return mount.Type == api.MountTypeVolume && + mount.VolumeOptions != nil && + mount.VolumeOptions.DriverConfig != nil && + mount.VolumeOptions.DriverConfig.Name != "" && + mount.VolumeOptions.DriverConfig.Name != "local" + +} + // SetTask returns true when the filter is enabled for a given task. func (f *PluginFilter) SetTask(t *api.Task) bool { c := t.Spec.GetContainer() @@ -100,12 +110,9 @@ func (f *PluginFilter) SetTask(t *api.Task) bool { var volumeTemplates bool if c != nil { for _, mount := range c.Mounts { - if mount.Type == api.MountTypeVolume && - mount.VolumeOptions != nil && - mount.VolumeOptions.DriverConfig != nil && - mount.VolumeOptions.DriverConfig.Name != "" && - mount.VolumeOptions.DriverConfig.Name != "local" { + if referencesVolumePlugin(mount) { volumeTemplates = true + break } } } @@ -128,7 +135,7 @@ func (f *PluginFilter) Check(n *NodeInfo) bool { container := f.t.Spec.GetContainer() if container != nil { for _, mount := range container.Mounts { - if mount.VolumeOptions != nil && mount.VolumeOptions.DriverConfig != nil { + if referencesVolumePlugin(mount) { if !f.pluginExistsOnNode("Volume", mount.VolumeOptions.DriverConfig.Name, nodePlugins) { return false } @@ -138,16 +145,30 @@ func (f *PluginFilter) Check(n *NodeInfo) bool { // Check if all network plugins required by task are installed on node for _, tn := range f.t.Networks { - if !f.pluginExistsOnNode("Network", tn.Network.DriverState.Name, nodePlugins) { - return false + if tn.Network != nil && tn.Network.DriverState != nil && tn.Network.DriverState.Name != "" { + if !f.pluginExistsOnNode("Network", tn.Network.DriverState.Name, nodePlugins) { + return false + } } } return true } +// pluginExistsOnNode returns true if the (pluginName, pluginType) pair is present in nodePlugins func (f *PluginFilter) pluginExistsOnNode(pluginType string, pluginName string, nodePlugins []api.PluginDescription) bool { for _, np := range nodePlugins { - if pluginType == np.Type && pluginName == np.Name { + if pluginType != np.Type { + continue + } + if pluginName == np.Name { + return true + } + // This does not use the reference package to avoid the + // overhead of parsing references as part of the scheduling + // loop. This is okay only because plugin names are a very + // strict subset of the reference grammar that is always + // name:tag. + if strings.HasPrefix(np.Name, pluginName) && np.Name[len(pluginName):] == ":latest" { return true } } diff --git a/components/engine/vendor/github.com/docker/swarmkit/manager/scheduler/pipeline.go b/components/engine/vendor/github.com/docker/swarmkit/manager/scheduler/pipeline.go index d9981aa125..00fd36c5c7 100644 --- a/components/engine/vendor/github.com/docker/swarmkit/manager/scheduler/pipeline.go +++ b/components/engine/vendor/github.com/docker/swarmkit/manager/scheduler/pipeline.go @@ -11,12 +11,7 @@ var ( // Always check for readiness first. &ReadyFilter{}, &ResourceFilter{}, - - // TODO(stevvooe): Do not filter based on plugins since they are lazy - // loaded in the engine. We can add this back when we can schedule - // plugins in the future. - // &PluginFilter{}, - + &PluginFilter{}, &ConstraintFilter{}, } ) diff --git a/components/engine/vendor/github.com/docker/swarmkit/manager/state/raft/raft.go b/components/engine/vendor/github.com/docker/swarmkit/manager/state/raft/raft.go index de1a607991..98b3f451cd 100644 --- a/components/engine/vendor/github.com/docker/swarmkit/manager/state/raft/raft.go +++ b/components/engine/vendor/github.com/docker/swarmkit/manager/state/raft/raft.go @@ -1259,8 +1259,6 @@ func (n *Node) saveToStorage( } if err := n.raftLogger.SaveEntries(hardState, entries); err != nil { - // TODO(aaronl): These error types should really wrap more - // detailed errors. return errors.Wrap(err, "failed to save raft log entries") } From ce25e5f9c1b36f90cdfe23b0dee9135a50dfd2f4 Mon Sep 17 00:00:00 2001 From: Aaron Lehmann Date: Tue, 13 Dec 2016 17:20:37 -0800 Subject: [PATCH 2/4] Publish installed v2 plugins to manager Signed-off-by: Aaron Lehmann Upstream-commit: 2a97ea9a6e03443d4d10fd2f440feb779ab8699e Component: engine --- .../cluster/executor/container/executor.go | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/components/engine/daemon/cluster/executor/container/executor.go b/components/engine/daemon/cluster/executor/container/executor.go index 86b957b005..f0c6f998b5 100644 --- a/components/engine/daemon/cluster/executor/container/executor.go +++ b/components/engine/daemon/cluster/executor/container/executor.go @@ -8,6 +8,7 @@ import ( "github.com/docker/docker/api/types/network" executorpkg "github.com/docker/docker/daemon/cluster/executor" clustertypes "github.com/docker/docker/daemon/cluster/provider" + "github.com/docker/docker/plugin" networktypes "github.com/docker/libnetwork/types" "github.com/docker/swarmkit/agent/exec" "github.com/docker/swarmkit/agent/secrets" @@ -45,12 +46,39 @@ func (e *executor) Describe(ctx context.Context) (*api.NodeDescription, error) { } } + // add v1 plugins addPlugins("Volume", info.Plugins.Volume) // Add builtin driver "overlay" (the only builtin multi-host driver) to // the plugin list by default. addPlugins("Network", append([]string{"overlay"}, info.Plugins.Network...)) addPlugins("Authorization", info.Plugins.Authorization) + // add v2 plugins + v2Plugins, err := plugin.GetManager().List() + if err == nil { + for _, plgn := range v2Plugins { + for _, typ := range plgn.Config.Interface.Types { + if typ.Prefix != "docker" || !plgn.Enabled { + continue + } + plgnTyp := typ.Capability + if typ.Capability == "volumedriver" { + plgnTyp = "Volume" + } else if typ.Capability == "networkdriver" { + plgnTyp = "Network" + } + plgnName := plgn.Name + if plgn.Tag != "" { + plgnName += ":" + plgn.Tag + } + plugins[api.PluginDescription{ + Type: plgnTyp, + Name: plgnName, + }] = struct{}{} + } + } + } + pluginFields := make([]api.PluginDescription, 0, len(plugins)) for k := range plugins { pluginFields = append(pluginFields, k) From 6f94fb07b2fe993adc8410989d58faec70c39a92 Mon Sep 17 00:00:00 2001 From: Aaron Lehmann Date: Tue, 13 Dec 2016 17:20:52 -0800 Subject: [PATCH 3/4] Fix volume Create to check against canonical driver name Previously, it was comparing against the driver name passed in by the caller. This could lead to subtle issues when using plugins, like "plugin" vs. "plugin:latest". Also, remove "conflict:" prefix to improve the error message. Signed-off-by: Aaron Lehmann Upstream-commit: 53d447c5d5c85d5595d5170411189c88a135a789 Component: engine --- ...ocker_cli_external_volume_driver_unix_test.go | 16 ++++++++++++++++ .../integration-cli/docker_cli_volume_test.go | 15 --------------- components/engine/volume/store/errors.go | 2 +- components/engine/volume/store/store.go | 13 +++++++++++-- 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/components/engine/integration-cli/docker_cli_external_volume_driver_unix_test.go b/components/engine/integration-cli/docker_cli_external_volume_driver_unix_test.go index 466d376d95..9c8ced9d79 100644 --- a/components/engine/integration-cli/docker_cli_external_volume_driver_unix_test.go +++ b/components/engine/integration-cli/docker_cli_external_volume_driver_unix_test.go @@ -284,6 +284,22 @@ func (s *DockerExternalVolumeSuite) TearDownSuite(c *check.C) { c.Assert(err, checker.IsNil) } +func (s *DockerExternalVolumeSuite) TestVolumeCLICreateOptionConflict(c *check.C) { + dockerCmd(c, "volume", "create", "test") + + out, _, err := dockerCmdWithError("volume", "create", "test", "--driver", volumePluginName) + c.Assert(err, check.NotNil, check.Commentf("volume create exception name already in use with another driver")) + c.Assert(out, checker.Contains, "A volume named test already exists") + + out, _ = dockerCmd(c, "volume", "inspect", "--format={{ .Driver }}", "test") + _, _, err = dockerCmdWithError("volume", "create", "test", "--driver", strings.TrimSpace(out)) + c.Assert(err, check.IsNil) + + // make sure hidden --name option conflicts with positional arg name + out, _, err = dockerCmdWithError("volume", "create", "--name", "test2", "test2") + c.Assert(err, check.NotNil, check.Commentf("Conflicting options: either specify --name or provide positional arg, not both")) +} + func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverNamed(c *check.C) { s.d.StartWithBusybox(c) diff --git a/components/engine/integration-cli/docker_cli_volume_test.go b/components/engine/integration-cli/docker_cli_volume_test.go index 0dace5d495..772b2d6359 100644 --- a/components/engine/integration-cli/docker_cli_volume_test.go +++ b/components/engine/integration-cli/docker_cli_volume_test.go @@ -29,21 +29,6 @@ func (s *DockerSuite) TestVolumeCLICreate(c *check.C) { c.Assert(name, check.Equals, "test2") } -func (s *DockerSuite) TestVolumeCLICreateOptionConflict(c *check.C) { - dockerCmd(c, "volume", "create", "test") - out, _, err := dockerCmdWithError("volume", "create", "test", "--driver", "nosuchdriver") - c.Assert(err, check.NotNil, check.Commentf("volume create exception name already in use with another driver")) - c.Assert(out, checker.Contains, "A volume named test already exists") - - out, _ = dockerCmd(c, "volume", "inspect", "--format={{ .Driver }}", "test") - _, _, err = dockerCmdWithError("volume", "create", "test", "--driver", strings.TrimSpace(out)) - c.Assert(err, check.IsNil) - - // make sure hidden --name option conflicts with positional arg name - out, _, err = dockerCmdWithError("volume", "create", "--name", "test2", "test2") - c.Assert(err, check.NotNil, check.Commentf("Conflicting options: either specify --name or provide positional arg, not both")) -} - func (s *DockerSuite) TestVolumeCLIInspect(c *check.C) { c.Assert( exec.Command(dockerBinary, "volume", "inspect", "doesntexist").Run(), diff --git a/components/engine/volume/store/errors.go b/components/engine/volume/store/errors.go index db7c3ce243..980175f29c 100644 --- a/components/engine/volume/store/errors.go +++ b/components/engine/volume/store/errors.go @@ -14,7 +14,7 @@ var ( // errInvalidName is a typed error returned when creating a volume with a name that is not valid on the platform errInvalidName = errors.New("volume name is not valid on this platform") // errNameConflict is a typed error returned on create when a volume exists with the given name, but for a different driver - errNameConflict = errors.New("conflict: volume name must be unique") + errNameConflict = errors.New("volume name must be unique") ) // OpErr is the error type returned by functions in the store package. It describes diff --git a/components/engine/volume/store/store.go b/components/engine/volume/store/store.go index 9b896703f6..b126800868 100644 --- a/components/engine/volume/store/store.go +++ b/components/engine/volume/store/store.go @@ -309,8 +309,17 @@ func (s *VolumeStore) checkConflict(name, driverName string) (volume.Volume, err vDriverName := v.DriverName() var conflict bool - if driverName != "" && vDriverName != driverName { - conflict = true + if driverName != "" { + // Retrieve canonical driver name to avoid inconsistencies (for example + // "plugin" vs. "plugin:latest") + vd, err := volumedrivers.GetDriver(driverName) + if err != nil { + return nil, err + } + + if vDriverName != vd.Name() { + conflict = true + } } // let's check if the found volume ref From dd0335969709cbc08453171aa10b973933c38c16 Mon Sep 17 00:00:00 2001 From: Aaron Lehmann Date: Thu, 15 Dec 2016 13:56:32 -0800 Subject: [PATCH 4/4] Add integration test for volume plugins on swarm Signed-off-by: Aaron Lehmann Upstream-commit: 45990d6e6144daaaf53b09325e7576f0cbec74f3 Component: engine --- .../integration-cli/daemon/daemon_swarm.go | 20 ++++--- .../docker_cli_swarm_unix_test.go | 52 +++++++++++++++++++ 2 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 components/engine/integration-cli/docker_cli_swarm_unix_test.go diff --git a/components/engine/integration-cli/daemon/daemon_swarm.go b/components/engine/integration-cli/daemon/daemon_swarm.go index 2b7f71908b..5d120d9936 100644 --- a/components/engine/integration-cli/daemon/daemon_swarm.go +++ b/components/engine/integration-cli/daemon/daemon_swarm.go @@ -148,20 +148,28 @@ func (d *Swarm) GetServiceTasks(c *check.C, service string) []swarm.Task { return tasks } -// CheckServiceRunningTasks returns the number of running tasks for the specified service -func (d *Swarm) CheckServiceRunningTasks(service string) func(*check.C) (interface{}, check.CommentInterface) { +// CheckServiceTasksInState returns the number of tasks with a matching state, +// and optional message substring. +func (d *Swarm) CheckServiceTasksInState(service string, state swarm.TaskState, message string) func(*check.C) (interface{}, check.CommentInterface) { return func(c *check.C) (interface{}, check.CommentInterface) { tasks := d.GetServiceTasks(c, service) - var runningCount int + var count int for _, task := range tasks { - if task.Status.State == swarm.TaskStateRunning { - runningCount++ + if task.Status.State == state { + if message == "" || strings.Contains(task.Status.Message, message) { + count++ + } } } - return runningCount, nil + return count, nil } } +// CheckServiceRunningTasks returns the number of running tasks for the specified service +func (d *Swarm) CheckServiceRunningTasks(service string) func(*check.C) (interface{}, check.CommentInterface) { + return d.CheckServiceTasksInState(service, swarm.TaskStateRunning, "") +} + // CheckServiceUpdateState returns the current update state for the specified service func (d *Swarm) CheckServiceUpdateState(service string) func(*check.C) (interface{}, check.CommentInterface) { return func(c *check.C) (interface{}, check.CommentInterface) { diff --git a/components/engine/integration-cli/docker_cli_swarm_unix_test.go b/components/engine/integration-cli/docker_cli_swarm_unix_test.go new file mode 100644 index 0000000000..96e77e258e --- /dev/null +++ b/components/engine/integration-cli/docker_cli_swarm_unix_test.go @@ -0,0 +1,52 @@ +// +build !windows + +package main + +import ( + "encoding/json" + "strings" + + "github.com/docker/docker/api/types/swarm" + "github.com/docker/docker/pkg/integration/checker" + "github.com/go-check/check" +) + +func (s *DockerSwarmSuite) TestSwarmVolumePlugin(c *check.C) { + d := s.AddDaemon(c, true, true) + + out, err := d.Cmd("service", "create", "--mount", "type=volume,source=my-volume,destination=/foo,volume-driver=customvolumedriver", "--name", "top", "busybox", "top") + c.Assert(err, checker.IsNil, check.Commentf(out)) + + // Make sure task stays pending before plugin is available + waitAndAssert(c, defaultReconciliationTimeout, d.CheckServiceTasksInState("top", swarm.TaskStatePending, "missing plugin on 1 node"), checker.Equals, 1) + + plugin := newVolumePlugin(c, "customvolumedriver") + defer plugin.Close() + + // create a dummy volume to trigger lazy loading of the plugin + out, err = d.Cmd("volume", "create", "-d", "customvolumedriver", "hello") + + // TODO(aaronl): It will take about 15 seconds for swarm to realize the + // plugin was loaded. Switching the test over to plugin v2 would avoid + // this long delay. + + // make sure task has been deployed. + waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1) + + out, err = d.Cmd("ps", "-q") + c.Assert(err, checker.IsNil) + containerID := strings.TrimSpace(out) + + out, err = d.Cmd("inspect", "-f", "{{json .Mounts}}", containerID) + c.Assert(err, checker.IsNil) + + var mounts []struct { + Name string + Driver string + } + + c.Assert(json.NewDecoder(strings.NewReader(out)).Decode(&mounts), checker.IsNil) + c.Assert(len(mounts), checker.Equals, 1, check.Commentf(out)) + c.Assert(mounts[0].Name, checker.Equals, "my-volume") + c.Assert(mounts[0].Driver, checker.Equals, "customvolumedriver") +}