Browse code

Vendor swarmkit 79381d0

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>

Aaron Lehmann authored on 2017/06/16 03:11:48
Showing 31 changed files
... ...
@@ -191,9 +191,9 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) {
191 191
 			"name": s.File.Name,
192 192
 			"path": fPath,
193 193
 		}).Debug("injecting secret")
194
-		secret := c.DependencyStore.Secrets().Get(s.SecretID)
195
-		if secret == nil {
196
-			return fmt.Errorf("unable to get secret from secret store")
194
+		secret, err := c.DependencyStore.Secrets().Get(s.SecretID)
195
+		if err != nil {
196
+			return errors.Wrap(err, "unable to get secret from secret store")
197 197
 		}
198 198
 		if err := ioutil.WriteFile(fPath, secret.Spec.Data, s.File.Mode); err != nil {
199 199
 			return errors.Wrap(err, "error injecting secret")
... ...
@@ -266,9 +266,9 @@ func (daemon *Daemon) setupConfigDir(c *container.Container) (setupErr error) {
266 266
 		}
267 267
 
268 268
 		log.Debug("injecting config")
269
-		config := c.DependencyStore.Configs().Get(configRef.ConfigID)
270
-		if config == nil {
271
-			return fmt.Errorf("unable to get config from config store")
269
+		config, err := c.DependencyStore.Configs().Get(configRef.ConfigID)
270
+		if err != nil {
271
+			return errors.Wrap(err, "unable to get config from config store")
272 272
 		}
273 273
 		if err := ioutil.WriteFile(fPath, config.Spec.Data, configRef.File.Mode); err != nil {
274 274
 			return errors.Wrap(err, "error injecting config")
... ...
@@ -53,9 +53,9 @@ func (daemon *Daemon) setupConfigDir(c *container.Container) (setupErr error) {
53 53
 		log := logrus.WithFields(logrus.Fields{"name": configRef.File.Name, "path": fPath})
54 54
 
55 55
 		log.Debug("injecting config")
56
-		config := c.DependencyStore.Configs().Get(configRef.ConfigID)
57
-		if config == nil {
58
-			return fmt.Errorf("unable to get config from config store")
56
+		config, err := c.DependencyStore.Configs().Get(configRef.ConfigID)
57
+		if err != nil {
58
+			return errors.Wrap(err, "unable to get config from config store")
59 59
 		}
60 60
 		if err := ioutil.WriteFile(fPath, config.Spec.Data, configRef.File.Mode); err != nil {
61 61
 			return errors.Wrap(err, "error injecting config")
... ...
@@ -128,9 +128,9 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) {
128 128
 			"name": s.File.Name,
129 129
 			"path": fPath,
130 130
 		}).Debug("injecting secret")
131
-		secret := c.DependencyStore.Secrets().Get(s.SecretID)
132
-		if secret == nil {
133
-			return fmt.Errorf("unable to get secret from secret store")
131
+		secret, err := c.DependencyStore.Secrets().Get(s.SecretID)
132
+		if err != nil {
133
+			return errors.Wrap(err, "unable to get secret from secret store")
134 134
 		}
135 135
 		if err := ioutil.WriteFile(fPath, secret.Spec.Data, s.File.Mode); err != nil {
136 136
 			return errors.Wrap(err, "error injecting secret")
... ...
@@ -104,7 +104,7 @@ github.com/containerd/containerd 3addd840653146c90a254301d6c3a663c7fd6429
104 104
 github.com/tonistiigi/fifo 1405643975692217d6720f8b54aeee1bf2cd5cf4
105 105
 
106 106
 # cluster
107
-github.com/docker/swarmkit a4bf0135f63fb60f0e76ae81579cde87f580db6e
107
+github.com/docker/swarmkit 79381d0840be27f8b3f5c667b348a4467d866eeb
108 108
 github.com/gogo/protobuf v0.4
109 109
 github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a
110 110
 github.com/google/certificate-transparency d90e65c3a07988180c5b1ece71791c0b6506826e
... ...
@@ -1,6 +1,7 @@
1 1
 package configs
2 2
 
3 3
 import (
4
+	"fmt"
4 5
 	"sync"
5 6
 
6 7
 	"github.com/docker/swarmkit/agent/exec"
... ...
@@ -22,13 +23,13 @@ func NewManager() exec.ConfigsManager {
22 22
 }
23 23
 
24 24
 // Get returns a config by ID.  If the config doesn't exist, returns nil.
25
-func (r *configs) Get(configID string) *api.Config {
25
+func (r *configs) Get(configID string) (*api.Config, error) {
26 26
 	r.mu.RLock()
27 27
 	defer r.mu.RUnlock()
28 28
 	if r, ok := r.m[configID]; ok {
29
-		return r
29
+		return r, nil
30 30
 	}
31
-	return nil
31
+	return nil, fmt.Errorf("config %s not found", configID)
32 32
 }
33 33
 
34 34
 // Add adds one or more configs to the config map.
... ...
@@ -63,9 +64,9 @@ type taskRestrictedConfigsProvider struct {
63 63
 	configIDs map[string]struct{} // allow list of config ids
64 64
 }
65 65
 
66
-func (sp *taskRestrictedConfigsProvider) Get(configID string) *api.Config {
66
+func (sp *taskRestrictedConfigsProvider) Get(configID string) (*api.Config, error) {
67 67
 	if _, ok := sp.configIDs[configID]; !ok {
68
-		return nil
68
+		return nil, fmt.Errorf("task not authorized to access config %s", configID)
69 69
 	}
70 70
 
71 71
 	return sp.configs.Get(configID)
... ...
@@ -52,7 +52,7 @@ type DependencyGetter interface {
52 52
 type SecretGetter interface {
53 53
 	// Get returns the the secret with a specific secret ID, if available.
54 54
 	// When the secret is not available, the return will be nil.
55
-	Get(secretID string) *api.Secret
55
+	Get(secretID string) (*api.Secret, error)
56 56
 }
57 57
 
58 58
 // SecretsManager is the interface for secret storage and updates.
... ...
@@ -68,7 +68,7 @@ type SecretsManager interface {
68 68
 type ConfigGetter interface {
69 69
 	// Get returns the the config with a specific config ID, if available.
70 70
 	// When the config is not available, the return will be nil.
71
-	Get(configID string) *api.Config
71
+	Get(configID string) (*api.Config, error)
72 72
 }
73 73
 
74 74
 // ConfigsManager is the interface for config storage and updates.
... ...
@@ -1,6 +1,7 @@
1 1
 package secrets
2 2
 
3 3
 import (
4
+	"fmt"
4 5
 	"sync"
5 6
 
6 7
 	"github.com/docker/swarmkit/agent/exec"
... ...
@@ -22,13 +23,13 @@ func NewManager() exec.SecretsManager {
22 22
 }
23 23
 
24 24
 // Get returns a secret by ID.  If the secret doesn't exist, returns nil.
25
-func (s *secrets) Get(secretID string) *api.Secret {
25
+func (s *secrets) Get(secretID string) (*api.Secret, error) {
26 26
 	s.mu.RLock()
27 27
 	defer s.mu.RUnlock()
28 28
 	if s, ok := s.m[secretID]; ok {
29
-		return s
29
+		return s, nil
30 30
 	}
31
-	return nil
31
+	return nil, fmt.Errorf("secret %s not found", secretID)
32 32
 }
33 33
 
34 34
 // Add adds one or more secrets to the secret map.
... ...
@@ -63,9 +64,9 @@ type taskRestrictedSecretsProvider struct {
63 63
 	secretIDs map[string]struct{} // allow list of secret ids
64 64
 }
65 65
 
66
-func (sp *taskRestrictedSecretsProvider) Get(secretID string) *api.Secret {
66
+func (sp *taskRestrictedSecretsProvider) Get(secretID string) (*api.Secret, error) {
67 67
 	if _, ok := sp.secretIDs[secretID]; !ok {
68
-		return nil
68
+		return nil, fmt.Errorf("task not authorized to access secret %s", secretID)
69 69
 	}
70 70
 
71 71
 	return sp.secrets.Get(secretID)
... ...
@@ -760,6 +760,12 @@ type SecretSpec struct {
760 760
 	Annotations Annotations `protobuf:"bytes,1,opt,name=annotations" json:"annotations"`
761 761
 	// Data is the secret payload - the maximum size is 500KB (that is, 500*1024 bytes)
762 762
 	Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
763
+	// Templating controls whether and how to evaluate the secret payload as
764
+	// a template. If it is not set, no templating is used.
765
+	//
766
+	// The currently recognized values are:
767
+	// - golang: Go templating
768
+	Templating *Driver `protobuf:"bytes,3,opt,name=templating" json:"templating,omitempty"`
763 769
 }
764 770
 
765 771
 func (m *SecretSpec) Reset()                    { *m = SecretSpec{} }
... ...
@@ -773,6 +779,12 @@ type ConfigSpec struct {
773 773
 	// TODO(aaronl): Do we want to revise this to include multiple payloads in a single
774 774
 	// ConfigSpec? Define this to be a tar? etc...
775 775
 	Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
776
+	// Templating controls whether and how to evaluate the secret payload as
777
+	// a template. If it is not set, no templating is used.
778
+	//
779
+	// The currently recognized values are:
780
+	// - golang: Go templating
781
+	Templating *Driver `protobuf:"bytes,3,opt,name=templating" json:"templating,omitempty"`
776 782
 }
777 783
 
778 784
 func (m *ConfigSpec) Reset()                    { *m = ConfigSpec{} }
... ...
@@ -1224,6 +1236,10 @@ func (m *SecretSpec) CopyFrom(src interface{}) {
1224 1224
 		m.Data = make([]byte, len(o.Data))
1225 1225
 		copy(m.Data, o.Data)
1226 1226
 	}
1227
+	if o.Templating != nil {
1228
+		m.Templating = &Driver{}
1229
+		github_com_docker_swarmkit_api_deepcopy.Copy(m.Templating, o.Templating)
1230
+	}
1227 1231
 }
1228 1232
 
1229 1233
 func (m *ConfigSpec) Copy() *ConfigSpec {
... ...
@@ -1244,6 +1260,10 @@ func (m *ConfigSpec) CopyFrom(src interface{}) {
1244 1244
 		m.Data = make([]byte, len(o.Data))
1245 1245
 		copy(m.Data, o.Data)
1246 1246
 	}
1247
+	if o.Templating != nil {
1248
+		m.Templating = &Driver{}
1249
+		github_com_docker_swarmkit_api_deepcopy.Copy(m.Templating, o.Templating)
1250
+	}
1247 1251
 }
1248 1252
 
1249 1253
 func (m *NodeSpec) Marshal() (dAtA []byte, err error) {
... ...
@@ -2227,6 +2247,16 @@ func (m *SecretSpec) MarshalTo(dAtA []byte) (int, error) {
2227 2227
 		i = encodeVarintSpecs(dAtA, i, uint64(len(m.Data)))
2228 2228
 		i += copy(dAtA[i:], m.Data)
2229 2229
 	}
2230
+	if m.Templating != nil {
2231
+		dAtA[i] = 0x1a
2232
+		i++
2233
+		i = encodeVarintSpecs(dAtA, i, uint64(m.Templating.Size()))
2234
+		n37, err := m.Templating.MarshalTo(dAtA[i:])
2235
+		if err != nil {
2236
+			return 0, err
2237
+		}
2238
+		i += n37
2239
+	}
2230 2240
 	return i, nil
2231 2241
 }
2232 2242
 
... ...
@@ -2248,17 +2278,27 @@ func (m *ConfigSpec) MarshalTo(dAtA []byte) (int, error) {
2248 2248
 	dAtA[i] = 0xa
2249 2249
 	i++
2250 2250
 	i = encodeVarintSpecs(dAtA, i, uint64(m.Annotations.Size()))
2251
-	n37, err := m.Annotations.MarshalTo(dAtA[i:])
2251
+	n38, err := m.Annotations.MarshalTo(dAtA[i:])
2252 2252
 	if err != nil {
2253 2253
 		return 0, err
2254 2254
 	}
2255
-	i += n37
2255
+	i += n38
2256 2256
 	if len(m.Data) > 0 {
2257 2257
 		dAtA[i] = 0x12
2258 2258
 		i++
2259 2259
 		i = encodeVarintSpecs(dAtA, i, uint64(len(m.Data)))
2260 2260
 		i += copy(dAtA[i:], m.Data)
2261 2261
 	}
2262
+	if m.Templating != nil {
2263
+		dAtA[i] = 0x1a
2264
+		i++
2265
+		i = encodeVarintSpecs(dAtA, i, uint64(m.Templating.Size()))
2266
+		n39, err := m.Templating.MarshalTo(dAtA[i:])
2267
+		if err != nil {
2268
+			return 0, err
2269
+		}
2270
+		i += n39
2271
+	}
2262 2272
 	return i, nil
2263 2273
 }
2264 2274
 
... ...
@@ -2685,6 +2725,10 @@ func (m *SecretSpec) Size() (n int) {
2685 2685
 	if l > 0 {
2686 2686
 		n += 1 + l + sovSpecs(uint64(l))
2687 2687
 	}
2688
+	if m.Templating != nil {
2689
+		l = m.Templating.Size()
2690
+		n += 1 + l + sovSpecs(uint64(l))
2691
+	}
2688 2692
 	return n
2689 2693
 }
2690 2694
 
... ...
@@ -2697,6 +2741,10 @@ func (m *ConfigSpec) Size() (n int) {
2697 2697
 	if l > 0 {
2698 2698
 		n += 1 + l + sovSpecs(uint64(l))
2699 2699
 	}
2700
+	if m.Templating != nil {
2701
+		l = m.Templating.Size()
2702
+		n += 1 + l + sovSpecs(uint64(l))
2703
+	}
2700 2704
 	return n
2701 2705
 }
2702 2706
 
... ...
@@ -2973,6 +3021,7 @@ func (this *SecretSpec) String() string {
2973 2973
 	s := strings.Join([]string{`&SecretSpec{`,
2974 2974
 		`Annotations:` + strings.Replace(strings.Replace(this.Annotations.String(), "Annotations", "Annotations", 1), `&`, ``, 1) + `,`,
2975 2975
 		`Data:` + fmt.Sprintf("%v", this.Data) + `,`,
2976
+		`Templating:` + strings.Replace(fmt.Sprintf("%v", this.Templating), "Driver", "Driver", 1) + `,`,
2976 2977
 		`}`,
2977 2978
 	}, "")
2978 2979
 	return s
... ...
@@ -2984,6 +3033,7 @@ func (this *ConfigSpec) String() string {
2984 2984
 	s := strings.Join([]string{`&ConfigSpec{`,
2985 2985
 		`Annotations:` + strings.Replace(strings.Replace(this.Annotations.String(), "Annotations", "Annotations", 1), `&`, ``, 1) + `,`,
2986 2986
 		`Data:` + fmt.Sprintf("%v", this.Data) + `,`,
2987
+		`Templating:` + strings.Replace(fmt.Sprintf("%v", this.Templating), "Driver", "Driver", 1) + `,`,
2987 2988
 		`}`,
2988 2989
 	}, "")
2989 2990
 	return s
... ...
@@ -5800,6 +5850,39 @@ func (m *SecretSpec) Unmarshal(dAtA []byte) error {
5800 5800
 				m.Data = []byte{}
5801 5801
 			}
5802 5802
 			iNdEx = postIndex
5803
+		case 3:
5804
+			if wireType != 2 {
5805
+				return fmt.Errorf("proto: wrong wireType = %d for field Templating", wireType)
5806
+			}
5807
+			var msglen int
5808
+			for shift := uint(0); ; shift += 7 {
5809
+				if shift >= 64 {
5810
+					return ErrIntOverflowSpecs
5811
+				}
5812
+				if iNdEx >= l {
5813
+					return io.ErrUnexpectedEOF
5814
+				}
5815
+				b := dAtA[iNdEx]
5816
+				iNdEx++
5817
+				msglen |= (int(b) & 0x7F) << shift
5818
+				if b < 0x80 {
5819
+					break
5820
+				}
5821
+			}
5822
+			if msglen < 0 {
5823
+				return ErrInvalidLengthSpecs
5824
+			}
5825
+			postIndex := iNdEx + msglen
5826
+			if postIndex > l {
5827
+				return io.ErrUnexpectedEOF
5828
+			}
5829
+			if m.Templating == nil {
5830
+				m.Templating = &Driver{}
5831
+			}
5832
+			if err := m.Templating.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
5833
+				return err
5834
+			}
5835
+			iNdEx = postIndex
5803 5836
 		default:
5804 5837
 			iNdEx = preIndex
5805 5838
 			skippy, err := skipSpecs(dAtA[iNdEx:])
... ...
@@ -5911,6 +5994,39 @@ func (m *ConfigSpec) Unmarshal(dAtA []byte) error {
5911 5911
 				m.Data = []byte{}
5912 5912
 			}
5913 5913
 			iNdEx = postIndex
5914
+		case 3:
5915
+			if wireType != 2 {
5916
+				return fmt.Errorf("proto: wrong wireType = %d for field Templating", wireType)
5917
+			}
5918
+			var msglen int
5919
+			for shift := uint(0); ; shift += 7 {
5920
+				if shift >= 64 {
5921
+					return ErrIntOverflowSpecs
5922
+				}
5923
+				if iNdEx >= l {
5924
+					return io.ErrUnexpectedEOF
5925
+				}
5926
+				b := dAtA[iNdEx]
5927
+				iNdEx++
5928
+				msglen |= (int(b) & 0x7F) << shift
5929
+				if b < 0x80 {
5930
+					break
5931
+				}
5932
+			}
5933
+			if msglen < 0 {
5934
+				return ErrInvalidLengthSpecs
5935
+			}
5936
+			postIndex := iNdEx + msglen
5937
+			if postIndex > l {
5938
+				return io.ErrUnexpectedEOF
5939
+			}
5940
+			if m.Templating == nil {
5941
+				m.Templating = &Driver{}
5942
+			}
5943
+			if err := m.Templating.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
5944
+				return err
5945
+			}
5946
+			iNdEx = postIndex
5914 5947
 		default:
5915 5948
 			iNdEx = preIndex
5916 5949
 			skippy, err := skipSpecs(dAtA[iNdEx:])
... ...
@@ -6040,121 +6156,122 @@ var (
6040 6040
 func init() { proto.RegisterFile("specs.proto", fileDescriptorSpecs) }
6041 6041
 
6042 6042
 var fileDescriptorSpecs = []byte{
6043
-	// 1846 bytes of a gzipped FileDescriptorProto
6044
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x57, 0xcf, 0x73, 0x1b, 0x49,
6045
-	0x15, 0xb6, 0x6c, 0x59, 0x3f, 0xde, 0xc8, 0x89, 0xd2, 0x24, 0x61, 0xac, 0xb0, 0xb2, 0xa2, 0x0d,
6046
-	0xc1, 0xcb, 0x16, 0x72, 0x61, 0xa8, 0x25, 0x4b, 0x58, 0x40, 0xb2, 0x84, 0x63, 0x8c, 0x1d, 0x55,
6047
-	0xdb, 0x1b, 0xc8, 0x49, 0xd5, 0x9e, 0x69, 0x4b, 0x53, 0x1e, 0x75, 0x0f, 0xdd, 0x3d, 0xda, 0xd2,
6048
-	0x8d, 0xe3, 0x56, 0xae, 0x9c, 0x5d, 0x1c, 0xf8, 0x67, 0x72, 0xa4, 0x38, 0x71, 0x72, 0xb1, 0xfe,
6049
-	0x17, 0xb8, 0x71, 0x81, 0xea, 0x9e, 0x1e, 0xfd, 0x48, 0xc6, 0x9b, 0x54, 0x11, 0x6e, 0xdd, 0xaf,
6050
-	0xbf, 0xef, 0x75, 0xf7, 0xeb, 0xaf, 0xfb, 0xbd, 0x06, 0x47, 0x46, 0xd4, 0x93, 0xad, 0x48, 0x70,
6051
-	0xc5, 0x11, 0xf2, 0xb9, 0x77, 0x41, 0x45, 0x4b, 0x7e, 0x45, 0xc4, 0xf8, 0x22, 0x50, 0xad, 0xc9,
6052
-	0x8f, 0x6b, 0x8e, 0x9a, 0x46, 0xd4, 0x02, 0x6a, 0x77, 0x87, 0x7c, 0xc8, 0x4d, 0x73, 0x47, 0xb7,
6053
-	0xac, 0xb5, 0x3e, 0xe4, 0x7c, 0x18, 0xd2, 0x1d, 0xd3, 0x3b, 0x8b, 0xcf, 0x77, 0xfc, 0x58, 0x10,
6054
-	0x15, 0x70, 0x66, 0xc7, 0x37, 0xdf, 0x1c, 0x27, 0x6c, 0x9a, 0x0c, 0x35, 0x2f, 0xf3, 0x50, 0x3a,
6055
-	0xe6, 0x3e, 0x3d, 0x89, 0xa8, 0x87, 0xf6, 0xc1, 0x21, 0x8c, 0x71, 0x65, 0xb8, 0xd2, 0xcd, 0x35,
6056
-	0x72, 0xdb, 0xce, 0xee, 0x56, 0xeb, 0xed, 0x45, 0xb5, 0xda, 0x73, 0x58, 0x27, 0xff, 0xfa, 0x6a,
6057
-	0x6b, 0x05, 0x2f, 0x32, 0xd1, 0xaf, 0xa0, 0xe2, 0x53, 0x19, 0x08, 0xea, 0x0f, 0x04, 0x0f, 0xa9,
6058
-	0xbb, 0xda, 0xc8, 0x6d, 0xdf, 0xda, 0xfd, 0x5e, 0x96, 0x27, 0x3d, 0x39, 0xe6, 0x21, 0xc5, 0x8e,
6059
-	0x65, 0xe8, 0x0e, 0xda, 0x07, 0x18, 0xd3, 0xf1, 0x19, 0x15, 0x72, 0x14, 0x44, 0xee, 0x9a, 0xa1,
6060
-	0xff, 0xe0, 0x26, 0xba, 0x5e, 0x7b, 0xeb, 0x68, 0x06, 0xc7, 0x0b, 0x54, 0x74, 0x04, 0x15, 0x32,
6061
-	0x21, 0x41, 0x48, 0xce, 0x82, 0x30, 0x50, 0x53, 0x37, 0x6f, 0x5c, 0x7d, 0xf2, 0xad, 0xae, 0xda,
6062
-	0x0b, 0x04, 0xbc, 0x44, 0x6f, 0xfa, 0x00, 0xf3, 0x89, 0xd0, 0x63, 0x28, 0xf6, 0x7b, 0xc7, 0xdd,
6063
-	0x83, 0xe3, 0xfd, 0xea, 0x4a, 0x6d, 0xf3, 0xd5, 0x65, 0xe3, 0x9e, 0xf6, 0x31, 0x07, 0xf4, 0x29,
6064
-	0xf3, 0x03, 0x36, 0x44, 0xdb, 0x50, 0x6a, 0xef, 0xed, 0xf5, 0xfa, 0xa7, 0xbd, 0x6e, 0x35, 0x57,
6065
-	0xab, 0xbd, 0xba, 0x6c, 0xdc, 0x5f, 0x06, 0xb6, 0x3d, 0x8f, 0x46, 0x8a, 0xfa, 0xb5, 0xfc, 0xd7,
6066
-	0x7f, 0xad, 0xaf, 0x34, 0xbf, 0xce, 0x41, 0x65, 0x71, 0x11, 0xe8, 0x31, 0x14, 0xda, 0x7b, 0xa7,
6067
-	0x07, 0x2f, 0x7a, 0xd5, 0x95, 0x39, 0x7d, 0x11, 0xd1, 0xf6, 0x54, 0x30, 0xa1, 0xe8, 0x11, 0xac,
6068
-	0xf7, 0xdb, 0x5f, 0x9e, 0xf4, 0xaa, 0xb9, 0xf9, 0x72, 0x16, 0x61, 0x7d, 0x12, 0x4b, 0x83, 0xea,
6069
-	0xe2, 0xf6, 0xc1, 0x71, 0x75, 0x35, 0x1b, 0xd5, 0x15, 0x24, 0x60, 0x76, 0x29, 0x7f, 0xc9, 0x83,
6070
-	0x73, 0x42, 0xc5, 0x24, 0xf0, 0x3e, 0xb0, 0x44, 0x3e, 0x83, 0xbc, 0x22, 0xf2, 0xc2, 0x48, 0xc3,
6071
-	0xc9, 0x96, 0xc6, 0x29, 0x91, 0x17, 0x7a, 0x52, 0x4b, 0x37, 0x78, 0xad, 0x0c, 0x41, 0xa3, 0x30,
6072
-	0xf0, 0x88, 0xa2, 0xbe, 0x51, 0x86, 0xb3, 0xfb, 0xfd, 0x2c, 0x36, 0x9e, 0xa1, 0xec, 0xfa, 0x9f,
6073
-	0xad, 0xe0, 0x05, 0x2a, 0x7a, 0x0a, 0x85, 0x61, 0xc8, 0xcf, 0x48, 0x68, 0x34, 0xe1, 0xec, 0x3e,
6074
-	0xcc, 0x72, 0xb2, 0x6f, 0x10, 0x73, 0x07, 0x96, 0x82, 0x9e, 0x40, 0x21, 0x8e, 0x7c, 0xa2, 0xa8,
6075
-	0x5b, 0x30, 0xe4, 0x46, 0x16, 0xf9, 0x4b, 0x83, 0xd8, 0xe3, 0xec, 0x3c, 0x18, 0x62, 0x8b, 0x47,
6076
-	0x87, 0x50, 0x62, 0x54, 0x7d, 0xc5, 0xc5, 0x85, 0x74, 0x8b, 0x8d, 0xb5, 0x6d, 0x67, 0xf7, 0xd3,
6077
-	0x4c, 0x31, 0x26, 0x98, 0xb6, 0x52, 0xc4, 0x1b, 0x8d, 0x29, 0x53, 0x89, 0x9b, 0xce, 0xaa, 0x9b,
6078
-	0xc3, 0x33, 0x07, 0xe8, 0x17, 0x50, 0xa2, 0xcc, 0x8f, 0x78, 0xc0, 0x94, 0x5b, 0xba, 0x79, 0x21,
6079
-	0x3d, 0x8b, 0xd1, 0xc1, 0xc4, 0x33, 0x86, 0x66, 0x0b, 0x1e, 0x86, 0x67, 0xc4, 0xbb, 0x70, 0xcb,
6080
-	0xef, 0xb9, 0x8d, 0x19, 0xa3, 0x53, 0x80, 0xfc, 0x98, 0xfb, 0xb4, 0xb9, 0x03, 0x77, 0xde, 0x0a,
6081
-	0x35, 0xaa, 0x41, 0xc9, 0x86, 0x3a, 0xd1, 0x48, 0x1e, 0xcf, 0xfa, 0xcd, 0xdb, 0xb0, 0xb1, 0x14,
6082
-	0xd6, 0xe6, 0xdf, 0xf3, 0x50, 0x4a, 0xcf, 0x1a, 0xb5, 0xa1, 0xec, 0x71, 0xa6, 0x48, 0xc0, 0xa8,
6083
-	0xb0, 0xf2, 0xca, 0x3c, 0x99, 0xbd, 0x14, 0xa4, 0x59, 0xcf, 0x56, 0xf0, 0x9c, 0x85, 0x7e, 0x03,
6084
-	0x65, 0x41, 0x25, 0x8f, 0x85, 0x47, 0xa5, 0xd5, 0xd7, 0x76, 0xb6, 0x42, 0x12, 0x10, 0xa6, 0x7f,
6085
-	0x8c, 0x03, 0x41, 0x75, 0x94, 0x25, 0x9e, 0x53, 0xd1, 0x53, 0x28, 0x0a, 0x2a, 0x15, 0x11, 0xea,
6086
-	0xdb, 0x24, 0x82, 0x13, 0x48, 0x9f, 0x87, 0x81, 0x37, 0xc5, 0x29, 0x03, 0x3d, 0x85, 0x72, 0x14,
6087
-	0x12, 0xcf, 0x78, 0x75, 0xd7, 0x0d, 0xfd, 0xa3, 0x2c, 0x7a, 0x3f, 0x05, 0xe1, 0x39, 0x1e, 0x7d,
6088
-	0x0e, 0x10, 0xf2, 0xe1, 0xc0, 0x17, 0xc1, 0x84, 0x0a, 0x2b, 0xb1, 0x5a, 0x16, 0xbb, 0x6b, 0x10,
6089
-	0xb8, 0x1c, 0xf2, 0x61, 0xd2, 0x44, 0xfb, 0xff, 0x93, 0xbe, 0x16, 0xb4, 0x75, 0x08, 0x40, 0x66,
6090
-	0xa3, 0x56, 0x5d, 0x9f, 0xbc, 0x97, 0x2b, 0x7b, 0x22, 0x0b, 0x74, 0xf4, 0x10, 0x2a, 0xe7, 0x5c,
6091
-	0x78, 0x74, 0x60, 0x6f, 0x4d, 0xd9, 0x68, 0xc2, 0x31, 0xb6, 0x44, 0x5f, 0xa8, 0x03, 0xc5, 0x21,
6092
-	0x65, 0x54, 0x04, 0x9e, 0x0b, 0x66, 0xb2, 0xc7, 0x99, 0x17, 0x32, 0x81, 0xe0, 0x98, 0xa9, 0x60,
6093
-	0x4c, 0xed, 0x4c, 0x29, 0xb1, 0x53, 0x86, 0xa2, 0x48, 0x46, 0x9a, 0x7f, 0x00, 0xf4, 0x36, 0x16,
6094
-	0x21, 0xc8, 0x5f, 0x04, 0xcc, 0x37, 0xc2, 0x2a, 0x63, 0xd3, 0x46, 0x2d, 0x28, 0x46, 0x64, 0x1a,
6095
-	0x72, 0xe2, 0x5b, 0xb1, 0xdc, 0x6d, 0x25, 0xf9, 0xb2, 0x95, 0xe6, 0xcb, 0x56, 0x9b, 0x4d, 0x71,
6096
-	0x0a, 0x6a, 0x1e, 0xc2, 0xbd, 0xcc, 0x2d, 0xa3, 0x5d, 0xa8, 0xcc, 0x44, 0x38, 0x08, 0xec, 0x24,
6097
-	0x9d, 0xdb, 0xd7, 0x57, 0x5b, 0xce, 0x4c, 0xad, 0x07, 0x5d, 0xec, 0xcc, 0x40, 0x07, 0x7e, 0xf3,
6098
-	0xcf, 0x65, 0xd8, 0x58, 0x92, 0x32, 0xba, 0x0b, 0xeb, 0xc1, 0x98, 0x0c, 0xa9, 0x5d, 0x63, 0xd2,
6099
-	0x41, 0x3d, 0x28, 0x84, 0xe4, 0x8c, 0x86, 0x5a, 0xd0, 0xfa, 0x50, 0x7f, 0xf4, 0xce, 0x3b, 0xd1,
6100
-	0xfa, 0x9d, 0xc1, 0xf7, 0x98, 0x12, 0x53, 0x6c, 0xc9, 0xc8, 0x85, 0xa2, 0xc7, 0xc7, 0x63, 0xc2,
6101
-	0xf4, 0xd3, 0xb9, 0xb6, 0x5d, 0xc6, 0x69, 0x57, 0x47, 0x86, 0x88, 0xa1, 0x74, 0xf3, 0xc6, 0x6c,
6102
-	0xda, 0xa8, 0x0a, 0x6b, 0x94, 0x4d, 0xdc, 0x75, 0x63, 0xd2, 0x4d, 0x6d, 0xf1, 0x83, 0x44, 0x91,
6103
-	0x65, 0xac, 0x9b, 0x9a, 0x17, 0x4b, 0x2a, 0xdc, 0x62, 0x12, 0x51, 0xdd, 0x46, 0x3f, 0x83, 0xc2,
6104
-	0x98, 0xc7, 0x4c, 0x49, 0xb7, 0x64, 0x16, 0xbb, 0x99, 0xb5, 0xd8, 0x23, 0x8d, 0xb0, 0x4f, 0xbb,
6105
-	0x85, 0xa3, 0x1e, 0xdc, 0x91, 0x8a, 0x47, 0x83, 0xa1, 0x20, 0x1e, 0x1d, 0x44, 0x54, 0x04, 0xdc,
6106
-	0xb7, 0x4f, 0xd3, 0xe6, 0x5b, 0x87, 0xd2, 0xb5, 0x45, 0x0e, 0xbe, 0xad, 0x39, 0xfb, 0x9a, 0xd2,
6107
-	0x37, 0x0c, 0xd4, 0x87, 0x4a, 0x14, 0x87, 0xe1, 0x80, 0x47, 0x49, 0x96, 0x4a, 0xf4, 0xf4, 0x1e,
6108
-	0x21, 0xeb, 0xc7, 0x61, 0xf8, 0x3c, 0x21, 0x61, 0x27, 0x9a, 0x77, 0xd0, 0x7d, 0x28, 0x0c, 0x05,
6109
-	0x8f, 0x23, 0xe9, 0x3a, 0x26, 0x18, 0xb6, 0x87, 0xbe, 0x80, 0xa2, 0xa4, 0x9e, 0xa0, 0x4a, 0xba,
6110
-	0x15, 0xb3, 0xd5, 0x8f, 0xb3, 0x26, 0x39, 0x31, 0x10, 0x4c, 0xcf, 0xa9, 0xa0, 0xcc, 0xa3, 0x38,
6111
-	0xe5, 0xa0, 0x4d, 0x58, 0x53, 0x6a, 0xea, 0x6e, 0x34, 0x72, 0xdb, 0xa5, 0x4e, 0xf1, 0xfa, 0x6a,
6112
-	0x6b, 0xed, 0xf4, 0xf4, 0x25, 0xd6, 0x36, 0xfd, 0x82, 0x8e, 0xb8, 0x54, 0x8c, 0x8c, 0xa9, 0x7b,
6113
-	0xcb, 0xc4, 0x76, 0xd6, 0x47, 0x2f, 0x01, 0x7c, 0x26, 0x07, 0x9e, 0xb9, 0xb2, 0xee, 0x6d, 0xb3,
6114
-	0xbb, 0x4f, 0xdf, 0xbd, 0xbb, 0xee, 0xf1, 0x89, 0xcd, 0x22, 0x1b, 0xd7, 0x57, 0x5b, 0xe5, 0x59,
6115
-	0x17, 0x97, 0x7d, 0x26, 0x93, 0x26, 0xea, 0x80, 0x33, 0xa2, 0x24, 0x54, 0x23, 0x6f, 0x44, 0xbd,
6116
-	0x0b, 0xb7, 0x7a, 0x73, 0x5a, 0x78, 0x66, 0x60, 0xd6, 0xc3, 0x22, 0x49, 0x2b, 0x58, 0x2f, 0x55,
6117
-	0xba, 0x77, 0x4c, 0xac, 0x92, 0x0e, 0xfa, 0x08, 0x80, 0x47, 0x94, 0x0d, 0xa4, 0xf2, 0x03, 0xe6,
6118
-	0x22, 0xbd, 0x65, 0x5c, 0xd6, 0x96, 0x13, 0x6d, 0x40, 0x0f, 0xf4, 0xa3, 0x4d, 0xfc, 0x01, 0x67,
6119
-	0xe1, 0xd4, 0xfd, 0x8e, 0x19, 0x2d, 0x69, 0xc3, 0x73, 0x16, 0x4e, 0xd1, 0x16, 0x38, 0x46, 0x17,
6120
-	0x32, 0x18, 0x32, 0x12, 0xba, 0x77, 0x4d, 0x3c, 0x40, 0x9b, 0x4e, 0x8c, 0x45, 0x9f, 0x43, 0x12,
6121
-	0x0d, 0xe9, 0xde, 0xbb, 0xf9, 0x1c, 0xec, 0x62, 0xe7, 0xe7, 0x60, 0x39, 0xe8, 0x97, 0x00, 0x91,
6122
-	0x08, 0x26, 0x41, 0x48, 0x87, 0x54, 0xba, 0xf7, 0xcd, 0xa6, 0xeb, 0x99, 0xaf, 0xf5, 0x0c, 0x85,
6123
-	0x17, 0x18, 0xb5, 0xcf, 0xc1, 0x59, 0xb8, 0x6d, 0xfa, 0x96, 0x5c, 0xd0, 0xa9, 0xbd, 0xc0, 0xba,
6124
-	0xa9, 0x43, 0x32, 0x21, 0x61, 0x9c, 0x54, 0xc2, 0x65, 0x9c, 0x74, 0x7e, 0xbe, 0xfa, 0x24, 0x57,
6125
-	0xdb, 0x05, 0x67, 0x41, 0x75, 0xe8, 0x63, 0xd8, 0x10, 0x74, 0x18, 0x48, 0x25, 0xa6, 0x03, 0x12,
6126
-	0xab, 0x91, 0xfb, 0x6b, 0x43, 0xa8, 0xa4, 0xc6, 0x76, 0xac, 0x46, 0xb5, 0x01, 0xcc, 0x0f, 0x0f,
6127
-	0x35, 0xc0, 0xd1, 0xa2, 0x90, 0x54, 0x4c, 0xa8, 0xd0, 0xd9, 0x56, 0xc7, 0x7c, 0xd1, 0xa4, 0xc5,
6128
-	0x2b, 0x29, 0x11, 0xde, 0xc8, 0xbc, 0x1d, 0x65, 0x6c, 0x7b, 0xfa, 0x31, 0x48, 0x6f, 0x88, 0x7d,
6129
-	0x0c, 0x6c, 0xb7, 0xf9, 0xaf, 0x1c, 0x54, 0x16, 0x8b, 0x06, 0xb4, 0x97, 0x24, 0x7b, 0xb3, 0xa5,
6130
-	0x5b, 0xbb, 0x3b, 0xef, 0x2a, 0x32, 0x4c, 0x6a, 0x0d, 0x63, 0xed, 0xec, 0x48, 0xd7, 0xf7, 0x86,
6131
-	0x8c, 0x7e, 0x0a, 0xeb, 0x11, 0x17, 0x2a, 0x7d, 0xc2, 0xb2, 0x03, 0xcc, 0x45, 0x9a, 0x8a, 0x12,
6132
-	0x70, 0x73, 0x04, 0xb7, 0x96, 0xbd, 0xa1, 0x47, 0xb0, 0xf6, 0xe2, 0xa0, 0x5f, 0x5d, 0xa9, 0x3d,
6133
-	0x78, 0x75, 0xd9, 0xf8, 0xee, 0xf2, 0xe0, 0x8b, 0x40, 0xa8, 0x98, 0x84, 0x07, 0x7d, 0xf4, 0x43,
6134
-	0x58, 0xef, 0x1e, 0x9f, 0x60, 0x5c, 0xcd, 0xd5, 0xb6, 0x5e, 0x5d, 0x36, 0x1e, 0x2c, 0xe3, 0xf4,
6135
-	0x10, 0x8f, 0x99, 0x8f, 0xf9, 0xd9, 0xac, 0xd6, 0xfd, 0xf7, 0x2a, 0x38, 0xf6, 0x65, 0xff, 0xd0,
6136
-	0xdf, 0xa1, 0x8d, 0x24, 0x95, 0xa7, 0x57, 0x76, 0xf5, 0x9d, 0x19, 0xbd, 0x92, 0x10, 0xec, 0x19,
6137
-	0x3f, 0x84, 0x4a, 0x10, 0x4d, 0x3e, 0x1b, 0x50, 0x46, 0xce, 0x42, 0x5b, 0xf6, 0x96, 0xb0, 0xa3,
6138
-	0x6d, 0xbd, 0xc4, 0xa4, 0xdf, 0x8b, 0x80, 0x29, 0x2a, 0x98, 0x2d, 0x68, 0x4b, 0x78, 0xd6, 0x47,
6139
-	0x5f, 0x40, 0x3e, 0x88, 0xc8, 0xd8, 0x96, 0x21, 0x99, 0x3b, 0x38, 0xe8, 0xb7, 0x8f, 0xac, 0x06,
6140
-	0x3b, 0xa5, 0xeb, 0xab, 0xad, 0xbc, 0x36, 0x60, 0x43, 0x43, 0xf5, 0xb4, 0x12, 0xd0, 0x33, 0x99,
6141
-	0xb7, 0xbf, 0x84, 0x17, 0x2c, 0x5a, 0x47, 0x01, 0x1b, 0x0a, 0x2a, 0xa5, 0xc9, 0x02, 0x25, 0x9c,
6142
-	0x76, 0x51, 0x0d, 0x8a, 0xb6, 0x9e, 0x30, 0x05, 0x44, 0x59, 0xe7, 0x6a, 0x6b, 0xe8, 0x6c, 0x80,
6143
-	0x93, 0x44, 0x63, 0x70, 0x2e, 0xf8, 0xb8, 0xf9, 0x9f, 0x3c, 0x38, 0x7b, 0x61, 0x2c, 0x95, 0x4d,
6144
-	0x83, 0x1f, 0x2c, 0xf8, 0x2f, 0xe1, 0x0e, 0x31, 0xdf, 0x2b, 0xc2, 0x74, 0x4e, 0x31, 0x65, 0x9a,
6145
-	0x3d, 0x80, 0x47, 0x99, 0xee, 0x66, 0xe0, 0xa4, 0xa4, 0xeb, 0x14, 0xb4, 0x4f, 0x37, 0x87, 0xab,
6146
-	0xe4, 0x8d, 0x11, 0x74, 0x02, 0x1b, 0x5c, 0x78, 0x23, 0x2a, 0x55, 0x92, 0x89, 0xec, 0x77, 0x24,
6147
-	0xf3, 0xa3, 0xfa, 0x7c, 0x11, 0x68, 0x9f, 0xe1, 0x64, 0xb5, 0xcb, 0x3e, 0xd0, 0x13, 0xc8, 0x0b,
6148
-	0x72, 0x9e, 0x96, 0x9c, 0x99, 0x97, 0x04, 0x93, 0x73, 0xb5, 0xe4, 0xc2, 0x30, 0xd0, 0x6f, 0x01,
6149
-	0xfc, 0x40, 0x46, 0x44, 0x79, 0x23, 0x2a, 0xec, 0x61, 0x67, 0x6e, 0xb1, 0x3b, 0x43, 0x2d, 0x79,
6150
-	0x59, 0x60, 0xa3, 0x43, 0x28, 0x7b, 0x24, 0x95, 0x6b, 0xe1, 0xe6, 0x3f, 0xda, 0x5e, 0xdb, 0xba,
6151
-	0xa8, 0x6a, 0x17, 0xd7, 0x57, 0x5b, 0xa5, 0xd4, 0x82, 0x4b, 0x1e, 0xb1, 0xf2, 0x3d, 0x84, 0x0d,
6152
-	0xfd, 0x77, 0x1b, 0xf8, 0xf4, 0x9c, 0xc4, 0xa1, 0x4a, 0x64, 0x72, 0x43, 0x5a, 0xd1, 0x1f, 0x81,
6153
-	0xae, 0xc5, 0xd9, 0x75, 0x55, 0xd4, 0x82, 0x0d, 0xfd, 0x1e, 0xee, 0x50, 0xe6, 0x89, 0xa9, 0x11,
6154
-	0x6b, 0xba, 0xc2, 0xd2, 0xcd, 0x9b, 0xed, 0xcd, 0xc0, 0x4b, 0x9b, 0xad, 0xd2, 0x37, 0xec, 0xcd,
6155
-	0x00, 0x20, 0x49, 0xd4, 0x1f, 0x56, 0x7f, 0x08, 0xf2, 0x3e, 0x51, 0xc4, 0x48, 0xae, 0x82, 0x4d,
6156
-	0x5b, 0x4f, 0x95, 0x4c, 0xfa, 0x7f, 0x9f, 0xaa, 0xe3, 0xbe, 0xfe, 0xa6, 0xbe, 0xf2, 0x8f, 0x6f,
6157
-	0xea, 0x2b, 0x7f, 0xba, 0xae, 0xe7, 0x5e, 0x5f, 0xd7, 0x73, 0x7f, 0xbb, 0xae, 0xe7, 0xfe, 0x79,
6158
-	0x5d, 0xcf, 0x9d, 0x15, 0x4c, 0x25, 0xf5, 0x93, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0xb3, 0x21,
6159
-	0x2b, 0x33, 0x82, 0x12, 0x00, 0x00,
6043
+	// 1867 bytes of a gzipped FileDescriptorProto
6044
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x57, 0xcf, 0x73, 0x1b, 0x49,
6045
+	0x15, 0xb6, 0x6c, 0x59, 0x3f, 0xde, 0xc8, 0x89, 0xd2, 0x24, 0x61, 0xa2, 0xb0, 0xb2, 0xa2, 0x0d,
6046
+	0xc1, 0xcb, 0x16, 0x72, 0x61, 0xa8, 0x25, 0xbb, 0x61, 0x01, 0xc9, 0x12, 0x8e, 0x31, 0x76, 0x54,
6047
+	0x6d, 0x6f, 0x20, 0x27, 0x55, 0x7b, 0xa6, 0x3d, 0x9a, 0xf2, 0xa8, 0x7b, 0xe8, 0xe9, 0xd1, 0x96,
6048
+	0x6e, 0x1c, 0xb7, 0x72, 0xe5, 0xec, 0xe2, 0x40, 0xf1, 0xbf, 0xe4, 0x48, 0x71, 0xe2, 0xe4, 0x62,
6049
+	0xfd, 0x2f, 0x70, 0xe3, 0x02, 0xd5, 0x3d, 0x3d, 0xd2, 0x28, 0x19, 0x27, 0xa9, 0x22, 0x07, 0x6e,
6050
+	0xdd, 0xaf, 0xbf, 0xef, 0xcd, 0xeb, 0xd7, 0x5f, 0xf7, 0x7b, 0x03, 0x56, 0x14, 0x52, 0x27, 0xea,
6051
+	0x84, 0x82, 0x4b, 0x8e, 0x90, 0xcb, 0x9d, 0x73, 0x2a, 0x3a, 0xd1, 0xd7, 0x44, 0x4c, 0xce, 0x7d,
6052
+	0xd9, 0x99, 0xfe, 0xb8, 0x61, 0xc9, 0x59, 0x48, 0x0d, 0xa0, 0x71, 0xdb, 0xe3, 0x1e, 0xd7, 0xc3,
6053
+	0x6d, 0x35, 0x32, 0xd6, 0xa6, 0xc7, 0xb9, 0x17, 0xd0, 0x6d, 0x3d, 0x3b, 0x8d, 0xcf, 0xb6, 0xdd,
6054
+	0x58, 0x10, 0xe9, 0x73, 0x66, 0xd6, 0xef, 0xbd, 0xbe, 0x4e, 0xd8, 0x2c, 0x59, 0x6a, 0x5f, 0x14,
6055
+	0xa1, 0x72, 0xc4, 0x5d, 0x7a, 0x1c, 0x52, 0x07, 0xed, 0x81, 0x45, 0x18, 0xe3, 0x52, 0x73, 0x23,
6056
+	0xbb, 0xd0, 0x2a, 0x6c, 0x59, 0x3b, 0x9b, 0x9d, 0x37, 0x83, 0xea, 0x74, 0x17, 0xb0, 0x5e, 0xf1,
6057
+	0xd5, 0xe5, 0xe6, 0x0a, 0xce, 0x32, 0xd1, 0x2f, 0xa1, 0xe6, 0xd2, 0xc8, 0x17, 0xd4, 0x1d, 0x09,
6058
+	0x1e, 0x50, 0x7b, 0xb5, 0x55, 0xd8, 0xba, 0xb1, 0xf3, 0xbd, 0x3c, 0x4f, 0xea, 0xe3, 0x98, 0x07,
6059
+	0x14, 0x5b, 0x86, 0xa1, 0x26, 0x68, 0x0f, 0x60, 0x42, 0x27, 0xa7, 0x54, 0x44, 0x63, 0x3f, 0xb4,
6060
+	0xd7, 0x34, 0xfd, 0x07, 0xd7, 0xd1, 0x55, 0xec, 0x9d, 0xc3, 0x39, 0x1c, 0x67, 0xa8, 0xe8, 0x10,
6061
+	0x6a, 0x64, 0x4a, 0xfc, 0x80, 0x9c, 0xfa, 0x81, 0x2f, 0x67, 0x76, 0x51, 0xbb, 0xfa, 0xe4, 0xad,
6062
+	0xae, 0xba, 0x19, 0x02, 0x5e, 0xa2, 0xb7, 0x5d, 0x80, 0xc5, 0x87, 0xd0, 0x23, 0x28, 0x0f, 0x07,
6063
+	0x47, 0xfd, 0xfd, 0xa3, 0xbd, 0xfa, 0x4a, 0xe3, 0xde, 0xcb, 0x8b, 0xd6, 0x1d, 0xe5, 0x63, 0x01,
6064
+	0x18, 0x52, 0xe6, 0xfa, 0xcc, 0x43, 0x5b, 0x50, 0xe9, 0xee, 0xee, 0x0e, 0x86, 0x27, 0x83, 0x7e,
6065
+	0xbd, 0xd0, 0x68, 0xbc, 0xbc, 0x68, 0xdd, 0x5d, 0x06, 0x76, 0x1d, 0x87, 0x86, 0x92, 0xba, 0x8d,
6066
+	0xe2, 0x37, 0x7f, 0x69, 0xae, 0xb4, 0xbf, 0x29, 0x40, 0x2d, 0x1b, 0x04, 0x7a, 0x04, 0xa5, 0xee,
6067
+	0xee, 0xc9, 0xfe, 0xf3, 0x41, 0x7d, 0x65, 0x41, 0xcf, 0x22, 0xba, 0x8e, 0xf4, 0xa7, 0x14, 0x3d,
6068
+	0x84, 0xf5, 0x61, 0xf7, 0xab, 0xe3, 0x41, 0xbd, 0xb0, 0x08, 0x27, 0x0b, 0x1b, 0x92, 0x38, 0xd2,
6069
+	0xa8, 0x3e, 0xee, 0xee, 0x1f, 0xd5, 0x57, 0xf3, 0x51, 0x7d, 0x41, 0x7c, 0x66, 0x42, 0xf9, 0x73,
6070
+	0x11, 0xac, 0x63, 0x2a, 0xa6, 0xbe, 0xf3, 0x81, 0x25, 0xf2, 0x19, 0x14, 0x25, 0x89, 0xce, 0xb5,
6071
+	0x34, 0xac, 0x7c, 0x69, 0x9c, 0x90, 0xe8, 0x5c, 0x7d, 0xd4, 0xd0, 0x35, 0x5e, 0x29, 0x43, 0xd0,
6072
+	0x30, 0xf0, 0x1d, 0x22, 0xa9, 0xab, 0x95, 0x61, 0xed, 0x7c, 0x3f, 0x8f, 0x8d, 0xe7, 0x28, 0x13,
6073
+	0xff, 0xd3, 0x15, 0x9c, 0xa1, 0xa2, 0x27, 0x50, 0xf2, 0x02, 0x7e, 0x4a, 0x02, 0xad, 0x09, 0x6b,
6074
+	0xe7, 0x41, 0x9e, 0x93, 0x3d, 0x8d, 0x58, 0x38, 0x30, 0x14, 0xf4, 0x18, 0x4a, 0x71, 0xe8, 0x12,
6075
+	0x49, 0xed, 0x92, 0x26, 0xb7, 0xf2, 0xc8, 0x5f, 0x69, 0xc4, 0x2e, 0x67, 0x67, 0xbe, 0x87, 0x0d,
6076
+	0x1e, 0x1d, 0x40, 0x85, 0x51, 0xf9, 0x35, 0x17, 0xe7, 0x91, 0x5d, 0x6e, 0xad, 0x6d, 0x59, 0x3b,
6077
+	0x9f, 0xe6, 0x8a, 0x31, 0xc1, 0x74, 0xa5, 0x24, 0xce, 0x78, 0x42, 0x99, 0x4c, 0xdc, 0xf4, 0x56,
6078
+	0xed, 0x02, 0x9e, 0x3b, 0x40, 0x3f, 0x87, 0x0a, 0x65, 0x6e, 0xc8, 0x7d, 0x26, 0xed, 0xca, 0xf5,
6079
+	0x81, 0x0c, 0x0c, 0x46, 0x25, 0x13, 0xcf, 0x19, 0x8a, 0x2d, 0x78, 0x10, 0x9c, 0x12, 0xe7, 0xdc,
6080
+	0xae, 0xbe, 0xe7, 0x36, 0xe6, 0x8c, 0x5e, 0x09, 0x8a, 0x13, 0xee, 0xd2, 0xf6, 0x36, 0xdc, 0x7a,
6081
+	0x23, 0xd5, 0xa8, 0x01, 0x15, 0x93, 0xea, 0x44, 0x23, 0x45, 0x3c, 0x9f, 0xb7, 0x6f, 0xc2, 0xc6,
6082
+	0x52, 0x5a, 0xdb, 0x7f, 0x2f, 0x42, 0x25, 0x3d, 0x6b, 0xd4, 0x85, 0xaa, 0xc3, 0x99, 0x24, 0x3e,
6083
+	0xa3, 0xc2, 0xc8, 0x2b, 0xf7, 0x64, 0x76, 0x53, 0x90, 0x62, 0x3d, 0x5d, 0xc1, 0x0b, 0x16, 0xfa,
6084
+	0x35, 0x54, 0x05, 0x8d, 0x78, 0x2c, 0x1c, 0x1a, 0x19, 0x7d, 0x6d, 0xe5, 0x2b, 0x24, 0x01, 0x61,
6085
+	0xfa, 0x87, 0xd8, 0x17, 0x54, 0x65, 0x39, 0xc2, 0x0b, 0x2a, 0x7a, 0x02, 0x65, 0x41, 0x23, 0x49,
6086
+	0x84, 0x7c, 0x9b, 0x44, 0x70, 0x02, 0x19, 0xf2, 0xc0, 0x77, 0x66, 0x38, 0x65, 0xa0, 0x27, 0x50,
6087
+	0x0d, 0x03, 0xe2, 0x68, 0xaf, 0xf6, 0xba, 0xa6, 0x7f, 0x94, 0x47, 0x1f, 0xa6, 0x20, 0xbc, 0xc0,
6088
+	0xa3, 0xcf, 0x01, 0x02, 0xee, 0x8d, 0x5c, 0xe1, 0x4f, 0xa9, 0x30, 0x12, 0x6b, 0xe4, 0xb1, 0xfb,
6089
+	0x1a, 0x81, 0xab, 0x01, 0xf7, 0x92, 0x21, 0xda, 0xfb, 0x9f, 0xf4, 0x95, 0xd1, 0xd6, 0x01, 0x00,
6090
+	0x99, 0xaf, 0x1a, 0x75, 0x7d, 0xf2, 0x5e, 0xae, 0xcc, 0x89, 0x64, 0xe8, 0xe8, 0x01, 0xd4, 0xce,
6091
+	0xb8, 0x70, 0xe8, 0xc8, 0xdc, 0x9a, 0xaa, 0xd6, 0x84, 0xa5, 0x6d, 0x89, 0xbe, 0x50, 0x0f, 0xca,
6092
+	0x1e, 0x65, 0x54, 0xf8, 0x8e, 0x0d, 0xfa, 0x63, 0x8f, 0x72, 0x2f, 0x64, 0x02, 0xc1, 0x31, 0x93,
6093
+	0xfe, 0x84, 0x9a, 0x2f, 0xa5, 0xc4, 0x5e, 0x15, 0xca, 0x22, 0x59, 0x69, 0xff, 0x1e, 0xd0, 0x9b,
6094
+	0x58, 0x84, 0xa0, 0x78, 0xee, 0x33, 0x57, 0x0b, 0xab, 0x8a, 0xf5, 0x18, 0x75, 0xa0, 0x1c, 0x92,
6095
+	0x59, 0xc0, 0x89, 0x6b, 0xc4, 0x72, 0xbb, 0x93, 0xd4, 0xcb, 0x4e, 0x5a, 0x2f, 0x3b, 0x5d, 0x36,
6096
+	0xc3, 0x29, 0xa8, 0x7d, 0x00, 0x77, 0x72, 0xb7, 0x8c, 0x76, 0xa0, 0x36, 0x17, 0xe1, 0xc8, 0x37,
6097
+	0x1f, 0xe9, 0xdd, 0xbc, 0xba, 0xdc, 0xb4, 0xe6, 0x6a, 0xdd, 0xef, 0x63, 0x6b, 0x0e, 0xda, 0x77,
6098
+	0xdb, 0x7f, 0xaa, 0xc2, 0xc6, 0x92, 0x94, 0xd1, 0x6d, 0x58, 0xf7, 0x27, 0xc4, 0xa3, 0x26, 0xc6,
6099
+	0x64, 0x82, 0x06, 0x50, 0x0a, 0xc8, 0x29, 0x0d, 0x94, 0xa0, 0xd5, 0xa1, 0xfe, 0xe8, 0x9d, 0x77,
6100
+	0xa2, 0xf3, 0x5b, 0x8d, 0x1f, 0x30, 0x29, 0x66, 0xd8, 0x90, 0x91, 0x0d, 0x65, 0x87, 0x4f, 0x26,
6101
+	0x84, 0xa9, 0xa7, 0x73, 0x6d, 0xab, 0x8a, 0xd3, 0xa9, 0xca, 0x0c, 0x11, 0x5e, 0x64, 0x17, 0xb5,
6102
+	0x59, 0x8f, 0x51, 0x1d, 0xd6, 0x28, 0x9b, 0xda, 0xeb, 0xda, 0xa4, 0x86, 0xca, 0xe2, 0xfa, 0x89,
6103
+	0x22, 0xab, 0x58, 0x0d, 0x15, 0x2f, 0x8e, 0xa8, 0xb0, 0xcb, 0x49, 0x46, 0xd5, 0x18, 0xfd, 0x0c,
6104
+	0x4a, 0x13, 0x1e, 0x33, 0x19, 0xd9, 0x15, 0x1d, 0xec, 0xbd, 0xbc, 0x60, 0x0f, 0x15, 0xc2, 0x3c,
6105
+	0xed, 0x06, 0x8e, 0x06, 0x70, 0x2b, 0x92, 0x3c, 0x1c, 0x79, 0x82, 0x38, 0x74, 0x14, 0x52, 0xe1,
6106
+	0x73, 0xd7, 0x3c, 0x4d, 0xf7, 0xde, 0x38, 0x94, 0xbe, 0x69, 0x72, 0xf0, 0x4d, 0xc5, 0xd9, 0x53,
6107
+	0x94, 0xa1, 0x66, 0xa0, 0x21, 0xd4, 0xc2, 0x38, 0x08, 0x46, 0x3c, 0x4c, 0xaa, 0x54, 0xa2, 0xa7,
6108
+	0xf7, 0x48, 0xd9, 0x30, 0x0e, 0x82, 0x67, 0x09, 0x09, 0x5b, 0xe1, 0x62, 0x82, 0xee, 0x42, 0xc9,
6109
+	0x13, 0x3c, 0x0e, 0x23, 0xdb, 0xd2, 0xc9, 0x30, 0x33, 0xf4, 0x25, 0x94, 0x23, 0xea, 0x08, 0x2a,
6110
+	0x23, 0xbb, 0xa6, 0xb7, 0xfa, 0x71, 0xde, 0x47, 0x8e, 0x35, 0x04, 0xd3, 0x33, 0x2a, 0x28, 0x73,
6111
+	0x28, 0x4e, 0x39, 0xe8, 0x1e, 0xac, 0x49, 0x39, 0xb3, 0x37, 0x5a, 0x85, 0xad, 0x4a, 0xaf, 0x7c,
6112
+	0x75, 0xb9, 0xb9, 0x76, 0x72, 0xf2, 0x02, 0x2b, 0x9b, 0x7a, 0x41, 0xc7, 0x3c, 0x92, 0x8c, 0x4c,
6113
+	0xa8, 0x7d, 0x43, 0xe7, 0x76, 0x3e, 0x47, 0x2f, 0x00, 0x5c, 0x16, 0x8d, 0x1c, 0x7d, 0x65, 0xed,
6114
+	0x9b, 0x7a, 0x77, 0x9f, 0xbe, 0x7b, 0x77, 0xfd, 0xa3, 0x63, 0x53, 0x45, 0x36, 0xae, 0x2e, 0x37,
6115
+	0xab, 0xf3, 0x29, 0xae, 0xba, 0x2c, 0x4a, 0x86, 0xa8, 0x07, 0xd6, 0x98, 0x92, 0x40, 0x8e, 0x9d,
6116
+	0x31, 0x75, 0xce, 0xed, 0xfa, 0xf5, 0x65, 0xe1, 0xa9, 0x86, 0x19, 0x0f, 0x59, 0x92, 0x52, 0xb0,
6117
+	0x0a, 0x35, 0xb2, 0x6f, 0xe9, 0x5c, 0x25, 0x13, 0xf4, 0x11, 0x00, 0x0f, 0x29, 0x1b, 0x45, 0xd2,
6118
+	0xf5, 0x99, 0x8d, 0xd4, 0x96, 0x71, 0x55, 0x59, 0x8e, 0x95, 0x01, 0xdd, 0x57, 0x8f, 0x36, 0x71,
6119
+	0x47, 0x9c, 0x05, 0x33, 0xfb, 0x3b, 0x7a, 0xb5, 0xa2, 0x0c, 0xcf, 0x58, 0x30, 0x43, 0x9b, 0x60,
6120
+	0x69, 0x5d, 0x44, 0xbe, 0xc7, 0x48, 0x60, 0xdf, 0xd6, 0xf9, 0x00, 0x65, 0x3a, 0xd6, 0x16, 0x75,
6121
+	0x0e, 0x49, 0x36, 0x22, 0xfb, 0xce, 0xf5, 0xe7, 0x60, 0x82, 0x5d, 0x9c, 0x83, 0xe1, 0xa0, 0x5f,
6122
+	0x00, 0x84, 0xc2, 0x9f, 0xfa, 0x01, 0xf5, 0x68, 0x64, 0xdf, 0xd5, 0x9b, 0x6e, 0xe6, 0xbe, 0xd6,
6123
+	0x73, 0x14, 0xce, 0x30, 0x1a, 0x9f, 0x83, 0x95, 0xb9, 0x6d, 0xea, 0x96, 0x9c, 0xd3, 0x99, 0xb9,
6124
+	0xc0, 0x6a, 0xa8, 0x52, 0x32, 0x25, 0x41, 0x9c, 0x74, 0xc2, 0x55, 0x9c, 0x4c, 0xbe, 0x58, 0x7d,
6125
+	0x5c, 0x68, 0xec, 0x80, 0x95, 0x51, 0x1d, 0xfa, 0x18, 0x36, 0x04, 0xf5, 0xfc, 0x48, 0x8a, 0xd9,
6126
+	0x88, 0xc4, 0x72, 0x6c, 0xff, 0x4a, 0x13, 0x6a, 0xa9, 0xb1, 0x1b, 0xcb, 0x71, 0x63, 0x04, 0x8b,
6127
+	0xc3, 0x43, 0x2d, 0xb0, 0x94, 0x28, 0x22, 0x2a, 0xa6, 0x54, 0xa8, 0x6a, 0xab, 0x72, 0x9e, 0x35,
6128
+	0x29, 0xf1, 0x46, 0x94, 0x08, 0x67, 0xac, 0xdf, 0x8e, 0x2a, 0x36, 0x33, 0xf5, 0x18, 0xa4, 0x37,
6129
+	0xc4, 0x3c, 0x06, 0x66, 0xda, 0xfe, 0x57, 0x01, 0x6a, 0xd9, 0xa6, 0x01, 0xed, 0x26, 0xc5, 0x5e,
6130
+	0x6f, 0xe9, 0xc6, 0xce, 0xf6, 0xbb, 0x9a, 0x0c, 0x5d, 0x5a, 0x83, 0x58, 0x39, 0x3b, 0x54, 0xfd,
6131
+	0xbd, 0x26, 0xa3, 0x9f, 0xc2, 0x7a, 0xc8, 0x85, 0x4c, 0x9f, 0xb0, 0xfc, 0x04, 0x73, 0x91, 0x96,
6132
+	0xa2, 0x04, 0xdc, 0x1e, 0xc3, 0x8d, 0x65, 0x6f, 0xe8, 0x21, 0xac, 0x3d, 0xdf, 0x1f, 0xd6, 0x57,
6133
+	0x1a, 0xf7, 0x5f, 0x5e, 0xb4, 0xbe, 0xbb, 0xbc, 0xf8, 0xdc, 0x17, 0x32, 0x26, 0xc1, 0xfe, 0x10,
6134
+	0xfd, 0x10, 0xd6, 0xfb, 0x47, 0xc7, 0x18, 0xd7, 0x0b, 0x8d, 0xcd, 0x97, 0x17, 0xad, 0xfb, 0xcb,
6135
+	0x38, 0xb5, 0xc4, 0x63, 0xe6, 0x62, 0x7e, 0x3a, 0xef, 0x75, 0xff, 0xbd, 0x0a, 0x96, 0x79, 0xd9,
6136
+	0x3f, 0xf4, 0xef, 0xd0, 0x46, 0x52, 0xca, 0xd3, 0x2b, 0xbb, 0xfa, 0xce, 0x8a, 0x5e, 0x4b, 0x08,
6137
+	0xe6, 0x8c, 0x1f, 0x40, 0xcd, 0x0f, 0xa7, 0x9f, 0x8d, 0x28, 0x23, 0xa7, 0x81, 0x69, 0x7b, 0x2b,
6138
+	0xd8, 0x52, 0xb6, 0x41, 0x62, 0x52, 0xef, 0x85, 0xcf, 0x24, 0x15, 0xcc, 0x34, 0xb4, 0x15, 0x3c,
6139
+	0x9f, 0xa3, 0x2f, 0xa1, 0xe8, 0x87, 0x64, 0x62, 0xda, 0x90, 0xdc, 0x1d, 0xec, 0x0f, 0xbb, 0x87,
6140
+	0x46, 0x83, 0xbd, 0xca, 0xd5, 0xe5, 0x66, 0x51, 0x19, 0xb0, 0xa6, 0xa1, 0x66, 0xda, 0x09, 0xa8,
6141
+	0x2f, 0xe9, 0xb7, 0xbf, 0x82, 0x33, 0x16, 0xa5, 0x23, 0x9f, 0x79, 0x82, 0x46, 0x91, 0xae, 0x02,
6142
+	0x15, 0x9c, 0x4e, 0x51, 0x03, 0xca, 0xa6, 0x9f, 0xd0, 0x0d, 0x44, 0x55, 0xd5, 0x6a, 0x63, 0xe8,
6143
+	0x6d, 0x80, 0x95, 0x64, 0x63, 0x74, 0x26, 0xf8, 0xa4, 0xfd, 0x9f, 0x22, 0x58, 0xbb, 0x41, 0x1c,
6144
+	0x49, 0x53, 0x06, 0x3f, 0x58, 0xf2, 0x5f, 0xc0, 0x2d, 0xa2, 0x7f, 0xaf, 0x08, 0x53, 0x35, 0x45,
6145
+	0xb7, 0x69, 0xe6, 0x00, 0x1e, 0xe6, 0xba, 0x9b, 0x83, 0x93, 0x96, 0xae, 0x57, 0x52, 0x3e, 0xed,
6146
+	0x02, 0xae, 0x93, 0xd7, 0x56, 0xd0, 0x31, 0x6c, 0x70, 0xe1, 0x8c, 0x69, 0x24, 0x93, 0x4a, 0x64,
6147
+	0x7e, 0x47, 0x72, 0x7f, 0x54, 0x9f, 0x65, 0x81, 0xe6, 0x19, 0x4e, 0xa2, 0x5d, 0xf6, 0x81, 0x1e,
6148
+	0x43, 0x51, 0x90, 0xb3, 0xb4, 0xe5, 0xcc, 0xbd, 0x24, 0x98, 0x9c, 0xc9, 0x25, 0x17, 0x9a, 0x81,
6149
+	0x7e, 0x03, 0xe0, 0xfa, 0x51, 0x48, 0xa4, 0x33, 0xa6, 0xc2, 0x1c, 0x76, 0xee, 0x16, 0xfb, 0x73,
6150
+	0xd4, 0x92, 0x97, 0x0c, 0x1b, 0x1d, 0x40, 0xd5, 0x21, 0xa9, 0x5c, 0x4b, 0xd7, 0xff, 0xa3, 0xed,
6151
+	0x76, 0x8d, 0x8b, 0xba, 0x72, 0x71, 0x75, 0xb9, 0x59, 0x49, 0x2d, 0xb8, 0xe2, 0x10, 0x23, 0xdf,
6152
+	0x03, 0xd8, 0x50, 0xff, 0x6e, 0x23, 0x97, 0x9e, 0x91, 0x38, 0x90, 0x89, 0x4c, 0xae, 0x29, 0x2b,
6153
+	0xea, 0x47, 0xa0, 0x6f, 0x70, 0x26, 0xae, 0x9a, 0xcc, 0xd8, 0xd0, 0xef, 0xe0, 0x16, 0x65, 0x8e,
6154
+	0x98, 0x69, 0xb1, 0xa6, 0x11, 0x56, 0xae, 0xdf, 0xec, 0x60, 0x0e, 0x5e, 0xda, 0x6c, 0x9d, 0xbe,
6155
+	0x66, 0x6f, 0xff, 0xb5, 0x00, 0x90, 0x54, 0xea, 0x0f, 0x2b, 0x40, 0x04, 0x45, 0x97, 0x48, 0xa2,
6156
+	0x35, 0x57, 0xc3, 0x7a, 0x8c, 0xbe, 0x00, 0x90, 0x74, 0x12, 0x06, 0x44, 0xfa, 0xcc, 0x33, 0xb2,
6157
+	0x79, 0xdb, 0x73, 0x90, 0x41, 0xeb, 0x38, 0x93, 0x90, 0xff, 0xaf, 0xe3, 0xec, 0xd9, 0xaf, 0xbe,
6158
+	0x6d, 0xae, 0xfc, 0xe3, 0xdb, 0xe6, 0xca, 0x1f, 0xaf, 0x9a, 0x85, 0x57, 0x57, 0xcd, 0xc2, 0xdf,
6159
+	0xae, 0x9a, 0x85, 0x7f, 0x5e, 0x35, 0x0b, 0xa7, 0x25, 0xdd, 0xc3, 0xfd, 0xe4, 0xbf, 0x01, 0x00,
6160
+	0x00, 0xff, 0xff, 0x06, 0x93, 0x6e, 0xba, 0xfc, 0x12, 0x00, 0x00,
6160 6161
 }
... ...
@@ -386,6 +386,13 @@ message SecretSpec {
386 386
 
387 387
 	// Data is the secret payload - the maximum size is 500KB (that is, 500*1024 bytes)
388 388
 	bytes data = 2;
389
+
390
+	// Templating controls whether and how to evaluate the secret payload as
391
+	// a template. If it is not set, no templating is used.
392
+	//
393
+	// The currently recognized values are:
394
+	// - golang: Go templating
395
+	Driver templating = 3;
389 396
 }
390 397
 
391 398
 // ConfigSpec specifies user-provided configuration files.
... ...
@@ -396,4 +403,11 @@ message ConfigSpec {
396 396
 	// TODO(aaronl): Do we want to revise this to include multiple payloads in a single
397 397
 	// ConfigSpec? Define this to be a tar? etc...
398 398
 	bytes data = 2;
399
+
400
+	// Templating controls whether and how to evaluate the secret payload as
401
+	// a template. If it is not set, no templating is used.
402
+	//
403
+	// The currently recognized values are:
404
+	// - golang: Go templating
405
+	Driver templating = 3;
399 406
 }
... ...
@@ -126,6 +126,11 @@ type LocalSigner struct {
126 126
 	cryptoSigner crypto.Signer
127 127
 }
128 128
 
129
+type x509UnknownAuthError struct {
130
+	error
131
+	failedLeafCert *x509.Certificate
132
+}
133
+
129 134
 // RootCA is the representation of everything we need to sign certificates and/or to verify certificates
130 135
 //
131 136
 // RootCA.Cert:          [CA cert1][CA cert2]
... ...
@@ -275,6 +280,17 @@ func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, kw KeyWrit
275 275
 	// Create an X509Cert so we can .Verify()
276 276
 	// Check to see if this certificate was signed by our CA, and isn't expired
277 277
 	parsedCerts, chains, err := ValidateCertChain(rca.Pool, signedCert, false)
278
+	// TODO(cyli): - right now we need the invalid certificate in order to determine whether or not we should
279
+	// download a new root, because we only want to do that in the case of workers.  When we have a single
280
+	// codepath for updating the root CAs for both managers and workers, this snippet can go.
281
+	if _, ok := err.(x509.UnknownAuthorityError); ok {
282
+		if parsedCerts, parseErr := helpers.ParseCertificatesPEM(signedCert); parseErr == nil && len(parsedCerts) > 0 {
283
+			return nil, nil, x509UnknownAuthError{
284
+				error:          err,
285
+				failedLeafCert: parsedCerts[0],
286
+			}
287
+		}
288
+	}
278 289
 	if err != nil {
279 290
 		return nil, nil, err
280 291
 	}
... ...
@@ -492,9 +492,35 @@ func (rootCA RootCA) CreateSecurityConfig(ctx context.Context, krw *KeyReadWrite
492 492
 	return secConfig, err
493 493
 }
494 494
 
495
+// TODO(cyli): currently we have to only update if it's a worker role - if we have a single root CA update path for
496
+// both managers and workers, we won't need to check any more.
497
+func updateRootThenUpdateCert(ctx context.Context, s *SecurityConfig, connBroker *connectionbroker.Broker, rootPaths CertPaths, failedCert *x509.Certificate) (*tls.Certificate, *IssuerInfo, error) {
498
+	if len(failedCert.Subject.OrganizationalUnit) == 0 || failedCert.Subject.OrganizationalUnit[0] != WorkerRole {
499
+		return nil, nil, errors.New("cannot update root CA since this is not a worker")
500
+	}
501
+	// try downloading a new root CA if it's an unknown authority issue, in case there was a root rotation completion
502
+	// and we just didn't get the new root
503
+	rootCA, err := GetRemoteCA(ctx, "", connBroker)
504
+	if err != nil {
505
+		return nil, nil, err
506
+	}
507
+	// validate against the existing security config creds
508
+	if err := s.UpdateRootCA(&rootCA, rootCA.Pool); err != nil {
509
+		return nil, nil, err
510
+	}
511
+	if err := SaveRootCA(rootCA, rootPaths); err != nil {
512
+		return nil, nil, err
513
+	}
514
+	return rootCA.RequestAndSaveNewCertificates(ctx, s.KeyWriter(),
515
+		CertificateRequestConfig{
516
+			ConnBroker:  connBroker,
517
+			Credentials: s.ClientTLSCreds,
518
+		})
519
+}
520
+
495 521
 // RenewTLSConfigNow gets a new TLS cert and key, and updates the security config if provided.  This is similar to
496 522
 // RenewTLSConfig, except while that monitors for expiry, and periodically renews, this renews once and is blocking
497
-func RenewTLSConfigNow(ctx context.Context, s *SecurityConfig, connBroker *connectionbroker.Broker) error {
523
+func RenewTLSConfigNow(ctx context.Context, s *SecurityConfig, connBroker *connectionbroker.Broker, rootPaths CertPaths) error {
498 524
 	s.renewalMu.Lock()
499 525
 	defer s.renewalMu.Unlock()
500 526
 
... ...
@@ -512,6 +538,15 @@ func RenewTLSConfigNow(ctx context.Context, s *SecurityConfig, connBroker *conne
512 512
 			ConnBroker:  connBroker,
513 513
 			Credentials: s.ClientTLSCreds,
514 514
 		})
515
+	if wrappedError, ok := err.(x509UnknownAuthError); ok {
516
+		var newErr error
517
+		tlsKeyPair, issuerInfo, newErr = updateRootThenUpdateCert(ctx, s, connBroker, rootPaths, wrappedError.failedLeafCert)
518
+		if newErr != nil {
519
+			err = wrappedError.error
520
+		} else {
521
+			err = nil
522
+		}
523
+	}
515 524
 	if err != nil {
516 525
 		log.WithError(err).Errorf("failed to renew the certificate")
517 526
 		return err
... ...
@@ -27,14 +27,16 @@ type TLSRenewer struct {
27 27
 	connBroker   *connectionbroker.Broker
28 28
 	renew        chan struct{}
29 29
 	expectedRole string
30
+	rootPaths    CertPaths
30 31
 }
31 32
 
32 33
 // NewTLSRenewer creates a new TLS renewer. It must be started with Start.
33
-func NewTLSRenewer(s *SecurityConfig, connBroker *connectionbroker.Broker) *TLSRenewer {
34
+func NewTLSRenewer(s *SecurityConfig, connBroker *connectionbroker.Broker, rootPaths CertPaths) *TLSRenewer {
34 35
 	return &TLSRenewer{
35 36
 		s:          s,
36 37
 		connBroker: connBroker,
37 38
 		renew:      make(chan struct{}, 1),
39
+		rootPaths:  rootPaths,
38 40
 	}
39 41
 }
40 42
 
... ...
@@ -135,7 +137,7 @@ func (t *TLSRenewer) Start(ctx context.Context) <-chan CertificateUpdate {
135 135
 
136 136
 			// ignore errors - it will just try again later
137 137
 			var certUpdate CertificateUpdate
138
-			if err := RenewTLSConfigNow(ctx, t.s, t.connBroker); err != nil {
138
+			if err := RenewTLSConfigNow(ctx, t.s, t.connBroker, t.rootPaths); err != nil {
139 139
 				certUpdate.Err = err
140 140
 				expBackoff.Failure(nil, nil)
141 141
 			} else {
... ...
@@ -624,10 +624,6 @@ func (s *Server) UpdateRootCA(ctx context.Context, cluster *api.Cluster) error {
624 624
 		if err != nil {
625 625
 			return errors.Wrap(err, "invalid Root CA object in cluster")
626 626
 		}
627
-		if err := SaveRootCA(updatedRootCA, s.rootPaths); err != nil {
628
-			return errors.Wrap(err, "unable to save new root CA certificates")
629
-		}
630
-
631 627
 		externalCARootPool := updatedRootCA.Pool
632 628
 		if rCA.RootRotation != nil {
633 629
 			// the external CA has to trust the new CA cert
... ...
@@ -640,6 +636,9 @@ func (s *Server) UpdateRootCA(ctx context.Context, cluster *api.Cluster) error {
640 640
 		if err := s.securityConfig.UpdateRootCA(&updatedRootCA, externalCARootPool); err != nil {
641 641
 			return errors.Wrap(err, "updating Root CA failed")
642 642
 		}
643
+		if err := SaveRootCA(updatedRootCA, s.rootPaths); err != nil {
644
+			return errors.Wrap(err, "unable to save new root CA certificates")
645
+		}
643 646
 		// only update the server cache if we've successfully updated the root CA
644 647
 		logger.Debugf("Root CA %s successfully", setOrUpdate)
645 648
 		s.lastSeenClusterRootCA = rCA
... ...
@@ -142,6 +142,10 @@ func (na *cnmNetworkAllocator) Allocate(n *api.Network) error {
142 142
 		n.DriverState = &api.Driver{
143 143
 			Name: d.name,
144 144
 		}
145
+		// In order to support backward compatibility with older daemon
146
+		// versions which assumes the network attachment to contains
147
+		// non nil IPAM attribute, passing an empty object
148
+		n.IPAM = &api.IPAMOptions{Driver: &api.Driver{}}
145 149
 	} else {
146 150
 		nw.pools, err = na.allocatePools(n)
147 151
 		if err != nil {
... ...
@@ -59,6 +59,12 @@ type networkContext struct {
59 59
 	// lastRetry is the last timestamp when unallocated
60 60
 	// tasks/services/networks were retried.
61 61
 	lastRetry time.Time
62
+
63
+	// somethingWasDeallocated indicates that we just deallocated at
64
+	// least one service/task/network, so we should retry failed
65
+	// allocations (in we are experiencing IP exhaustion and an IP was
66
+	// released).
67
+	somethingWasDeallocated bool
62 68
 }
63 69
 
64 70
 func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
... ...
@@ -226,6 +232,8 @@ func (a *Allocator) doNetworkAlloc(ctx context.Context, ev events.Event) {
226 226
 		// resources.
227 227
 		if err := nc.nwkAllocator.Deallocate(n); err != nil {
228 228
 			log.G(ctx).WithError(err).Errorf("Failed during network free for network %s", n.ID)
229
+		} else {
230
+			nc.somethingWasDeallocated = true
229 231
 		}
230 232
 
231 233
 		delete(nc.unallocatedNetworks, n.ID)
... ...
@@ -292,6 +300,8 @@ func (a *Allocator) doNetworkAlloc(ctx context.Context, ev events.Event) {
292 292
 
293 293
 		if err := nc.nwkAllocator.DeallocateService(s); err != nil {
294 294
 			log.G(ctx).WithError(err).Errorf("Failed deallocation during delete of service %s", s.ID)
295
+		} else {
296
+			nc.somethingWasDeallocated = true
295 297
 		}
296 298
 
297 299
 		// Remove it from unallocatedServices just in case
... ...
@@ -304,11 +314,12 @@ func (a *Allocator) doNetworkAlloc(ctx context.Context, ev events.Event) {
304 304
 	case state.EventCommit:
305 305
 		a.procTasksNetwork(ctx, false)
306 306
 
307
-		if time.Since(nc.lastRetry) > retryInterval {
307
+		if time.Since(nc.lastRetry) > retryInterval || nc.somethingWasDeallocated {
308 308
 			a.procUnallocatedNetworks(ctx)
309 309
 			a.procUnallocatedServices(ctx)
310 310
 			a.procTasksNetwork(ctx, true)
311 311
 			nc.lastRetry = time.Now()
312
+			nc.somethingWasDeallocated = false
312 313
 		}
313 314
 
314 315
 		// Any left over tasks are moved to the unallocated set
... ...
@@ -353,6 +364,8 @@ func (a *Allocator) doNodeAlloc(ctx context.Context, ev events.Event) {
353 353
 		if nc.nwkAllocator.IsNodeAllocated(node) {
354 354
 			if err := nc.nwkAllocator.DeallocateNode(node); err != nil {
355 355
 				log.G(ctx).WithError(err).Errorf("Failed freeing network resources for node %s", node.ID)
356
+			} else {
357
+				nc.somethingWasDeallocated = true
356 358
 			}
357 359
 		}
358 360
 		return
... ...
@@ -447,6 +460,8 @@ func (a *Allocator) deallocateNodes(ctx context.Context) error {
447 447
 		if nc.nwkAllocator.IsNodeAllocated(node) {
448 448
 			if err := nc.nwkAllocator.DeallocateNode(node); err != nil {
449 449
 				log.G(ctx).WithError(err).Errorf("Failed freeing network resources for node %s", node.ID)
450
+			} else {
451
+				nc.somethingWasDeallocated = true
450 452
 			}
451 453
 			node.Attachment = nil
452 454
 			if err := a.store.Batch(func(batch *store.Batch) error {
... ...
@@ -695,12 +710,15 @@ func (a *Allocator) doTaskAlloc(ctx context.Context, ev events.Event) {
695 695
 		if nc.nwkAllocator.IsTaskAllocated(t) {
696 696
 			if err := nc.nwkAllocator.DeallocateTask(t); err != nil {
697 697
 				log.G(ctx).WithError(err).Errorf("Failed freeing network resources for task %s", t.ID)
698
+			} else {
699
+				nc.somethingWasDeallocated = true
698 700
 			}
699 701
 		}
700 702
 
701 703
 		// Cleanup any task references that might exist
702 704
 		delete(nc.pendingTasks, t.ID)
703 705
 		delete(nc.unallocatedTasks, t.ID)
706
+
704 707
 		return
705 708
 	}
706 709
 
... ...
@@ -835,6 +853,7 @@ func (a *Allocator) allocateService(ctx context.Context, s *api.Service) error {
835 835
 		if err := nc.nwkAllocator.DeallocateService(s); err != nil {
836 836
 			return err
837 837
 		}
838
+		nc.somethingWasDeallocated = true
838 839
 	}
839 840
 
840 841
 	if err := nc.nwkAllocator.AllocateService(s); err != nil {
... ...
@@ -887,7 +906,7 @@ func (a *Allocator) allocateNetwork(ctx context.Context, n *api.Network) error {
887 887
 
888 888
 	if err := nc.nwkAllocator.Allocate(n); err != nil {
889 889
 		nc.unallocatedNetworks[n.ID] = n
890
-		return errors.Wrapf(err, "failed during network allocation for network %s", n.ID)
890
+		return err
891 891
 	}
892 892
 
893 893
 	return nil
... ...
@@ -954,7 +973,6 @@ func (a *Allocator) allocateTask(ctx context.Context, t *api.Task) (err error) {
954 954
 			}
955 955
 
956 956
 			if err = nc.nwkAllocator.AllocateTask(t); err != nil {
957
-				err = errors.Wrapf(err, "failed during network allocation for task %s", t.ID)
958 957
 				return
959 958
 			}
960 959
 			if nc.nwkAllocator.IsTaskAllocated(t) {
... ...
@@ -247,6 +247,11 @@ func redactClusters(clusters []*api.Cluster) []*api.Cluster {
247 247
 		// Do not copy secret keys
248 248
 		redactedSpec := cluster.Spec.Copy()
249 249
 		redactedSpec.CAConfig.SigningCAKey = nil
250
+		// the cert is not a secret, but if API users get the cluster spec and then update,
251
+		// then because the cert is included but not the key, the user can get update errors
252
+		// or unintended consequences (such as telling swarm to forget about the key so long
253
+		// as there is a corresponding external CA)
254
+		redactedSpec.CAConfig.SigningCACert = nil
250 255
 
251 256
 		redactedRootCA := cluster.RootCA.Copy()
252 257
 		redactedRootCA.CAKey = nil
... ...
@@ -631,7 +631,7 @@ func (d *Dispatcher) processUpdates(ctx context.Context) {
631 631
 					logger.WithError(err).Error("failed to update task status")
632 632
 					return nil
633 633
 				}
634
-				logger.Debug("task status updated")
634
+				logger.Debug("dispatcher committed status update to store")
635 635
 				return nil
636 636
 			})
637 637
 			if err != nil {
... ...
@@ -698,7 +698,7 @@ func (m *Manager) updateKEK(ctx context.Context, cluster *api.Cluster) error {
698 698
 
699 699
 			connBroker := connectionbroker.New(remotes.NewRemotes())
700 700
 			connBroker.SetLocalConn(conn)
701
-			if err := ca.RenewTLSConfigNow(ctx, securityConfig, connBroker); err != nil {
701
+			if err := ca.RenewTLSConfigNow(ctx, securityConfig, connBroker, m.config.RootCAPaths); err != nil {
702 702
 				logger.WithError(err).Error("failed to download new TLS certificate after locking the cluster")
703 703
 			}
704 704
 		}()
... ...
@@ -945,18 +945,19 @@ func (m *Manager) becomeLeader(ctx context.Context) {
945 945
 			if err := store.CreateNetwork(tx, newIngressNetwork()); err != nil {
946 946
 				log.G(ctx).WithError(err).Error("failed to create default ingress network")
947 947
 			}
948
-			// Create now the static predefined node-local networks which
949
-			// are known to be present in each cluster node. This is needed
950
-			// in order to allow running services on the predefined docker
951
-			// networks like `bridge` and `host`.
952
-			log.G(ctx).Info("Creating node-local predefined networks")
953
-			for _, p := range allocator.PredefinedNetworks() {
948
+		}
949
+		// Create now the static predefined if the store does not contain predefined
950
+		//networks like bridge/host node-local networks which
951
+		// are known to be present in each cluster node. This is needed
952
+		// in order to allow running services on the predefined docker
953
+		// networks like `bridge` and `host`.
954
+		for _, p := range allocator.PredefinedNetworks() {
955
+			if store.GetNetwork(tx, p.Name) == nil {
954 956
 				if err := store.CreateNetwork(tx, newPredefinedNetwork(p.Name, p.Driver)); err != nil {
955 957
 					log.G(ctx).WithError(err).Error("failed to create predefined network " + p.Name)
956 958
 				}
957 959
 			}
958 960
 		}
959
-
960 961
 		return nil
961 962
 	})
962 963
 
... ...
@@ -1033,7 +1034,7 @@ func (m *Manager) becomeLeader(ctx context.Context) {
1033 1033
 	}(m.constraintEnforcer)
1034 1034
 
1035 1035
 	go func(taskReaper *taskreaper.TaskReaper) {
1036
-		taskReaper.Run()
1036
+		taskReaper.Run(ctx)
1037 1037
 	}(m.taskReaper)
1038 1038
 
1039 1039
 	go func(orchestrator *replicated.Orchestrator) {
... ...
@@ -4,7 +4,6 @@ import (
4 4
 	"sort"
5 5
 	"time"
6 6
 
7
-	"github.com/docker/go-events"
8 7
 	"github.com/docker/swarmkit/api"
9 8
 	"github.com/docker/swarmkit/log"
10 9
 	"github.com/docker/swarmkit/manager/state"
... ...
@@ -33,29 +32,28 @@ type TaskReaper struct {
33 33
 	taskHistory int64
34 34
 	dirty       map[instanceTuple]struct{}
35 35
 	orphaned    []string
36
-	watcher     chan events.Event
37
-	cancelWatch func()
38 36
 	stopChan    chan struct{}
39 37
 	doneChan    chan struct{}
40 38
 }
41 39
 
42 40
 // New creates a new TaskReaper.
43 41
 func New(store *store.MemoryStore) *TaskReaper {
44
-	watcher, cancel := state.Watch(store.WatchQueue(), api.EventCreateTask{}, api.EventUpdateTask{}, api.EventUpdateCluster{})
45
-
46 42
 	return &TaskReaper{
47
-		store:       store,
48
-		watcher:     watcher,
49
-		cancelWatch: cancel,
50
-		dirty:       make(map[instanceTuple]struct{}),
51
-		stopChan:    make(chan struct{}),
52
-		doneChan:    make(chan struct{}),
43
+		store:    store,
44
+		dirty:    make(map[instanceTuple]struct{}),
45
+		stopChan: make(chan struct{}),
46
+		doneChan: make(chan struct{}),
53 47
 	}
54 48
 }
55 49
 
56 50
 // Run is the TaskReaper's main loop.
57
-func (tr *TaskReaper) Run() {
58
-	defer close(tr.doneChan)
51
+func (tr *TaskReaper) Run(ctx context.Context) {
52
+	watcher, watchCancel := state.Watch(tr.store.WatchQueue(), api.EventCreateTask{}, api.EventUpdateTask{}, api.EventUpdateCluster{})
53
+
54
+	defer func() {
55
+		close(tr.doneChan)
56
+		watchCancel()
57
+	}()
59 58
 
60 59
 	var tasks []*api.Task
61 60
 	tr.store.View(func(readTx store.ReadTx) {
... ...
@@ -68,7 +66,7 @@ func (tr *TaskReaper) Run() {
68 68
 
69 69
 		tasks, err = store.FindTasks(readTx, store.ByTaskState(api.TaskStateOrphaned))
70 70
 		if err != nil {
71
-			log.G(context.TODO()).WithError(err).Error("failed to find Orphaned tasks in task reaper init")
71
+			log.G(ctx).WithError(err).Error("failed to find Orphaned tasks in task reaper init")
72 72
 		}
73 73
 	})
74 74
 
... ...
@@ -91,7 +89,7 @@ func (tr *TaskReaper) Run() {
91 91
 
92 92
 	for {
93 93
 		select {
94
-		case event := <-tr.watcher:
94
+		case event := <-watcher:
95 95
 			switch v := event.(type) {
96 96
 			case api.EventCreateTask:
97 97
 				t := v.Task
... ...
@@ -218,7 +216,6 @@ func (tr *TaskReaper) tick() {
218 218
 
219 219
 // Stop stops the TaskReaper and waits for the main loop to exit.
220 220
 func (tr *TaskReaper) Stop() {
221
-	tr.cancelWatch()
222 221
 	close(tr.stopChan)
223 222
 	<-tr.doneChan
224 223
 }
... ...
@@ -128,7 +128,7 @@ func (f *PluginFilter) SetTask(t *api.Task) bool {
128 128
 		}
129 129
 	}
130 130
 
131
-	if (c != nil && volumeTemplates) || len(t.Networks) > 0 {
131
+	if (c != nil && volumeTemplates) || len(t.Networks) > 0 || t.Spec.LogDriver != nil {
132 132
 		f.t = t
133 133
 		return true
134 134
 	}
... ...
@@ -153,7 +153,7 @@ func (f *PluginFilter) Check(n *NodeInfo) bool {
153 153
 	if container != nil {
154 154
 		for _, mount := range container.Mounts {
155 155
 			if referencesVolumePlugin(mount) {
156
-				if !f.pluginExistsOnNode("Volume", mount.VolumeOptions.DriverConfig.Name, nodePlugins) {
156
+				if _, exists := f.pluginExistsOnNode("Volume", mount.VolumeOptions.DriverConfig.Name, nodePlugins); !exists {
157 157
 					return false
158 158
 				}
159 159
 			}
... ...
@@ -163,22 +163,34 @@ func (f *PluginFilter) Check(n *NodeInfo) bool {
163 163
 	// Check if all network plugins required by task are installed on node
164 164
 	for _, tn := range f.t.Networks {
165 165
 		if tn.Network != nil && tn.Network.DriverState != nil && tn.Network.DriverState.Name != "" {
166
-			if !f.pluginExistsOnNode("Network", tn.Network.DriverState.Name, nodePlugins) {
166
+			if _, exists := f.pluginExistsOnNode("Network", tn.Network.DriverState.Name, nodePlugins); !exists {
167 167
 				return false
168 168
 			}
169 169
 		}
170 170
 	}
171
+
172
+	if f.t.Spec.LogDriver != nil {
173
+		// If there are no log driver types in the list at all, most likely this is
174
+		// an older daemon that did not report this information. In this case don't filter
175
+		if typeFound, exists := f.pluginExistsOnNode("Log", f.t.Spec.LogDriver.Name, nodePlugins); !exists && typeFound {
176
+			return false
177
+		}
178
+	}
171 179
 	return true
172 180
 }
173 181
 
174 182
 // pluginExistsOnNode returns true if the (pluginName, pluginType) pair is present in nodePlugins
175
-func (f *PluginFilter) pluginExistsOnNode(pluginType string, pluginName string, nodePlugins []api.PluginDescription) bool {
183
+func (f *PluginFilter) pluginExistsOnNode(pluginType string, pluginName string, nodePlugins []api.PluginDescription) (bool, bool) {
184
+	var typeFound bool
185
+
176 186
 	for _, np := range nodePlugins {
177 187
 		if pluginType != np.Type {
178 188
 			continue
179 189
 		}
190
+		typeFound = true
191
+
180 192
 		if pluginName == np.Name {
181
-			return true
193
+			return true, true
182 194
 		}
183 195
 		// This does not use the reference package to avoid the
184 196
 		// overhead of parsing references as part of the scheduling
... ...
@@ -186,10 +198,10 @@ func (f *PluginFilter) pluginExistsOnNode(pluginType string, pluginName string,
186 186
 		// strict subset of the reference grammar that is always
187 187
 		// name:tag.
188 188
 		if strings.HasPrefix(np.Name, pluginName) && np.Name[len(pluginName):] == ":latest" {
189
-			return true
189
+			return true, true
190 190
 		}
191 191
 	}
192
-	return false
192
+	return typeFound, false
193 193
 }
194 194
 
195 195
 // Explain returns an explanation of a failure.
... ...
@@ -63,6 +63,15 @@ func (nodeInfo *NodeInfo) removeTask(t *api.Task) bool {
63 63
 		nodeInfo.ActiveTasksCountByService[t.ServiceID]--
64 64
 	}
65 65
 
66
+	if t.Endpoint != nil {
67
+		for _, port := range t.Endpoint.Ports {
68
+			if port.PublishMode == api.PublishModeHost && port.PublishedPort != 0 {
69
+				portSpec := hostPortSpec{protocol: port.Protocol, publishedPort: port.PublishedPort}
70
+				delete(nodeInfo.usedHostPorts, portSpec)
71
+			}
72
+		}
73
+	}
74
+
66 75
 	reservations := taskReservations(t.Spec)
67 76
 	resources := nodeInfo.AvailableResources
68 77
 
... ...
@@ -79,15 +88,6 @@ func (nodeInfo *NodeInfo) removeTask(t *api.Task) bool {
79 79
 	nodeRes := nodeInfo.Description.Resources.Generic
80 80
 	genericresource.Reclaim(nodeAvailableResources, taskAssigned, nodeRes)
81 81
 
82
-	if t.Endpoint != nil {
83
-		for _, port := range t.Endpoint.Ports {
84
-			if port.PublishMode == api.PublishModeHost && port.PublishedPort != 0 {
85
-				portSpec := hostPortSpec{protocol: port.Protocol, publishedPort: port.PublishedPort}
86
-				delete(nodeInfo.usedHostPorts, portSpec)
87
-			}
88
-		}
89
-	}
90
-
91 82
 	return true
92 83
 }
93 84
 
... ...
@@ -4,7 +4,6 @@ import (
4 4
 	"container/heap"
5 5
 	"errors"
6 6
 	"strings"
7
-	"time"
8 7
 
9 8
 	"github.com/docker/swarmkit/api"
10 9
 	"github.com/docker/swarmkit/manager/constraint"
... ...
@@ -32,16 +31,6 @@ func (ns *nodeSet) nodeInfo(nodeID string) (NodeInfo, error) {
32 32
 // addOrUpdateNode sets the number of tasks for a given node. It adds the node
33 33
 // to the set if it wasn't already tracked.
34 34
 func (ns *nodeSet) addOrUpdateNode(n NodeInfo) {
35
-	if n.Tasks == nil {
36
-		n.Tasks = make(map[string]*api.Task)
37
-	}
38
-	if n.ActiveTasksCountByService == nil {
39
-		n.ActiveTasksCountByService = make(map[string]int)
40
-	}
41
-	if n.recentFailures == nil {
42
-		n.recentFailures = make(map[string][]time.Time)
43
-	}
44
-
45 35
 	ns.nodes[n.ID] = n
46 36
 }
47 37
 
... ...
@@ -31,8 +31,11 @@ type schedulingDecision struct {
31 31
 type Scheduler struct {
32 32
 	store           *store.MemoryStore
33 33
 	unassignedTasks map[string]*api.Task
34
-	// preassignedTasks already have NodeID, need resource validation
35
-	preassignedTasks map[string]*api.Task
34
+	// pendingPreassignedTasks already have NodeID, need resource validation
35
+	pendingPreassignedTasks map[string]*api.Task
36
+	// preassignedTasks tracks tasks that were preassigned, including those
37
+	// past the pending state.
38
+	preassignedTasks map[string]struct{}
36 39
 	nodeSet          nodeSet
37 40
 	allTasks         map[string]*api.Task
38 41
 	pipeline         *Pipeline
... ...
@@ -46,13 +49,14 @@ type Scheduler struct {
46 46
 // New creates a new scheduler.
47 47
 func New(store *store.MemoryStore) *Scheduler {
48 48
 	return &Scheduler{
49
-		store:            store,
50
-		unassignedTasks:  make(map[string]*api.Task),
51
-		preassignedTasks: make(map[string]*api.Task),
52
-		allTasks:         make(map[string]*api.Task),
53
-		stopChan:         make(chan struct{}),
54
-		doneChan:         make(chan struct{}),
55
-		pipeline:         NewPipeline(),
49
+		store:                   store,
50
+		unassignedTasks:         make(map[string]*api.Task),
51
+		pendingPreassignedTasks: make(map[string]*api.Task),
52
+		preassignedTasks:        make(map[string]struct{}),
53
+		allTasks:                make(map[string]*api.Task),
54
+		stopChan:                make(chan struct{}),
55
+		doneChan:                make(chan struct{}),
56
+		pipeline:                NewPipeline(),
56 57
 	}
57 58
 }
58 59
 
... ...
@@ -77,7 +81,8 @@ func (s *Scheduler) setupTasksList(tx store.ReadTx) error {
77 77
 		}
78 78
 		// preassigned tasks need to validate resource requirement on corresponding node
79 79
 		if t.Status.State == api.TaskStatePending {
80
-			s.preassignedTasks[t.ID] = t
80
+			s.preassignedTasks[t.ID] = struct{}{}
81
+			s.pendingPreassignedTasks[t.ID] = t
81 82
 			continue
82 83
 		}
83 84
 
... ...
@@ -129,7 +134,7 @@ func (s *Scheduler) Run(ctx context.Context) error {
129 129
 	tickRequired := false
130 130
 
131 131
 	schedule := func() {
132
-		if len(s.preassignedTasks) > 0 {
132
+		if len(s.pendingPreassignedTasks) > 0 {
133 133
 			s.processPreassignedTasks(ctx)
134 134
 		}
135 135
 		if tickRequired {
... ...
@@ -152,7 +157,7 @@ func (s *Scheduler) Run(ctx context.Context) error {
152 152
 					tickRequired = true
153 153
 				}
154 154
 			case api.EventDeleteTask:
155
-				if s.deleteTask(ctx, v.Task) {
155
+				if s.deleteTask(v.Task) {
156 156
 					// deleting tasks may free up node resource, pending tasks should be re-evaluated.
157 157
 					tickRequired = true
158 158
 				}
... ...
@@ -216,7 +221,8 @@ func (s *Scheduler) createTask(ctx context.Context, t *api.Task) bool {
216 216
 	}
217 217
 
218 218
 	if t.Status.State == api.TaskStatePending {
219
-		s.preassignedTasks[t.ID] = t
219
+		s.preassignedTasks[t.ID] = struct{}{}
220
+		s.pendingPreassignedTasks[t.ID] = t
220 221
 		// preassigned tasks do not contribute to running tasks count
221 222
 		return false
222 223
 	}
... ...
@@ -244,22 +250,32 @@ func (s *Scheduler) updateTask(ctx context.Context, t *api.Task) bool {
244 244
 		if oldTask == nil {
245 245
 			return false
246 246
 		}
247
-		s.deleteTask(ctx, oldTask)
247
+
248 248
 		if t.Status.State != oldTask.Status.State &&
249 249
 			(t.Status.State == api.TaskStateFailed || t.Status.State == api.TaskStateRejected) {
250
-			nodeInfo, err := s.nodeSet.nodeInfo(t.NodeID)
251
-			if err == nil {
252
-				nodeInfo.taskFailed(ctx, t.ServiceID)
253
-				s.nodeSet.updateNode(nodeInfo)
250
+			// Keep track of task failures, so other nodes can be preferred
251
+			// for scheduling this service if it looks like the service is
252
+			// failing in a loop on this node. However, skip this for
253
+			// preassigned tasks, because the scheduler does not choose
254
+			// which nodes those run on.
255
+			if _, wasPreassigned := s.preassignedTasks[t.ID]; !wasPreassigned {
256
+				nodeInfo, err := s.nodeSet.nodeInfo(t.NodeID)
257
+				if err == nil {
258
+					nodeInfo.taskFailed(ctx, t.ServiceID)
259
+					s.nodeSet.updateNode(nodeInfo)
260
+				}
254 261
 			}
255 262
 		}
263
+
264
+		s.deleteTask(oldTask)
265
+
256 266
 		return true
257 267
 	}
258 268
 
259 269
 	if t.NodeID == "" {
260 270
 		// unassigned task
261 271
 		if oldTask != nil {
262
-			s.deleteTask(ctx, oldTask)
272
+			s.deleteTask(oldTask)
263 273
 		}
264 274
 		s.allTasks[t.ID] = t
265 275
 		s.enqueue(t)
... ...
@@ -268,10 +284,11 @@ func (s *Scheduler) updateTask(ctx context.Context, t *api.Task) bool {
268 268
 
269 269
 	if t.Status.State == api.TaskStatePending {
270 270
 		if oldTask != nil {
271
-			s.deleteTask(ctx, oldTask)
271
+			s.deleteTask(oldTask)
272 272
 		}
273
+		s.preassignedTasks[t.ID] = struct{}{}
273 274
 		s.allTasks[t.ID] = t
274
-		s.preassignedTasks[t.ID] = t
275
+		s.pendingPreassignedTasks[t.ID] = t
275 276
 		// preassigned tasks do not contribute to running tasks count
276 277
 		return false
277 278
 	}
... ...
@@ -285,9 +302,10 @@ func (s *Scheduler) updateTask(ctx context.Context, t *api.Task) bool {
285 285
 	return false
286 286
 }
287 287
 
288
-func (s *Scheduler) deleteTask(ctx context.Context, t *api.Task) bool {
288
+func (s *Scheduler) deleteTask(t *api.Task) bool {
289 289
 	delete(s.allTasks, t.ID)
290 290
 	delete(s.preassignedTasks, t.ID)
291
+	delete(s.pendingPreassignedTasks, t.ID)
291 292
 	nodeInfo, err := s.nodeSet.nodeInfo(t.NodeID)
292 293
 	if err == nil && nodeInfo.removeTask(t) {
293 294
 		s.nodeSet.updateNode(nodeInfo)
... ...
@@ -297,31 +315,38 @@ func (s *Scheduler) deleteTask(ctx context.Context, t *api.Task) bool {
297 297
 }
298 298
 
299 299
 func (s *Scheduler) createOrUpdateNode(n *api.Node) {
300
-	nodeInfo, _ := s.nodeSet.nodeInfo(n.ID)
300
+	nodeInfo, nodeInfoErr := s.nodeSet.nodeInfo(n.ID)
301 301
 	var resources *api.Resources
302 302
 	if n.Description != nil && n.Description.Resources != nil {
303 303
 		resources = n.Description.Resources.Copy()
304 304
 		// reconcile resources by looping over all tasks in this node
305
-		for _, task := range nodeInfo.Tasks {
306
-			reservations := taskReservations(task.Spec)
305
+		if nodeInfoErr == nil {
306
+			for _, task := range nodeInfo.Tasks {
307
+				reservations := taskReservations(task.Spec)
307 308
 
308
-			resources.MemoryBytes -= reservations.MemoryBytes
309
-			resources.NanoCPUs -= reservations.NanoCPUs
309
+				resources.MemoryBytes -= reservations.MemoryBytes
310
+				resources.NanoCPUs -= reservations.NanoCPUs
310 311
 
311
-			genericresource.ConsumeNodeResources(&resources.Generic,
312
-				task.AssignedGenericResources)
312
+				genericresource.ConsumeNodeResources(&resources.Generic,
313
+					task.AssignedGenericResources)
314
+			}
313 315
 		}
314 316
 	} else {
315 317
 		resources = &api.Resources{}
316 318
 	}
317
-	nodeInfo.Node = n
318
-	nodeInfo.AvailableResources = resources
319
+
320
+	if nodeInfoErr != nil {
321
+		nodeInfo = newNodeInfo(n, nil, *resources)
322
+	} else {
323
+		nodeInfo.Node = n
324
+		nodeInfo.AvailableResources = resources
325
+	}
319 326
 	s.nodeSet.addOrUpdateNode(nodeInfo)
320 327
 }
321 328
 
322 329
 func (s *Scheduler) processPreassignedTasks(ctx context.Context) {
323
-	schedulingDecisions := make(map[string]schedulingDecision, len(s.preassignedTasks))
324
-	for _, t := range s.preassignedTasks {
330
+	schedulingDecisions := make(map[string]schedulingDecision, len(s.pendingPreassignedTasks))
331
+	for _, t := range s.pendingPreassignedTasks {
325 332
 		newT := s.taskFitNode(ctx, t, t.NodeID)
326 333
 		if newT == nil {
327 334
 			continue
... ...
@@ -333,7 +358,7 @@ func (s *Scheduler) processPreassignedTasks(ctx context.Context) {
333 333
 
334 334
 	for _, decision := range successful {
335 335
 		if decision.new.Status.State == api.TaskStateAssigned {
336
-			delete(s.preassignedTasks, decision.old.ID)
336
+			delete(s.pendingPreassignedTasks, decision.old.ID)
337 337
 		}
338 338
 	}
339 339
 	for _, decision := range failed {
... ...
@@ -421,12 +446,7 @@ func (s *Scheduler) applySchedulingDecisions(ctx context.Context, schedulingDeci
421 421
 					t := store.GetTask(tx, taskID)
422 422
 					if t == nil {
423 423
 						// Task no longer exists
424
-						nodeInfo, err := s.nodeSet.nodeInfo(decision.new.NodeID)
425
-						if err == nil && nodeInfo.removeTask(decision.new) {
426
-							s.nodeSet.updateNode(nodeInfo)
427
-						}
428
-						delete(s.allTasks, decision.old.ID)
429
-
424
+						s.deleteTask(decision.new)
430 425
 						continue
431 426
 					}
432 427
 
... ...
@@ -281,7 +281,7 @@ func (n *Node) run(ctx context.Context) (err error) {
281 281
 		return err
282 282
 	}
283 283
 
284
-	renewer := ca.NewTLSRenewer(securityConfig, n.connBroker)
284
+	renewer := ca.NewTLSRenewer(securityConfig, n.connBroker, paths.RootCA)
285 285
 
286 286
 	ctx = log.WithLogger(ctx, log.G(ctx).WithField("node.id", n.NodeID()))
287 287
 
... ...
@@ -3,13 +3,22 @@ package template
3 3
 import (
4 4
 	"bytes"
5 5
 	"fmt"
6
+	"strings"
7
+	"text/template"
6 8
 
9
+	"github.com/docker/swarmkit/agent/configs"
10
+	"github.com/docker/swarmkit/agent/exec"
11
+	"github.com/docker/swarmkit/agent/secrets"
7 12
 	"github.com/docker/swarmkit/api"
8 13
 	"github.com/docker/swarmkit/api/naming"
14
+	"github.com/pkg/errors"
9 15
 )
10 16
 
11 17
 // Context defines the strict set of values that can be injected into a
12 18
 // template expression in SwarmKit data structure.
19
+// NOTE: Be very careful adding any fields to this structure with types
20
+// that have methods defined on them. The template would be able to
21
+// invoke those methods.
13 22
 type Context struct {
14 23
 	Service struct {
15 24
 		ID     string
... ...
@@ -58,7 +67,118 @@ func NewContextFromTask(t *api.Task) (ctx Context) {
58 58
 // Expand treats the string s as a template and populates it with values from
59 59
 // the context.
60 60
 func (ctx *Context) Expand(s string) (string, error) {
61
-	tmpl, err := newTemplate(s)
61
+	tmpl, err := newTemplate(s, nil)
62
+	if err != nil {
63
+		return s, err
64
+	}
65
+
66
+	var buf bytes.Buffer
67
+	if err := tmpl.Execute(&buf, ctx); err != nil {
68
+		return s, err
69
+	}
70
+
71
+	return buf.String(), nil
72
+}
73
+
74
+// PayloadContext provides a context for expanding a config or secret payload.
75
+// NOTE: Be very careful adding any fields to this structure with types
76
+// that have methods defined on them. The template would be able to
77
+// invoke those methods.
78
+type PayloadContext struct {
79
+	Context
80
+
81
+	t                 *api.Task
82
+	restrictedSecrets exec.SecretGetter
83
+	restrictedConfigs exec.ConfigGetter
84
+}
85
+
86
+func (ctx PayloadContext) secretGetter(target string) (string, error) {
87
+	if ctx.restrictedSecrets == nil {
88
+		return "", errors.New("secrets unavailable")
89
+	}
90
+
91
+	container := ctx.t.Spec.GetContainer()
92
+	if container == nil {
93
+		return "", errors.New("task is not a container")
94
+	}
95
+
96
+	for _, secretRef := range container.Secrets {
97
+		file := secretRef.GetFile()
98
+		if file != nil && file.Name == target {
99
+			secret, err := ctx.restrictedSecrets.Get(secretRef.SecretID)
100
+			if err != nil {
101
+				return "", err
102
+			}
103
+			return string(secret.Spec.Data), nil
104
+		}
105
+	}
106
+
107
+	return "", errors.Errorf("secret target %s not found", target)
108
+}
109
+
110
+func (ctx PayloadContext) configGetter(target string) (string, error) {
111
+	if ctx.restrictedConfigs == nil {
112
+		return "", errors.New("configs unavailable")
113
+	}
114
+
115
+	container := ctx.t.Spec.GetContainer()
116
+	if container == nil {
117
+		return "", errors.New("task is not a container")
118
+	}
119
+
120
+	for _, configRef := range container.Configs {
121
+		file := configRef.GetFile()
122
+		if file != nil && file.Name == target {
123
+			config, err := ctx.restrictedConfigs.Get(configRef.ConfigID)
124
+			if err != nil {
125
+				return "", err
126
+			}
127
+			return string(config.Spec.Data), nil
128
+		}
129
+	}
130
+
131
+	return "", errors.Errorf("config target %s not found", target)
132
+}
133
+
134
+func (ctx PayloadContext) envGetter(variable string) (string, error) {
135
+	container := ctx.t.Spec.GetContainer()
136
+	if container == nil {
137
+		return "", errors.New("task is not a container")
138
+	}
139
+
140
+	for _, env := range container.Env {
141
+		parts := strings.SplitN(env, "=", 2)
142
+
143
+		if len(parts) > 1 && parts[0] == variable {
144
+			return parts[1], nil
145
+		}
146
+	}
147
+	return "", nil
148
+}
149
+
150
+// NewPayloadContextFromTask returns a new template context from the data
151
+// available in the task. This context also provides access to the configs
152
+// and secrets that the task has access to. The provided context can then
153
+// be used to populate runtime values in a templated config or secret.
154
+func NewPayloadContextFromTask(t *api.Task, dependencies exec.DependencyGetter) (ctx PayloadContext) {
155
+	return PayloadContext{
156
+		Context:           NewContextFromTask(t),
157
+		t:                 t,
158
+		restrictedSecrets: secrets.Restrict(dependencies.Secrets(), t),
159
+		restrictedConfigs: configs.Restrict(dependencies.Configs(), t),
160
+	}
161
+}
162
+
163
+// Expand treats the string s as a template and populates it with values from
164
+// the context.
165
+func (ctx *PayloadContext) Expand(s string) (string, error) {
166
+	funcMap := template.FuncMap{
167
+		"secret": ctx.secretGetter,
168
+		"config": ctx.configGetter,
169
+		"env":    ctx.envGetter,
170
+	}
171
+
172
+	tmpl, err := newTemplate(s, funcMap)
62 173
 	if err != nil {
63 174
 		return s, err
64 175
 	}
... ...
@@ -4,6 +4,7 @@ import (
4 4
 	"fmt"
5 5
 	"strings"
6 6
 
7
+	"github.com/docker/swarmkit/agent/exec"
7 8
 	"github.com/docker/swarmkit/api"
8 9
 	"github.com/pkg/errors"
9 10
 )
... ...
@@ -116,3 +117,45 @@ func expandEnv(ctx Context, values []string) ([]string, error) {
116 116
 
117 117
 	return result, nil
118 118
 }
119
+
120
+func expandPayload(ctx PayloadContext, payload []byte) ([]byte, error) {
121
+	result, err := ctx.Expand(string(payload))
122
+	if err != nil {
123
+		return payload, err
124
+	}
125
+	return []byte(result), nil
126
+}
127
+
128
+// ExpandSecretSpec expands the template inside the secret payload, if any.
129
+// Templating is evaluated on the agent-side.
130
+func ExpandSecretSpec(s *api.Secret, t *api.Task, dependencies exec.DependencyGetter) (*api.SecretSpec, error) {
131
+	if s.Spec.Templating == nil {
132
+		return &s.Spec, nil
133
+	}
134
+	if s.Spec.Templating.Name == "golang" {
135
+		ctx := NewPayloadContextFromTask(t, dependencies)
136
+		secretSpec := s.Spec.Copy()
137
+
138
+		var err error
139
+		secretSpec.Data, err = expandPayload(ctx, secretSpec.Data)
140
+		return secretSpec, err
141
+	}
142
+	return &s.Spec, errors.New("unrecognized template type")
143
+}
144
+
145
+// ExpandConfigSpec expands the template inside the config payload, if any.
146
+// Templating is evaluated on the agent-side.
147
+func ExpandConfigSpec(c *api.Config, t *api.Task, dependencies exec.DependencyGetter) (*api.ConfigSpec, error) {
148
+	if c.Spec.Templating == nil {
149
+		return &c.Spec, nil
150
+	}
151
+	if c.Spec.Templating.Name == "golang" {
152
+		ctx := NewPayloadContextFromTask(t, dependencies)
153
+		configSpec := c.Spec.Copy()
154
+
155
+		var err error
156
+		configSpec.Data, err = expandPayload(ctx, configSpec.Data)
157
+		return configSpec, err
158
+	}
159
+	return &c.Spec, errors.New("unrecognized template type")
160
+}
119 161
new file mode 100644
... ...
@@ -0,0 +1,98 @@
0
+package template
1
+
2
+import (
3
+	"github.com/docker/swarmkit/agent/exec"
4
+	"github.com/docker/swarmkit/api"
5
+	"github.com/pkg/errors"
6
+)
7
+
8
+type templatedSecretGetter struct {
9
+	dependencies exec.DependencyGetter
10
+	t            *api.Task
11
+}
12
+
13
+// NewTemplatedSecretGetter returns a SecretGetter that evaluates templates.
14
+func NewTemplatedSecretGetter(dependencies exec.DependencyGetter, t *api.Task) exec.SecretGetter {
15
+	return templatedSecretGetter{dependencies: dependencies, t: t}
16
+}
17
+
18
+func (t templatedSecretGetter) Get(secretID string) (*api.Secret, error) {
19
+	if t.dependencies == nil {
20
+		return nil, errors.New("no secret provider available")
21
+	}
22
+
23
+	secrets := t.dependencies.Secrets()
24
+	if secrets == nil {
25
+		return nil, errors.New("no secret provider available")
26
+	}
27
+
28
+	secret, err := secrets.Get(secretID)
29
+	if err != nil {
30
+		return secret, err
31
+	}
32
+
33
+	newSpec, err := ExpandSecretSpec(secret, t.t, t.dependencies)
34
+	if err != nil {
35
+		return secret, errors.Wrapf(err, "failed to expand templated secret %s", secretID)
36
+	}
37
+
38
+	secretCopy := *secret
39
+	secretCopy.Spec = *newSpec
40
+	return &secretCopy, nil
41
+}
42
+
43
+type templatedConfigGetter struct {
44
+	dependencies exec.DependencyGetter
45
+	t            *api.Task
46
+}
47
+
48
+// NewTemplatedConfigGetter returns a ConfigGetter that evaluates templates.
49
+func NewTemplatedConfigGetter(dependencies exec.DependencyGetter, t *api.Task) exec.ConfigGetter {
50
+	return templatedConfigGetter{dependencies: dependencies, t: t}
51
+}
52
+
53
+func (t templatedConfigGetter) Get(configID string) (*api.Config, error) {
54
+	if t.dependencies == nil {
55
+		return nil, errors.New("no config provider available")
56
+	}
57
+
58
+	configs := t.dependencies.Configs()
59
+	if configs == nil {
60
+		return nil, errors.New("no config provider available")
61
+	}
62
+
63
+	config, err := configs.Get(configID)
64
+	if err != nil {
65
+		return config, err
66
+	}
67
+
68
+	newSpec, err := ExpandConfigSpec(config, t.t, t.dependencies)
69
+	if err != nil {
70
+		return config, errors.Wrapf(err, "failed to expand templated config %s", configID)
71
+	}
72
+
73
+	configCopy := *config
74
+	configCopy.Spec = *newSpec
75
+	return &configCopy, nil
76
+}
77
+
78
+type templatedDependencyGetter struct {
79
+	secrets exec.SecretGetter
80
+	configs exec.ConfigGetter
81
+}
82
+
83
+// NewTemplatedDependencyGetter returns a DependencyGetter that evaluates templates.
84
+func NewTemplatedDependencyGetter(dependencies exec.DependencyGetter, t *api.Task) exec.DependencyGetter {
85
+	return templatedDependencyGetter{
86
+		secrets: NewTemplatedSecretGetter(dependencies, t),
87
+		configs: NewTemplatedConfigGetter(dependencies, t),
88
+	}
89
+}
90
+
91
+func (t templatedDependencyGetter) Secrets() exec.SecretGetter {
92
+	return t.secrets
93
+}
94
+
95
+func (t templatedDependencyGetter) Configs() exec.ConfigGetter {
96
+	return t.configs
97
+}
... ...
@@ -13,6 +13,10 @@ var funcMap = template.FuncMap{
13 13
 	},
14 14
 }
15 15
 
16
-func newTemplate(s string) (*template.Template, error) {
17
-	return template.New("expansion").Option("missingkey=error").Funcs(funcMap).Parse(s)
16
+func newTemplate(s string, extraFuncs template.FuncMap) (*template.Template, error) {
17
+	tmpl := template.New("expansion").Option("missingkey=error").Funcs(funcMap)
18
+	if len(extraFuncs) != 0 {
19
+		tmpl = tmpl.Funcs(extraFuncs)
20
+	}
21
+	return tmpl.Parse(s)
18 22
 }
... ...
@@ -30,6 +30,14 @@ github.com/opencontainers/runc b6b70e53451794e8333e9b602cc096b47a20bd0f
30 30
 github.com/opencontainers/go-digest a6d0ee40d4207ea02364bd3b9e8e77b9159ba1eb
31 31
 github.com/opencontainers/image-spec f03dbe35d449c54915d235f1a3cf8f585a24babe
32 32
 
33
+# containerd executor
34
+github.com/containerd/containerd 7fc91b05917e93d474fab9465547d44eacd10ce3
35
+github.com/containerd/continuity f4ad4294c92f596c9241947c416d1297f9faf3ea
36
+github.com/containerd/fifo 69b99525e472735860a5269b75af1970142b3062
37
+github.com/opencontainers/runtime-spec v1.0.0-rc5
38
+github.com/nightlyone/lockfile 1d49c987357a327b5b03aa84cbddd582c328615d
39
+golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c
40
+
33 41
 github.com/davecgh/go-spew 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d
34 42
 github.com/Microsoft/go-winio f778f05015353be65d242f3fedc18695756153bb
35 43
 github.com/Sirupsen/logrus v0.11.0
36 44
deleted file mode 100644
... ...
@@ -1,231 +0,0 @@
1
-// Copyright 2015 Red Hat Inc. All rights reserved.
2
-//
3
-// Licensed under the Apache License, Version 2.0 (the "License");
4
-// you may not use this file except in compliance with the License.
5
-// You may obtain a copy of the License at
6
-// http://www.apache.org/licenses/LICENSE-2.0
7
-//
8
-// Unless required by applicable law or agreed to in writing, software
9
-// distributed under the License is distributed on an "AS IS" BASIS,
10
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
-// See the License for the specific language governing permissions and
12
-// limitations under the License.
13
-
14
-package doc
15
-
16
-import (
17
-	"bytes"
18
-	"fmt"
19
-	"io"
20
-	"os"
21
-	"path/filepath"
22
-	"sort"
23
-	"strings"
24
-	"time"
25
-
26
-	mangen "github.com/cpuguy83/go-md2man/md2man"
27
-	"github.com/spf13/cobra"
28
-	"github.com/spf13/pflag"
29
-)
30
-
31
-// GenManTree will generate a man page for this command and all descendants
32
-// in the directory given. The header may be nil. This function may not work
33
-// correctly if your command names have - in them. If you have `cmd` with two
34
-// subcmds, `sub` and `sub-third`. And `sub` has a subcommand called `third`
35
-// it is undefined which help output will be in the file `cmd-sub-third.1`.
36
-func GenManTree(cmd *cobra.Command, header *GenManHeader, dir string) error {
37
-	return GenManTreeFromOpts(cmd, GenManTreeOptions{
38
-		Header:           header,
39
-		Path:             dir,
40
-		CommandSeparator: "_",
41
-	})
42
-}
43
-
44
-// GenManTreeFromOpts generates a man page for the command and all descendants.
45
-// The pages are written to the opts.Path directory.
46
-func GenManTreeFromOpts(cmd *cobra.Command, opts GenManTreeOptions) error {
47
-	header := opts.Header
48
-	if header == nil {
49
-		header = &GenManHeader{}
50
-	}
51
-	for _, c := range cmd.Commands() {
52
-		if !c.IsAvailableCommand() || c.IsHelpCommand() {
53
-			continue
54
-		}
55
-		if err := GenManTreeFromOpts(c, opts); err != nil {
56
-			return err
57
-		}
58
-	}
59
-	section := "1"
60
-	if header.Section != "" {
61
-		section = header.Section
62
-	}
63
-
64
-	separator := "_"
65
-	if opts.CommandSeparator != "" {
66
-		separator = opts.CommandSeparator
67
-	}
68
-	basename := strings.Replace(cmd.CommandPath(), " ", separator, -1)
69
-	filename := filepath.Join(opts.Path, basename+"."+section)
70
-	f, err := os.Create(filename)
71
-	if err != nil {
72
-		return err
73
-	}
74
-	defer f.Close()
75
-
76
-	headerCopy := *header
77
-	return GenMan(cmd, &headerCopy, f)
78
-}
79
-
80
-type GenManTreeOptions struct {
81
-	Header           *GenManHeader
82
-	Path             string
83
-	CommandSeparator string
84
-}
85
-
86
-// GenManHeader is a lot like the .TH header at the start of man pages. These
87
-// include the title, section, date, source, and manual. We will use the
88
-// current time if Date if unset and will use "Auto generated by spf13/cobra"
89
-// if the Source is unset.
90
-type GenManHeader struct {
91
-	Title   string
92
-	Section string
93
-	Date    *time.Time
94
-	date    string
95
-	Source  string
96
-	Manual  string
97
-}
98
-
99
-// GenMan will generate a man page for the given command and write it to
100
-// w. The header argument may be nil, however obviously w may not.
101
-func GenMan(cmd *cobra.Command, header *GenManHeader, w io.Writer) error {
102
-	if header == nil {
103
-		header = &GenManHeader{}
104
-	}
105
-	fillHeader(header, cmd.CommandPath())
106
-
107
-	b := genMan(cmd, header)
108
-	_, err := w.Write(mangen.Render(b))
109
-	return err
110
-}
111
-
112
-func fillHeader(header *GenManHeader, name string) {
113
-	if header.Title == "" {
114
-		header.Title = strings.ToUpper(strings.Replace(name, " ", "\\-", -1))
115
-	}
116
-	if header.Section == "" {
117
-		header.Section = "1"
118
-	}
119
-	if header.Date == nil {
120
-		now := time.Now()
121
-		header.Date = &now
122
-	}
123
-	header.date = (*header.Date).Format("Jan 2006")
124
-	if header.Source == "" {
125
-		header.Source = "Auto generated by spf13/cobra"
126
-	}
127
-}
128
-
129
-func manPreamble(out io.Writer, header *GenManHeader, cmd *cobra.Command, dashedName string) {
130
-	description := cmd.Long
131
-	if len(description) == 0 {
132
-		description = cmd.Short
133
-	}
134
-
135
-	fmt.Fprintf(out, `%% %s(%s)%s
136
-%% %s
137
-%% %s
138
-# NAME
139
-`, header.Title, header.Section, header.date, header.Source, header.Manual)
140
-	fmt.Fprintf(out, "%s \\- %s\n\n", dashedName, cmd.Short)
141
-	fmt.Fprintf(out, "# SYNOPSIS\n")
142
-	fmt.Fprintf(out, "**%s**\n\n", cmd.UseLine())
143
-	fmt.Fprintf(out, "# DESCRIPTION\n")
144
-	fmt.Fprintf(out, "%s\n\n", description)
145
-}
146
-
147
-func manPrintFlags(out io.Writer, flags *pflag.FlagSet) {
148
-	flags.VisitAll(func(flag *pflag.Flag) {
149
-		if len(flag.Deprecated) > 0 || flag.Hidden {
150
-			return
151
-		}
152
-		format := ""
153
-		if len(flag.Shorthand) > 0 && len(flag.ShorthandDeprecated) == 0 {
154
-			format = fmt.Sprintf("**-%s**, **--%s**", flag.Shorthand, flag.Name)
155
-		} else {
156
-			format = fmt.Sprintf("**--%s**", flag.Name)
157
-		}
158
-		if len(flag.NoOptDefVal) > 0 {
159
-			format = format + "["
160
-		}
161
-		if flag.Value.Type() == "string" {
162
-			// put quotes on the value
163
-			format = format + "=%q"
164
-		} else {
165
-			format = format + "=%s"
166
-		}
167
-		if len(flag.NoOptDefVal) > 0 {
168
-			format = format + "]"
169
-		}
170
-		format = format + "\n\t%s\n\n"
171
-		fmt.Fprintf(out, format, flag.DefValue, flag.Usage)
172
-	})
173
-}
174
-
175
-func manPrintOptions(out io.Writer, command *cobra.Command) {
176
-	flags := command.NonInheritedFlags()
177
-	if flags.HasFlags() {
178
-		fmt.Fprintf(out, "# OPTIONS\n")
179
-		manPrintFlags(out, flags)
180
-		fmt.Fprintf(out, "\n")
181
-	}
182
-	flags = command.InheritedFlags()
183
-	if flags.HasFlags() {
184
-		fmt.Fprintf(out, "# OPTIONS INHERITED FROM PARENT COMMANDS\n")
185
-		manPrintFlags(out, flags)
186
-		fmt.Fprintf(out, "\n")
187
-	}
188
-}
189
-
190
-func genMan(cmd *cobra.Command, header *GenManHeader) []byte {
191
-	// something like `rootcmd-subcmd1-subcmd2`
192
-	dashCommandName := strings.Replace(cmd.CommandPath(), " ", "-", -1)
193
-
194
-	buf := new(bytes.Buffer)
195
-
196
-	manPreamble(buf, header, cmd, dashCommandName)
197
-	manPrintOptions(buf, cmd)
198
-	if len(cmd.Example) > 0 {
199
-		fmt.Fprintf(buf, "# EXAMPLE\n")
200
-		fmt.Fprintf(buf, "\n%s\n\n", cmd.Example)
201
-	}
202
-	if hasSeeAlso(cmd) {
203
-		fmt.Fprintf(buf, "# SEE ALSO\n")
204
-		seealsos := make([]string, 0)
205
-		if cmd.HasParent() {
206
-			parentPath := cmd.Parent().CommandPath()
207
-			dashParentPath := strings.Replace(parentPath, " ", "-", -1)
208
-			seealso := fmt.Sprintf("**%s(%s)**", dashParentPath, header.Section)
209
-			seealsos = append(seealsos, seealso)
210
-			cmd.VisitParents(func(c *cobra.Command) {
211
-				if c.DisableAutoGenTag {
212
-					cmd.DisableAutoGenTag = c.DisableAutoGenTag
213
-				}
214
-			})
215
-		}
216
-		children := cmd.Commands()
217
-		sort.Sort(byName(children))
218
-		for _, c := range children {
219
-			if !c.IsAvailableCommand() || c.IsHelpCommand() {
220
-				continue
221
-			}
222
-			seealso := fmt.Sprintf("**%s-%s(%s)**", dashCommandName, c.Name(), header.Section)
223
-			seealsos = append(seealsos, seealso)
224
-		}
225
-		fmt.Fprintf(buf, "%s\n", strings.Join(seealsos, ", "))
226
-	}
227
-	if !cmd.DisableAutoGenTag {
228
-		fmt.Fprintf(buf, "# HISTORY\n%s Auto generated by spf13/cobra\n", header.Date.Format("2-Jan-2006"))
229
-	}
230
-	return buf.Bytes()
231
-}
232 1
deleted file mode 100644
... ...
@@ -1,175 +0,0 @@
1
-//Copyright 2015 Red Hat Inc. All rights reserved.
2
-//
3
-// Licensed under the Apache License, Version 2.0 (the "License");
4
-// you may not use this file except in compliance with the License.
5
-// You may obtain a copy of the License at
6
-// http://www.apache.org/licenses/LICENSE-2.0
7
-//
8
-// Unless required by applicable law or agreed to in writing, software
9
-// distributed under the License is distributed on an "AS IS" BASIS,
10
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
-// See the License for the specific language governing permissions and
12
-// limitations under the License.
13
-
14
-package doc
15
-
16
-import (
17
-	"fmt"
18
-	"io"
19
-	"os"
20
-	"path/filepath"
21
-	"sort"
22
-	"strings"
23
-	"time"
24
-
25
-	"github.com/spf13/cobra"
26
-)
27
-
28
-func printOptions(w io.Writer, cmd *cobra.Command, name string) error {
29
-	flags := cmd.NonInheritedFlags()
30
-	flags.SetOutput(w)
31
-	if flags.HasFlags() {
32
-		if _, err := fmt.Fprintf(w, "### Options\n\n```\n"); err != nil {
33
-			return err
34
-		}
35
-		flags.PrintDefaults()
36
-		if _, err := fmt.Fprintf(w, "```\n\n"); err != nil {
37
-			return err
38
-		}
39
-	}
40
-
41
-	parentFlags := cmd.InheritedFlags()
42
-	parentFlags.SetOutput(w)
43
-	if parentFlags.HasFlags() {
44
-		if _, err := fmt.Fprintf(w, "### Options inherited from parent commands\n\n```\n"); err != nil {
45
-			return err
46
-		}
47
-		parentFlags.PrintDefaults()
48
-		if _, err := fmt.Fprintf(w, "```\n\n"); err != nil {
49
-			return err
50
-		}
51
-	}
52
-	return nil
53
-}
54
-
55
-func GenMarkdown(cmd *cobra.Command, w io.Writer) error {
56
-	return GenMarkdownCustom(cmd, w, func(s string) string { return s })
57
-}
58
-
59
-func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error {
60
-	name := cmd.CommandPath()
61
-
62
-	short := cmd.Short
63
-	long := cmd.Long
64
-	if len(long) == 0 {
65
-		long = short
66
-	}
67
-
68
-	if _, err := fmt.Fprintf(w, "## %s\n\n", name); err != nil {
69
-		return err
70
-	}
71
-	if _, err := fmt.Fprintf(w, "%s\n\n", short); err != nil {
72
-		return err
73
-	}
74
-	if _, err := fmt.Fprintf(w, "### Synopsis\n\n"); err != nil {
75
-		return err
76
-	}
77
-	if _, err := fmt.Fprintf(w, "\n%s\n\n", long); err != nil {
78
-		return err
79
-	}
80
-
81
-	if cmd.Runnable() {
82
-		if _, err := fmt.Fprintf(w, "```\n%s\n```\n\n", cmd.UseLine()); err != nil {
83
-			return err
84
-		}
85
-	}
86
-
87
-	if len(cmd.Example) > 0 {
88
-		if _, err := fmt.Fprintf(w, "### Examples\n\n"); err != nil {
89
-			return err
90
-		}
91
-		if _, err := fmt.Fprintf(w, "```\n%s\n```\n\n", cmd.Example); err != nil {
92
-			return err
93
-		}
94
-	}
95
-
96
-	if err := printOptions(w, cmd, name); err != nil {
97
-		return err
98
-	}
99
-	if hasSeeAlso(cmd) {
100
-		if _, err := fmt.Fprintf(w, "### SEE ALSO\n"); err != nil {
101
-			return err
102
-		}
103
-		if cmd.HasParent() {
104
-			parent := cmd.Parent()
105
-			pname := parent.CommandPath()
106
-			link := pname + ".md"
107
-			link = strings.Replace(link, " ", "_", -1)
108
-			if _, err := fmt.Fprintf(w, "* [%s](%s)\t - %s\n", pname, linkHandler(link), parent.Short); err != nil {
109
-				return err
110
-			}
111
-			cmd.VisitParents(func(c *cobra.Command) {
112
-				if c.DisableAutoGenTag {
113
-					cmd.DisableAutoGenTag = c.DisableAutoGenTag
114
-				}
115
-			})
116
-		}
117
-
118
-		children := cmd.Commands()
119
-		sort.Sort(byName(children))
120
-
121
-		for _, child := range children {
122
-			if !child.IsAvailableCommand() || child.IsHelpCommand() {
123
-				continue
124
-			}
125
-			cname := name + " " + child.Name()
126
-			link := cname + ".md"
127
-			link = strings.Replace(link, " ", "_", -1)
128
-			if _, err := fmt.Fprintf(w, "* [%s](%s)\t - %s\n", cname, linkHandler(link), child.Short); err != nil {
129
-				return err
130
-			}
131
-		}
132
-		if _, err := fmt.Fprintf(w, "\n"); err != nil {
133
-			return err
134
-		}
135
-	}
136
-	if !cmd.DisableAutoGenTag {
137
-		if _, err := fmt.Fprintf(w, "###### Auto generated by spf13/cobra on %s\n", time.Now().Format("2-Jan-2006")); err != nil {
138
-			return err
139
-		}
140
-	}
141
-	return nil
142
-}
143
-
144
-func GenMarkdownTree(cmd *cobra.Command, dir string) error {
145
-	identity := func(s string) string { return s }
146
-	emptyStr := func(s string) string { return "" }
147
-	return GenMarkdownTreeCustom(cmd, dir, emptyStr, identity)
148
-}
149
-
150
-func GenMarkdownTreeCustom(cmd *cobra.Command, dir string, filePrepender, linkHandler func(string) string) error {
151
-	for _, c := range cmd.Commands() {
152
-		if !c.IsAvailableCommand() || c.IsHelpCommand() {
153
-			continue
154
-		}
155
-		if err := GenMarkdownTreeCustom(c, dir, filePrepender, linkHandler); err != nil {
156
-			return err
157
-		}
158
-	}
159
-
160
-	basename := strings.Replace(cmd.CommandPath(), " ", "_", -1) + ".md"
161
-	filename := filepath.Join(dir, basename)
162
-	f, err := os.Create(filename)
163
-	if err != nil {
164
-		return err
165
-	}
166
-	defer f.Close()
167
-
168
-	if _, err := io.WriteString(f, filePrepender(filename)); err != nil {
169
-		return err
170
-	}
171
-	if err := GenMarkdownCustom(cmd, f, linkHandler); err != nil {
172
-		return err
173
-	}
174
-	return nil
175
-}
176 1
deleted file mode 100644
... ...
@@ -1,38 +0,0 @@
1
-// Copyright 2015 Red Hat Inc. All rights reserved.
2
-//
3
-// Licensed under the Apache License, Version 2.0 (the "License");
4
-// you may not use this file except in compliance with the License.
5
-// You may obtain a copy of the License at
6
-// http://www.apache.org/licenses/LICENSE-2.0
7
-//
8
-// Unless required by applicable law or agreed to in writing, software
9
-// distributed under the License is distributed on an "AS IS" BASIS,
10
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
-// See the License for the specific language governing permissions and
12
-// limitations under the License.
13
-
14
-package doc
15
-
16
-import "github.com/spf13/cobra"
17
-
18
-// Test to see if we have a reason to print See Also information in docs
19
-// Basically this is a test for a parent commend or a subcommand which is
20
-// both not deprecated and not the autogenerated help command.
21
-func hasSeeAlso(cmd *cobra.Command) bool {
22
-	if cmd.HasParent() {
23
-		return true
24
-	}
25
-	for _, c := range cmd.Commands() {
26
-		if !c.IsAvailableCommand() || c.IsHelpCommand() {
27
-			continue
28
-		}
29
-		return true
30
-	}
31
-	return false
32
-}
33
-
34
-type byName []*cobra.Command
35
-
36
-func (s byName) Len() int           { return len(s) }
37
-func (s byName) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
38
-func (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() }