Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
| ... | ... |
@@ -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() }
|