Merge pull request #45924 from janetkuo/daemonset-history

Automatic merge from submit-queue

Implement Daemonset history

~Depends on #45867 (the 1st commit, ignore it when reviewing)~ (already merged)

Ref https://github.com/kubernetes/community/pull/527/ and https://github.com/kubernetes/community/pull/594

@kubernetes/sig-apps-api-reviews @kubernetes/sig-apps-pr-reviews @erictune @kow3ns @lukaszo @kargakis 

---

TODOs:
- [x] API changes
  - [x] (maybe) Remove rollback subresource if we decide to do client-side rollback 
- [x] deployment controller 
  - [x] controller revision
    - [x] owner ref (claim & adoption)
    - [x] history reconstruct (put revision number, hash collision avoidance)
    - [x] de-dup history and relabel pods
    - [x] compare ds template with history 
  - [x] hash labels (put it in controller revision, pods, and maybe deployment)
  - [x] clean up old history 
  - [x] Rename status.uniquifier when we reach consensus in #44774 
- [x] e2e tests 
- [x] unit tests 
  - [x] daemoncontroller_test.go 
  - [x] update_test.go 
  - [x] ~(maybe) storage_test.go // if we do server side rollback~

kubectl part is in #46144

--- 

**Release note**:

```release-note
```
This commit is contained in:
Kubernetes Submit Queue
2017-06-03 16:52:38 -07:00
committed by GitHub
53 changed files with 3220 additions and 1630 deletions

View File

@@ -52564,6 +52564,11 @@
"type": "integer",
"format": "int32"
},
"revisionHistoryLimit": {
"description": "The number of old history to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 10.",
"type": "integer",
"format": "int32"
},
"selector": {
"description": "A label query over pods that are managed by the daemon set. Must match in order to be controlled. If empty, defaulted to labels on Pod template. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors",
"$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector"
@@ -52573,7 +52578,7 @@
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.PodTemplateSpec"
},
"templateGeneration": {
"description": "A sequence number representing a specific generation of the template. Populated by the system. It can be set only during the creation.",
"description": "DEPRECATED. A sequence number representing a specific generation of the template. Populated by the system. It can be set only during the creation.",
"type": "integer",
"format": "int64"
},
@@ -52592,6 +52597,11 @@
"numberReady"
],
"properties": {
"collisionCount": {
"description": "Count of hash collisions for the DaemonSet. The DaemonSet controller uses this field as a collision avoidance mechanism when it needs to create the name for the newest ControllerRevision.",
"type": "integer",
"format": "int64"
},
"currentNumberScheduled": {
"description": "The number of nodes that are running at least 1 daemon pod and are supposed to run the daemon pod. More info: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/",
"type": "integer",

View File

@@ -7117,7 +7117,12 @@
"templateGeneration": {
"type": "integer",
"format": "int64",
"description": "A sequence number representing a specific generation of the template. Populated by the system. It can be set only during the creation."
"description": "DEPRECATED. A sequence number representing a specific generation of the template. Populated by the system. It can be set only during the creation."
},
"revisionHistoryLimit": {
"type": "integer",
"format": "int32",
"description": "The number of old history to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 10."
}
}
},
@@ -9159,6 +9164,11 @@
"type": "integer",
"format": "int32",
"description": "The number of nodes that should be running the daemon pod and have none of the daemon pod running and available (ready for at least spec.minReadySeconds)"
},
"collisionCount": {
"type": "integer",
"format": "int64",
"description": "Count of hash collisions for the DaemonSet. The DaemonSet controller uses this field as a collision avoidance mechanism when it needs to create the name for the newest ControllerRevision."
}
}
},

View File

@@ -33,6 +33,7 @@ func startDaemonSetController(ctx ControllerContext) (bool, error) {
}
go daemon.NewDaemonSetsController(
ctx.InformerFactory.Extensions().V1beta1().DaemonSets(),
ctx.InformerFactory.Apps().V1beta1().ControllerRevisions(),
ctx.InformerFactory.Core().V1().Pods(),
ctx.InformerFactory.Core().V1().Nodes(),
ctx.ClientBuilder.ClientOrDie("daemon-set-controller"),

View File

@@ -6607,7 +6607,7 @@ Examples:<br>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2017-05-31 19:35:31 UTC
Last updated 2017-06-01 17:29:15 UTC
</div>
</div>
</body>

View File

@@ -6634,7 +6634,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
</div>
<div id="footer">
<div id="footer-text">
Last updated 2017-05-25 16:54:16 UTC
Last updated 2017-05-25 21:02:39 UTC
</div>
</div>
</body>

View File

@@ -689,6 +689,13 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">collisionCount</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Count of hash collisions for the DaemonSet. The DaemonSet controller uses this field as a collision avoidance mechanism when it needs to create the name for the newest ControllerRevision.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int64)</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
@@ -2362,11 +2369,18 @@ When an object is created, the system will populate this list with the current s
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">templateGeneration</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">A sequence number representing a specific generation of the template. Populated by the system. It can be set only during the creation.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">DEPRECATED. A sequence number representing a specific generation of the template. Populated by the system. It can be set only during the creation.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int64)</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">revisionHistoryLimit</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The number of old history to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 10.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
@@ -8134,7 +8148,7 @@ Both these may change in the future. Incoming requests are matched against the h
</div>
<div id="footer">
<div id="footer-text">
Last updated 2017-05-31 19:36:09 UTC
Last updated 2017-06-01 17:29:53 UTC
</div>
</div>
</body>

View File

@@ -12964,6 +12964,11 @@
"type": "integer",
"format": "int32"
},
"revisionHistoryLimit": {
"description": "The number of old history to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 10.",
"type": "integer",
"format": "int32"
},
"selector": {
"description": "A label query over pods that are managed by the daemon set. Must match in order to be controlled. If empty, defaulted to labels on Pod template. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors",
"$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector"
@@ -12973,7 +12978,7 @@
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.PodTemplateSpec"
},
"templateGeneration": {
"description": "A sequence number representing a specific generation of the template. Populated by the system. It can be set only during the creation.",
"description": "DEPRECATED. A sequence number representing a specific generation of the template. Populated by the system. It can be set only during the creation.",
"type": "integer",
"format": "int64"
},
@@ -12992,6 +12997,11 @@
"numberReady"
],
"properties": {
"collisionCount": {
"description": "Count of hash collisions for the DaemonSet. The DaemonSet controller uses this field as a collision avoidance mechanism when it needs to create the name for the newest ControllerRevision.",
"type": "integer",
"format": "int64"
},
"currentNumberScheduled": {
"description": "The number of nodes that are running at least 1 daemon pod and are supposed to run the daemon pod. More info: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/",
"type": "integer",

View File

@@ -4861,7 +4861,12 @@
"templateGeneration": {
"type": "integer",
"format": "int64",
"description": "A sequence number representing a specific generation of the template. Populated by the system. It can be set only during the creation."
"description": "DEPRECATED. A sequence number representing a specific generation of the template. Populated by the system. It can be set only during the creation."
},
"revisionHistoryLimit": {
"type": "integer",
"format": "int32",
"description": "The number of old history to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 10."
}
}
},
@@ -6903,6 +6908,11 @@
"type": "integer",
"format": "int32",
"description": "The number of nodes that should be running the daemon pod and have none of the daemon pod running and available (ready for at least spec.minReadySeconds)"
},
"collisionCount": {
"type": "integer",
"format": "int64",
"description": "Count of hash collisions for the DaemonSet. The DaemonSet controller uses this field as a collision avoidance mechanism when it needs to create the name for the newest ControllerRevision."
}
}
},

View File

@@ -671,6 +671,13 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">collisionCount</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Count of hash collisions for the DaemonSet. The DaemonSet controller uses this field as a collision avoidance mechanism when it needs to create the name for the newest ControllerRevision.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int64)</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
@@ -2193,11 +2200,18 @@ When an object is created, the system will populate this list with the current s
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">templateGeneration</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">A sequence number representing a specific generation of the template. Populated by the system. It can be set only during the creation.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">DEPRECATED. A sequence number representing a specific generation of the template. Populated by the system. It can be set only during the creation.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int64)</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">revisionHistoryLimit</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The number of old history to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 10.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
@@ -7204,7 +7218,7 @@ Both these may change in the future. Incoming requests are matched against the h
</div>
<div id="footer">
<div id="footer-text">
Last updated 2017-05-31 19:38:40 UTC
Last updated 2017-06-01 17:32:20 UTC
</div>
</div>
</body>

View File

@@ -553,6 +553,11 @@ func extensionFuncs(t apitesting.TestingCommon) []interface{} {
}
}
},
func(j *extensions.DaemonSetSpec, c fuzz.Continue) {
c.FuzzNoCustom(j) // fuzz self without calling this function again
rhl := int32(c.Rand.Int31())
j.RevisionHistoryLimit = &rhl
},
func(j *extensions.DaemonSetUpdateStrategy, c fuzz.Continue) {
c.FuzzNoCustom(j) // fuzz self without calling this function again
// Ensure that strategyType is one of valid values.

View File

@@ -386,7 +386,7 @@ type DaemonSetUpdateStrategy struct {
// Rolling update config params. Present only if type = "RollingUpdate".
//---
// TODO: Update this to follow our convention for oneOf, whatever we decide it
// to be. Same as DeploymentStrategy.RollingUpdate.
// to be. Same as Deployment `strategy.rollingUpdate`.
// See https://github.com/kubernetes/kubernetes/issues/35345
// +optional
RollingUpdate *RollingUpdateDaemonSet
@@ -449,10 +449,17 @@ type DaemonSetSpec struct {
// +optional
MinReadySeconds int32
// DEPRECATED.
// A sequence number representing a specific generation of the template.
// Populated by the system. It can be set only during the creation.
// +optional
TemplateGeneration int64
// The number of old history to retain to allow rollback.
// This is a pointer to distinguish between explicit zero and not specified.
// Defaults to 10.
// +optional
RevisionHistoryLimit *int32
}
// DaemonSetStatus represents the current status of a daemon set.
@@ -492,6 +499,12 @@ type DaemonSetStatus struct {
// (ready for at least spec.minReadySeconds)
// +optional
NumberUnavailable int32
// Count of hash collisions for the DaemonSet. The DaemonSet controller
// uses this field as a collision avoidance mechanism when it needs to
// create the name for the newest ControllerRevision.
// +optional
CollisionCount *int64
}
// +genclient=true
@@ -519,10 +532,16 @@ type DaemonSet struct {
}
const (
// DEPRECATED: DefaultDaemonSetUniqueLabelKey is used instead.
// DaemonSetTemplateGenerationKey is the key of the labels that is added
// to daemon set pods to distinguish between old and new pod templates
// during DaemonSet template update.
DaemonSetTemplateGenerationKey string = "pod-template-generation"
// DefaultDaemonSetUniqueLabelKey is the default label key that is added
// to existing DaemonSet pods to distinguish between old and new
// DaemonSet pods during DaemonSet template updates.
DefaultDaemonSetUniqueLabelKey string = "daemonset-controller-hash"
)
// DaemonSetList is a collection of daemon sets.

View File

@@ -56,6 +56,10 @@ func SetDefaults_DaemonSet(obj *DaemonSet) {
updateStrategy.RollingUpdate.MaxUnavailable = &maxUnavailable
}
}
if obj.Spec.RevisionHistoryLimit == nil {
obj.Spec.RevisionHistoryLimit = new(int32)
*obj.Spec.RevisionHistoryLimit = 10
}
}
func SetDefaults_Deployment(obj *Deployment) {

View File

@@ -32,7 +32,7 @@ import (
. "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
)
func TestSetDefaultDaemonSet(t *testing.T) {
func TestSetDefaultDaemonSetSpec(t *testing.T) {
defaultLabels := map[string]string{"foo": "bar"}
period := int64(v1.DefaultTerminationGracePeriodSeconds)
defaultTemplate := v1.PodTemplateSpec{
@@ -78,6 +78,7 @@ func TestSetDefaultDaemonSet(t *testing.T) {
UpdateStrategy: DaemonSetUpdateStrategy{
Type: OnDeleteDaemonSetStrategyType,
},
RevisionHistoryLimit: newInt32(10),
},
},
},
@@ -90,6 +91,7 @@ func TestSetDefaultDaemonSet(t *testing.T) {
},
Spec: DaemonSetSpec{
Template: defaultTemplate,
RevisionHistoryLimit: newInt32(1),
},
},
expected: &DaemonSet{
@@ -106,6 +108,7 @@ func TestSetDefaultDaemonSet(t *testing.T) {
UpdateStrategy: DaemonSetUpdateStrategy{
Type: OnDeleteDaemonSetStrategyType,
},
RevisionHistoryLimit: newInt32(1),
},
},
},
@@ -117,19 +120,7 @@ func TestSetDefaultDaemonSet(t *testing.T) {
UpdateStrategy: DaemonSetUpdateStrategy{
Type: OnDeleteDaemonSetStrategyType,
},
},
},
},
{ // Update strategy.
original: &DaemonSet{
Spec: DaemonSetSpec{},
},
expected: &DaemonSet{
Spec: DaemonSetSpec{
Template: templateNoLabel,
UpdateStrategy: DaemonSetUpdateStrategy{
Type: OnDeleteDaemonSetStrategyType,
},
RevisionHistoryLimit: newInt32(10),
},
},
},
@@ -143,6 +134,7 @@ func TestSetDefaultDaemonSet(t *testing.T) {
UpdateStrategy: DaemonSetUpdateStrategy{
Type: OnDeleteDaemonSetStrategyType,
},
RevisionHistoryLimit: newInt32(10),
},
},
},

View File

@@ -689,6 +689,11 @@ func (m *DaemonSetSpec) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0x28
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.TemplateGeneration))
if m.RevisionHistoryLimit != nil {
dAtA[i] = 0x30
i++
i = encodeVarintGenerated(dAtA, i, uint64(*m.RevisionHistoryLimit))
}
return i, nil
}
@@ -731,6 +736,11 @@ func (m *DaemonSetStatus) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0x40
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.NumberUnavailable))
if m.CollisionCount != nil {
dAtA[i] = 0x48
i++
i = encodeVarintGenerated(dAtA, i, uint64(*m.CollisionCount))
}
return i, nil
}
@@ -2795,6 +2805,9 @@ func (m *DaemonSetSpec) Size() (n int) {
n += 1 + l + sovGenerated(uint64(l))
n += 1 + sovGenerated(uint64(m.MinReadySeconds))
n += 1 + sovGenerated(uint64(m.TemplateGeneration))
if m.RevisionHistoryLimit != nil {
n += 1 + sovGenerated(uint64(*m.RevisionHistoryLimit))
}
return n
}
@@ -2809,6 +2822,9 @@ func (m *DaemonSetStatus) Size() (n int) {
n += 1 + sovGenerated(uint64(m.UpdatedNumberScheduled))
n += 1 + sovGenerated(uint64(m.NumberAvailable))
n += 1 + sovGenerated(uint64(m.NumberUnavailable))
if m.CollisionCount != nil {
n += 1 + sovGenerated(uint64(*m.CollisionCount))
}
return n
}
@@ -3605,6 +3621,7 @@ func (this *DaemonSetSpec) String() string {
`UpdateStrategy:` + strings.Replace(strings.Replace(this.UpdateStrategy.String(), "DaemonSetUpdateStrategy", "DaemonSetUpdateStrategy", 1), `&`, ``, 1) + `,`,
`MinReadySeconds:` + fmt.Sprintf("%v", this.MinReadySeconds) + `,`,
`TemplateGeneration:` + fmt.Sprintf("%v", this.TemplateGeneration) + `,`,
`RevisionHistoryLimit:` + valueToStringGenerated(this.RevisionHistoryLimit) + `,`,
`}`,
}, "")
return s
@@ -3622,6 +3639,7 @@ func (this *DaemonSetStatus) String() string {
`UpdatedNumberScheduled:` + fmt.Sprintf("%v", this.UpdatedNumberScheduled) + `,`,
`NumberAvailable:` + fmt.Sprintf("%v", this.NumberAvailable) + `,`,
`NumberUnavailable:` + fmt.Sprintf("%v", this.NumberUnavailable) + `,`,
`CollisionCount:` + valueToStringGenerated(this.CollisionCount) + `,`,
`}`,
}, "")
return s
@@ -5102,6 +5120,26 @@ func (m *DaemonSetSpec) Unmarshal(dAtA []byte) error {
break
}
}
case 6:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field RevisionHistoryLimit", wireType)
}
var v int32
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= (int32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.RevisionHistoryLimit = &v
default:
iNdEx = preIndex
skippy, err := skipGenerated(dAtA[iNdEx:])
@@ -5304,6 +5342,26 @@ func (m *DaemonSetStatus) Unmarshal(dAtA []byte) error {
break
}
}
case 9:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field CollisionCount", wireType)
}
var v int64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.CollisionCount = &v
default:
iNdEx = preIndex
skippy, err := skipGenerated(dAtA[iNdEx:])
@@ -11873,219 +11931,220 @@ func init() {
}
var fileDescriptorGenerated = []byte{
// 3412 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x5b, 0xdd, 0x6f, 0x1c, 0x57,
0x15, 0xcf, 0x78, 0xbd, 0xf1, 0xfa, 0x6c, 0x6c, 0xc7, 0xd7, 0xae, 0xb3, 0x75, 0x5b, 0x3b, 0x1d,
0x44, 0x9b, 0x42, 0xbb, 0xa6, 0x29, 0x29, 0x6d, 0xda, 0xa6, 0xf5, 0xda, 0xf9, 0x30, 0xb2, 0x9d,
0xed, 0xdd, 0x75, 0x44, 0xd3, 0x2f, 0xc6, 0xbb, 0xd7, 0xeb, 0x49, 0xe6, 0xab, 0x33, 0x77, 0x5c,
0xaf, 0x2a, 0xa0, 0x12, 0xa2, 0x0f, 0x3c, 0x20, 0x78, 0x41, 0x45, 0x82, 0x47, 0x1e, 0x78, 0x81,
0xf6, 0x01, 0x0a, 0x7f, 0x01, 0x79, 0x40, 0xa8, 0x48, 0x20, 0x55, 0xa8, 0x58, 0xc4, 0x15, 0xfd,
0x07, 0xa0, 0x2f, 0x79, 0x42, 0xf7, 0xce, 0x9d, 0xef, 0x19, 0x27, 0xbb, 0x4e, 0x56, 0x48, 0xbc,
0xed, 0xdc, 0x7b, 0xce, 0xef, 0x7c, 0xdc, 0x73, 0xcf, 0x3d, 0xf7, 0x63, 0xe1, 0x85, 0xeb, 0xcf,
0x38, 0x55, 0xd5, 0x5c, 0xb8, 0xee, 0x6e, 0x12, 0xdb, 0x20, 0x94, 0x38, 0x0b, 0xd6, 0xf5, 0xce,
0x82, 0x62, 0xa9, 0xce, 0x02, 0xd9, 0xa5, 0xc4, 0x70, 0x54, 0xd3, 0x70, 0x16, 0x76, 0x9e, 0xdc,
0x24, 0x54, 0x79, 0x72, 0xa1, 0x43, 0x0c, 0x62, 0x2b, 0x94, 0xb4, 0xab, 0x96, 0x6d, 0x52, 0x13,
0x3d, 0xe1, 0xb1, 0x57, 0x43, 0xf6, 0xaa, 0x75, 0xbd, 0x53, 0x65, 0xec, 0xd5, 0x90, 0xbd, 0x2a,
0xd8, 0x67, 0x9f, 0xe8, 0xa8, 0x74, 0xdb, 0xdd, 0xac, 0xb6, 0x4c, 0x7d, 0xa1, 0x63, 0x76, 0xcc,
0x05, 0x8e, 0xb2, 0xe9, 0x6e, 0xf1, 0x2f, 0xfe, 0xc1, 0x7f, 0x79, 0xe8, 0xb3, 0x5f, 0x17, 0xca,
0x29, 0x96, 0xaa, 0x2b, 0xad, 0x6d, 0xd5, 0x20, 0x76, 0xd7, 0x57, 0x6f, 0xc1, 0x26, 0x8e, 0xe9,
0xda, 0x2d, 0x92, 0xd4, 0xe9, 0x40, 0x2e, 0x67, 0x41, 0x27, 0x54, 0x59, 0xd8, 0x49, 0x59, 0x32,
0xbb, 0x90, 0xc7, 0x65, 0xbb, 0x06, 0x55, 0xf5, 0xb4, 0x98, 0xa7, 0x6f, 0xc7, 0xe0, 0xb4, 0xb6,
0x89, 0xae, 0xa4, 0xf8, 0x9e, 0xca, 0xe3, 0x73, 0xa9, 0xaa, 0x2d, 0xa8, 0x06, 0x75, 0xa8, 0x9d,
0x62, 0x7a, 0x3c, 0x77, 0x98, 0xb2, 0x6c, 0x79, 0xf6, 0x80, 0x41, 0xb5, 0x4c, 0x4d, 0x6d, 0x75,
0xf3, 0x06, 0x54, 0xae, 0x02, 0x2c, 0xd6, 0x57, 0xae, 0x10, 0x9b, 0x0d, 0x1c, 0x3a, 0x09, 0xc3,
0x86, 0xa2, 0x93, 0x8a, 0x74, 0x52, 0x3a, 0x35, 0x5a, 0x3b, 0x76, 0x63, 0x6f, 0xfe, 0xc8, 0xfe,
0xde, 0xfc, 0xf0, 0xba, 0xa2, 0x13, 0xcc, 0x7b, 0xe4, 0x9f, 0x49, 0x70, 0xff, 0x92, 0xeb, 0x50,
0x53, 0x5f, 0x23, 0xd4, 0x56, 0x5b, 0x4b, 0xae, 0x6d, 0x13, 0x83, 0x36, 0xa8, 0x42, 0x5d, 0xe7,
0xf6, 0xfc, 0xe8, 0x2a, 0x14, 0x77, 0x14, 0xcd, 0x25, 0x95, 0xa1, 0x93, 0xd2, 0xa9, 0xf2, 0xe9,
0x6a, 0x55, 0x04, 0x54, 0xd4, 0x3b, 0x7e, 0x48, 0x55, 0xfd, 0x21, 0xaf, 0xbe, 0xec, 0x2a, 0x06,
0x55, 0x69, 0xb7, 0x36, 0x2d, 0x20, 0x8f, 0x09, 0xb9, 0x57, 0x18, 0x16, 0xf6, 0x20, 0xe5, 0x1f,
0x49, 0xf0, 0x50, 0xae, 0x6e, 0xab, 0xaa, 0x43, 0x91, 0x0e, 0x45, 0x95, 0x12, 0xdd, 0xa9, 0x48,
0x27, 0x0b, 0xa7, 0xca, 0xa7, 0x2f, 0x55, 0x7b, 0x0a, 0xe7, 0x6a, 0x2e, 0x78, 0x6d, 0x4c, 0xe8,
0x55, 0x5c, 0x61, 0xf0, 0xd8, 0x93, 0x22, 0xff, 0x44, 0x02, 0x14, 0xe5, 0x69, 0x2a, 0x76, 0x87,
0xd0, 0x3b, 0xf0, 0xd2, 0x2b, 0x87, 0xf3, 0xd2, 0x94, 0x80, 0x2c, 0x7b, 0x02, 0x63, 0x4e, 0x7a,
0x57, 0x82, 0x99, 0xb4, 0x4e, 0xdc, 0x3b, 0x5b, 0x71, 0xef, 0x2c, 0x1e, 0xc2, 0x3b, 0x1e, 0x6a,
0x8e, 0x5b, 0x7e, 0x3b, 0x04, 0xa3, 0xcb, 0x0a, 0xd1, 0x4d, 0xa3, 0x41, 0x28, 0xfa, 0x36, 0x94,
0xd8, 0x1c, 0x6d, 0x2b, 0x54, 0xe1, 0x1e, 0x29, 0x9f, 0xfe, 0xda, 0x41, 0xe6, 0x3a, 0x55, 0x46,
0x5d, 0xdd, 0x79, 0xb2, 0x7a, 0x79, 0xf3, 0x1a, 0x69, 0xd1, 0x35, 0x42, 0x95, 0x1a, 0x12, 0x72,
0x20, 0x6c, 0xc3, 0x01, 0x2a, 0x7a, 0x03, 0x86, 0x1d, 0x8b, 0xb4, 0x84, 0x33, 0x9f, 0xef, 0xd1,
0xac, 0x40, 0xd3, 0x86, 0x45, 0x5a, 0xe1, 0x68, 0xb1, 0x2f, 0xcc, 0x71, 0xd1, 0x16, 0x1c, 0x75,
0x78, 0x18, 0x54, 0x0a, 0x5c, 0xc2, 0xb9, 0xbe, 0x25, 0x78, 0xc1, 0x34, 0x2e, 0x64, 0x1c, 0xf5,
0xbe, 0xb1, 0x40, 0x97, 0xff, 0x24, 0xc1, 0x58, 0x40, 0xcb, 0x47, 0xec, 0xb5, 0x94, 0xef, 0xaa,
0x77, 0xe6, 0x3b, 0xc6, 0xcd, 0x3d, 0x77, 0x5c, 0xc8, 0x2a, 0xf9, 0x2d, 0x11, 0xbf, 0xbd, 0xee,
0xc7, 0xc3, 0x10, 0x8f, 0x87, 0x67, 0xfa, 0x35, 0x2b, 0x27, 0x0c, 0x3e, 0x2b, 0x44, 0xcc, 0x61,
0xee, 0x44, 0xaf, 0x43, 0xc9, 0x21, 0x1a, 0x69, 0x51, 0xd3, 0x16, 0xe6, 0x3c, 0x75, 0x87, 0xe6,
0x28, 0x9b, 0x44, 0x6b, 0x08, 0xd6, 0xda, 0x31, 0x66, 0x8f, 0xff, 0x85, 0x03, 0x48, 0xf4, 0x2a,
0x94, 0x28, 0xd1, 0x2d, 0x4d, 0xa1, 0xfe, 0xc4, 0x7a, 0x22, 0xdf, 0x24, 0x06, 0x5b, 0x37, 0xdb,
0x4d, 0xc1, 0xc0, 0x07, 0x3f, 0x70, 0x96, 0xdf, 0x8a, 0x03, 0x40, 0xf4, 0x9e, 0x04, 0xe3, 0xae,
0xd5, 0x66, 0xa4, 0x94, 0x25, 0xd8, 0x4e, 0x57, 0x44, 0xc3, 0x85, 0x7e, 0xdd, 0xb6, 0x11, 0x43,
0xab, 0xcd, 0x08, 0xe1, 0xe3, 0xf1, 0x76, 0x9c, 0x90, 0x8a, 0x16, 0x61, 0x42, 0x57, 0x0d, 0x4c,
0x94, 0x76, 0xb7, 0x41, 0x5a, 0xa6, 0xd1, 0x76, 0x2a, 0xc3, 0x27, 0xa5, 0x53, 0xc5, 0xda, 0x09,
0x01, 0x30, 0xb1, 0x16, 0xef, 0xc6, 0x49, 0x7a, 0xf4, 0x4d, 0x40, 0xbe, 0x5d, 0x17, 0xbd, 0xf5,
0x42, 0x35, 0x8d, 0x4a, 0xf1, 0xa4, 0x74, 0xaa, 0x50, 0x9b, 0x15, 0x28, 0xa8, 0x99, 0xa2, 0xc0,
0x19, 0x5c, 0xf2, 0x7f, 0x86, 0x61, 0x22, 0x11, 0xe0, 0xe8, 0x0a, 0xcc, 0xb4, 0xbc, 0xf4, 0xb9,
0xee, 0xea, 0x9b, 0xc4, 0x6e, 0xb4, 0xb6, 0x49, 0xdb, 0xd5, 0x48, 0x9b, 0x8f, 0x7a, 0xb1, 0x36,
0x27, 0x64, 0xcc, 0x2c, 0x65, 0x52, 0xe1, 0x1c, 0x6e, 0xa6, 0xb7, 0xc1, 0x9b, 0xd6, 0x54, 0xc7,
0x09, 0x30, 0x87, 0x38, 0x66, 0xa0, 0xf7, 0x7a, 0x8a, 0x02, 0x67, 0x70, 0x31, 0x1d, 0xdb, 0xc4,
0x51, 0x6d, 0xd2, 0x4e, 0xea, 0x58, 0x88, 0xeb, 0xb8, 0x9c, 0x49, 0x85, 0x73, 0xb8, 0xd1, 0x19,
0x28, 0x7b, 0xd2, 0xb8, 0xc7, 0xc5, 0xd0, 0x04, 0x09, 0x7b, 0x3d, 0xec, 0xc2, 0x51, 0x3a, 0x66,
0x9a, 0xb9, 0xe9, 0x10, 0x7b, 0x87, 0xb4, 0xf3, 0x87, 0xe4, 0x72, 0x8a, 0x02, 0x67, 0x70, 0x31,
0xd3, 0xbc, 0x98, 0x49, 0x99, 0x76, 0x34, 0x6e, 0xda, 0x46, 0x26, 0x15, 0xce, 0xe1, 0x66, 0x91,
0xe7, 0xa9, 0xbc, 0xb8, 0xa3, 0xa8, 0x9a, 0xb2, 0xa9, 0x91, 0xca, 0x48, 0x3c, 0xf2, 0xd6, 0xe3,
0xdd, 0x38, 0x49, 0x8f, 0x2e, 0xc2, 0xa4, 0xd7, 0xb4, 0x61, 0x28, 0x01, 0x48, 0x89, 0x83, 0xdc,
0x2f, 0x40, 0x26, 0xd7, 0x93, 0x04, 0x38, 0xcd, 0x23, 0xff, 0x5d, 0x82, 0x13, 0x39, 0x33, 0x09,
0xbd, 0x08, 0xc3, 0xb4, 0x6b, 0xf9, 0xeb, 0xef, 0x57, 0xfd, 0x8c, 0xde, 0xec, 0x5a, 0xe4, 0xd6,
0xde, 0xfc, 0x03, 0x39, 0x6c, 0xac, 0x1b, 0x73, 0x46, 0xf4, 0x5d, 0x18, 0xb3, 0x4d, 0x4d, 0x53,
0x8d, 0x8e, 0x47, 0x22, 0xb2, 0xc9, 0xf9, 0x1e, 0x67, 0x3a, 0x8e, 0x62, 0x84, 0xd9, 0x72, 0x72,
0x7f, 0x6f, 0x7e, 0x2c, 0xd6, 0x87, 0xe3, 0xe2, 0xe4, 0xdf, 0x0f, 0x01, 0x2c, 0x13, 0x4b, 0x33,
0xbb, 0x3a, 0x31, 0x06, 0xb1, 0x82, 0xbe, 0x19, 0x5b, 0x41, 0x5f, 0xe8, 0x35, 0xa3, 0x05, 0xaa,
0xe6, 0x2e, 0xa1, 0x9d, 0xc4, 0x12, 0xfa, 0x62, 0xff, 0x22, 0x0e, 0x5e, 0x43, 0x6f, 0x16, 0x60,
0x2a, 0x24, 0x5e, 0x32, 0x8d, 0xb6, 0xca, 0xe7, 0xc4, 0x73, 0xb1, 0x98, 0x78, 0x34, 0x11, 0x13,
0x27, 0x32, 0x58, 0x22, 0xf1, 0x70, 0x25, 0xd0, 0x7e, 0x88, 0xb3, 0x9f, 0x8b, 0x0b, 0xbf, 0xb5,
0x37, 0x7f, 0x60, 0x3d, 0x5f, 0x0d, 0x30, 0xe3, 0xca, 0xa2, 0x47, 0xe0, 0xa8, 0x4d, 0x14, 0xc7,
0x34, 0x78, 0x9a, 0x18, 0x0d, 0x8d, 0xc2, 0xbc, 0x15, 0x8b, 0x5e, 0xf4, 0x18, 0x8c, 0xe8, 0xc4,
0x71, 0x94, 0x0e, 0xe1, 0x19, 0x61, 0xb4, 0x36, 0x21, 0x08, 0x47, 0xd6, 0xbc, 0x66, 0xec, 0xf7,
0xa3, 0x6b, 0x30, 0xae, 0x29, 0x8e, 0x08, 0xed, 0xa6, 0xaa, 0x13, 0x3e, 0xe7, 0xcb, 0xa7, 0xbf,
0x72, 0x67, 0x11, 0xc3, 0x38, 0xc2, 0x95, 0x68, 0x35, 0x86, 0x84, 0x13, 0xc8, 0x68, 0x07, 0x10,
0x6b, 0x69, 0xda, 0x8a, 0xe1, 0x78, 0x2e, 0x63, 0xf2, 0x46, 0x7a, 0x96, 0x17, 0xe4, 0xb7, 0xd5,
0x14, 0x1a, 0xce, 0x90, 0x20, 0xff, 0x59, 0x82, 0xf1, 0x70, 0xc0, 0x06, 0x50, 0x28, 0xbd, 0x11,
0x2f, 0x94, 0x9e, 0xed, 0x3b, 0x78, 0x73, 0x2a, 0xa5, 0xf7, 0x0b, 0x80, 0x42, 0x22, 0x96, 0x1a,
0x36, 0x95, 0xd6, 0xf5, 0x3b, 0xd8, 0x47, 0xfc, 0x52, 0x02, 0x24, 0x92, 0xf5, 0xa2, 0x61, 0x98,
0x94, 0xe7, 0x7f, 0x5f, 0xcd, 0x57, 0xfa, 0x56, 0xd3, 0xd7, 0xa0, 0xba, 0x91, 0xc2, 0x3e, 0x6f,
0x50, 0xbb, 0x1b, 0x8e, 0x58, 0x9a, 0x00, 0x67, 0x28, 0x84, 0xde, 0x02, 0xb0, 0x05, 0x66, 0xd3,
0x14, 0x29, 0xe0, 0x85, 0x3e, 0xb2, 0x29, 0x03, 0x58, 0x32, 0x8d, 0x2d, 0xb5, 0x13, 0x26, 0x34,
0x1c, 0x00, 0xe3, 0x88, 0x90, 0xd9, 0xf3, 0x70, 0x22, 0x47, 0x7b, 0x74, 0x1c, 0x0a, 0xd7, 0x49,
0xd7, 0x73, 0x2b, 0x66, 0x3f, 0xd1, 0x74, 0x74, 0x3f, 0x36, 0x2a, 0xb6, 0x52, 0x67, 0x87, 0x9e,
0x91, 0xe4, 0xcf, 0x8b, 0xd1, 0x58, 0xe3, 0x55, 0xec, 0x29, 0x28, 0xd9, 0xc4, 0xd2, 0xd4, 0x96,
0xe2, 0x88, 0x7a, 0x86, 0x17, 0xa4, 0x58, 0xb4, 0xe1, 0xa0, 0x37, 0x56, 0xef, 0x0e, 0xdd, 0xdb,
0x7a, 0xb7, 0x70, 0xb7, 0xeb, 0x5d, 0x13, 0x4a, 0x8e, 0x5f, 0xe8, 0x0e, 0x73, 0xf0, 0xc5, 0x43,
0xe4, 0x6c, 0x51, 0xe3, 0x06, 0x02, 0x83, 0xea, 0x36, 0x10, 0x92, 0x55, 0xd7, 0x16, 0x7b, 0xac,
0x6b, 0x57, 0x61, 0xda, 0x26, 0x3b, 0x2a, 0x53, 0xe3, 0x92, 0xea, 0x50, 0xd3, 0xee, 0xae, 0xaa,
0xba, 0x4a, 0x45, 0xd9, 0x53, 0xd9, 0xdf, 0x9b, 0x9f, 0xc6, 0x19, 0xfd, 0x38, 0x93, 0x8b, 0x65,
0x67, 0x4b, 0x71, 0x1d, 0xd2, 0xe6, 0x29, 0xad, 0x14, 0x66, 0xe7, 0x3a, 0x6f, 0xc5, 0xa2, 0x17,
0xe9, 0xb1, 0xe0, 0x2e, 0xdd, 0x8d, 0xe0, 0x1e, 0xcf, 0x0f, 0x6c, 0xb4, 0x01, 0x27, 0x2c, 0xdb,
0xec, 0xd8, 0xc4, 0x71, 0x96, 0x89, 0xd2, 0xd6, 0x54, 0x83, 0xf8, 0xfe, 0x1a, 0xe5, 0x76, 0x3e,
0xb0, 0xbf, 0x37, 0x7f, 0xa2, 0x9e, 0x4d, 0x82, 0xf3, 0x78, 0xe5, 0x4f, 0x86, 0xe1, 0x78, 0x72,
0x95, 0xcd, 0xa9, 0x4a, 0xa5, 0xbe, 0xaa, 0xd2, 0xc7, 0x23, 0xd3, 0xc6, 0x2b, 0xd9, 0x83, 0x68,
0xc8, 0x98, 0x3a, 0x8b, 0x30, 0x21, 0xf2, 0x88, 0xdf, 0x29, 0xea, 0xf2, 0x20, 0x1a, 0x36, 0xe2,
0xdd, 0x38, 0x49, 0xcf, 0x6a, 0xcd, 0xb0, 0x84, 0xf4, 0x41, 0x86, 0xe3, 0xb5, 0xe6, 0x62, 0x92,
0x00, 0xa7, 0x79, 0xd0, 0x1a, 0x4c, 0xb9, 0x46, 0x1a, 0xca, 0x8b, 0xce, 0x07, 0x04, 0xd4, 0xd4,
0x46, 0x9a, 0x04, 0x67, 0xf1, 0xa1, 0x1d, 0x80, 0x96, 0x5f, 0x10, 0x38, 0x95, 0xa3, 0x3c, 0x57,
0xd7, 0xfa, 0x9e, 0x5b, 0x41, 0x6d, 0x11, 0x66, 0xc4, 0xa0, 0xc9, 0xc1, 0x11, 0x49, 0xe8, 0x39,
0x18, 0xb3, 0xf9, 0xc6, 0xc3, 0x37, 0xc0, 0x2b, 0xde, 0xef, 0x13, 0x6c, 0x63, 0x38, 0xda, 0x89,
0xe3, 0xb4, 0xe8, 0x2c, 0x8c, 0xb7, 0x58, 0x8d, 0xca, 0xd4, 0x58, 0x32, 0x5d, 0x83, 0xf2, 0x40,
0x2f, 0xd4, 0x10, 0xab, 0x13, 0x96, 0x62, 0x3d, 0x38, 0x41, 0x29, 0xff, 0x45, 0x8a, 0x2e, 0x6f,
0x41, 0x99, 0x7e, 0x36, 0x56, 0x92, 0x3d, 0x92, 0x28, 0xc9, 0x66, 0xd2, 0x1c, 0x91, 0x8a, 0xec,
0x7b, 0xd9, 0x15, 0xfa, 0x85, 0x43, 0x55, 0xe8, 0xe1, 0x32, 0x7d, 0xfb, 0x12, 0xfd, 0x43, 0x09,
0x66, 0x2e, 0x34, 0x2e, 0xda, 0xa6, 0x6b, 0xf9, 0xea, 0x5d, 0xb6, 0x3c, 0x3f, 0x7f, 0x03, 0x86,
0x6d, 0x57, 0xf3, 0xed, 0xfa, 0x92, 0x6f, 0x17, 0x76, 0x35, 0x66, 0xd7, 0x54, 0x82, 0xcb, 0x33,
0x8a, 0x31, 0xa0, 0x37, 0xe0, 0xa8, 0xad, 0x18, 0x1d, 0xe2, 0x2f, 0xe0, 0x4f, 0xf7, 0x68, 0xcd,
0xca, 0x32, 0x66, 0xec, 0x91, 0x32, 0x92, 0xa3, 0x61, 0x81, 0x2a, 0xff, 0x42, 0x82, 0x89, 0x4b,
0xcd, 0x66, 0x7d, 0xc5, 0xe0, 0x19, 0xa0, 0xae, 0xd0, 0x6d, 0x56, 0x63, 0x58, 0x0a, 0xdd, 0x4e,
0xd6, 0x18, 0xac, 0x0f, 0xf3, 0x1e, 0xb4, 0x0d, 0x23, 0x2c, 0xf3, 0x10, 0xa3, 0xdd, 0xe7, 0xf6,
0x40, 0x88, 0xab, 0x79, 0x20, 0x61, 0xed, 0x2a, 0x1a, 0xb0, 0x0f, 0x2f, 0xbf, 0x03, 0xd3, 0x11,
0xf5, 0x98, 0xbf, 0xf8, 0xc9, 0x26, 0x6a, 0x41, 0x91, 0x69, 0xe2, 0x9f, 0x5b, 0xf6, 0x7a, 0xfc,
0x96, 0x30, 0x39, 0xac, 0xc1, 0xd8, 0x97, 0x83, 0x3d, 0x6c, 0x79, 0x0d, 0xc6, 0x2e, 0x99, 0x0e,
0xad, 0x9b, 0x36, 0xe5, 0x6e, 0x43, 0x0f, 0x41, 0x41, 0x57, 0x0d, 0xb1, 0xc2, 0x97, 0x05, 0x4f,
0x81, 0xad, 0x41, 0xac, 0x9d, 0x77, 0x2b, 0xbb, 0x22, 0x93, 0x85, 0xdd, 0xca, 0x2e, 0x66, 0xed,
0xf2, 0x45, 0x18, 0x11, 0xc3, 0x11, 0x05, 0x2a, 0x1c, 0x0c, 0x54, 0xc8, 0x00, 0xfa, 0xcd, 0x10,
0x8c, 0x08, 0xed, 0x07, 0xb0, 0x11, 0x7c, 0x2d, 0xb6, 0x11, 0x3c, 0xdb, 0xdf, 0x48, 0xe7, 0xee,
0x02, 0xdb, 0x89, 0x5d, 0xe0, 0xf3, 0x7d, 0xe2, 0x1f, 0xbc, 0x05, 0xfc, 0x40, 0x82, 0xf1, 0x78,
0xcc, 0xa1, 0x33, 0x50, 0x66, 0xeb, 0x91, 0xda, 0x22, 0xeb, 0x61, 0x41, 0x1d, 0x1c, 0xca, 0x34,
0xc2, 0x2e, 0x1c, 0xa5, 0x43, 0x9d, 0x80, 0x8d, 0x85, 0x85, 0x70, 0x4a, 0xbe, 0xcb, 0x5d, 0xaa,
0x6a, 0x55, 0xef, 0xc2, 0xa7, 0xba, 0x62, 0xd0, 0xcb, 0x76, 0x83, 0xda, 0xaa, 0xd1, 0x49, 0x09,
0xe2, 0x31, 0x16, 0x45, 0x96, 0x6f, 0x48, 0x50, 0x16, 0x2a, 0x0f, 0x60, 0x3b, 0xf3, 0x6a, 0x7c,
0x3b, 0xf3, 0x74, 0x9f, 0xf3, 0x39, 0x7b, 0x2f, 0xf3, 0x51, 0x68, 0x0a, 0x9b, 0xc1, 0x2c, 0xc1,
0x6c, 0x9b, 0x0e, 0x4d, 0x26, 0x18, 0x36, 0xd7, 0x30, 0xef, 0x41, 0x3f, 0x90, 0xe0, 0xb8, 0x9a,
0x98, 0xf3, 0xc2, 0xd7, 0x2f, 0xf6, 0xa7, 0x5a, 0x00, 0x53, 0xab, 0x08, 0x79, 0xc7, 0x93, 0x3d,
0x38, 0x25, 0x52, 0x76, 0x21, 0x45, 0x85, 0x14, 0x18, 0xde, 0xa6, 0xd4, 0x12, 0x83, 0xb0, 0xd4,
0x7f, 0xe6, 0x09, 0x55, 0x2a, 0x71, 0xf3, 0x9b, 0xcd, 0x3a, 0xe6, 0xd0, 0xf2, 0xaf, 0x87, 0x02,
0x87, 0x35, 0xbc, 0x49, 0x12, 0xe4, 0x5b, 0xe9, 0x6e, 0xe4, 0xdb, 0x72, 0x56, 0xae, 0x45, 0xdf,
0x82, 0x02, 0xd5, 0xfa, 0xdd, 0xd0, 0x0a, 0x09, 0xcd, 0xd5, 0x46, 0x98, 0xb0, 0x9a, 0xab, 0x0d,
0xcc, 0x20, 0xd1, 0x9b, 0x50, 0x64, 0xab, 0x19, 0x9b, 0xe3, 0x85, 0xfe, 0x73, 0x08, 0xf3, 0x57,
0x18, 0x61, 0xec, 0xcb, 0xc1, 0x1e, 0xae, 0xfc, 0x0e, 0x8c, 0xc5, 0x12, 0x01, 0xba, 0x06, 0xc7,
0x34, 0x53, 0x69, 0xd7, 0x14, 0x4d, 0x31, 0x5a, 0xc4, 0x4e, 0xa6, 0xc6, 0xec, 0xbd, 0xd0, 0x6a,
0x84, 0x43, 0x24, 0x94, 0xe0, 0xf2, 0x31, 0xda, 0x87, 0x63, 0xd8, 0xb2, 0x02, 0x10, 0x5a, 0x8f,
0xe6, 0xa1, 0xc8, 0x42, 0xd8, 0x5b, 0x99, 0x46, 0x6b, 0xa3, 0x4c, 0x57, 0x16, 0xd9, 0x0e, 0xf6,
0xda, 0xd1, 0x69, 0x00, 0x87, 0xb4, 0x6c, 0x42, 0x79, 0xde, 0xf1, 0x4e, 0x8f, 0x82, 0x0c, 0xdc,
0x08, 0x7a, 0x70, 0x84, 0x4a, 0xfe, 0x9b, 0x04, 0x63, 0xeb, 0x84, 0xbe, 0x6d, 0xda, 0xd7, 0xeb,
0xfc, 0x72, 0x77, 0x00, 0x79, 0x7f, 0x33, 0x96, 0xf7, 0x5f, 0xea, 0x71, 0xcc, 0x62, 0xda, 0xe6,
0x65, 0x7f, 0xf9, 0x5f, 0x12, 0x54, 0x62, 0x94, 0xd1, 0x34, 0x41, 0xa0, 0x68, 0x99, 0x36, 0xf5,
0xd7, 0xf8, 0x43, 0x69, 0xc0, 0x52, 0x6a, 0x64, 0x95, 0x67, 0xb0, 0xd8, 0x43, 0x67, 0x76, 0x6e,
0xd9, 0xa6, 0x2e, 0xe2, 0xfe, 0x70, 0x52, 0x08, 0xb1, 0x43, 0x3b, 0x2f, 0xd8, 0xa6, 0x8e, 0x39,
0xb6, 0xfc, 0x57, 0x09, 0x26, 0x63, 0x94, 0x03, 0x48, 0xe9, 0x4a, 0x3c, 0xa5, 0x3f, 0x7f, 0x18,
0xc3, 0x72, 0x12, 0xfb, 0x17, 0x49, 0xb3, 0x98, 0x03, 0xd0, 0x16, 0x94, 0x2d, 0xb3, 0xdd, 0xb8,
0x0b, 0xb7, 0x7a, 0x13, 0x6c, 0x85, 0xac, 0x87, 0x58, 0x38, 0x0a, 0x8c, 0x76, 0x61, 0xd2, 0x50,
0x74, 0xe2, 0x58, 0x4a, 0x8b, 0x34, 0xee, 0xc2, 0x99, 0xca, 0x7d, 0xfc, 0xa6, 0x21, 0x89, 0x88,
0xd3, 0x42, 0xe4, 0xdf, 0xa5, 0xec, 0x36, 0x6d, 0x8a, 0x5e, 0x86, 0x12, 0x7f, 0x60, 0xd1, 0x32,
0x35, 0xb1, 0xb4, 0x9d, 0x61, 0x43, 0x53, 0x17, 0x6d, 0xb7, 0xf6, 0xe6, 0xbf, 0x7c, 0xe0, 0x91,
0xb0, 0x4f, 0x88, 0x03, 0x18, 0xb4, 0x0e, 0xc3, 0xd6, 0x61, 0xca, 0x0c, 0xbe, 0xb0, 0xf0, 0xda,
0x82, 0xe3, 0xc8, 0xff, 0x4e, 0x2a, 0xce, 0x97, 0x97, 0x6b, 0x77, 0x6d, 0xc0, 0x82, 0xb2, 0x26,
0x77, 0xd0, 0x6c, 0x18, 0x11, 0xab, 0xac, 0x88, 0xcb, 0x8b, 0x87, 0x89, 0xcb, 0xe8, 0xca, 0x10,
0x6c, 0x22, 0xfc, 0x46, 0x5f, 0x90, 0xfc, 0x0f, 0x09, 0x26, 0xb9, 0x42, 0x2d, 0xd7, 0x56, 0x69,
0x77, 0x60, 0x19, 0x74, 0x2b, 0x96, 0x41, 0x97, 0x7b, 0x34, 0x34, 0xa5, 0x71, 0x6e, 0x16, 0xfd,
0x54, 0x82, 0xfb, 0x52, 0xd4, 0x03, 0xc8, 0x30, 0x24, 0x9e, 0x61, 0x5e, 0x3a, 0xac, 0x81, 0x39,
0x59, 0xe6, 0x87, 0xe5, 0x0c, 0xf3, 0x78, 0xe0, 0x9e, 0x06, 0xb0, 0x6c, 0x75, 0x47, 0xd5, 0x48,
0x47, 0x5c, 0x24, 0x97, 0xc2, 0x21, 0xa9, 0x07, 0x3d, 0x38, 0x42, 0x85, 0xbe, 0x03, 0x33, 0x6d,
0xb2, 0xa5, 0xb8, 0x1a, 0x5d, 0x6c, 0xb7, 0x97, 0x14, 0x4b, 0xd9, 0x54, 0x35, 0x95, 0xaa, 0x62,
0x87, 0x3d, 0x5a, 0x3b, 0xef, 0x5d, 0xf0, 0x66, 0x51, 0xdc, 0xda, 0x9b, 0x7f, 0xf4, 0xe0, 0x4b,
0x1d, 0x9f, 0xb8, 0x8b, 0x73, 0x84, 0xa0, 0xef, 0x4b, 0x50, 0xb1, 0xc9, 0x5b, 0xae, 0x6a, 0x93,
0xf6, 0xb2, 0x6d, 0x5a, 0x31, 0x0d, 0x0a, 0x5c, 0x83, 0x8b, 0xfb, 0x7b, 0xf3, 0x15, 0x9c, 0x43,
0xd3, 0x8b, 0x0e, 0xb9, 0x82, 0x10, 0x85, 0x29, 0x45, 0xd3, 0xcc, 0xb7, 0x49, 0xdc, 0x03, 0xc3,
0x5c, 0x7e, 0x6d, 0x7f, 0x6f, 0x7e, 0x6a, 0x31, 0xdd, 0xdd, 0x8b, 0xe8, 0x2c, 0x78, 0xb4, 0x00,
0x23, 0x3b, 0xa6, 0xe6, 0xea, 0xc4, 0xa9, 0x14, 0xb9, 0x24, 0x96, 0x71, 0x47, 0xae, 0x78, 0x4d,
0xb7, 0xf6, 0xe6, 0x8f, 0x5e, 0x68, 0xf0, 0xa3, 0x0f, 0x9f, 0x8a, 0xed, 0xd1, 0x58, 0xcd, 0x24,
0xa6, 0x3c, 0x3f, 0xb3, 0x2d, 0x85, 0x39, 0xe6, 0x52, 0xd8, 0x85, 0xa3, 0x74, 0x48, 0x87, 0xd1,
0x6d, 0xb1, 0x6f, 0x77, 0x2a, 0x23, 0x7d, 0xad, 0x7e, 0xb1, 0x7d, 0x7f, 0x6d, 0x52, 0x88, 0x1c,
0xf5, 0x9b, 0x1d, 0x1c, 0x4a, 0x40, 0x8f, 0xc1, 0x08, 0xff, 0x58, 0x59, 0xe6, 0x07, 0x60, 0xa5,
0x30, 0x13, 0x5d, 0xf2, 0x9a, 0xb1, 0xdf, 0xef, 0x93, 0xae, 0xd4, 0x97, 0xf8, 0xc1, 0x6c, 0x82,
0x74, 0xa5, 0xbe, 0x84, 0xfd, 0x7e, 0x64, 0xc1, 0x88, 0x43, 0x56, 0x55, 0xc3, 0xdd, 0xad, 0x40,
0x5f, 0x57, 0xcd, 0x8d, 0xf3, 0x9c, 0x3b, 0x71, 0x14, 0x15, 0x4a, 0x14, 0xfd, 0xd8, 0x17, 0x83,
0x76, 0x61, 0xd4, 0x76, 0x8d, 0x45, 0x67, 0xc3, 0x21, 0x76, 0xa5, 0xcc, 0x65, 0xf6, 0x9a, 0x9c,
0xb1, 0xcf, 0x9f, 0x94, 0x1a, 0x78, 0x30, 0xa0, 0xc0, 0xa1, 0x30, 0xf4, 0x73, 0x09, 0x90, 0xe3,
0x5a, 0x96, 0x46, 0x74, 0x62, 0x50, 0x45, 0xe3, 0xa7, 0x61, 0x4e, 0xe5, 0x18, 0xd7, 0xa1, 0xde,
0xab, 0xdd, 0x29, 0xa0, 0xa4, 0x32, 0xc1, 0x31, 0x75, 0x9a, 0x14, 0x67, 0xe8, 0xc1, 0x86, 0x62,
0xcb, 0xe1, 0xbf, 0x2b, 0x63, 0x7d, 0x0d, 0x45, 0xf6, 0xa9, 0x60, 0x38, 0x14, 0xa2, 0x1f, 0xfb,
0x62, 0xd0, 0x15, 0x98, 0xb1, 0x89, 0xd2, 0xbe, 0x6c, 0x68, 0x5d, 0x6c, 0x9a, 0xf4, 0x82, 0xaa,
0x11, 0xa7, 0xeb, 0x50, 0xa2, 0x57, 0xc6, 0x79, 0xd8, 0x04, 0xcf, 0x35, 0x70, 0x26, 0x15, 0xce,
0xe1, 0x46, 0x2f, 0xc1, 0x71, 0x31, 0x31, 0x79, 0x68, 0xf2, 0x13, 0xb4, 0x09, 0x3e, 0x15, 0xa7,
0xd9, 0x8e, 0x78, 0x31, 0xd1, 0x87, 0x53, 0xd4, 0xfc, 0x1d, 0x82, 0x38, 0x01, 0x1e, 0xcc, 0x4b,
0xbe, 0xc3, 0xbd, 0x43, 0x08, 0x55, 0xbd, 0x67, 0xef, 0x10, 0x22, 0x22, 0x0e, 0x3e, 0x84, 0xfa,
0x62, 0x08, 0xa6, 0x42, 0xe2, 0x3b, 0x7e, 0x87, 0x90, 0xc1, 0x32, 0x80, 0x77, 0x08, 0xd9, 0x17,
0xf9, 0x85, 0x7b, 0x7d, 0x91, 0x7f, 0x0f, 0xde, 0x3f, 0xf0, 0xb7, 0x01, 0xa1, 0x13, 0xff, 0xf7,
0xdf, 0x06, 0x84, 0xba, 0xe6, 0x14, 0x44, 0x7f, 0x18, 0x8a, 0x1a, 0xf4, 0x7f, 0x74, 0x01, 0x7d,
0xf8, 0x77, 0x8e, 0xf2, 0xa7, 0x05, 0x38, 0x9e, 0x9c, 0xb1, 0xb1, 0x7b, 0x48, 0xe9, 0xb6, 0xf7,
0x90, 0x75, 0x98, 0xde, 0x72, 0x35, 0xad, 0xcb, 0x1d, 0x12, 0xb9, 0x8c, 0xf4, 0xce, 0xfd, 0x1f,
0x14, 0x9c, 0xd3, 0x17, 0x32, 0x68, 0x70, 0x26, 0x67, 0xce, 0x9d, 0x6a, 0xa1, 0xaf, 0x3b, 0xd5,
0xd4, 0x95, 0xde, 0x70, 0x0f, 0x57, 0x7a, 0x99, 0xf7, 0xa3, 0xc5, 0x3e, 0xee, 0x47, 0xef, 0xc6,
0x85, 0x66, 0x46, 0xe2, 0xbb, 0xdd, 0x85, 0xa6, 0xfc, 0x20, 0xcc, 0x0a, 0x36, 0xca, 0xef, 0x1a,
0x0d, 0x6a, 0x9b, 0x9a, 0x46, 0xec, 0x65, 0x57, 0xd7, 0xbb, 0xf2, 0x39, 0x18, 0x8f, 0xdf, 0xaa,
0x7b, 0x23, 0xef, 0x5d, 0xf4, 0x8b, 0xdb, 0x98, 0xc8, 0xc8, 0x7b, 0xed, 0x38, 0xa0, 0x90, 0xdf,
0x93, 0x60, 0x26, 0xfb, 0x05, 0x1f, 0xd2, 0x60, 0x5c, 0x57, 0x76, 0xa3, 0x4f, 0x18, 0xa5, 0x3e,
0xf7, 0xec, 0xfc, 0xfa, 0x74, 0x2d, 0x86, 0x85, 0x13, 0xd8, 0xf2, 0x67, 0x12, 0x9c, 0xc8, 0xb9,
0xa8, 0x1c, 0xac, 0x26, 0xe8, 0x2a, 0x94, 0x74, 0x65, 0xb7, 0xe1, 0xda, 0x1d, 0xd2, 0xf7, 0x29,
0x05, 0xcf, 0x25, 0x6b, 0x02, 0x05, 0x07, 0x78, 0xf2, 0x87, 0x12, 0x54, 0xf2, 0x2a, 0x4a, 0x74,
0x26, 0x76, 0xa5, 0xfa, 0x70, 0xe2, 0x4a, 0x75, 0x32, 0xc5, 0x37, 0xa0, 0x0b, 0xd5, 0x8f, 0x24,
0x98, 0xc9, 0xae, 0xbc, 0xd1, 0x53, 0x31, 0x8d, 0xe7, 0x13, 0x1a, 0x4f, 0x24, 0xb8, 0x84, 0xbe,
0xdb, 0x30, 0x2e, 0xea, 0x73, 0x01, 0x23, 0xbc, 0xfc, 0xf8, 0xc1, 0x59, 0x55, 0x80, 0xf9, 0x95,
0x26, 0x1f, 0xc9, 0x78, 0x1b, 0x4e, 0xe0, 0xca, 0xbf, 0x1a, 0x82, 0x62, 0xa3, 0xa5, 0x68, 0x64,
0x00, 0x45, 0xdd, 0xd5, 0x58, 0x51, 0xd7, 0xeb, 0xbf, 0x0c, 0xb8, 0x96, 0xb9, 0xf5, 0xdc, 0x66,
0xa2, 0x9e, 0x3b, 0xdb, 0x17, 0xfa, 0xc1, 0xa5, 0xdc, 0xb3, 0x30, 0x1a, 0x28, 0xd1, 0xdb, 0xea,
0x21, 0x7f, 0x30, 0x04, 0xe5, 0x88, 0x88, 0x1e, 0xd7, 0x9e, 0x9d, 0xd8, 0xea, 0xdd, 0xcf, 0x1f,
0x9a, 0x22, 0xb2, 0xab, 0xfe, 0xfa, 0xed, 0xbd, 0xe0, 0x0b, 0x5f, 0x62, 0xa5, 0x97, 0xf5, 0x73,
0x30, 0x4e, 0xf9, 0xff, 0x7b, 0x82, 0x53, 0xc2, 0x02, 0x8f, 0xe2, 0xe0, 0x5d, 0x68, 0x33, 0xd6,
0x8b, 0x13, 0xd4, 0xb3, 0xcf, 0xc1, 0x58, 0x4c, 0x58, 0x4f, 0x0f, 0xee, 0xfe, 0x28, 0xc1, 0xc3,
0xb7, 0xdd, 0xd5, 0xa1, 0x5a, 0x6c, 0x7a, 0x55, 0x13, 0xd3, 0x6b, 0x2e, 0x1f, 0x60, 0x80, 0xcf,
0x2d, 0x7e, 0x3a, 0x04, 0xa8, 0xb9, 0xad, 0xda, 0xed, 0xba, 0x62, 0xd3, 0x2e, 0x16, 0xff, 0xe2,
0x1a, 0xc0, 0x84, 0x3b, 0x03, 0xe5, 0x36, 0x71, 0x5a, 0xb6, 0xca, 0x9d, 0x25, 0xf6, 0x0a, 0xc1,
0x49, 0xca, 0x72, 0xd8, 0x85, 0xa3, 0x74, 0xa8, 0x03, 0xa5, 0x1d, 0xef, 0x7f, 0x82, 0xfe, 0xdd,
0x5d, 0xaf, 0xc5, 0x6c, 0xf8, 0x4f, 0xc3, 0x30, 0xbe, 0x44, 0x83, 0x83, 0x03, 0x70, 0xf9, 0x7d,
0x09, 0x66, 0xd2, 0x8e, 0x59, 0x66, 0xaa, 0xdf, 0x7b, 0xe7, 0x3c, 0x08, 0xc3, 0x1c, 0x9d, 0x79,
0xe5, 0x98, 0x77, 0x66, 0xce, 0x24, 0x63, 0xde, 0x2a, 0x7f, 0x2e, 0xc1, 0x6c, 0xb6, 0x6a, 0x03,
0xd8, 0x4a, 0x5c, 0x8b, 0x6f, 0x25, 0x7a, 0x3d, 0x78, 0xc8, 0xd6, 0x3b, 0x67, 0x5b, 0xb1, 0x97,
0x39, 0x06, 0x03, 0x30, 0x72, 0x2b, 0x6e, 0xe4, 0xe2, 0xa1, 0x8d, 0xcc, 0x36, 0xb0, 0xf6, 0xd8,
0x8d, 0x9b, 0x73, 0x47, 0x3e, 0xbe, 0x39, 0x77, 0xe4, 0x93, 0x9b, 0x73, 0x47, 0xde, 0xdd, 0x9f,
0x93, 0x6e, 0xec, 0xcf, 0x49, 0x1f, 0xef, 0xcf, 0x49, 0xff, 0xdc, 0x9f, 0x93, 0x7e, 0xfc, 0xd9,
0xdc, 0x91, 0xab, 0x23, 0x02, 0xf3, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x6d, 0x3f, 0x0c, 0xbe,
0x34, 0x3d, 0x00, 0x00,
// 3427 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x5b, 0xcd, 0x6f, 0x1c, 0xc7,
0x95, 0x57, 0x73, 0x38, 0xe4, 0xf0, 0x8d, 0x48, 0x8a, 0x45, 0x9a, 0x1a, 0xd3, 0x36, 0x29, 0xf7,
0x62, 0x6d, 0x79, 0xd7, 0x1e, 0xae, 0xe5, 0x95, 0xd7, 0x96, 0x6d, 0xd9, 0x1c, 0x52, 0x1f, 0x5c,
0x90, 0xd4, 0xb8, 0x66, 0x28, 0xac, 0xe5, 0xaf, 0x6d, 0xce, 0x14, 0x87, 0x2d, 0xf5, 0x97, 0xbb,
0xab, 0x69, 0x0e, 0x8c, 0xdd, 0x35, 0xb0, 0x88, 0x0f, 0x39, 0x04, 0xc9, 0x25, 0x70, 0x80, 0xe4,
0x98, 0x43, 0x2e, 0x89, 0x7d, 0x48, 0x9c, 0xfc, 0x05, 0xd1, 0x21, 0x08, 0x1c, 0x20, 0x01, 0x8c,
0xc0, 0x21, 0x22, 0x1a, 0xf1, 0x3f, 0x10, 0xf8, 0xa2, 0x53, 0x50, 0xd5, 0xd5, 0xdf, 0xdd, 0x94,
0x66, 0x48, 0x0d, 0x02, 0xe4, 0x36, 0x5d, 0xf5, 0xde, 0xef, 0x7d, 0xd4, 0xab, 0x57, 0xaf, 0x3e,
0x06, 0x5e, 0xb9, 0xf5, 0x82, 0x53, 0x55, 0xcd, 0xc5, 0x5b, 0xee, 0x16, 0xb1, 0x0d, 0x42, 0x89,
0xb3, 0x68, 0xdd, 0xea, 0x2c, 0x2a, 0x96, 0xea, 0x2c, 0x92, 0x3d, 0x4a, 0x0c, 0x47, 0x35, 0x0d,
0x67, 0x71, 0xf7, 0xd9, 0x2d, 0x42, 0x95, 0x67, 0x17, 0x3b, 0xc4, 0x20, 0xb6, 0x42, 0x49, 0xbb,
0x6a, 0xd9, 0x26, 0x35, 0xd1, 0x33, 0x1e, 0x7b, 0x35, 0x64, 0xaf, 0x5a, 0xb7, 0x3a, 0x55, 0xc6,
0x5e, 0x0d, 0xd9, 0xab, 0x82, 0x7d, 0xee, 0x99, 0x8e, 0x4a, 0x77, 0xdc, 0xad, 0x6a, 0xcb, 0xd4,
0x17, 0x3b, 0x66, 0xc7, 0x5c, 0xe4, 0x28, 0x5b, 0xee, 0x36, 0xff, 0xe2, 0x1f, 0xfc, 0x97, 0x87,
0x3e, 0xf7, 0xef, 0x42, 0x39, 0xc5, 0x52, 0x75, 0xa5, 0xb5, 0xa3, 0x1a, 0xc4, 0xee, 0xfa, 0xea,
0x2d, 0xda, 0xc4, 0x31, 0x5d, 0xbb, 0x45, 0x92, 0x3a, 0x1d, 0xca, 0xe5, 0x2c, 0xea, 0x84, 0x2a,
0x8b, 0xbb, 0x29, 0x4b, 0xe6, 0x16, 0xf3, 0xb8, 0x6c, 0xd7, 0xa0, 0xaa, 0x9e, 0x16, 0xf3, 0xfc,
0xbd, 0x18, 0x9c, 0xd6, 0x0e, 0xd1, 0x95, 0x14, 0xdf, 0x73, 0x79, 0x7c, 0x2e, 0x55, 0xb5, 0x45,
0xd5, 0xa0, 0x0e, 0xb5, 0x53, 0x4c, 0x4f, 0xe7, 0x0e, 0x53, 0x96, 0x2d, 0x2f, 0x1e, 0x32, 0xa8,
0x96, 0xa9, 0xa9, 0xad, 0x6e, 0xde, 0x80, 0xca, 0x55, 0x80, 0xa5, 0xfa, 0xea, 0x75, 0x62, 0xb3,
0x81, 0x43, 0x67, 0x60, 0xd8, 0x50, 0x74, 0x52, 0x91, 0xce, 0x48, 0x67, 0xc7, 0x6a, 0x27, 0x6f,
0xef, 0x2f, 0x9c, 0x38, 0xd8, 0x5f, 0x18, 0xde, 0x50, 0x74, 0x82, 0x79, 0x8f, 0xfc, 0x03, 0x09,
0x1e, 0x5e, 0x76, 0x1d, 0x6a, 0xea, 0xeb, 0x84, 0xda, 0x6a, 0x6b, 0xd9, 0xb5, 0x6d, 0x62, 0xd0,
0x06, 0x55, 0xa8, 0xeb, 0xdc, 0x9b, 0x1f, 0xdd, 0x80, 0xe2, 0xae, 0xa2, 0xb9, 0xa4, 0x32, 0x74,
0x46, 0x3a, 0x5b, 0x3e, 0x57, 0xad, 0x8a, 0x80, 0x8a, 0x7a, 0xc7, 0x0f, 0xa9, 0xaa, 0x3f, 0xe4,
0xd5, 0xd7, 0x5d, 0xc5, 0xa0, 0x2a, 0xed, 0xd6, 0x66, 0x04, 0xe4, 0x49, 0x21, 0xf7, 0x3a, 0xc3,
0xc2, 0x1e, 0xa4, 0xfc, 0x1d, 0x09, 0x1e, 0xcb, 0xd5, 0x6d, 0x4d, 0x75, 0x28, 0xd2, 0xa1, 0xa8,
0x52, 0xa2, 0x3b, 0x15, 0xe9, 0x4c, 0xe1, 0x6c, 0xf9, 0xdc, 0xd5, 0x6a, 0x4f, 0xe1, 0x5c, 0xcd,
0x05, 0xaf, 0x8d, 0x0b, 0xbd, 0x8a, 0xab, 0x0c, 0x1e, 0x7b, 0x52, 0xe4, 0xef, 0x49, 0x80, 0xa2,
0x3c, 0x4d, 0xc5, 0xee, 0x10, 0x7a, 0x1f, 0x5e, 0x7a, 0xe3, 0x68, 0x5e, 0x9a, 0x16, 0x90, 0x65,
0x4f, 0x60, 0xcc, 0x49, 0x1f, 0x4a, 0x30, 0x9b, 0xd6, 0x89, 0x7b, 0x67, 0x3b, 0xee, 0x9d, 0xa5,
0x23, 0x78, 0xc7, 0x43, 0xcd, 0x71, 0xcb, 0xcf, 0x87, 0x60, 0x6c, 0x45, 0x21, 0xba, 0x69, 0x34,
0x08, 0x45, 0xff, 0x0d, 0x25, 0x36, 0x47, 0xdb, 0x0a, 0x55, 0xb8, 0x47, 0xca, 0xe7, 0xfe, 0xed,
0x30, 0x73, 0x9d, 0x2a, 0xa3, 0xae, 0xee, 0x3e, 0x5b, 0xbd, 0xb6, 0x75, 0x93, 0xb4, 0xe8, 0x3a,
0xa1, 0x4a, 0x0d, 0x09, 0x39, 0x10, 0xb6, 0xe1, 0x00, 0x15, 0xbd, 0x03, 0xc3, 0x8e, 0x45, 0x5a,
0xc2, 0x99, 0x2f, 0xf7, 0x68, 0x56, 0xa0, 0x69, 0xc3, 0x22, 0xad, 0x70, 0xb4, 0xd8, 0x17, 0xe6,
0xb8, 0x68, 0x1b, 0x46, 0x1c, 0x1e, 0x06, 0x95, 0x02, 0x97, 0x70, 0xb1, 0x6f, 0x09, 0x5e, 0x30,
0x4d, 0x08, 0x19, 0x23, 0xde, 0x37, 0x16, 0xe8, 0xf2, 0x6f, 0x24, 0x18, 0x0f, 0x68, 0xf9, 0x88,
0xbd, 0x95, 0xf2, 0x5d, 0xf5, 0xfe, 0x7c, 0xc7, 0xb8, 0xb9, 0xe7, 0x4e, 0x09, 0x59, 0x25, 0xbf,
0x25, 0xe2, 0xb7, 0xb7, 0xfd, 0x78, 0x18, 0xe2, 0xf1, 0xf0, 0x42, 0xbf, 0x66, 0xe5, 0x84, 0xc1,
0xa7, 0xc3, 0x11, 0x73, 0x98, 0x3b, 0xd1, 0xdb, 0x50, 0x72, 0x88, 0x46, 0x5a, 0xd4, 0xb4, 0x85,
0x39, 0xcf, 0xdd, 0xa7, 0x39, 0xca, 0x16, 0xd1, 0x1a, 0x82, 0xb5, 0x76, 0x92, 0xd9, 0xe3, 0x7f,
0xe1, 0x00, 0x12, 0xbd, 0x09, 0x25, 0x4a, 0x74, 0x4b, 0x53, 0xa8, 0x3f, 0xb1, 0x9e, 0xc9, 0x37,
0x89, 0xc1, 0xd6, 0xcd, 0x76, 0x53, 0x30, 0xf0, 0xc1, 0x0f, 0x9c, 0xe5, 0xb7, 0xe2, 0x00, 0x10,
0x7d, 0x24, 0xc1, 0x84, 0x6b, 0xb5, 0x19, 0x29, 0x65, 0x09, 0xb6, 0xd3, 0x15, 0xd1, 0x70, 0xb9,
0x5f, 0xb7, 0x6d, 0xc6, 0xd0, 0x6a, 0xb3, 0x42, 0xf8, 0x44, 0xbc, 0x1d, 0x27, 0xa4, 0xa2, 0x25,
0x98, 0xd4, 0x55, 0x03, 0x13, 0xa5, 0xdd, 0x6d, 0x90, 0x96, 0x69, 0xb4, 0x9d, 0xca, 0xf0, 0x19,
0xe9, 0x6c, 0xb1, 0x76, 0x5a, 0x00, 0x4c, 0xae, 0xc7, 0xbb, 0x71, 0x92, 0x1e, 0xfd, 0x27, 0x20,
0xdf, 0xae, 0x2b, 0xde, 0x7a, 0xa1, 0x9a, 0x46, 0xa5, 0x78, 0x46, 0x3a, 0x5b, 0xa8, 0xcd, 0x09,
0x14, 0xd4, 0x4c, 0x51, 0xe0, 0x0c, 0x2e, 0xb4, 0x06, 0x33, 0x36, 0xd9, 0x55, 0x99, 0x8d, 0x57,
0x55, 0x87, 0x9a, 0x76, 0x77, 0x4d, 0xd5, 0x55, 0x5a, 0x19, 0xe1, 0x3a, 0x55, 0x0e, 0xf6, 0x17,
0x66, 0x70, 0x46, 0x3f, 0xce, 0xe4, 0x92, 0x3f, 0x29, 0xc2, 0x64, 0x62, 0xba, 0xa0, 0xeb, 0x30,
0xdb, 0xf2, 0x92, 0xf1, 0x86, 0xab, 0x6f, 0x11, 0xbb, 0xd1, 0xda, 0x21, 0x6d, 0x57, 0x23, 0x6d,
0x1e, 0x43, 0xc5, 0xda, 0xbc, 0xd0, 0x78, 0x76, 0x39, 0x93, 0x0a, 0xe7, 0x70, 0x33, 0x2f, 0x18,
0xbc, 0x69, 0x5d, 0x75, 0x9c, 0x00, 0x73, 0x88, 0x63, 0x06, 0x5e, 0xd8, 0x48, 0x51, 0xe0, 0x0c,
0x2e, 0xa6, 0x63, 0x9b, 0x38, 0xaa, 0x4d, 0xda, 0x49, 0x1d, 0x0b, 0x71, 0x1d, 0x57, 0x32, 0xa9,
0x70, 0x0e, 0x37, 0x3a, 0x0f, 0x65, 0x4f, 0x1a, 0x1f, 0x3f, 0x31, 0xd0, 0x41, 0xfa, 0xdf, 0x08,
0xbb, 0x70, 0x94, 0x8e, 0x99, 0x66, 0x6e, 0x39, 0xc4, 0xde, 0x25, 0xed, 0xfc, 0x01, 0xbe, 0x96,
0xa2, 0xc0, 0x19, 0x5c, 0xcc, 0x34, 0x2f, 0x02, 0x53, 0xa6, 0x8d, 0xc4, 0x4d, 0xdb, 0xcc, 0xa4,
0xc2, 0x39, 0xdc, 0x2c, 0x8e, 0x3d, 0x95, 0x97, 0x76, 0x15, 0x55, 0x53, 0xb6, 0x34, 0x52, 0x19,
0x8d, 0xc7, 0xf1, 0x46, 0xbc, 0x1b, 0x27, 0xe9, 0xd1, 0x15, 0x98, 0xf2, 0x9a, 0x36, 0x0d, 0x25,
0x00, 0x29, 0x71, 0x90, 0x87, 0x05, 0xc8, 0xd4, 0x46, 0x92, 0x00, 0xa7, 0x79, 0xd0, 0x05, 0x98,
0x68, 0x99, 0x9a, 0xc6, 0xe3, 0x71, 0xd9, 0x74, 0x0d, 0x5a, 0x19, 0xe3, 0xbe, 0x42, 0x6c, 0x3e,
0x2e, 0xc7, 0x7a, 0x70, 0x82, 0x52, 0xfe, 0xa3, 0x04, 0xa7, 0x73, 0xe6, 0x34, 0x7a, 0x15, 0x86,
0x69, 0xd7, 0xf2, 0x2b, 0x81, 0x7f, 0xf5, 0xd7, 0x96, 0x66, 0xd7, 0x22, 0x77, 0xf7, 0x17, 0x1e,
0xc9, 0x61, 0x63, 0xdd, 0x98, 0x33, 0xa2, 0xff, 0x85, 0x71, 0x9b, 0x89, 0x33, 0x3a, 0x1e, 0x89,
0xc8, 0x6b, 0x97, 0x7a, 0xcc, 0x39, 0x38, 0x8a, 0x11, 0xe6, 0xed, 0xa9, 0x83, 0xfd, 0x85, 0xf1,
0x58, 0x1f, 0x8e, 0x8b, 0x93, 0x7f, 0x39, 0x04, 0xb0, 0x42, 0x2c, 0xcd, 0xec, 0xea, 0xc4, 0x18,
0xc4, 0x5a, 0xfe, 0x6e, 0x6c, 0x2d, 0x7f, 0xa5, 0xd7, 0xdc, 0x1a, 0xa8, 0x9a, 0xbb, 0x98, 0x77,
0x12, 0x8b, 0xf9, 0xab, 0xfd, 0x8b, 0x38, 0x7c, 0x35, 0xbf, 0x53, 0x80, 0xe9, 0x90, 0x78, 0xd9,
0x34, 0xda, 0x2a, 0x9f, 0x4f, 0x2f, 0xc5, 0x62, 0xe2, 0xc9, 0x44, 0x4c, 0x9c, 0xce, 0x60, 0x89,
0xc4, 0xc3, 0xf5, 0x40, 0xfb, 0x21, 0xce, 0x7e, 0x31, 0x2e, 0xfc, 0xee, 0xfe, 0xc2, 0xa1, 0x3b,
0x8b, 0x6a, 0x80, 0x19, 0x57, 0x16, 0x3d, 0x01, 0x23, 0x36, 0x51, 0x1c, 0xd3, 0xe0, 0x29, 0x66,
0x2c, 0x34, 0x0a, 0xf3, 0x56, 0x2c, 0x7a, 0xd1, 0x53, 0x30, 0xaa, 0x13, 0xc7, 0x51, 0x3a, 0x84,
0x67, 0x93, 0xb1, 0xda, 0xa4, 0x20, 0x1c, 0x5d, 0xf7, 0x9a, 0xb1, 0xdf, 0x8f, 0x6e, 0xc2, 0x84,
0xa6, 0x38, 0x22, 0xb4, 0x9b, 0xaa, 0x4e, 0x78, 0xbe, 0x28, 0x9f, 0xfb, 0x97, 0xfb, 0x8b, 0x18,
0xc6, 0x11, 0xae, 0x89, 0x6b, 0x31, 0x24, 0x9c, 0x40, 0x46, 0xbb, 0x80, 0x58, 0x4b, 0xd3, 0x56,
0x0c, 0xc7, 0x73, 0x19, 0x93, 0x37, 0xda, 0xb3, 0xbc, 0x20, 0x37, 0xae, 0xa5, 0xd0, 0x70, 0x86,
0x04, 0xf9, 0xb7, 0x12, 0x4c, 0x84, 0x03, 0x36, 0x80, 0x92, 0xed, 0x9d, 0x78, 0xc9, 0xf6, 0x62,
0xdf, 0xc1, 0x9b, 0x53, 0xb3, 0x7d, 0x5c, 0x00, 0x14, 0x12, 0xb1, 0xd4, 0xb0, 0xa5, 0xb4, 0x6e,
0xdd, 0xc7, 0x8e, 0xe6, 0xc7, 0x12, 0x20, 0x91, 0xe8, 0x97, 0x0c, 0xc3, 0xa4, 0x7c, 0xed, 0xf0,
0xd5, 0x7c, 0xa3, 0x6f, 0x35, 0x7d, 0x0d, 0xaa, 0x9b, 0x29, 0xec, 0x4b, 0x06, 0xb5, 0xbb, 0xe1,
0x88, 0xa5, 0x09, 0x70, 0x86, 0x42, 0xe8, 0x3d, 0x00, 0x5b, 0x60, 0x36, 0x4d, 0x91, 0x02, 0x5e,
0xe9, 0x23, 0x9b, 0x32, 0x80, 0x65, 0xd3, 0xd8, 0x56, 0x3b, 0x61, 0x42, 0xc3, 0x01, 0x30, 0x8e,
0x08, 0x99, 0xbb, 0x04, 0xa7, 0x73, 0xb4, 0x47, 0xa7, 0xa0, 0x70, 0x8b, 0x74, 0x3d, 0xb7, 0x62,
0xf6, 0x13, 0xcd, 0x44, 0x77, 0x86, 0x63, 0x62, 0x53, 0x77, 0x61, 0xe8, 0x05, 0x49, 0xfe, 0xba,
0x18, 0x8d, 0x35, 0x5e, 0x4f, 0x9f, 0x85, 0x92, 0x4d, 0x2c, 0x4d, 0x6d, 0x29, 0x8e, 0xa8, 0x85,
0x78, 0x69, 0x8c, 0x45, 0x1b, 0x0e, 0x7a, 0x63, 0x95, 0xf7, 0xd0, 0x83, 0xad, 0xbc, 0x0b, 0xc7,
0x5d, 0x79, 0x9b, 0x50, 0x72, 0xfc, 0x92, 0x7b, 0x98, 0x83, 0x2f, 0x1d, 0x21, 0x67, 0x8b, 0x6a,
0x3b, 0x10, 0x18, 0xd4, 0xd9, 0x81, 0x90, 0xac, 0x0a, 0xbb, 0xd8, 0x63, 0x85, 0x7d, 0xac, 0x55,
0x31, 0xcb, 0xce, 0x96, 0xe2, 0x3a, 0xa4, 0xcd, 0x53, 0x5a, 0x29, 0xcc, 0xce, 0x75, 0xde, 0x8a,
0x45, 0x2f, 0xd2, 0x63, 0xc1, 0x5d, 0x3a, 0x8e, 0xe0, 0x9e, 0xc8, 0x0f, 0x6c, 0xb4, 0x09, 0xa7,
0x2d, 0xdb, 0xec, 0xd8, 0xc4, 0x71, 0x56, 0x88, 0xd2, 0xd6, 0x54, 0x83, 0xf8, 0xfe, 0x1a, 0xe3,
0x76, 0x3e, 0x72, 0xb0, 0xbf, 0x70, 0xba, 0x9e, 0x4d, 0x82, 0xf3, 0x78, 0xe5, 0x2f, 0x86, 0xe1,
0x54, 0x72, 0x95, 0xcd, 0xa9, 0x68, 0xa5, 0xbe, 0x2a, 0xda, 0xa7, 0x23, 0xd3, 0xc6, 0x2b, 0xf7,
0x83, 0x68, 0xc8, 0x98, 0x3a, 0x4b, 0x30, 0x29, 0xf2, 0x88, 0xdf, 0x29, 0x6a, 0xfa, 0x20, 0x1a,
0x36, 0xe3, 0xdd, 0x38, 0x49, 0xcf, 0xea, 0xd4, 0xb0, 0xfc, 0xf4, 0x41, 0x86, 0xe3, 0x75, 0xea,
0x52, 0x92, 0x00, 0xa7, 0x79, 0xd0, 0x3a, 0x4c, 0xbb, 0x46, 0x1a, 0xca, 0x8b, 0xce, 0x47, 0x04,
0xd4, 0xf4, 0x66, 0x9a, 0x04, 0x67, 0xf1, 0xa1, 0x5d, 0x80, 0x96, 0x5f, 0x10, 0x38, 0x95, 0x11,
0x9e, 0xab, 0x6b, 0x7d, 0xcf, 0xad, 0xa0, 0xb6, 0x08, 0x33, 0x62, 0xd0, 0xe4, 0xe0, 0x88, 0x24,
0xf4, 0x12, 0x8c, 0xdb, 0x7c, 0xd3, 0xe2, 0x1b, 0xe0, 0x15, 0xfe, 0x0f, 0x09, 0xb6, 0x71, 0x1c,
0xed, 0xc4, 0x71, 0xda, 0x8c, 0x5a, 0xbd, 0x74, 0xdf, 0xb5, 0xfa, 0xef, 0xa4, 0xe8, 0xf2, 0x16,
0x94, 0xe9, 0x17, 0x62, 0x25, 0xd9, 0x13, 0x89, 0x92, 0x6c, 0x36, 0xcd, 0x11, 0xa9, 0xc8, 0xfe,
0x2f, 0xbb, 0x42, 0xbf, 0x7c, 0xa4, 0x0a, 0x3d, 0x5c, 0xa6, 0xef, 0x5d, 0xa2, 0x7f, 0x2a, 0xc1,
0xec, 0xe5, 0xc6, 0x15, 0xdb, 0x74, 0x2d, 0x5f, 0xbd, 0x6b, 0x96, 0xe7, 0xe7, 0xff, 0x80, 0x61,
0xdb, 0xd5, 0x7c, 0xbb, 0xfe, 0xc9, 0xb7, 0x0b, 0xbb, 0x1a, 0xb3, 0x6b, 0x3a, 0xc1, 0xe5, 0x19,
0xc5, 0x18, 0xd0, 0x3b, 0x30, 0x62, 0x2b, 0x46, 0x87, 0xf8, 0x0b, 0xf8, 0xf3, 0x3d, 0x5a, 0xb3,
0xba, 0x82, 0x19, 0x7b, 0xa4, 0x8c, 0xe4, 0x68, 0x58, 0xa0, 0xca, 0x3f, 0x92, 0x60, 0xf2, 0x6a,
0xb3, 0x59, 0x5f, 0x35, 0x78, 0x06, 0xa8, 0x2b, 0x74, 0x87, 0xd5, 0x18, 0x96, 0x42, 0x77, 0x92,
0x35, 0x06, 0xeb, 0xc3, 0xbc, 0x07, 0xed, 0xc0, 0x28, 0xcb, 0x3c, 0xc4, 0x68, 0xf7, 0xb9, 0x3d,
0x10, 0xe2, 0x6a, 0x1e, 0x48, 0x58, 0xbb, 0x8a, 0x06, 0xec, 0xc3, 0xcb, 0x1f, 0xc0, 0x4c, 0x44,
0x3d, 0xe6, 0x2f, 0x7e, 0xc6, 0x8a, 0x5a, 0x50, 0x64, 0x9a, 0xf8, 0x27, 0xa8, 0xbd, 0x1e, 0x04,
0x26, 0x4c, 0x0e, 0x6b, 0x30, 0xf6, 0xe5, 0x60, 0x0f, 0x5b, 0x5e, 0x87, 0xf1, 0xab, 0xa6, 0x43,
0xeb, 0xa6, 0x4d, 0xb9, 0xdb, 0xd0, 0x63, 0x50, 0xd0, 0x55, 0x43, 0xac, 0xf0, 0x65, 0xc1, 0x53,
0x60, 0x6b, 0x10, 0x6b, 0xe7, 0xdd, 0xca, 0x9e, 0xc8, 0x64, 0x61, 0xb7, 0xb2, 0x87, 0x59, 0xbb,
0x7c, 0x05, 0x46, 0xc5, 0x70, 0x44, 0x81, 0x0a, 0x87, 0x03, 0x15, 0x32, 0x80, 0x7e, 0x36, 0x04,
0xa3, 0x42, 0xfb, 0x01, 0x6c, 0x04, 0xdf, 0x8a, 0x6d, 0x04, 0x2f, 0xf4, 0x37, 0xd2, 0xb9, 0xbb,
0xc0, 0x76, 0x62, 0x17, 0xf8, 0x72, 0x9f, 0xf8, 0x87, 0x6f, 0x01, 0x3f, 0x91, 0x60, 0x22, 0x1e,
0x73, 0xe8, 0x3c, 0x94, 0xd9, 0x7a, 0xa4, 0xb6, 0xc8, 0x46, 0x58, 0x50, 0x07, 0x07, 0x3a, 0x8d,
0xb0, 0x0b, 0x47, 0xe9, 0x50, 0x27, 0x60, 0x63, 0x61, 0x21, 0x9c, 0x92, 0xef, 0x72, 0x97, 0xaa,
0x5a, 0xd5, 0xbb, 0x7a, 0xaa, 0xae, 0x1a, 0xf4, 0x9a, 0xdd, 0xa0, 0xb6, 0x6a, 0x74, 0x52, 0x82,
0x78, 0x8c, 0x45, 0x91, 0xe5, 0xdb, 0x12, 0x94, 0x85, 0xca, 0x03, 0xd8, 0xce, 0xbc, 0x19, 0xdf,
0xce, 0x3c, 0xdf, 0xe7, 0x7c, 0xce, 0xde, 0xcb, 0x7c, 0x16, 0x9a, 0xc2, 0x66, 0x30, 0x4b, 0x30,
0x3b, 0xa6, 0x43, 0x93, 0x09, 0x86, 0xcd, 0x35, 0xcc, 0x7b, 0xd0, 0xb7, 0x24, 0x38, 0xa5, 0x26,
0xe6, 0xbc, 0xf0, 0xf5, 0xab, 0xfd, 0xa9, 0x16, 0xc0, 0xd4, 0x2a, 0x42, 0xde, 0xa9, 0x64, 0x0f,
0x4e, 0x89, 0x94, 0x5d, 0x48, 0x51, 0x21, 0x05, 0x86, 0x77, 0x28, 0xb5, 0xc4, 0x20, 0x2c, 0xf7,
0x9f, 0x79, 0x42, 0x95, 0x4a, 0xdc, 0xfc, 0x66, 0xb3, 0x8e, 0x39, 0xb4, 0xfc, 0xd3, 0xa1, 0xc0,
0x61, 0x0d, 0x6f, 0x92, 0x04, 0xf9, 0x56, 0x3a, 0x8e, 0x7c, 0x5b, 0xce, 0xca, 0xb5, 0xe8, 0xbf,
0xa0, 0x40, 0xb5, 0x7e, 0x37, 0xb4, 0x42, 0x42, 0x73, 0xad, 0x11, 0x26, 0xac, 0xe6, 0x5a, 0x03,
0x33, 0x48, 0xf4, 0x2e, 0x14, 0xd9, 0x6a, 0xc6, 0xe6, 0x78, 0xa1, 0xff, 0x1c, 0xc2, 0xfc, 0x15,
0x46, 0x18, 0xfb, 0x72, 0xb0, 0x87, 0x2b, 0x7f, 0x00, 0xe3, 0xb1, 0x44, 0x80, 0x6e, 0xc2, 0x49,
0xcd, 0x54, 0xda, 0x35, 0x45, 0x53, 0x8c, 0x16, 0xb1, 0x93, 0xa9, 0x31, 0x7b, 0x2f, 0xb4, 0x16,
0xe1, 0x10, 0x09, 0x25, 0xb8, 0x06, 0x8d, 0xf6, 0xe1, 0x18, 0xb6, 0xac, 0x00, 0x84, 0xd6, 0xa3,
0x05, 0x28, 0xb2, 0x10, 0xf6, 0x56, 0xa6, 0xb1, 0xda, 0x18, 0xd3, 0x95, 0x45, 0xb6, 0x83, 0xbd,
0x76, 0x74, 0x0e, 0xc0, 0x21, 0x2d, 0x9b, 0x50, 0x9e, 0x77, 0xbc, 0xd3, 0xa3, 0x20, 0x03, 0x37,
0x82, 0x1e, 0x1c, 0xa1, 0x92, 0xff, 0x20, 0xc1, 0xf8, 0x06, 0xa1, 0xef, 0x9b, 0xf6, 0xad, 0x3a,
0xbf, 0x66, 0x1e, 0x40, 0xde, 0xdf, 0x8a, 0xe5, 0xfd, 0xd7, 0x7a, 0x1c, 0xb3, 0x98, 0xb6, 0x79,
0xd9, 0x5f, 0xfe, 0x8b, 0x04, 0x95, 0x18, 0x65, 0x34, 0x4d, 0x10, 0x28, 0x5a, 0xa6, 0x4d, 0xfd,
0x35, 0xfe, 0x48, 0x1a, 0xb0, 0x94, 0x1a, 0x59, 0xe5, 0x19, 0x2c, 0xf6, 0xd0, 0x99, 0x9d, 0xdb,
0xb6, 0xa9, 0x8b, 0xb8, 0x3f, 0x9a, 0x14, 0x42, 0xec, 0xd0, 0xce, 0xcb, 0xb6, 0xa9, 0x63, 0x8e,
0x2d, 0xff, 0x5e, 0x82, 0xa9, 0x18, 0xe5, 0x00, 0x52, 0xba, 0x12, 0x4f, 0xe9, 0x2f, 0x1f, 0xc5,
0xb0, 0x9c, 0xc4, 0xfe, 0x4d, 0xd2, 0x2c, 0xe6, 0x00, 0xb4, 0x0d, 0x65, 0xcb, 0x6c, 0x37, 0x8e,
0xe1, 0x7e, 0x71, 0x92, 0xad, 0x90, 0xf5, 0x10, 0x0b, 0x47, 0x81, 0xd1, 0x1e, 0x4c, 0x19, 0x8a,
0x4e, 0x1c, 0x4b, 0x69, 0x91, 0xc6, 0x31, 0x9c, 0xa9, 0x3c, 0xc4, 0x6f, 0x29, 0x92, 0x88, 0x38,
0x2d, 0x44, 0xfe, 0x45, 0xca, 0x6e, 0xd3, 0xa6, 0xe8, 0x75, 0x28, 0xf1, 0xa7, 0x1e, 0x2d, 0x53,
0x13, 0x4b, 0xdb, 0x79, 0x36, 0x34, 0x75, 0xd1, 0x76, 0x77, 0x7f, 0xe1, 0x9f, 0x0f, 0x3d, 0x12,
0xf6, 0x09, 0x71, 0x00, 0x83, 0x36, 0x60, 0xd8, 0x3a, 0x4a, 0x99, 0xc1, 0x17, 0x16, 0x5e, 0x5b,
0x70, 0x1c, 0xf9, 0xaf, 0x49, 0xc5, 0xf9, 0xf2, 0x72, 0xf3, 0xd8, 0x06, 0x2c, 0x28, 0x6b, 0x72,
0x07, 0xcd, 0x86, 0x51, 0xb1, 0xca, 0x8a, 0xb8, 0xbc, 0x72, 0x94, 0xb8, 0x8c, 0xae, 0x0c, 0xc1,
0x26, 0xc2, 0x6f, 0xf4, 0x05, 0xc9, 0x7f, 0x92, 0x60, 0x8a, 0x2b, 0xd4, 0x72, 0x6d, 0x95, 0x76,
0x07, 0x96, 0x41, 0xb7, 0x63, 0x19, 0x74, 0xa5, 0x47, 0x43, 0x53, 0x1a, 0xe7, 0x66, 0xd1, 0x2f,
0x25, 0x78, 0x28, 0x45, 0x3d, 0x80, 0x0c, 0x43, 0xe2, 0x19, 0xe6, 0xb5, 0xa3, 0x1a, 0x98, 0x93,
0x65, 0xbe, 0x5d, 0xce, 0x30, 0x8f, 0x07, 0xee, 0x39, 0x00, 0xcb, 0x56, 0x77, 0x55, 0x8d, 0x74,
0xc4, 0x25, 0x74, 0x29, 0x1c, 0x92, 0x7a, 0xd0, 0x83, 0x23, 0x54, 0xe8, 0x7f, 0x60, 0xb6, 0x4d,
0xb6, 0x15, 0x57, 0xa3, 0x4b, 0xed, 0xf6, 0xb2, 0x62, 0x29, 0x5b, 0xaa, 0xa6, 0x52, 0x55, 0xec,
0xb0, 0xc7, 0x6a, 0x97, 0xbc, 0xcb, 0xe1, 0x2c, 0x8a, 0xbb, 0xfb, 0x0b, 0x4f, 0x1e, 0x7e, 0xa9,
0xe3, 0x13, 0x77, 0x71, 0x8e, 0x10, 0xf4, 0xff, 0x12, 0x54, 0x6c, 0xf2, 0x9e, 0xab, 0xda, 0xa4,
0xbd, 0x62, 0x9b, 0x56, 0x4c, 0x83, 0x02, 0xd7, 0xe0, 0xca, 0xc1, 0xfe, 0x42, 0x05, 0xe7, 0xd0,
0xf4, 0xa2, 0x43, 0xae, 0x20, 0x44, 0x61, 0x5a, 0xd1, 0x34, 0xf3, 0x7d, 0x12, 0xf7, 0xc0, 0x30,
0x97, 0x5f, 0x3b, 0xd8, 0x5f, 0x98, 0x5e, 0x4a, 0x77, 0xf7, 0x22, 0x3a, 0x0b, 0x1e, 0x2d, 0xc2,
0xe8, 0xae, 0xa9, 0xb9, 0x3a, 0x71, 0x2a, 0x45, 0x2e, 0x89, 0x65, 0xdc, 0xd1, 0xeb, 0x5e, 0xd3,
0xdd, 0xfd, 0x85, 0x91, 0xcb, 0x0d, 0x7e, 0xf4, 0xe1, 0x53, 0xb1, 0x3d, 0x1a, 0xab, 0x99, 0xc4,
0x94, 0xe7, 0x67, 0xb6, 0xa5, 0x30, 0xc7, 0x5c, 0x0d, 0xbb, 0x70, 0x94, 0x0e, 0xe9, 0x30, 0xb6,
0x23, 0xf6, 0xed, 0x4e, 0x65, 0xb4, 0xaf, 0xd5, 0x2f, 0xb6, 0xef, 0xaf, 0x4d, 0x09, 0x91, 0x63,
0x7e, 0xb3, 0x83, 0x43, 0x09, 0xe8, 0x29, 0x18, 0xe5, 0x1f, 0xab, 0x2b, 0xfc, 0x00, 0xac, 0x14,
0x66, 0xa2, 0xab, 0x5e, 0x33, 0xf6, 0xfb, 0x7d, 0xd2, 0xd5, 0xfa, 0x32, 0x3f, 0x98, 0x4d, 0x90,
0xae, 0xd6, 0x97, 0xb1, 0xdf, 0x8f, 0x2c, 0x18, 0x75, 0xc8, 0x9a, 0x6a, 0xb8, 0x7b, 0x15, 0xe8,
0xeb, 0xaa, 0xb9, 0x71, 0x89, 0x73, 0x27, 0x8e, 0xa2, 0x42, 0x89, 0xa2, 0x1f, 0xfb, 0x62, 0xd0,
0x1e, 0x8c, 0xd9, 0xae, 0xb1, 0xe4, 0x6c, 0x3a, 0xc4, 0xae, 0x94, 0xb9, 0xcc, 0x5e, 0x93, 0x33,
0xf6, 0xf9, 0x93, 0x52, 0x03, 0x0f, 0x06, 0x14, 0x38, 0x14, 0x86, 0x7e, 0x28, 0x01, 0x72, 0x5c,
0xcb, 0xd2, 0x88, 0x4e, 0x0c, 0xaa, 0x68, 0xfc, 0x34, 0xcc, 0xa9, 0x9c, 0xe4, 0x3a, 0xd4, 0x7b,
0xb5, 0x3b, 0x05, 0x94, 0x54, 0x26, 0x38, 0xa6, 0x4e, 0x93, 0xe2, 0x0c, 0x3d, 0xd8, 0x50, 0x6c,
0x3b, 0xfc, 0x77, 0x65, 0xbc, 0xaf, 0xa1, 0xc8, 0x3e, 0x15, 0x0c, 0x87, 0x42, 0xf4, 0x63, 0x5f,
0x0c, 0xba, 0x0e, 0xb3, 0x36, 0x51, 0xda, 0xd7, 0x0c, 0xad, 0x8b, 0x4d, 0x93, 0x5e, 0x56, 0x35,
0xe2, 0x74, 0x1d, 0x4a, 0xf4, 0xca, 0x04, 0x0f, 0x9b, 0xe0, 0xa9, 0x07, 0xce, 0xa4, 0xc2, 0x39,
0xdc, 0xe8, 0x35, 0x38, 0x25, 0x26, 0x26, 0x0f, 0x4d, 0x7e, 0x82, 0x36, 0xc9, 0xa7, 0xe2, 0x0c,
0xdb, 0x11, 0x2f, 0x25, 0xfa, 0x70, 0x8a, 0x9a, 0xbf, 0x43, 0x10, 0x27, 0xc0, 0x83, 0x79, 0x53,
0x78, 0xb4, 0x77, 0x08, 0xa1, 0xaa, 0x0f, 0xec, 0x1d, 0x42, 0x44, 0xc4, 0xe1, 0x87, 0x50, 0xdf,
0x0c, 0xc1, 0x74, 0x48, 0x7c, 0xdf, 0xef, 0x10, 0x32, 0x58, 0x06, 0xf0, 0x0e, 0x21, 0xfb, 0x22,
0xbf, 0xf0, 0xa0, 0x2f, 0xf2, 0x1f, 0xc0, 0xfb, 0x07, 0xfe, 0x36, 0x20, 0x74, 0xe2, 0xdf, 0xff,
0xdb, 0x80, 0x50, 0xd7, 0x9c, 0x82, 0xe8, 0x57, 0x43, 0x51, 0x83, 0xfe, 0x81, 0x2e, 0xa0, 0x8f,
0xfe, 0xe2, 0x52, 0xfe, 0xb2, 0x00, 0xa7, 0x92, 0x33, 0x36, 0x76, 0x0f, 0x29, 0xdd, 0xf3, 0x1e,
0xb2, 0x0e, 0x33, 0xdb, 0xae, 0xa6, 0x75, 0xb9, 0x43, 0x22, 0x97, 0x91, 0xde, 0xb9, 0xff, 0xa3,
0x82, 0x73, 0xe6, 0x72, 0x06, 0x0d, 0xce, 0xe4, 0xcc, 0xb9, 0x53, 0x2d, 0xf4, 0x75, 0xa7, 0x9a,
0xba, 0xd2, 0x1b, 0xee, 0xe1, 0x4a, 0x2f, 0xf3, 0x7e, 0xb4, 0xd8, 0xc7, 0xfd, 0xe8, 0x71, 0x5c,
0x68, 0x66, 0x24, 0xbe, 0x7b, 0x5d, 0x68, 0xca, 0x8f, 0xc2, 0x9c, 0x60, 0xa3, 0xfc, 0xae, 0xd1,
0xa0, 0xb6, 0xa9, 0x69, 0xc4, 0x5e, 0x71, 0x75, 0xbd, 0x2b, 0x5f, 0x84, 0x89, 0xf8, 0xad, 0xba,
0x37, 0xf2, 0xde, 0x45, 0xbf, 0xb8, 0x8d, 0x89, 0x8c, 0xbc, 0xd7, 0x8e, 0x03, 0x0a, 0xf9, 0x23,
0x09, 0x66, 0xb3, 0x5f, 0xf0, 0x21, 0x0d, 0x26, 0x74, 0x65, 0x2f, 0xfa, 0xfc, 0x51, 0xea, 0x73,
0xcf, 0xce, 0xaf, 0x4f, 0xd7, 0x63, 0x58, 0x38, 0x81, 0x2d, 0x7f, 0x25, 0xc1, 0xe9, 0x9c, 0x8b,
0xca, 0xc1, 0x6a, 0x82, 0x6e, 0x40, 0x49, 0x57, 0xf6, 0x1a, 0xae, 0xdd, 0x21, 0x7d, 0x9f, 0x52,
0xf0, 0x5c, 0xb2, 0x2e, 0x50, 0x70, 0x80, 0x27, 0x7f, 0x2a, 0x41, 0x25, 0xaf, 0xa2, 0x44, 0xe7,
0x63, 0x57, 0xaa, 0x8f, 0x27, 0xae, 0x54, 0xa7, 0x52, 0x7c, 0x03, 0xba, 0x50, 0xfd, 0x4c, 0x82,
0xd9, 0xec, 0xca, 0x1b, 0x3d, 0x17, 0xd3, 0x78, 0x21, 0xa1, 0xf1, 0x64, 0x82, 0x4b, 0xe8, 0xbb,
0x03, 0x13, 0xa2, 0x3e, 0x17, 0x30, 0xc2, 0xcb, 0x4f, 0x1f, 0x9e, 0x55, 0x05, 0x98, 0x5f, 0x69,
0xf2, 0x91, 0x8c, 0xb7, 0xe1, 0x04, 0xae, 0xfc, 0x93, 0x21, 0x28, 0x36, 0x5a, 0x8a, 0x46, 0x06,
0x50, 0xd4, 0xdd, 0x88, 0x15, 0x75, 0xbd, 0xfe, 0xdf, 0x81, 0x6b, 0x99, 0x5b, 0xcf, 0x6d, 0x25,
0xea, 0xb9, 0x0b, 0x7d, 0xa1, 0x1f, 0x5e, 0xca, 0xbd, 0x08, 0x63, 0x81, 0x12, 0xbd, 0xad, 0x1e,
0xf2, 0x27, 0x43, 0x50, 0x8e, 0x88, 0xe8, 0x71, 0xed, 0xd9, 0x8d, 0xad, 0xde, 0xfd, 0xfc, 0xb5,
0x2a, 0x22, 0xbb, 0xea, 0xaf, 0xdf, 0xde, 0x0b, 0xbe, 0xf0, 0x25, 0x56, 0x7a, 0x59, 0xbf, 0x08,
0x13, 0x94, 0xff, 0xd3, 0x28, 0x38, 0x25, 0x2c, 0xf0, 0x28, 0x0e, 0xde, 0x85, 0x36, 0x63, 0xbd,
0x38, 0x41, 0x3d, 0xf7, 0x12, 0x8c, 0xc7, 0x84, 0xf5, 0xf4, 0xe0, 0xee, 0xd7, 0x12, 0x3c, 0x7e,
0xcf, 0x5d, 0x1d, 0xaa, 0xc5, 0xa6, 0x57, 0x35, 0x31, 0xbd, 0xe6, 0xf3, 0x01, 0x06, 0xf8, 0xdc,
0xe2, 0xfb, 0x43, 0x80, 0x9a, 0x3b, 0xaa, 0xdd, 0xae, 0x2b, 0x36, 0xed, 0x62, 0xf1, 0x7f, 0xb2,
0x01, 0x4c, 0xb8, 0xf3, 0x50, 0x6e, 0x13, 0xa7, 0x65, 0xab, 0xdc, 0x59, 0x62, 0xaf, 0x10, 0x9c,
0xa4, 0xac, 0x84, 0x5d, 0x38, 0x4a, 0x87, 0x3a, 0x50, 0xda, 0xf5, 0xfe, 0xb1, 0xe8, 0xdf, 0xdd,
0xf5, 0x5a, 0xcc, 0x86, 0xff, 0x79, 0x0c, 0xe3, 0x4b, 0x34, 0x38, 0x38, 0x00, 0x97, 0x3f, 0x96,
0x60, 0x36, 0xed, 0x98, 0x15, 0xa6, 0xfa, 0x83, 0x77, 0xce, 0xa3, 0x30, 0xcc, 0xd1, 0x99, 0x57,
0x4e, 0x7a, 0x67, 0xe6, 0x4c, 0x32, 0xe6, 0xad, 0xf2, 0xd7, 0x12, 0xcc, 0x65, 0xab, 0x36, 0x80,
0xad, 0xc4, 0xcd, 0xf8, 0x56, 0xa2, 0xd7, 0x83, 0x87, 0x6c, 0xbd, 0x73, 0xb6, 0x15, 0xfb, 0x99,
0x63, 0x30, 0x00, 0x23, 0xb7, 0xe3, 0x46, 0x2e, 0x1d, 0xd9, 0xc8, 0x6c, 0x03, 0x6b, 0x4f, 0xdd,
0xbe, 0x33, 0x7f, 0xe2, 0xf3, 0x3b, 0xf3, 0x27, 0xbe, 0xb8, 0x33, 0x7f, 0xe2, 0xc3, 0x83, 0x79,
0xe9, 0xf6, 0xc1, 0xbc, 0xf4, 0xf9, 0xc1, 0xbc, 0xf4, 0xe7, 0x83, 0x79, 0xe9, 0xbb, 0x5f, 0xcd,
0x9f, 0xb8, 0x31, 0x2a, 0x30, 0xff, 0x16, 0x00, 0x00, 0xff, 0xff, 0x9e, 0x01, 0x30, 0x7b, 0xbe,
0x3d, 0x00, 0x00,
}

View File

@@ -123,10 +123,17 @@ message DaemonSetSpec {
// +optional
optional int32 minReadySeconds = 4;
// DEPRECATED.
// A sequence number representing a specific generation of the template.
// Populated by the system. It can be set only during the creation.
// +optional
optional int64 templateGeneration = 5;
// The number of old history to retain to allow rollback.
// This is a pointer to distinguish between explicit zero and not specified.
// Defaults to 10.
// +optional
optional int32 revisionHistoryLimit = 6;
}
// DaemonSetStatus represents the current status of a daemon set.
@@ -169,6 +176,12 @@ message DaemonSetStatus {
// (ready for at least spec.minReadySeconds)
// +optional
optional int32 numberUnavailable = 8;
// Count of hash collisions for the DaemonSet. The DaemonSet controller
// uses this field as a collision avoidance mechanism when it needs to
// create the name for the newest ControllerRevision.
// +optional
optional int64 collisionCount = 9;
}
message DaemonSetUpdateStrategy {
@@ -180,7 +193,7 @@ message DaemonSetUpdateStrategy {
// Rolling update config params. Present only if type = "RollingUpdate".
// ---
// TODO: Update this to follow our convention for oneOf, whatever we decide it
// to be. Same as DeploymentStrategy.RollingUpdate.
// to be. Same as Deployment `strategy.rollingUpdate`.
// See https://github.com/kubernetes/kubernetes/issues/35345
// +optional
optional RollingUpdateDaemonSet rollingUpdate = 2;

View File

@@ -7552,16 +7552,17 @@ func (x *DaemonSetSpec) CodecEncodeSelf(e *codec1978.Encoder) {
} else {
yysep2 := !z.EncBinary()
yy2arr2 := z.EncBasicHandle().StructToArray
var yyq2 [5]bool
var yyq2 [6]bool
_, _, _ = yysep2, yyq2, yy2arr2
const yyr2 bool = false
yyq2[0] = x.Selector != nil
yyq2[2] = true
yyq2[3] = x.MinReadySeconds != 0
yyq2[4] = x.TemplateGeneration != 0
yyq2[5] = x.RevisionHistoryLimit != nil
var yynn2 int
if yyr2 || yy2arr2 {
r.EncodeArrayStart(5)
r.EncodeArrayStart(6)
} else {
yynn2 = 1
for _, b := range yyq2 {
@@ -7685,6 +7686,41 @@ func (x *DaemonSetSpec) CodecEncodeSelf(e *codec1978.Encoder) {
}
}
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
if yyq2[5] {
if x.RevisionHistoryLimit == nil {
r.EncodeNil()
} else {
yy23 := *x.RevisionHistoryLimit
yym24 := z.EncBinary()
_ = yym24
if false {
} else {
r.EncodeInt(int64(yy23))
}
}
} else {
r.EncodeNil()
}
} else {
if yyq2[5] {
z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("revisionHistoryLimit"))
z.EncSendContainerState(codecSelfer_containerMapValue1234)
if x.RevisionHistoryLimit == nil {
r.EncodeNil()
} else {
yy25 := *x.RevisionHistoryLimit
yym26 := z.EncBinary()
_ = yym26
if false {
} else {
r.EncodeInt(int64(yy25))
}
}
}
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
} else {
@@ -7801,6 +7837,22 @@ func (x *DaemonSetSpec) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
*((*int64)(yyv10)) = int64(r.DecodeInt(64))
}
}
case "revisionHistoryLimit":
if r.TryDecodeAsNil() {
if x.RevisionHistoryLimit != nil {
x.RevisionHistoryLimit = nil
}
} else {
if x.RevisionHistoryLimit == nil {
x.RevisionHistoryLimit = new(int32)
}
yym13 := z.DecBinary()
_ = yym13
if false {
} else {
*((*int32)(x.RevisionHistoryLimit)) = int32(r.DecodeInt(32))
}
}
default:
z.DecStructFieldNotFound(-1, yys3)
} // end switch yys3
@@ -7812,16 +7864,16 @@ func (x *DaemonSetSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r
var yyj12 int
var yyb12 bool
var yyhl12 bool = l >= 0
yyj12++
if yyhl12 {
yyb12 = yyj12 > l
var yyj14 int
var yyb14 bool
var yyhl14 bool = l >= 0
yyj14++
if yyhl14 {
yyb14 = yyj14 > l
} else {
yyb12 = r.CheckBreak()
yyb14 = r.CheckBreak()
}
if yyb12 {
if yyb14 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
@@ -7834,21 +7886,21 @@ func (x *DaemonSetSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
if x.Selector == nil {
x.Selector = new(pkg1_v1.LabelSelector)
}
yym14 := z.DecBinary()
_ = yym14
yym16 := z.DecBinary()
_ = yym16
if false {
} else if z.HasExtensions() && z.DecExt(x.Selector) {
} else {
z.DecFallback(x.Selector, false)
}
}
yyj12++
if yyhl12 {
yyb12 = yyj12 > l
yyj14++
if yyhl14 {
yyb14 = yyj14 > l
} else {
yyb12 = r.CheckBreak()
yyb14 = r.CheckBreak()
}
if yyb12 {
if yyb14 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
@@ -7856,16 +7908,16 @@ func (x *DaemonSetSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
if r.TryDecodeAsNil() {
x.Template = pkg4_v1.PodTemplateSpec{}
} else {
yyv15 := &x.Template
yyv15.CodecDecodeSelf(d)
yyv17 := &x.Template
yyv17.CodecDecodeSelf(d)
}
yyj12++
if yyhl12 {
yyb12 = yyj12 > l
yyj14++
if yyhl14 {
yyb14 = yyj14 > l
} else {
yyb12 = r.CheckBreak()
yyb14 = r.CheckBreak()
}
if yyb12 {
if yyb14 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
@@ -7873,16 +7925,16 @@ func (x *DaemonSetSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
if r.TryDecodeAsNil() {
x.UpdateStrategy = DaemonSetUpdateStrategy{}
} else {
yyv16 := &x.UpdateStrategy
yyv16.CodecDecodeSelf(d)
yyv18 := &x.UpdateStrategy
yyv18.CodecDecodeSelf(d)
}
yyj12++
if yyhl12 {
yyb12 = yyj12 > l
yyj14++
if yyhl14 {
yyb14 = yyj14 > l
} else {
yyb12 = r.CheckBreak()
yyb14 = r.CheckBreak()
}
if yyb12 {
if yyb14 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
@@ -7890,21 +7942,21 @@ func (x *DaemonSetSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
if r.TryDecodeAsNil() {
x.MinReadySeconds = 0
} else {
yyv17 := &x.MinReadySeconds
yym18 := z.DecBinary()
_ = yym18
yyv19 := &x.MinReadySeconds
yym20 := z.DecBinary()
_ = yym20
if false {
} else {
*((*int32)(yyv17)) = int32(r.DecodeInt(32))
*((*int32)(yyv19)) = int32(r.DecodeInt(32))
}
}
yyj12++
if yyhl12 {
yyb12 = yyj12 > l
yyj14++
if yyhl14 {
yyb14 = yyj14 > l
} else {
yyb12 = r.CheckBreak()
yyb14 = r.CheckBreak()
}
if yyb12 {
if yyb14 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
@@ -7912,26 +7964,52 @@ func (x *DaemonSetSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
if r.TryDecodeAsNil() {
x.TemplateGeneration = 0
} else {
yyv19 := &x.TemplateGeneration
yym20 := z.DecBinary()
_ = yym20
yyv21 := &x.TemplateGeneration
yym22 := z.DecBinary()
_ = yym22
if false {
} else {
*((*int64)(yyv19)) = int64(r.DecodeInt(64))
*((*int64)(yyv21)) = int64(r.DecodeInt(64))
}
}
yyj14++
if yyhl14 {
yyb14 = yyj14 > l
} else {
yyb14 = r.CheckBreak()
}
if yyb14 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
if x.RevisionHistoryLimit != nil {
x.RevisionHistoryLimit = nil
}
} else {
if x.RevisionHistoryLimit == nil {
x.RevisionHistoryLimit = new(int32)
}
yym24 := z.DecBinary()
_ = yym24
if false {
} else {
*((*int32)(x.RevisionHistoryLimit)) = int32(r.DecodeInt(32))
}
}
for {
yyj12++
if yyhl12 {
yyb12 = yyj12 > l
yyj14++
if yyhl14 {
yyb14 = yyj14 > l
} else {
yyb12 = r.CheckBreak()
yyb14 = r.CheckBreak()
}
if yyb12 {
if yyb14 {
break
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
z.DecStructFieldNotFound(yyj12-1, "")
z.DecStructFieldNotFound(yyj14-1, "")
}
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
}
@@ -7950,16 +8028,17 @@ func (x *DaemonSetStatus) CodecEncodeSelf(e *codec1978.Encoder) {
} else {
yysep2 := !z.EncBinary()
yy2arr2 := z.EncBasicHandle().StructToArray
var yyq2 [8]bool
var yyq2 [9]bool
_, _, _ = yysep2, yyq2, yy2arr2
const yyr2 bool = false
yyq2[4] = x.ObservedGeneration != 0
yyq2[5] = x.UpdatedNumberScheduled != 0
yyq2[6] = x.NumberAvailable != 0
yyq2[7] = x.NumberUnavailable != 0
yyq2[8] = x.CollisionCount != nil
var yynn2 int
if yyr2 || yy2arr2 {
r.EncodeArrayStart(8)
r.EncodeArrayStart(9)
} else {
yynn2 = 4
for _, b := range yyq2 {
@@ -8146,6 +8225,41 @@ func (x *DaemonSetStatus) CodecEncodeSelf(e *codec1978.Encoder) {
}
}
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
if yyq2[8] {
if x.CollisionCount == nil {
r.EncodeNil()
} else {
yy28 := *x.CollisionCount
yym29 := z.EncBinary()
_ = yym29
if false {
} else {
r.EncodeInt(int64(yy28))
}
}
} else {
r.EncodeNil()
}
} else {
if yyq2[8] {
z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("collisionCount"))
z.EncSendContainerState(codecSelfer_containerMapValue1234)
if x.CollisionCount == nil {
r.EncodeNil()
} else {
yy30 := *x.CollisionCount
yym31 := z.EncBinary()
_ = yym31
if false {
} else {
r.EncodeInt(int64(yy30))
}
}
}
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
} else {
@@ -8303,6 +8417,22 @@ func (x *DaemonSetStatus) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
*((*int32)(yyv18)) = int32(r.DecodeInt(32))
}
}
case "collisionCount":
if r.TryDecodeAsNil() {
if x.CollisionCount != nil {
x.CollisionCount = nil
}
} else {
if x.CollisionCount == nil {
x.CollisionCount = new(int64)
}
yym21 := z.DecBinary()
_ = yym21
if false {
} else {
*((*int64)(x.CollisionCount)) = int64(r.DecodeInt(64))
}
}
default:
z.DecStructFieldNotFound(-1, yys3)
} // end switch yys3
@@ -8314,16 +8444,16 @@ func (x *DaemonSetStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r
var yyj20 int
var yyb20 bool
var yyhl20 bool = l >= 0
yyj20++
if yyhl20 {
yyb20 = yyj20 > l
var yyj22 int
var yyb22 bool
var yyhl22 bool = l >= 0
yyj22++
if yyhl22 {
yyb22 = yyj22 > l
} else {
yyb20 = r.CheckBreak()
yyb22 = r.CheckBreak()
}
if yyb20 {
if yyb22 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
@@ -8331,29 +8461,7 @@ func (x *DaemonSetStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
if r.TryDecodeAsNil() {
x.CurrentNumberScheduled = 0
} else {
yyv21 := &x.CurrentNumberScheduled
yym22 := z.DecBinary()
_ = yym22
if false {
} else {
*((*int32)(yyv21)) = int32(r.DecodeInt(32))
}
}
yyj20++
if yyhl20 {
yyb20 = yyj20 > l
} else {
yyb20 = r.CheckBreak()
}
if yyb20 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.NumberMisscheduled = 0
} else {
yyv23 := &x.NumberMisscheduled
yyv23 := &x.CurrentNumberScheduled
yym24 := z.DecBinary()
_ = yym24
if false {
@@ -8361,21 +8469,21 @@ func (x *DaemonSetStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
*((*int32)(yyv23)) = int32(r.DecodeInt(32))
}
}
yyj20++
if yyhl20 {
yyb20 = yyj20 > l
yyj22++
if yyhl22 {
yyb22 = yyj22 > l
} else {
yyb20 = r.CheckBreak()
yyb22 = r.CheckBreak()
}
if yyb20 {
if yyb22 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.DesiredNumberScheduled = 0
x.NumberMisscheduled = 0
} else {
yyv25 := &x.DesiredNumberScheduled
yyv25 := &x.NumberMisscheduled
yym26 := z.DecBinary()
_ = yym26
if false {
@@ -8383,21 +8491,21 @@ func (x *DaemonSetStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
*((*int32)(yyv25)) = int32(r.DecodeInt(32))
}
}
yyj20++
if yyhl20 {
yyb20 = yyj20 > l
yyj22++
if yyhl22 {
yyb22 = yyj22 > l
} else {
yyb20 = r.CheckBreak()
yyb22 = r.CheckBreak()
}
if yyb20 {
if yyb22 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.NumberReady = 0
x.DesiredNumberScheduled = 0
} else {
yyv27 := &x.NumberReady
yyv27 := &x.DesiredNumberScheduled
yym28 := z.DecBinary()
_ = yym28
if false {
@@ -8405,13 +8513,35 @@ func (x *DaemonSetStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
*((*int32)(yyv27)) = int32(r.DecodeInt(32))
}
}
yyj20++
if yyhl20 {
yyb20 = yyj20 > l
yyj22++
if yyhl22 {
yyb22 = yyj22 > l
} else {
yyb20 = r.CheckBreak()
yyb22 = r.CheckBreak()
}
if yyb20 {
if yyb22 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.NumberReady = 0
} else {
yyv29 := &x.NumberReady
yym30 := z.DecBinary()
_ = yym30
if false {
} else {
*((*int32)(yyv29)) = int32(r.DecodeInt(32))
}
}
yyj22++
if yyhl22 {
yyb22 = yyj22 > l
} else {
yyb22 = r.CheckBreak()
}
if yyb22 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
@@ -8419,21 +8549,21 @@ func (x *DaemonSetStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
if r.TryDecodeAsNil() {
x.ObservedGeneration = 0
} else {
yyv29 := &x.ObservedGeneration
yym30 := z.DecBinary()
_ = yym30
yyv31 := &x.ObservedGeneration
yym32 := z.DecBinary()
_ = yym32
if false {
} else {
*((*int64)(yyv29)) = int64(r.DecodeInt(64))
*((*int64)(yyv31)) = int64(r.DecodeInt(64))
}
}
yyj20++
if yyhl20 {
yyb20 = yyj20 > l
yyj22++
if yyhl22 {
yyb22 = yyj22 > l
} else {
yyb20 = r.CheckBreak()
yyb22 = r.CheckBreak()
}
if yyb20 {
if yyb22 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
@@ -8441,29 +8571,7 @@ func (x *DaemonSetStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
if r.TryDecodeAsNil() {
x.UpdatedNumberScheduled = 0
} else {
yyv31 := &x.UpdatedNumberScheduled
yym32 := z.DecBinary()
_ = yym32
if false {
} else {
*((*int32)(yyv31)) = int32(r.DecodeInt(32))
}
}
yyj20++
if yyhl20 {
yyb20 = yyj20 > l
} else {
yyb20 = r.CheckBreak()
}
if yyb20 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.NumberAvailable = 0
} else {
yyv33 := &x.NumberAvailable
yyv33 := &x.UpdatedNumberScheduled
yym34 := z.DecBinary()
_ = yym34
if false {
@@ -8471,21 +8579,21 @@ func (x *DaemonSetStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
*((*int32)(yyv33)) = int32(r.DecodeInt(32))
}
}
yyj20++
if yyhl20 {
yyb20 = yyj20 > l
yyj22++
if yyhl22 {
yyb22 = yyj22 > l
} else {
yyb20 = r.CheckBreak()
yyb22 = r.CheckBreak()
}
if yyb20 {
if yyb22 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.NumberUnavailable = 0
x.NumberAvailable = 0
} else {
yyv35 := &x.NumberUnavailable
yyv35 := &x.NumberAvailable
yym36 := z.DecBinary()
_ = yym36
if false {
@@ -8493,18 +8601,66 @@ func (x *DaemonSetStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
*((*int32)(yyv35)) = int32(r.DecodeInt(32))
}
}
for {
yyj20++
if yyhl20 {
yyb20 = yyj20 > l
yyj22++
if yyhl22 {
yyb22 = yyj22 > l
} else {
yyb20 = r.CheckBreak()
yyb22 = r.CheckBreak()
}
if yyb20 {
if yyb22 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.NumberUnavailable = 0
} else {
yyv37 := &x.NumberUnavailable
yym38 := z.DecBinary()
_ = yym38
if false {
} else {
*((*int32)(yyv37)) = int32(r.DecodeInt(32))
}
}
yyj22++
if yyhl22 {
yyb22 = yyj22 > l
} else {
yyb22 = r.CheckBreak()
}
if yyb22 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
if x.CollisionCount != nil {
x.CollisionCount = nil
}
} else {
if x.CollisionCount == nil {
x.CollisionCount = new(int64)
}
yym40 := z.DecBinary()
_ = yym40
if false {
} else {
*((*int64)(x.CollisionCount)) = int64(r.DecodeInt(64))
}
}
for {
yyj22++
if yyhl22 {
yyb22 = yyj22 > l
} else {
yyb22 = r.CheckBreak()
}
if yyb22 {
break
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
z.DecStructFieldNotFound(yyj20-1, "")
z.DecStructFieldNotFound(yyj22-1, "")
}
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
}
@@ -19917,7 +20073,7 @@ func (x codecSelfer1234) decSliceDaemonSet(v *[]DaemonSet, d *codec1978.Decoder)
yyrg1 := len(yyv1) > 0
yyv21 := yyv1
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 912)
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 928)
if yyrt1 {
if yyrl1 <= cap(yyv1) {
yyv1 = yyv1[:yyrl1]

View File

@@ -386,7 +386,7 @@ type DaemonSetUpdateStrategy struct {
// Rolling update config params. Present only if type = "RollingUpdate".
//---
// TODO: Update this to follow our convention for oneOf, whatever we decide it
// to be. Same as DeploymentStrategy.RollingUpdate.
// to be. Same as Deployment `strategy.rollingUpdate`.
// See https://github.com/kubernetes/kubernetes/issues/35345
// +optional
RollingUpdate *RollingUpdateDaemonSet `json:"rollingUpdate,omitempty" protobuf:"bytes,2,opt,name=rollingUpdate"`
@@ -449,10 +449,17 @@ type DaemonSetSpec struct {
// +optional
MinReadySeconds int32 `json:"minReadySeconds,omitempty" protobuf:"varint,4,opt,name=minReadySeconds"`
// DEPRECATED.
// A sequence number representing a specific generation of the template.
// Populated by the system. It can be set only during the creation.
// +optional
TemplateGeneration int64 `json:"templateGeneration,omitempty" protobuf:"varint,5,opt,name=templateGeneration"`
// The number of old history to retain to allow rollback.
// This is a pointer to distinguish between explicit zero and not specified.
// Defaults to 10.
// +optional
RevisionHistoryLimit *int32 `json:"revisionHistoryLimit,omitempty" protobuf:"varint,6,opt,name=revisionHistoryLimit"`
}
// DaemonSetStatus represents the current status of a daemon set.
@@ -495,6 +502,12 @@ type DaemonSetStatus struct {
// (ready for at least spec.minReadySeconds)
// +optional
NumberUnavailable int32 `json:"numberUnavailable,omitempty" protobuf:"varint,8,opt,name=numberUnavailable"`
// Count of hash collisions for the DaemonSet. The DaemonSet controller
// uses this field as a collision avoidance mechanism when it needs to
// create the name for the newest ControllerRevision.
// +optional
CollisionCount *int64 `json:"collisionCount,omitempty" protobuf:"varint,9,opt,name=collisionCount"`
}
// +genclient=true
@@ -522,10 +535,16 @@ type DaemonSet struct {
}
const (
// DEPRECATED: DefaultDaemonSetUniqueLabelKey is used instead.
// DaemonSetTemplateGenerationKey is the key of the labels that is added
// to daemon set pods to distinguish between old and new pod templates
// during DaemonSet template update.
DaemonSetTemplateGenerationKey string = "pod-template-generation"
// DefaultDaemonSetUniqueLabelKey is the default label key that is added
// to existing DaemonSet pods to distinguish between old and new
// DaemonSet pods during DaemonSet template updates.
DefaultDaemonSetUniqueLabelKey string = "daemonset-controller-hash"
)
// DaemonSetList is a collection of daemon sets.

View File

@@ -82,7 +82,8 @@ var map_DaemonSetSpec = map[string]string{
"template": "An object that describes the pod that will be created. The DaemonSet will create exactly one copy of this pod on every node that matches the template's node selector (or on every node if no node selector is specified). More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#pod-template",
"updateStrategy": "An update strategy to replace existing DaemonSet pods with new pods.",
"minReadySeconds": "The minimum number of seconds for which a newly created DaemonSet pod should be ready without any of its container crashing, for it to be considered available. Defaults to 0 (pod will be considered available as soon as it is ready).",
"templateGeneration": "A sequence number representing a specific generation of the template. Populated by the system. It can be set only during the creation.",
"templateGeneration": "DEPRECATED. A sequence number representing a specific generation of the template. Populated by the system. It can be set only during the creation.",
"revisionHistoryLimit": "The number of old history to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 10.",
}
func (DaemonSetSpec) SwaggerDoc() map[string]string {
@@ -99,6 +100,7 @@ var map_DaemonSetStatus = map[string]string{
"updatedNumberScheduled": "The total number of nodes that are running updated daemon pod",
"numberAvailable": "The number of nodes that should be running the daemon pod and have one or more of the daemon pod running and available (ready for at least spec.minReadySeconds)",
"numberUnavailable": "The number of nodes that should be running the daemon pod and have none of the daemon pod running and available (ready for at least spec.minReadySeconds)",
"collisionCount": "Count of hash collisions for the DaemonSet. The DaemonSet controller uses this field as a collision avoidance mechanism when it needs to create the name for the newest ControllerRevision.",
}
func (DaemonSetStatus) SwaggerDoc() map[string]string {

View File

@@ -352,6 +352,7 @@ func autoConvert_v1beta1_DaemonSetSpec_To_extensions_DaemonSetSpec(in *DaemonSet
}
out.MinReadySeconds = in.MinReadySeconds
out.TemplateGeneration = in.TemplateGeneration
out.RevisionHistoryLimit = (*int32)(unsafe.Pointer(in.RevisionHistoryLimit))
return nil
}
@@ -370,6 +371,7 @@ func autoConvert_extensions_DaemonSetSpec_To_v1beta1_DaemonSetSpec(in *extension
}
out.MinReadySeconds = in.MinReadySeconds
out.TemplateGeneration = in.TemplateGeneration
out.RevisionHistoryLimit = (*int32)(unsafe.Pointer(in.RevisionHistoryLimit))
return nil
}
@@ -387,6 +389,7 @@ func autoConvert_v1beta1_DaemonSetStatus_To_extensions_DaemonSetStatus(in *Daemo
out.UpdatedNumberScheduled = in.UpdatedNumberScheduled
out.NumberAvailable = in.NumberAvailable
out.NumberUnavailable = in.NumberUnavailable
out.CollisionCount = (*int64)(unsafe.Pointer(in.CollisionCount))
return nil
}
@@ -404,6 +407,7 @@ func autoConvert_extensions_DaemonSetStatus_To_v1beta1_DaemonSetStatus(in *exten
out.UpdatedNumberScheduled = in.UpdatedNumberScheduled
out.NumberAvailable = in.NumberAvailable
out.NumberUnavailable = in.NumberUnavailable
out.CollisionCount = (*int64)(unsafe.Pointer(in.CollisionCount))
return nil
}

View File

@@ -182,6 +182,9 @@ func DeepCopy_v1beta1_DaemonSet(in interface{}, out interface{}, c *conversion.C
if err := DeepCopy_v1beta1_DaemonSetSpec(&in.Spec, &out.Spec, c); err != nil {
return err
}
if err := DeepCopy_v1beta1_DaemonSetStatus(&in.Status, &out.Status, c); err != nil {
return err
}
return nil
}
}
@@ -225,6 +228,11 @@ func DeepCopy_v1beta1_DaemonSetSpec(in interface{}, out interface{}, c *conversi
if err := DeepCopy_v1beta1_DaemonSetUpdateStrategy(&in.UpdateStrategy, &out.UpdateStrategy, c); err != nil {
return err
}
if in.RevisionHistoryLimit != nil {
in, out := &in.RevisionHistoryLimit, &out.RevisionHistoryLimit
*out = new(int32)
**out = **in
}
return nil
}
}
@@ -235,6 +243,11 @@ func DeepCopy_v1beta1_DaemonSetStatus(in interface{}, out interface{}, c *conver
in := in.(*DaemonSetStatus)
out := out.(*DaemonSetStatus)
*out = *in
if in.CollisionCount != nil {
in, out := &in.CollisionCount, &out.CollisionCount
*out = new(int64)
**out = **in
}
return nil
}
}

View File

@@ -134,6 +134,9 @@ func validateDaemonSetStatus(status *extensions.DaemonSetStatus, fldPath *field.
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.UpdatedNumberScheduled), fldPath.Child("updatedNumberScheduled"))...)
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.NumberAvailable), fldPath.Child("numberAvailable"))...)
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.NumberUnavailable), fldPath.Child("numberUnavailable"))...)
if status.CollisionCount != nil {
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*status.CollisionCount), fldPath.Child("collisionCount"))...)
}
return allErrs
}
@@ -141,6 +144,13 @@ func validateDaemonSetStatus(status *extensions.DaemonSetStatus, fldPath *field.
func ValidateDaemonSetStatusUpdate(ds, oldDS *extensions.DaemonSet) field.ErrorList {
allErrs := apivalidation.ValidateObjectMetaUpdate(&ds.ObjectMeta, &oldDS.ObjectMeta, field.NewPath("metadata"))
allErrs = append(allErrs, validateDaemonSetStatus(&ds.Status, field.NewPath("status"))...)
if isDecremented(ds.Status.CollisionCount, oldDS.Status.CollisionCount) {
value := int64(0)
if ds.Status.CollisionCount != nil {
value = *ds.Status.CollisionCount
}
allErrs = append(allErrs, field.Invalid(field.NewPath("status").Child("collisionCount"), value, "cannot be decremented"))
}
return allErrs
}
@@ -172,6 +182,10 @@ func ValidateDaemonSetSpec(spec *extensions.DaemonSetSpec, fldPath *field.Path)
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(spec.TemplateGeneration), fldPath.Child("templateGeneration"))...)
allErrs = append(allErrs, ValidateDaemonSetUpdateStrategy(&spec.UpdateStrategy, fldPath.Child("updateStrategy"))...)
if spec.RevisionHistoryLimit != nil {
// zero is a valid RevisionHistoryLimit
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.RevisionHistoryLimit), fldPath.Child("revisionHistoryLimit"))...)
}
return allErrs
}

View File

@@ -183,6 +183,9 @@ func DeepCopy_extensions_DaemonSet(in interface{}, out interface{}, c *conversio
if err := DeepCopy_extensions_DaemonSetSpec(&in.Spec, &out.Spec, c); err != nil {
return err
}
if err := DeepCopy_extensions_DaemonSetStatus(&in.Status, &out.Status, c); err != nil {
return err
}
return nil
}
}
@@ -226,6 +229,11 @@ func DeepCopy_extensions_DaemonSetSpec(in interface{}, out interface{}, c *conve
if err := DeepCopy_extensions_DaemonSetUpdateStrategy(&in.UpdateStrategy, &out.UpdateStrategy, c); err != nil {
return err
}
if in.RevisionHistoryLimit != nil {
in, out := &in.RevisionHistoryLimit, &out.RevisionHistoryLimit
*out = new(int32)
**out = **in
}
return nil
}
}
@@ -236,6 +244,11 @@ func DeepCopy_extensions_DaemonSetStatus(in interface{}, out interface{}, c *con
in := in.(*DaemonSetStatus)
out := out.(*DaemonSetStatus)
*out = *in
if in.CollisionCount != nil {
in, out := &in.CollisionCount, &out.CollisionCount
*out = new(int64)
**out = **in
}
return nil
}
}

View File

@@ -26,6 +26,7 @@ go_library(
tags = ["automanaged"],
deps = [
"//pkg/api/v1:go_default_library",
"//pkg/apis/apps/v1beta1:go_default_library",
"//pkg/apis/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",

View File

@@ -22,6 +22,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/kubernetes/pkg/api/v1"
apps "k8s.io/kubernetes/pkg/apis/apps/v1beta1"
"k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
)
@@ -29,6 +30,7 @@ import (
// DaemonSetLister.
type DaemonSetListerExpansion interface {
GetPodDaemonSets(pod *v1.Pod) ([]*v1beta1.DaemonSet, error)
GetHistoryDaemonSets(history *apps.ControllerRevision) ([]*v1beta1.DaemonSet, error)
}
// DaemonSetNamespaceListerExpansion allows custom methods to be added to
@@ -76,3 +78,37 @@ func (s *daemonSetLister) GetPodDaemonSets(pod *v1.Pod) ([]*v1beta1.DaemonSet, e
return daemonSets, nil
}
// GetHistoryDaemonSets returns a list of DaemonSets that potentially
// match a ControllerRevision. Only the one specified in the ControllerRevision's ControllerRef
// will actually manage it.
// Returns an error only if no matching DaemonSets are found.
func (s *daemonSetLister) GetHistoryDaemonSets(history *apps.ControllerRevision) ([]*v1beta1.DaemonSet, error) {
if len(history.Labels) == 0 {
return nil, fmt.Errorf("no DaemonSet found for ControllerRevision %s because it has no labels", history.Name)
}
list, err := s.DaemonSets(history.Namespace).List(labels.Everything())
if err != nil {
return nil, err
}
var daemonSets []*v1beta1.DaemonSet
for _, ds := range list {
selector, err := metav1.LabelSelectorAsSelector(ds.Spec.Selector)
if err != nil {
return nil, fmt.Errorf("invalid label selector: %v", err)
}
// If a DaemonSet with a nil or empty selector creeps in, it should match nothing, not everything.
if selector.Empty() || !selector.Matches(labels.Set(history.Labels)) {
continue
}
daemonSets = append(daemonSets, ds)
}
if len(daemonSets) == 0 {
return nil, fmt.Errorf("could not find DaemonSets for ControllerRevision %s in namespace %s with labels: %v", history.Name, history.Namespace, history.Labels)
}
return daemonSets, nil
}

View File

@@ -17,8 +17,10 @@ limitations under the License.
package controller
import (
"encoding/binary"
"encoding/json"
"fmt"
"hash/fnv"
"sync"
"sync/atomic"
"time"
@@ -29,16 +31,14 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/clock"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/strategicpatch"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apimachinery/pkg/util/clock"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/record"
"k8s.io/client-go/util/integer"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/v1"
v1helper "k8s.io/kubernetes/pkg/api/v1/helper"
@@ -48,6 +48,7 @@ import (
extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
clientretry "k8s.io/kubernetes/pkg/client/retry"
hashutil "k8s.io/kubernetes/pkg/util/hash"
"github.com/golang/glog"
)
@@ -980,3 +981,18 @@ func WaitForCacheSync(controllerName string, stopCh <-chan struct{}, cacheSyncs
glog.Infof("Caches are synced for %s controller", controllerName)
return true
}
// ComputeHash returns a hash value calculated from pod template and a collisionCount to avoid hash collision
func ComputeHash(template *v1.PodTemplateSpec, collisionCount *int64) uint32 {
podTemplateSpecHasher := fnv.New32a()
hashutil.DeepHashObject(podTemplateSpecHasher, *template)
// Add collisionCount in the hash if it exists.
if collisionCount != nil {
collisionCountBytes := make([]byte, 8)
binary.LittleEndian.PutUint64(collisionCountBytes, uint64(*collisionCount))
podTemplateSpecHasher.Write(collisionCountBytes)
}
return podTemplateSpecHasher.Sum32()
}

View File

@@ -19,6 +19,7 @@ package controller
import (
"encoding/json"
"fmt"
"math"
"math/rand"
"net/http/httptest"
"reflect"
@@ -443,3 +444,38 @@ func TestActiveReplicaSetsFiltering(t *testing.T) {
t.Errorf("expected %v, got %v", expectedNames.List(), gotNames.List())
}
}
func int64P(num int64) *int64 {
return &num
}
func TestComputeHash(t *testing.T) {
tests := []struct {
name string
template *v1.PodTemplateSpec
collisionCount *int64
otherCollisionCount *int64
}{
{
name: "simple",
template: &v1.PodTemplateSpec{},
collisionCount: int64P(1),
otherCollisionCount: int64P(2),
},
{
name: "using math.MaxInt64",
template: &v1.PodTemplateSpec{},
collisionCount: nil,
otherCollisionCount: int64P(int64(math.MaxInt64)),
},
}
for _, test := range tests {
hash := ComputeHash(test.template, test.collisionCount)
otherHash := ComputeHash(test.template, test.otherCollisionCount)
if hash == otherHash {
t.Errorf("expected different hashes but got the same: %d", hash)
}
}
}

View File

@@ -21,25 +21,31 @@ go_library(
"//pkg/api/v1:go_default_library",
"//pkg/api/v1/helper:go_default_library",
"//pkg/api/v1/pod:go_default_library",
"//pkg/apis/apps/v1beta1:go_default_library",
"//pkg/apis/extensions/v1beta1:go_default_library",
"//pkg/client/clientset_generated/clientset:go_default_library",
"//pkg/client/clientset_generated/clientset/typed/extensions/v1beta1:go_default_library",
"//pkg/client/informers/informers_generated/externalversions/apps/v1beta1:go_default_library",
"//pkg/client/informers/informers_generated/externalversions/core/v1:go_default_library",
"//pkg/client/informers/informers_generated/externalversions/extensions/v1beta1:go_default_library",
"//pkg/client/listers/apps/v1beta1:go_default_library",
"//pkg/client/listers/core/v1:go_default_library",
"//pkg/client/listers/extensions/v1beta1:go_default_library",
"//pkg/controller:go_default_library",
"//pkg/controller/daemon/util:go_default_library",
"//pkg/features:go_default_library",
"//pkg/kubelet/types:go_default_library",
"//pkg/util/labels:go_default_library",
"//pkg/util/metrics:go_default_library",
"//plugin/pkg/scheduler/algorithm:go_default_library",
"//plugin/pkg/scheduler/algorithm/predicates:go_default_library",
"//plugin/pkg/scheduler/schedulercache:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
@@ -72,6 +78,7 @@ go_test(
"//pkg/controller:go_default_library",
"//pkg/kubelet/types:go_default_library",
"//pkg/securitycontext:go_default_library",
"//pkg/util/labels:go_default_library",
"//plugin/pkg/scheduler/algorithm:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",

View File

@@ -39,11 +39,14 @@ import (
"k8s.io/kubernetes/pkg/api/v1"
v1helper "k8s.io/kubernetes/pkg/api/v1/helper"
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
apps "k8s.io/kubernetes/pkg/apis/apps/v1beta1"
extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
unversionedextensions "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/extensions/v1beta1"
appsinformers "k8s.io/kubernetes/pkg/client/informers/informers_generated/externalversions/apps/v1beta1"
coreinformers "k8s.io/kubernetes/pkg/client/informers/informers_generated/externalversions/core/v1"
extensionsinformers "k8s.io/kubernetes/pkg/client/informers/informers_generated/externalversions/extensions/v1beta1"
appslisters "k8s.io/kubernetes/pkg/client/listers/apps/v1beta1"
corelisters "k8s.io/kubernetes/pkg/client/listers/core/v1"
extensionslisters "k8s.io/kubernetes/pkg/client/listers/extensions/v1beta1"
"k8s.io/kubernetes/pkg/controller"
@@ -99,6 +102,11 @@ type DaemonSetsController struct {
// dsStoreSynced returns true if the daemonset store has been synced at least once.
// Added as a member to the struct to allow injection for testing.
dsStoreSynced cache.InformerSynced
// historyLister get list/get history from the shared informers's store
historyLister appslisters.ControllerRevisionLister
// historyStoreSynced returns true if the history store has been synced at least once.
// Added as a member to the struct to allow injection for testing.
historyStoreSynced cache.InformerSynced
// podLister get list/get pods from the shared informers's store
podLister corelisters.PodLister
// podStoreSynced returns true if the pod store has been synced at least once.
@@ -114,7 +122,7 @@ type DaemonSetsController struct {
queue workqueue.RateLimitingInterface
}
func NewDaemonSetsController(daemonSetInformer extensionsinformers.DaemonSetInformer, podInformer coreinformers.PodInformer, nodeInformer coreinformers.NodeInformer, kubeClient clientset.Interface) *DaemonSetsController {
func NewDaemonSetsController(daemonSetInformer extensionsinformers.DaemonSetInformer, historyInformer appsinformers.ControllerRevisionInformer, podInformer coreinformers.PodInformer, nodeInformer coreinformers.NodeInformer, kubeClient clientset.Interface) *DaemonSetsController {
eventBroadcaster := record.NewBroadcaster()
eventBroadcaster.StartLogging(glog.Infof)
// TODO: remove the wrapper when every clients have moved to use the clientset.
@@ -152,6 +160,14 @@ func NewDaemonSetsController(daemonSetInformer extensionsinformers.DaemonSetInfo
dsc.dsLister = daemonSetInformer.Lister()
dsc.dsStoreSynced = daemonSetInformer.Informer().HasSynced
historyInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: dsc.addHistory,
UpdateFunc: dsc.updateHistory,
DeleteFunc: dsc.deleteHistory,
})
dsc.historyLister = historyInformer.Lister()
dsc.historyStoreSynced = historyInformer.Informer().HasSynced
// Watch for creation/deletion of pods. The reason we watch is that we don't want a daemon set to create/delete
// more pods until all the effects (expectations) of a daemon set's create/delete have been observed.
podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
@@ -273,6 +289,138 @@ func (dsc *DaemonSetsController) getPodDaemonSets(pod *v1.Pod) []*extensions.Dae
return sets
}
// getDaemonSetsForHistory returns a list of DaemonSets that potentially
// match a ControllerRevision.
func (dsc *DaemonSetsController) getDaemonSetsForHistory(history *apps.ControllerRevision) []*extensions.DaemonSet {
daemonSets, err := dsc.dsLister.GetHistoryDaemonSets(history)
if err != nil || len(daemonSets) == 0 {
return nil
}
if len(daemonSets) > 1 {
// ControllerRef will ensure we don't do anything crazy, but more than one
// item in this list nevertheless constitutes user error.
glog.V(4).Infof("User error! more than one DaemonSets is selecting ControllerRevision %s/%s with labels: %#v",
history.Namespace, history.Name, history.Labels)
}
return daemonSets
}
// addHistory enqueues the DaemonSet that manages a ControllerRevision when the ControllerRevision is created
// or when the controller manager is restarted.
func (dsc *DaemonSetsController) addHistory(obj interface{}) {
history := obj.(*apps.ControllerRevision)
if history.DeletionTimestamp != nil {
// On a restart of the controller manager, it's possible for an object to
// show up in a state that is already pending deletion.
dsc.deleteHistory(history)
return
}
// If it has a ControllerRef, that's all that matters.
if controllerRef := controller.GetControllerOf(history); controllerRef != nil {
ds := dsc.resolveControllerRef(history.Namespace, controllerRef)
if ds == nil {
return
}
glog.V(4).Infof("ControllerRevision %s added.", history.Name)
return
}
// Otherwise, it's an orphan. Get a list of all matching DaemonSets and sync
// them to see if anyone wants to adopt it.
daemonSets := dsc.getDaemonSetsForHistory(history)
if len(daemonSets) == 0 {
return
}
glog.V(4).Infof("Orphan ControllerRevision %s added.", history.Name)
for _, ds := range daemonSets {
dsc.enqueueDaemonSet(ds)
}
}
// updateHistory figures out what DaemonSet(s) manage a ControllerRevision when the ControllerRevision
// is updated and wake them up. If the anything of the ControllerRevision have changed, we need to
// awaken both the old and new DaemonSets.
func (dsc *DaemonSetsController) updateHistory(old, cur interface{}) {
curHistory := cur.(*apps.ControllerRevision)
oldHistory := old.(*apps.ControllerRevision)
if curHistory.ResourceVersion == oldHistory.ResourceVersion {
// Periodic resync will send update events for all known ControllerRevisions.
return
}
curControllerRef := controller.GetControllerOf(curHistory)
oldControllerRef := controller.GetControllerOf(oldHistory)
controllerRefChanged := !reflect.DeepEqual(curControllerRef, oldControllerRef)
if controllerRefChanged && oldControllerRef != nil {
// The ControllerRef was changed. Sync the old controller, if any.
if ds := dsc.resolveControllerRef(oldHistory.Namespace, oldControllerRef); ds != nil {
dsc.enqueueDaemonSet(ds)
}
}
// If it has a ControllerRef, that's all that matters.
if curControllerRef != nil {
ds := dsc.resolveControllerRef(curHistory.Namespace, curControllerRef)
if ds == nil {
return
}
glog.V(4).Infof("ControllerRevision %s updated.", curHistory.Name)
dsc.enqueueDaemonSet(ds)
return
}
// Otherwise, it's an orphan. If anything changed, sync matching controllers
// to see if anyone wants to adopt it now.
labelChanged := !reflect.DeepEqual(curHistory.Labels, oldHistory.Labels)
if labelChanged || controllerRefChanged {
daemonSets := dsc.getDaemonSetsForHistory(curHistory)
if len(daemonSets) == 0 {
return
}
glog.V(4).Infof("Orphan ControllerRevision %s updated.", curHistory.Name)
for _, ds := range daemonSets {
dsc.enqueueDaemonSet(ds)
}
}
}
// deleteHistory enqueues the DaemonSet that manages a ControllerRevision when
// the ControllerRevision is deleted. obj could be an *app.ControllerRevision, or
// a DeletionFinalStateUnknown marker item.
func (dsc *DaemonSetsController) deleteHistory(obj interface{}) {
history, ok := obj.(*apps.ControllerRevision)
// When a delete is dropped, the relist will notice a ControllerRevision in the store not
// in the list, leading to the insertion of a tombstone object which contains
// the deleted key/value. Note that this value might be stale. If the ControllerRevision
// changed labels the new DaemonSet will not be woken up till the periodic resync.
if !ok {
tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
if !ok {
utilruntime.HandleError(fmt.Errorf("Couldn't get object from tombstone %#v", obj))
return
}
history, ok = tombstone.Obj.(*apps.ControllerRevision)
if !ok {
utilruntime.HandleError(fmt.Errorf("Tombstone contained object that is not a ControllerRevision %#v", obj))
return
}
}
controllerRef := controller.GetControllerOf(history)
if controllerRef == nil {
// No controller should care about orphans being deleted.
return
}
ds := dsc.resolveControllerRef(history.Namespace, controllerRef)
if ds == nil {
return
}
glog.V(4).Infof("ControllerRevision %s deleted.", history.Name)
dsc.enqueueDaemonSet(ds)
}
func (dsc *DaemonSetsController) addPod(obj interface{}) {
pod := obj.(*v1.Pod)
@@ -486,11 +634,11 @@ func (dsc *DaemonSetsController) updateNode(old, cur interface{}) {
}
}
// getNodesToDaemonSetPods returns a map from nodes to daemon pods (corresponding to ds) running on the nodes.
// getDaemonPods returns daemon pods owned by the given ds.
// This also reconciles ControllerRef by adopting/orphaning.
// Note that returned Pods are pointers to objects in the cache.
// If you want to modify one, you need to deep-copy it first.
func (dsc *DaemonSetsController) getNodesToDaemonPods(ds *extensions.DaemonSet) (map[string][]*v1.Pod, error) {
func (dsc *DaemonSetsController) getDaemonPods(ds *extensions.DaemonSet) ([]*v1.Pod, error) {
selector, err := metav1.LabelSelectorAsSelector(ds.Spec.Selector)
if err != nil {
return nil, err
@@ -516,7 +664,15 @@ func (dsc *DaemonSetsController) getNodesToDaemonPods(ds *extensions.DaemonSet)
})
// Use ControllerRefManager to adopt/orphan as needed.
cm := controller.NewPodControllerRefManager(dsc.podControl, ds, selector, controllerKind, canAdoptFunc)
claimedPods, err := cm.ClaimPods(pods)
return cm.ClaimPods(pods)
}
// getNodesToDaemonPods returns a map from nodes to daemon pods (corresponding to ds) running on the nodes.
// This also reconciles ControllerRef by adopting/orphaning.
// Note that returned Pods are pointers to objects in the cache.
// If you want to modify one, you need to deep-copy it first.
func (dsc *DaemonSetsController) getNodesToDaemonPods(ds *extensions.DaemonSet) (map[string][]*v1.Pod, error) {
claimedPods, err := dsc.getDaemonPods(ds)
if err != nil {
return nil, err
}
@@ -554,18 +710,18 @@ func (dsc *DaemonSetsController) resolveControllerRef(namespace string, controll
return ds
}
func (dsc *DaemonSetsController) manage(ds *extensions.DaemonSet) error {
func (dsc *DaemonSetsController) manage(ds *extensions.DaemonSet) (string, error) {
// Find out which nodes are running the daemon pods controlled by ds.
nodeToDaemonPods, err := dsc.getNodesToDaemonPods(ds)
if err != nil {
return fmt.Errorf("couldn't get node to daemon pod mapping for daemon set %q: %v", ds.Name, err)
return "", fmt.Errorf("couldn't get node to daemon pod mapping for daemon set %q: %v", ds.Name, err)
}
// For each node, if the node is running the daemon pod but isn't supposed to, kill the daemon
// pod. If the node is supposed to run the daemon pod, but isn't, create the daemon pod on the node.
nodeList, err := dsc.nodeLister.List(labels.Everything())
if err != nil {
return fmt.Errorf("couldn't get list of nodes when syncing daemon set %#v: %v", ds, err)
return "", fmt.Errorf("couldn't get list of nodes when syncing daemon set %#v: %v", ds, err)
}
var nodesNeedingDaemonPods, podsToDelete []string
var failedPodsObserved int
@@ -612,23 +768,33 @@ func (dsc *DaemonSetsController) manage(ds *extensions.DaemonSet) error {
}
}
}
errors := dsc.syncNodes(ds, podsToDelete, nodesNeedingDaemonPods)
// Find current history of the DaemonSet, and label new pods using the hash label value of the current history when creating them
cur, _, err := dsc.constructHistory(ds)
if err != nil {
return "", fmt.Errorf("failed to construct revisions of DaemonSet: %v", err)
}
hash := cur.Labels[extensions.DefaultDaemonSetUniqueLabelKey]
if err = dsc.syncNodes(ds, podsToDelete, nodesNeedingDaemonPods, hash); err != nil {
return "", err
}
// Throw an error when the daemon pods fail, to use ratelimiter to prevent kill-recreate hot loop
if failedPodsObserved > 0 {
errors = append(errors, fmt.Errorf("deleted %d failed pods of DaemonSet %s/%s", failedPodsObserved, ds.Namespace, ds.Name))
return "", fmt.Errorf("deleted %d failed pods of DaemonSet %s/%s", failedPodsObserved, ds.Namespace, ds.Name)
}
return utilerrors.NewAggregate(errors)
return hash, nil
}
// syncNodes deletes given pods and creates new daemon set pods on the given nodes
// returns slice with erros if any
func (dsc *DaemonSetsController) syncNodes(ds *extensions.DaemonSet, podsToDelete, nodesNeedingDaemonPods []string) []error {
func (dsc *DaemonSetsController) syncNodes(ds *extensions.DaemonSet, podsToDelete, nodesNeedingDaemonPods []string, hash string) error {
// We need to set expectations before creating/deleting pods to avoid race conditions.
dsKey, err := controller.KeyFunc(ds)
if err != nil {
return []error{fmt.Errorf("couldn't get key for object %#v: %v", ds, err)}
return fmt.Errorf("couldn't get key for object %#v: %v", ds, err)
}
createDiff := len(nodesNeedingDaemonPods)
@@ -649,7 +815,7 @@ func (dsc *DaemonSetsController) syncNodes(ds *extensions.DaemonSet, podsToDelet
glog.V(4).Infof("Nodes needing daemon pods for daemon set %s: %+v, creating %d", ds.Name, nodesNeedingDaemonPods, createDiff)
createWait := sync.WaitGroup{}
createWait.Add(createDiff)
template := util.GetPodTemplateWithGeneration(ds.Spec.Template, ds.Spec.TemplateGeneration)
template := util.CreatePodTemplate(ds.Spec.Template, ds.Spec.TemplateGeneration, hash)
for i := 0; i < createDiff; i++ {
go func(ix int) {
defer createWait.Done()
@@ -685,7 +851,7 @@ func (dsc *DaemonSetsController) syncNodes(ds *extensions.DaemonSet, podsToDelet
for err := range errCh {
errors = append(errors, err)
}
return errors
return utilerrors.NewAggregate(errors)
}
func storeDaemonSetStatus(dsClient unversionedextensions.DaemonSetInterface, ds *extensions.DaemonSet, desiredNumberScheduled, currentNumberScheduled, numberMisscheduled, numberReady, updatedNumberScheduled, numberAvailable, numberUnavailable int) error {
@@ -767,7 +933,7 @@ func (dsc *DaemonSetsController) updateDaemonSetStatus(ds *extensions.DaemonSet)
numberAvailable++
}
}
if util.IsPodUpdated(ds.Spec.TemplateGeneration, pod) {
if util.IsPodUpdated(ds.Spec.TemplateGeneration, pod, ds.Labels[extensions.DefaultDaemonSetUniqueLabelKey]) {
updatedNumberScheduled++
}
}
@@ -825,21 +991,28 @@ func (dsc *DaemonSetsController) syncDaemonSet(key string) error {
return dsc.updateDaemonSetStatus(ds)
}
if err := dsc.manage(ds); err != nil {
hash, err := dsc.manage(ds)
if err != nil {
return err
}
// Process rolling updates if we're ready.
if dsc.expectations.SatisfiedExpectations(dsKey) {
switch ds.Spec.UpdateStrategy.Type {
case extensions.OnDeleteDaemonSetStrategyType:
case extensions.RollingUpdateDaemonSetStrategyType:
err = dsc.rollingUpdate(ds)
err = dsc.rollingUpdate(ds, hash)
}
if err != nil {
return err
}
}
err = dsc.cleanupHistory(ds)
if err != nil {
return fmt.Errorf("failed to clean up revisions of DaemonSet: %v", err)
}
return dsc.updateDaemonSetStatus(ds)
}

View File

@@ -27,6 +27,7 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/uuid"
"k8s.io/apiserver/pkg/storage/names"
utilfeature "k8s.io/apiserver/pkg/util/feature"
@@ -44,6 +45,7 @@ import (
"k8s.io/kubernetes/pkg/controller"
kubelettypes "k8s.io/kubernetes/pkg/kubelet/types"
"k8s.io/kubernetes/pkg/securitycontext"
labelsutil "k8s.io/kubernetes/pkg/util/labels"
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
)
@@ -84,6 +86,7 @@ func getKey(ds *extensions.DaemonSet, t *testing.T) string {
}
func newDaemonSet(name string) *extensions.DaemonSet {
two := int32(2)
return &extensions.DaemonSet{
TypeMeta: metav1.TypeMeta{APIVersion: testapi.Extensions.GroupVersion().String()},
ObjectMeta: metav1.ObjectMeta{
@@ -92,6 +95,10 @@ func newDaemonSet(name string) *extensions.DaemonSet {
Namespace: metav1.NamespaceDefault,
},
Spec: extensions.DaemonSetSpec{
RevisionHistoryLimit: &two,
UpdateStrategy: extensions.DaemonSetUpdateStrategy{
Type: extensions.OnDeleteDaemonSetStrategyType,
},
Selector: &metav1.LabelSelector{MatchLabels: simpleDaemonSetLabel},
Template: v1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
@@ -113,6 +120,24 @@ func newDaemonSet(name string) *extensions.DaemonSet {
}
}
func newRollbackStrategy() *extensions.DaemonSetUpdateStrategy {
one := intstr.FromInt(1)
return &extensions.DaemonSetUpdateStrategy{
Type: extensions.RollingUpdateDaemonSetStrategyType,
RollingUpdate: &extensions.RollingUpdateDaemonSet{MaxUnavailable: &one},
}
}
func newOnDeleteStrategy() *extensions.DaemonSetUpdateStrategy {
return &extensions.DaemonSetUpdateStrategy{
Type: extensions.OnDeleteDaemonSetStrategyType,
}
}
func updateStrategies() []*extensions.DaemonSetUpdateStrategy {
return []*extensions.DaemonSetUpdateStrategy{newOnDeleteStrategy(), newRollbackStrategy()}
}
func newNode(name string, label map[string]string) *v1.Node {
return &v1.Node{
TypeMeta: metav1.TypeMeta{APIVersion: api.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()},
@@ -139,11 +164,18 @@ func addNodes(nodeStore cache.Store, startIndex, numNodes int, label map[string]
}
func newPod(podName string, nodeName string, label map[string]string, ds *extensions.DaemonSet) *v1.Pod {
// Add hash unique label to the pod
newLabels := label
if ds != nil {
hash := fmt.Sprint(controller.ComputeHash(&ds.Spec.Template, ds.Status.CollisionCount))
newLabels = labelsutil.CloneAndAddLabel(label, extensions.DefaultDaemonSetUniqueLabelKey, hash)
}
pod := &v1.Pod{
TypeMeta: metav1.TypeMeta{APIVersion: api.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
GenerateName: podName,
Labels: label,
Labels: newLabels,
Namespace: metav1.NamespaceDefault,
},
Spec: v1.PodSpec{
@@ -168,7 +200,8 @@ func newPod(podName string, nodeName string, label map[string]string, ds *extens
func addPods(podStore cache.Store, nodeName string, label map[string]string, ds *extensions.DaemonSet, number int) {
for i := 0; i < number; i++ {
podStore.Add(newPod(fmt.Sprintf("%s-", nodeName), nodeName, label, ds))
pod := newPod(fmt.Sprintf("%s-", nodeName), nodeName, label, ds)
podStore.Add(pod)
}
}
@@ -251,6 +284,7 @@ func newTestController(initialObjects ...runtime.Object) (*daemonSetsController,
manager := NewDaemonSetsController(
informerFactory.Extensions().V1beta1().DaemonSets(),
informerFactory.Apps().V1beta1().ControllerRevisions(),
informerFactory.Core().V1().Pods(),
informerFactory.Core().V1().Nodes(),
clientset,
@@ -319,15 +353,18 @@ func clearExpectations(t *testing.T, manager *daemonSetsController, ds *extensio
}
func TestDeleteFinalStateUnknown(t *testing.T) {
for _, strategy := range updateStrategies() {
manager, _, _ := newTestController()
addNodes(manager.nodeStore, 0, 1, nil)
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
// DeletedFinalStateUnknown should queue the embedded DS if found.
manager.deleteDaemonset(cache.DeletedFinalStateUnknown{Key: "foo", Obj: ds})
enqueuedKey, _ := manager.queue.Get()
if enqueuedKey.(string) != "default/foo" {
t.Errorf("expected delete of DeletedFinalStateUnknown to enqueue the daemonset but found: %#v", enqueuedKey)
}
}
}
func markPodsReady(store cache.Store) {
@@ -345,15 +382,20 @@ func markPodReady(pod *v1.Pod) {
// DaemonSets without node selectors should launch pods on every node.
func TestSimpleDaemonSetLaunchesPods(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
manager, podControl, _ := newTestController(ds)
addNodes(manager.nodeStore, 0, 5, nil)
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 5, 0)
}
}
func TestSimpleDaemonSetUpdatesStatusAfterLaunchingPods(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
manager, podControl, clientset := newTestController(ds)
var updated *extensions.DaemonSet
@@ -376,29 +418,38 @@ func TestSimpleDaemonSetUpdatesStatusAfterLaunchingPods(t *testing.T) {
if got, want := updated.Status.CurrentNumberScheduled, int32(5); got != want {
t.Errorf("Status.CurrentNumberScheduled = %v, want %v", got, want)
}
}
}
// DaemonSets should do nothing if there aren't any nodes
func TestNoNodesDoesNothing(t *testing.T) {
for _, strategy := range updateStrategies() {
manager, podControl, _ := newTestController()
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0)
}
}
// DaemonSets without node selectors should launch on a single node in a
// single node cluster.
func TestOneNodeDaemonLaunchesPod(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
manager, podControl, _ := newTestController(ds)
manager.nodeStore.Add(newNode("only-node", nil))
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0)
}
}
// DaemonSets should place onto NotReady nodes
func TestNotReadNodeDaemonDoesNotLaunchPod(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
manager, podControl, _ := newTestController(ds)
node := newNode("not-ready", nil)
node.Status.Conditions = []v1.NodeCondition{
@@ -407,17 +458,21 @@ func TestNotReadNodeDaemonDoesNotLaunchPod(t *testing.T) {
manager.nodeStore.Add(node)
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0)
}
}
// DaemonSets should not place onto OutOfDisk nodes
func TestOutOfDiskNodeDaemonDoesNotLaunchPod(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
manager, podControl, _ := newTestController(ds)
node := newNode("not-enough-disk", nil)
node.Status.Conditions = []v1.NodeCondition{{Type: v1.NodeOutOfDisk, Status: v1.ConditionTrue}}
manager.nodeStore.Add(node)
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0)
}
}
func resourcePodSpec(nodeName, memory, cpu string) v1.PodSpec {
@@ -441,8 +496,10 @@ func allocatableResources(memory, cpu string) v1.ResourceList {
// DaemonSets should not place onto nodes with insufficient free resource
func TestInsufficientCapacityNodeDaemonDoesNotLaunchPod(t *testing.T) {
for _, strategy := range updateStrategies() {
podSpec := resourcePodSpec("too-much-mem", "75M", "75m")
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
ds.Spec.Template.Spec = podSpec
manager, podControl, _ := newTestController(ds)
node := newNode("too-much-mem", nil)
@@ -453,13 +510,16 @@ func TestInsufficientCapacityNodeDaemonDoesNotLaunchPod(t *testing.T) {
})
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0)
}
}
// DaemonSets should not unschedule a daemonset pod from a node with insufficient free resource
func TestInsufficientCapacityNodeDaemonDoesNotUnscheduleRunningPod(t *testing.T) {
for _, strategy := range updateStrategies() {
podSpec := resourcePodSpec("too-much-mem", "75M", "75m")
podSpec.NodeName = "too-much-mem"
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
ds.Spec.Template.Spec = podSpec
manager, podControl, _ := newTestController(ds)
node := newNode("too-much-mem", nil)
@@ -470,11 +530,14 @@ func TestInsufficientCapacityNodeDaemonDoesNotUnscheduleRunningPod(t *testing.T)
})
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0)
}
}
func TestSufficientCapacityWithTerminatedPodsDaemonLaunchesPod(t *testing.T) {
for _, strategy := range updateStrategies() {
podSpec := resourcePodSpec("too-much-mem", "75M", "75m")
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
ds.Spec.Template.Spec = podSpec
manager, podControl, _ := newTestController(ds)
node := newNode("too-much-mem", nil)
@@ -486,12 +549,15 @@ func TestSufficientCapacityWithTerminatedPodsDaemonLaunchesPod(t *testing.T) {
})
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0)
}
}
// DaemonSets should place onto nodes with sufficient free resource
func TestSufficientCapacityNodeDaemonLaunchesPod(t *testing.T) {
for _, strategy := range updateStrategies() {
podSpec := resourcePodSpec("not-too-much-mem", "75M", "75m")
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
ds.Spec.Template.Spec = podSpec
manager, podControl, _ := newTestController(ds)
node := newNode("not-too-much-mem", nil)
@@ -502,11 +568,14 @@ func TestSufficientCapacityNodeDaemonLaunchesPod(t *testing.T) {
})
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0)
}
}
// DaemonSet should launch a pod on a node with taint NetworkUnavailable condition.
func TestNetworkUnavailableNodeDaemonLaunchesPod(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("simple")
ds.Spec.UpdateStrategy = *strategy
manager, podControl, _ := newTestController(ds)
node := newNode("network-unavailable", nil)
@@ -517,12 +586,15 @@ func TestNetworkUnavailableNodeDaemonLaunchesPod(t *testing.T) {
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0)
}
}
// DaemonSets not take any actions when being deleted
func TestDontDoAnythingIfBeingDeleted(t *testing.T) {
for _, strategy := range updateStrategies() {
podSpec := resourcePodSpec("not-too-much-mem", "75M", "75m")
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
ds.Spec.Template.Spec = podSpec
now := metav1.Now()
ds.DeletionTimestamp = &now
@@ -535,11 +607,14 @@ func TestDontDoAnythingIfBeingDeleted(t *testing.T) {
})
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0)
}
}
func TestDontDoAnythingIfBeingDeletedRace(t *testing.T) {
for _, strategy := range updateStrategies() {
// Bare client says it IS deleted.
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
now := metav1.Now()
ds.DeletionTimestamp = &now
manager, podControl, _ := newTestController(ds)
@@ -555,10 +630,12 @@ func TestDontDoAnythingIfBeingDeletedRace(t *testing.T) {
manager.podStore.Add(pod)
syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0)
}
}
// DaemonSets should not place onto nodes that would cause port conflicts
func TestPortConflictNodeDaemonDoesNotLaunchPod(t *testing.T) {
for _, strategy := range updateStrategies() {
podSpec := v1.PodSpec{
NodeName: "port-conflict",
Containers: []v1.Container{{
@@ -575,9 +652,11 @@ func TestPortConflictNodeDaemonDoesNotLaunchPod(t *testing.T) {
})
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
ds.Spec.Template.Spec = podSpec
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0)
}
}
// Test that if the node is already scheduled with a pod using a host port
@@ -585,6 +664,7 @@ func TestPortConflictNodeDaemonDoesNotLaunchPod(t *testing.T) {
//
// Issue: https://github.com/kubernetes/kubernetes/issues/22309
func TestPortConflictWithSameDaemonPodDoesNotDeletePod(t *testing.T) {
for _, strategy := range updateStrategies() {
podSpec := v1.PodSpec{
NodeName: "port-conflict",
Containers: []v1.Container{{
@@ -597,6 +677,7 @@ func TestPortConflictWithSameDaemonPodDoesNotDeletePod(t *testing.T) {
node := newNode("port-conflict", nil)
manager.nodeStore.Add(node)
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
ds.Spec.Template.Spec = podSpec
manager.dsStore.Add(ds)
manager.podStore.Add(&v1.Pod{
@@ -608,10 +689,12 @@ func TestPortConflictWithSameDaemonPodDoesNotDeletePod(t *testing.T) {
Spec: podSpec,
})
syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0)
}
}
// DaemonSets should place onto nodes that would not cause port conflicts
func TestNoPortConflictNodeDaemonLaunchesPod(t *testing.T) {
for _, strategy := range updateStrategies() {
podSpec1 := v1.PodSpec{
NodeName: "no-port-conflict",
Containers: []v1.Container{{
@@ -629,6 +712,7 @@ func TestNoPortConflictNodeDaemonLaunchesPod(t *testing.T) {
}},
}
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
ds.Spec.Template.Spec = podSpec2
manager, podControl, _ := newTestController(ds)
node := newNode("no-port-conflict", nil)
@@ -638,6 +722,7 @@ func TestNoPortConflictNodeDaemonLaunchesPod(t *testing.T) {
})
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0)
}
}
// DaemonSetController should not sync DaemonSets with empty pod selectors.
@@ -653,7 +738,9 @@ func TestPodIsNotDeletedByDaemonsetWithEmptyLabelSelector(t *testing.T) {
// this case even though it's empty pod selector matches all pods. The DaemonSetController
// should detect this misconfiguration and choose not to sync the DaemonSet. We should
// not observe a deletion of the pod on node1.
for _, strategy := range updateStrategies() {
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
ls := metav1.LabelSelector{}
ds.Spec.Selector = &ls
ds.Spec.Template.Spec.NodeSelector = map[string]string{"foo": "bar"}
@@ -673,11 +760,14 @@ func TestPodIsNotDeletedByDaemonsetWithEmptyLabelSelector(t *testing.T) {
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0)
}
}
// Controller should not create pods on nodes which have daemon pods, and should remove excess pods from nodes that have extra pods.
func TestDealsWithExistingPods(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
manager, podControl, _ := newTestController(ds)
manager.dsStore.Add(ds)
addNodes(manager.nodeStore, 0, 5, nil)
@@ -686,22 +776,28 @@ func TestDealsWithExistingPods(t *testing.T) {
addPods(manager.podStore, "node-3", simpleDaemonSetLabel, ds, 5)
addPods(manager.podStore, "node-4", simpleDaemonSetLabel2, ds, 2)
syncAndValidateDaemonSets(t, manager, ds, podControl, 2, 5)
}
}
// Daemon with node selector should launch pods on nodes matching selector.
func TestSelectorDaemonLaunchesPods(t *testing.T) {
for _, strategy := range updateStrategies() {
daemon := newDaemonSet("foo")
daemon.Spec.UpdateStrategy = *strategy
daemon.Spec.Template.Spec.NodeSelector = simpleNodeLabel
manager, podControl, _ := newTestController(daemon)
addNodes(manager.nodeStore, 0, 4, nil)
addNodes(manager.nodeStore, 4, 3, simpleNodeLabel)
manager.dsStore.Add(daemon)
syncAndValidateDaemonSets(t, manager, daemon, podControl, 3, 0)
}
}
// Daemon with node selector should delete pods from nodes that do not satisfy selector.
func TestSelectorDaemonDeletesUnselectedPods(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
ds.Spec.Template.Spec.NodeSelector = simpleNodeLabel
manager, podControl, _ := newTestController(ds)
manager.dsStore.Add(ds)
@@ -712,11 +808,14 @@ func TestSelectorDaemonDeletesUnselectedPods(t *testing.T) {
addPods(manager.podStore, "node-1", simpleDaemonSetLabel2, ds, 1)
addPods(manager.podStore, "node-4", simpleDaemonSetLabel, ds, 1)
syncAndValidateDaemonSets(t, manager, ds, podControl, 5, 4)
}
}
// DaemonSet with node selector should launch pods on nodes matching selector, but also deal with existing pods on nodes.
func TestSelectorDaemonDealsWithExistingPods(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
ds.Spec.Template.Spec.NodeSelector = simpleNodeLabel
manager, podControl, _ := newTestController(ds)
manager.dsStore.Add(ds)
@@ -731,42 +830,54 @@ func TestSelectorDaemonDealsWithExistingPods(t *testing.T) {
addPods(manager.podStore, "node-9", simpleDaemonSetLabel, ds, 1)
addPods(manager.podStore, "node-9", simpleDaemonSetLabel2, ds, 1)
syncAndValidateDaemonSets(t, manager, ds, podControl, 3, 20)
}
}
// DaemonSet with node selector which does not match any node labels should not launch pods.
func TestBadSelectorDaemonDoesNothing(t *testing.T) {
for _, strategy := range updateStrategies() {
manager, podControl, _ := newTestController()
addNodes(manager.nodeStore, 0, 4, nil)
addNodes(manager.nodeStore, 4, 3, simpleNodeLabel)
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
ds.Spec.Template.Spec.NodeSelector = simpleNodeLabel2
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0)
}
}
// DaemonSet with node name should launch pod on node with corresponding name.
func TestNameDaemonSetLaunchesPods(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
ds.Spec.Template.Spec.NodeName = "node-0"
manager, podControl, _ := newTestController(ds)
addNodes(manager.nodeStore, 0, 5, nil)
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0)
}
}
// DaemonSet with node name that does not exist should not launch pods.
func TestBadNameDaemonSetDoesNothing(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
ds.Spec.Template.Spec.NodeName = "node-10"
manager, podControl, _ := newTestController(ds)
addNodes(manager.nodeStore, 0, 5, nil)
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0)
}
}
// DaemonSet with node selector, and node name, matching a node, should launch a pod on the node.
func TestNameAndSelectorDaemonSetLaunchesPods(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
ds.Spec.Template.Spec.NodeSelector = simpleNodeLabel
ds.Spec.Template.Spec.NodeName = "node-6"
manager, podControl, _ := newTestController(ds)
@@ -774,11 +885,14 @@ func TestNameAndSelectorDaemonSetLaunchesPods(t *testing.T) {
addNodes(manager.nodeStore, 4, 3, simpleNodeLabel)
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0)
}
}
// DaemonSet with node selector that matches some nodes, and node name that matches a different node, should do nothing.
func TestInconsistentNameSelectorDaemonSetDoesNothing(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
ds.Spec.Template.Spec.NodeSelector = simpleNodeLabel
ds.Spec.Template.Spec.NodeName = "node-0"
manager, podControl, _ := newTestController(ds)
@@ -786,6 +900,7 @@ func TestInconsistentNameSelectorDaemonSetDoesNothing(t *testing.T) {
addNodes(manager.nodeStore, 4, 3, simpleNodeLabel)
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0)
}
}
// DaemonSet with node selector, matching some nodes, should launch pods on all the nodes.
@@ -801,7 +916,9 @@ func TestSelectorDaemonSetLaunchesPods(t *testing.T) {
// Daemon with node affinity should launch pods on nodes matching affinity.
func TestNodeAffinityDaemonLaunchesPods(t *testing.T) {
for _, strategy := range updateStrategies() {
daemon := newDaemonSet("foo")
daemon.Spec.UpdateStrategy = *strategy
daemon.Spec.Template.Spec.Affinity = &v1.Affinity{
NodeAffinity: &v1.NodeAffinity{
RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{
@@ -825,10 +942,13 @@ func TestNodeAffinityDaemonLaunchesPods(t *testing.T) {
addNodes(manager.nodeStore, 4, 3, simpleNodeLabel)
manager.dsStore.Add(daemon)
syncAndValidateDaemonSets(t, manager, daemon, podControl, 3, 0)
}
}
func TestNumberReadyStatus(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
manager, podControl, clientset := newTestController(ds)
var updated *extensions.DaemonSet
clientset.PrependReactor("update", "daemonsets", func(action core.Action) (handled bool, ret runtime.Object, err error) {
@@ -861,10 +981,13 @@ func TestNumberReadyStatus(t *testing.T) {
if updated.Status.NumberReady != 2 {
t.Errorf("Wrong daemon %s status: %v", updated.Name, updated.Status)
}
}
}
func TestObservedGeneration(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
ds.Generation = 1
manager, podControl, clientset := newTestController(ds)
var updated *extensions.DaemonSet
@@ -886,6 +1009,7 @@ func TestObservedGeneration(t *testing.T) {
if updated.Status.ObservedGeneration != ds.Generation {
t.Errorf("Wrong ObservedGeneration for daemon %s in status. Expected %d, got %d", updated.Name, ds.Generation, updated.Status.ObservedGeneration)
}
}
}
// DaemonSet controller should kill all failed pods and create at most 1 pod on every node.
@@ -903,7 +1027,9 @@ func TestDaemonKillFailedPods(t *testing.T) {
for _, test := range tests {
t.Logf("test case: %s\n", test.test)
for _, strategy := range updateStrategies() {
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
manager, podControl, _ := newTestController(ds)
manager.dsStore.Add(ds)
addNodes(manager.nodeStore, 0, 1, nil)
@@ -911,11 +1037,14 @@ func TestDaemonKillFailedPods(t *testing.T) {
addPods(manager.podStore, "node-0", simpleDaemonSetLabel, ds, test.numNormalPods)
syncAndValidateDaemonSets(t, manager, ds, podControl, test.expectedCreates, test.expectedDeletes)
}
}
}
// DaemonSet should not launch a pod on a tainted node when the pod doesn't tolerate that taint.
func TestTaintedNodeDaemonDoesNotLaunchUntoleratePod(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("untolerate")
ds.Spec.UpdateStrategy = *strategy
manager, podControl, _ := newTestController(ds)
node := newNode("tainted", nil)
@@ -924,11 +1053,14 @@ func TestTaintedNodeDaemonDoesNotLaunchUntoleratePod(t *testing.T) {
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0)
}
}
// DaemonSet should launch a pod on a tainted node when the pod can tolerate that taint.
func TestTaintedNodeDaemonLaunchesToleratePod(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("tolerate")
ds.Spec.UpdateStrategy = *strategy
setDaemonSetToleration(ds, noScheduleTolerations)
manager, podControl, _ := newTestController(ds)
@@ -938,11 +1070,14 @@ func TestTaintedNodeDaemonLaunchesToleratePod(t *testing.T) {
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0)
}
}
// DaemonSet should launch a pod on a not ready node with taint notReady:NoExecute.
func TestNotReadyNodeDaemonLaunchesPod(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("simple")
ds.Spec.UpdateStrategy = *strategy
manager, podControl, _ := newTestController(ds)
node := newNode("tainted", nil)
@@ -954,11 +1089,14 @@ func TestNotReadyNodeDaemonLaunchesPod(t *testing.T) {
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0)
}
}
// DaemonSet should launch a pod on an unreachable node with taint unreachable:NoExecute.
func TestUnreachableNodeDaemonLaunchesPod(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("simple")
ds.Spec.UpdateStrategy = *strategy
manager, podControl, _ := newTestController(ds)
node := newNode("tainted", nil)
@@ -970,11 +1108,14 @@ func TestUnreachableNodeDaemonLaunchesPod(t *testing.T) {
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0)
}
}
// DaemonSet should launch a pod on an untainted node when the pod has tolerations.
func TestNodeDaemonLaunchesToleratePod(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("tolerate")
ds.Spec.UpdateStrategy = *strategy
setDaemonSetToleration(ds, noScheduleTolerations)
manager, podControl, _ := newTestController(ds)
@@ -983,6 +1124,7 @@ func TestNodeDaemonLaunchesToleratePod(t *testing.T) {
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0)
}
}
func setNodeTaint(node *v1.Node, taints []v1.Taint) {
@@ -995,7 +1137,9 @@ func setDaemonSetToleration(ds *extensions.DaemonSet, tolerations []v1.Toleratio
// DaemonSet should launch a critical pod even when the node is OutOfDisk.
func TestOutOfDiskNodeDaemonLaunchesCriticalPod(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("critical")
ds.Spec.UpdateStrategy = *strategy
setDaemonSetCritical(ds)
manager, podControl, _ := newTestController(ds)
@@ -1011,12 +1155,15 @@ func TestOutOfDiskNodeDaemonLaunchesCriticalPod(t *testing.T) {
// Enabling critical pod annotation feature gate should create critical pod
utilfeature.DefaultFeatureGate.Set("ExperimentalCriticalPodAnnotation=True")
syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0)
}
}
// DaemonSet should launch a critical pod even when the node has insufficient free resource.
func TestInsufficientCapacityNodeDaemonLaunchesCriticalPod(t *testing.T) {
for _, strategy := range updateStrategies() {
podSpec := resourcePodSpec("too-much-mem", "75M", "75m")
ds := newDaemonSet("critical")
ds.Spec.UpdateStrategy = *strategy
ds.Spec.Template.Spec = podSpec
setDaemonSetCritical(ds)
@@ -1036,10 +1183,12 @@ func TestInsufficientCapacityNodeDaemonLaunchesCriticalPod(t *testing.T) {
// Enabling critical pod annotation feature gate should create critical pod
utilfeature.DefaultFeatureGate.Set("ExperimentalCriticalPodAnnotation=True")
syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0)
}
}
// DaemonSets should NOT launch a critical pod when there are port conflicts.
func TestPortConflictNodeDaemonDoesNotLaunchCriticalPod(t *testing.T) {
for _, strategy := range updateStrategies() {
podSpec := v1.PodSpec{
NodeName: "port-conflict",
Containers: []v1.Container{{
@@ -1057,10 +1206,12 @@ func TestPortConflictNodeDaemonDoesNotLaunchCriticalPod(t *testing.T) {
utilfeature.DefaultFeatureGate.Set("ExperimentalCriticalPodAnnotation=True")
ds := newDaemonSet("critical")
ds.Spec.UpdateStrategy = *strategy
ds.Spec.Template.Spec = podSpec
setDaemonSetCritical(ds)
manager.dsStore.Add(ds)
syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0)
}
}
func setDaemonSetCritical(ds *extensions.DaemonSet) {
@@ -1162,6 +1313,7 @@ func TestNodeShouldRunDaemonPod(t *testing.T) {
}
for i, c := range cases {
for _, strategy := range updateStrategies() {
node := newNode("test-node", nil)
node.Status.Allocatable = allocatableResources("100M", "1")
manager, _, _ := newTestController()
@@ -1170,6 +1322,7 @@ func TestNodeShouldRunDaemonPod(t *testing.T) {
manager.podStore.Add(p)
p.Spec.NodeName = "test-node"
}
c.ds.Spec.UpdateStrategy = *strategy
wantToRun, shouldSchedule, shouldContinueRunning, err := manager.nodeShouldRunDaemonPod(node, c.ds)
if wantToRun != c.wantToRun {
@@ -1185,6 +1338,7 @@ func TestNodeShouldRunDaemonPod(t *testing.T) {
t.Errorf("[%v] expected err: %v, got: %v", i, c.err, err)
}
}
}
}
// DaemonSets should be resynced when node labels or taints changed
@@ -1270,8 +1424,10 @@ func TestUpdateNode(t *testing.T) {
},
}
for _, c := range cases {
for _, strategy := range updateStrategies() {
manager, podControl, _ := newTestController()
manager.nodeStore.Add(c.oldNode)
c.ds.Spec.UpdateStrategy = *strategy
manager.dsStore.Add(c.ds)
syncAndValidateDaemonSets(t, manager, c.ds, podControl, 0, 0)
@@ -1287,11 +1443,15 @@ func TestUpdateNode(t *testing.T) {
t.Errorf("Test case: '%s', expected: %t, got: %t", c.test, c.shouldEnqueue, enqueued)
}
}
}
}
func TestGetNodesToDaemonPods(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
ds2 := newDaemonSet("foo2")
ds2.Spec.UpdateStrategy = *strategy
manager, _, _ := newTestController(ds, ds2)
manager.dsStore.Add(ds)
manager.dsStore.Add(ds2)
@@ -1349,6 +1509,7 @@ func TestGetNodesToDaemonPods(t *testing.T) {
for podName := range gotPods {
t.Errorf("unexpected pod %v was returned", podName)
}
}
}
func TestAddNode(t *testing.T) {
@@ -1375,9 +1536,12 @@ func TestAddNode(t *testing.T) {
}
func TestAddPod(t *testing.T) {
for _, strategy := range updateStrategies() {
manager, _, _ := newTestController()
ds1 := newDaemonSet("foo1")
ds1.Spec.UpdateStrategy = *strategy
ds2 := newDaemonSet("foo2")
ds2.Spec.UpdateStrategy = *strategy
manager.dsStore.Add(ds1)
manager.dsStore.Add(ds2)
@@ -1408,13 +1572,18 @@ func TestAddPod(t *testing.T) {
if got, want := key.(string), expectedKey; got != want {
t.Errorf("queue.Get() = %v, want %v", got, want)
}
}
}
func TestAddPodOrphan(t *testing.T) {
for _, strategy := range updateStrategies() {
manager, _, _ := newTestController()
ds1 := newDaemonSet("foo1")
ds1.Spec.UpdateStrategy = *strategy
ds2 := newDaemonSet("foo2")
ds2.Spec.UpdateStrategy = *strategy
ds3 := newDaemonSet("foo3")
ds3.Spec.UpdateStrategy = *strategy
ds3.Spec.Selector.MatchLabels = simpleDaemonSetLabel2
manager.dsStore.Add(ds1)
manager.dsStore.Add(ds2)
@@ -1429,12 +1598,16 @@ func TestAddPodOrphan(t *testing.T) {
if got, want := getQueuedKeys(manager.queue), []string{"default/foo1", "default/foo2"}; !reflect.DeepEqual(got, want) {
t.Errorf("getQueuedKeys() = %v, want %v", got, want)
}
}
}
func TestUpdatePod(t *testing.T) {
for _, strategy := range updateStrategies() {
manager, _, _ := newTestController()
ds1 := newDaemonSet("foo1")
ds1.Spec.UpdateStrategy = *strategy
ds2 := newDaemonSet("foo2")
ds2.Spec.UpdateStrategy = *strategy
manager.dsStore.Add(ds1)
manager.dsStore.Add(ds2)
@@ -1469,12 +1642,16 @@ func TestUpdatePod(t *testing.T) {
if got, want := key.(string), expectedKey; got != want {
t.Errorf("queue.Get() = %v, want %v", got, want)
}
}
}
func TestUpdatePodOrphanSameLabels(t *testing.T) {
for _, strategy := range updateStrategies() {
manager, _, _ := newTestController()
ds1 := newDaemonSet("foo1")
ds1.Spec.UpdateStrategy = *strategy
ds2 := newDaemonSet("foo2")
ds2.Spec.UpdateStrategy = *strategy
manager.dsStore.Add(ds1)
manager.dsStore.Add(ds2)
@@ -1485,12 +1662,16 @@ func TestUpdatePodOrphanSameLabels(t *testing.T) {
if got, want := manager.queue.Len(), 0; got != want {
t.Fatalf("queue.Len() = %v, want %v", got, want)
}
}
}
func TestUpdatePodOrphanWithNewLabels(t *testing.T) {
for _, strategy := range updateStrategies() {
manager, _, _ := newTestController()
ds1 := newDaemonSet("foo1")
ds1.Spec.UpdateStrategy = *strategy
ds2 := newDaemonSet("foo2")
ds2.Spec.UpdateStrategy = *strategy
manager.dsStore.Add(ds1)
manager.dsStore.Add(ds2)
@@ -1505,9 +1686,13 @@ func TestUpdatePodOrphanWithNewLabels(t *testing.T) {
if got, want := getQueuedKeys(manager.queue), []string{"default/foo1", "default/foo2"}; !reflect.DeepEqual(got, want) {
t.Errorf("getQueuedKeys() = %v, want %v", got, want)
}
}
}
func TestUpdatePodChangeControllerRef(t *testing.T) {
for _, strategy := range updateStrategies() {
ds := newDaemonSet("foo")
ds.Spec.UpdateStrategy = *strategy
manager, _, _ := newTestController()
ds1 := newDaemonSet("foo1")
ds2 := newDaemonSet("foo2")
@@ -1522,12 +1707,16 @@ func TestUpdatePodChangeControllerRef(t *testing.T) {
if got, want := manager.queue.Len(), 2; got != want {
t.Fatalf("queue.Len() = %v, want %v", got, want)
}
}
}
func TestUpdatePodControllerRefRemoved(t *testing.T) {
for _, strategy := range updateStrategies() {
manager, _, _ := newTestController()
ds1 := newDaemonSet("foo1")
ds1.Spec.UpdateStrategy = *strategy
ds2 := newDaemonSet("foo2")
ds2.Spec.UpdateStrategy = *strategy
manager.dsStore.Add(ds1)
manager.dsStore.Add(ds2)
@@ -1539,12 +1728,16 @@ func TestUpdatePodControllerRefRemoved(t *testing.T) {
if got, want := manager.queue.Len(), 2; got != want {
t.Fatalf("queue.Len() = %v, want %v", got, want)
}
}
}
func TestDeletePod(t *testing.T) {
for _, strategy := range updateStrategies() {
manager, _, _ := newTestController()
ds1 := newDaemonSet("foo1")
ds1.Spec.UpdateStrategy = *strategy
ds2 := newDaemonSet("foo2")
ds2.Spec.UpdateStrategy = *strategy
manager.dsStore.Add(ds1)
manager.dsStore.Add(ds2)
@@ -1575,13 +1768,18 @@ func TestDeletePod(t *testing.T) {
if got, want := key.(string), expectedKey; got != want {
t.Errorf("queue.Get() = %v, want %v", got, want)
}
}
}
func TestDeletePodOrphan(t *testing.T) {
for _, strategy := range updateStrategies() {
manager, _, _ := newTestController()
ds1 := newDaemonSet("foo1")
ds1.Spec.UpdateStrategy = *strategy
ds2 := newDaemonSet("foo2")
ds2.Spec.UpdateStrategy = *strategy
ds3 := newDaemonSet("foo3")
ds3.Spec.UpdateStrategy = *strategy
ds3.Spec.Selector.MatchLabels = simpleDaemonSetLabel2
manager.dsStore.Add(ds1)
manager.dsStore.Add(ds2)
@@ -1592,6 +1790,7 @@ func TestDeletePodOrphan(t *testing.T) {
if got, want := manager.queue.Len(), 0; got != want {
t.Fatalf("queue.Len() = %v, want %v", got, want)
}
}
}
func bumpResourceVersion(obj metav1.Object) {

View File

@@ -17,28 +17,37 @@ limitations under the License.
package daemon
import (
"bytes"
"encoding/json"
"fmt"
"sort"
"github.com/golang/glog"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/runtime"
intstrutil "k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/v1"
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
apps "k8s.io/kubernetes/pkg/apis/apps/v1beta1"
extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
"k8s.io/kubernetes/pkg/controller"
"k8s.io/kubernetes/pkg/controller/daemon/util"
labelsutil "k8s.io/kubernetes/pkg/util/labels"
)
// rollingUpdate deletes old daemon set pods making sure that no more than
// ds.Spec.UpdateStrategy.RollingUpdate.MaxUnavailable pods are unavailable
func (dsc *DaemonSetsController) rollingUpdate(ds *extensions.DaemonSet) error {
func (dsc *DaemonSetsController) rollingUpdate(ds *extensions.DaemonSet, hash string) error {
nodeToDaemonPods, err := dsc.getNodesToDaemonPods(ds)
if err != nil {
return fmt.Errorf("couldn't get node to daemon pod mapping for daemon set %q: %v", ds.Name, err)
}
_, oldPods := dsc.getAllDaemonSetPods(ds, nodeToDaemonPods)
_, oldPods := dsc.getAllDaemonSetPods(ds, nodeToDaemonPods, hash)
maxUnavailable, numUnavailable, err := dsc.getUnavailableNumbers(ds, nodeToDaemonPods)
if err != nil {
return fmt.Errorf("Couldn't get unavailable numbers: %v", err)
@@ -46,7 +55,7 @@ func (dsc *DaemonSetsController) rollingUpdate(ds *extensions.DaemonSet) error {
oldAvailablePods, oldUnavailablePods := util.SplitByAvailablePods(ds.Spec.MinReadySeconds, oldPods)
// for oldPods delete all not running pods
var podsToDelete []string
var oldPodsToDelete []string
glog.V(4).Infof("Marking all unavailable old pods for deletion")
for _, pod := range oldUnavailablePods {
// Skip terminating pods. We won't delete them again
@@ -54,7 +63,7 @@ func (dsc *DaemonSetsController) rollingUpdate(ds *extensions.DaemonSet) error {
continue
}
glog.V(4).Infof("Marking pod %s/%s for deletion", ds.Name, pod.Name)
podsToDelete = append(podsToDelete, pod.Name)
oldPodsToDelete = append(oldPodsToDelete, pod.Name)
}
glog.V(4).Infof("Marking old pods for deletion")
@@ -64,20 +73,311 @@ func (dsc *DaemonSetsController) rollingUpdate(ds *extensions.DaemonSet) error {
break
}
glog.V(4).Infof("Marking pod %s/%s for deletion", ds.Name, pod.Name)
podsToDelete = append(podsToDelete, pod.Name)
oldPodsToDelete = append(oldPodsToDelete, pod.Name)
numUnavailable++
}
errors := dsc.syncNodes(ds, podsToDelete, []string{})
return utilerrors.NewAggregate(errors)
return dsc.syncNodes(ds, oldPodsToDelete, []string{}, hash)
}
func (dsc *DaemonSetsController) getAllDaemonSetPods(ds *extensions.DaemonSet, nodeToDaemonPods map[string][]*v1.Pod) ([]*v1.Pod, []*v1.Pod) {
func (dsc *DaemonSetsController) constructHistory(ds *extensions.DaemonSet) (cur *apps.ControllerRevision, old []*apps.ControllerRevision, err error) {
var histories []*apps.ControllerRevision
var currentHistories []*apps.ControllerRevision
histories, err = dsc.controlledHistories(ds)
if err != nil {
return nil, nil, err
}
for _, history := range histories {
// Add the unique label if it's not already added to the history
// We use history name instead of computing hash, so that we don't need to worry about hash collision
if _, ok := history.Labels[extensions.DefaultDaemonSetUniqueLabelKey]; !ok {
var clone interface{}
clone, err = api.Scheme.DeepCopy(history)
if err != nil {
return nil, nil, err
}
toUpdate := clone.(*apps.ControllerRevision)
toUpdate.Labels[extensions.DefaultDaemonSetUniqueLabelKey] = toUpdate.Name
history, err = dsc.kubeClient.AppsV1beta1().ControllerRevisions(ds.Namespace).Update(toUpdate)
if err != nil {
return nil, nil, err
}
}
// Compare histories with ds to separate cur and old history
found := false
found, err = Match(&ds.Spec.Template, history)
if err != nil {
return nil, nil, err
}
if found {
currentHistories = append(currentHistories, history)
} else {
old = append(old, history)
}
}
currRevision := maxRevision(old) + 1
switch len(currentHistories) {
case 0:
// Create a new history if the current one isn't found
cur, err = dsc.snapshot(ds, currRevision)
if err != nil {
return nil, nil, err
}
default:
cur, err = dsc.dedupCurHistories(ds, currentHistories)
if err != nil {
return nil, nil, err
}
// Update revision number if necessary
if cur.Revision < currRevision {
var clone interface{}
clone, err = api.Scheme.DeepCopy(cur)
if err != nil {
return nil, nil, err
}
toUpdate := clone.(*apps.ControllerRevision)
toUpdate.Revision = currRevision
_, err = dsc.kubeClient.AppsV1beta1().ControllerRevisions(ds.Namespace).Update(toUpdate)
if err != nil {
return nil, nil, err
}
}
}
// Label ds with current history's unique label as well
if ds.Labels[extensions.DefaultDaemonSetUniqueLabelKey] != cur.Labels[extensions.DefaultDaemonSetUniqueLabelKey] {
var clone interface{}
clone, err = api.Scheme.DeepCopy(ds)
if err != nil {
return nil, nil, err
}
toUpdate := clone.(*extensions.DaemonSet)
if toUpdate.Labels == nil {
toUpdate.Labels = make(map[string]string)
}
toUpdate.Labels[extensions.DefaultDaemonSetUniqueLabelKey] = cur.Labels[extensions.DefaultDaemonSetUniqueLabelKey]
_, err = dsc.kubeClient.ExtensionsV1beta1().DaemonSets(ds.Namespace).UpdateStatus(toUpdate)
}
return cur, old, err
}
func (dsc *DaemonSetsController) cleanupHistory(ds *extensions.DaemonSet) error {
nodesToDaemonPods, err := dsc.getNodesToDaemonPods(ds)
if err != nil {
return fmt.Errorf("couldn't get node to daemon pod mapping for daemon set %q: %v", ds.Name, err)
}
_, old, err := dsc.constructHistory(ds)
if err != nil {
return fmt.Errorf("failed to construct revisions of DaemonSet: %v", err)
}
toKeep := int(*ds.Spec.RevisionHistoryLimit)
toKill := len(old) - toKeep
if toKill <= 0 {
return nil
}
// Find all hashes of live pods
liveHashes := make(map[string]bool)
for _, pods := range nodesToDaemonPods {
for _, pod := range pods {
if hash := pod.Labels[extensions.DefaultDaemonSetUniqueLabelKey]; len(hash) > 0 {
liveHashes[hash] = true
}
}
}
// Find all live history with the above hashes
liveHistory := make(map[string]bool)
for _, history := range old {
if hash := history.Labels[extensions.DefaultDaemonSetUniqueLabelKey]; liveHashes[hash] {
liveHistory[history.Name] = true
}
}
// Clean up old history from smallest to highest revision (from oldest to newest)
sort.Sort(historiesByRevision(old))
for _, history := range old {
if toKill <= 0 {
break
}
if liveHistory[history.Name] {
continue
}
// Clean up
err := dsc.kubeClient.AppsV1beta1().ControllerRevisions(ds.Namespace).Delete(history.Name, nil)
if err != nil {
return err
}
toKill--
}
return nil
}
// maxRevision returns the max revision number of the given list of histories
func maxRevision(histories []*apps.ControllerRevision) int64 {
max := int64(0)
for _, history := range histories {
if history.Revision > max {
max = history.Revision
}
}
return max
}
func (dsc *DaemonSetsController) dedupCurHistories(ds *extensions.DaemonSet, curHistories []*apps.ControllerRevision) (*apps.ControllerRevision, error) {
if len(curHistories) == 1 {
return curHistories[0], nil
}
var maxRevision int64
var keepCur *apps.ControllerRevision
for _, cur := range curHistories {
if cur.Revision >= maxRevision {
keepCur = cur
maxRevision = cur.Revision
}
}
// Clean up duplicates and relabel pods
for _, cur := range curHistories {
if cur.Name == keepCur.Name {
continue
}
// Relabel pods before dedup
pods, err := dsc.getDaemonPods(ds)
if err != nil {
return nil, err
}
for _, pod := range pods {
if pod.Labels[extensions.DefaultDaemonSetUniqueLabelKey] != keepCur.Labels[extensions.DefaultDaemonSetUniqueLabelKey] {
clone, err := api.Scheme.DeepCopy(pod)
if err != nil {
return nil, err
}
toUpdate := clone.(*v1.Pod)
if toUpdate.Labels == nil {
toUpdate.Labels = make(map[string]string)
}
toUpdate.Labels[extensions.DefaultDaemonSetUniqueLabelKey] = keepCur.Labels[extensions.DefaultDaemonSetUniqueLabelKey]
_, err = dsc.kubeClient.Core().Pods(ds.Namespace).Update(toUpdate)
if err != nil {
return nil, err
}
}
}
// Remove duplicates
err = dsc.kubeClient.AppsV1beta1().ControllerRevisions(ds.Namespace).Delete(cur.Name, nil)
if err != nil {
return nil, err
}
}
return keepCur, nil
}
// controlledHistories returns all ControllerRevisions controlled by the given DaemonSet
// Note that returned histories are pointers to objects in the cache.
// If you want to modify one, you need to deep-copy it first.
func (dsc *DaemonSetsController) controlledHistories(ds *extensions.DaemonSet) ([]*apps.ControllerRevision, error) {
var result []*apps.ControllerRevision
selector, err := metav1.LabelSelectorAsSelector(ds.Spec.Selector)
if err != nil {
return nil, err
}
histories, err := dsc.historyLister.List(selector)
if err != nil {
return nil, err
}
for _, history := range histories {
// Skip history that doesn't belong to the DaemonSet
if controllerRef := controller.GetControllerOf(history); controllerRef == nil || controllerRef.UID != ds.UID {
continue
}
result = append(result, history)
}
return result, nil
}
// Match check if ds template is semantically equal to the template stored in history
func Match(template *v1.PodTemplateSpec, history *apps.ControllerRevision) (bool, error) {
t, err := decodeHistory(history)
return apiequality.Semantic.DeepEqual(template, t), err
}
func decodeHistory(history *apps.ControllerRevision) (*v1.PodTemplateSpec, error) {
raw := history.Data.Raw
decoder := json.NewDecoder(bytes.NewBuffer(raw))
template := v1.PodTemplateSpec{}
err := decoder.Decode(&template)
return &template, err
}
func encodeTemplate(template *v1.PodTemplateSpec) ([]byte, error) {
buffer := new(bytes.Buffer)
encoder := json.NewEncoder(buffer)
err := encoder.Encode(template)
return buffer.Bytes(), err
}
func (dsc *DaemonSetsController) snapshot(ds *extensions.DaemonSet, revision int64) (*apps.ControllerRevision, error) {
encodedTemplate, err := encodeTemplate(&ds.Spec.Template)
if err != nil {
return nil, err
}
hash := fmt.Sprint(controller.ComputeHash(&ds.Spec.Template, ds.Status.CollisionCount))
name := ds.Name + "-" + hash
history := &apps.ControllerRevision{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: ds.Namespace,
Labels: labelsutil.CloneAndAddLabel(ds.Spec.Template.Labels, extensions.DefaultDaemonSetUniqueLabelKey, hash),
Annotations: ds.Annotations,
OwnerReferences: []metav1.OwnerReference{*newControllerRef(ds)},
},
Data: runtime.RawExtension{Raw: encodedTemplate},
Revision: revision,
}
history, err = dsc.kubeClient.AppsV1beta1().ControllerRevisions(ds.Namespace).Create(history)
if errors.IsAlreadyExists(err) {
// TODO: Is it okay to get from historyLister?
existedHistory, getErr := dsc.kubeClient.AppsV1beta1().ControllerRevisions(ds.Namespace).Get(name, metav1.GetOptions{})
if getErr != nil {
return nil, getErr
}
// Check if we already created it
done, err := Match(&ds.Spec.Template, existedHistory)
if err != nil {
return nil, err
}
if done {
return existedHistory, nil
}
// Handle name collisions between different history
// TODO: Is it okay to get from dsLister?
currDS, getErr := dsc.kubeClient.ExtensionsV1beta1().DaemonSets(ds.Namespace).Get(ds.Name, metav1.GetOptions{})
if getErr != nil {
return nil, getErr
}
if currDS.Status.CollisionCount == nil {
currDS.Status.CollisionCount = new(int64)
}
*currDS.Status.CollisionCount++
_, updateErr := dsc.kubeClient.ExtensionsV1beta1().DaemonSets(ds.Namespace).UpdateStatus(currDS)
if updateErr != nil {
return nil, updateErr
}
glog.V(2).Infof("Found a hash collision for DaemonSet %q - bumping collisionCount to %d to resolve it", ds.Name, *currDS.Status.CollisionCount)
return nil, err
}
return history, err
}
func (dsc *DaemonSetsController) getAllDaemonSetPods(ds *extensions.DaemonSet, nodeToDaemonPods map[string][]*v1.Pod, hash string) ([]*v1.Pod, []*v1.Pod) {
var newPods []*v1.Pod
var oldPods []*v1.Pod
for _, pods := range nodeToDaemonPods {
for _, pod := range pods {
if util.IsPodUpdated(ds.Spec.TemplateGeneration, pod) {
if util.IsPodUpdated(ds.Spec.TemplateGeneration, pod, hash) {
newPods = append(newPods, pod)
} else {
oldPods = append(oldPods, pod)
@@ -129,3 +429,11 @@ func (dsc *DaemonSetsController) getUnavailableNumbers(ds *extensions.DaemonSet,
glog.V(4).Infof(" DaemonSet %s/%s, maxUnavailable: %d, numUnavailable: %d", ds.Namespace, ds.Name, maxUnavailable, numUnavailable)
return maxUnavailable, numUnavailable, nil
}
type historiesByRevision []*apps.ControllerRevision
func (h historiesByRevision) Len() int { return len(h) }
func (h historiesByRevision) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h historiesByRevision) Less(i, j int) bool {
return h[i].Revision < h[j].Revision
}

View File

@@ -29,9 +29,10 @@ import (
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
)
// GetPodTemplateWithHash returns copy of provided template with additional
// label which contains hash of provided template and sets default daemon tolerations.
func GetPodTemplateWithGeneration(template v1.PodTemplateSpec, generation int64) v1.PodTemplateSpec {
// CreatePodTemplate returns copy of provided template with additional
// label which contains templateGeneration (for backward compatibility),
// hash of provided template and sets default daemon tolerations.
func CreatePodTemplate(template v1.PodTemplateSpec, generation int64, hash string) v1.PodTemplateSpec {
obj, _ := api.Scheme.DeepCopy(template)
newTemplate := obj.(v1.PodTemplateSpec)
// DaemonSet pods shouldn't be deleted by NodeController in case of node problems.
@@ -60,14 +61,19 @@ func GetPodTemplateWithGeneration(template v1.PodTemplateSpec, generation int64)
extensions.DaemonSetTemplateGenerationKey,
templateGenerationStr,
)
// TODO: do we need to validate if the DaemonSet is RollingUpdate or not?
if len(hash) > 0 {
newTemplate.ObjectMeta.Labels[extensions.DefaultDaemonSetUniqueLabelKey] = hash
}
return newTemplate
}
// IsPodUpdate checks if pod contains label with provided hash
func IsPodUpdated(dsTemplateGeneration int64, pod *v1.Pod) bool {
podTemplateGeneration, generationExists := pod.ObjectMeta.Labels[extensions.DaemonSetTemplateGenerationKey]
dsTemplateGenerationStr := fmt.Sprint(dsTemplateGeneration)
return generationExists && podTemplateGeneration == dsTemplateGenerationStr
// IsPodUpdate checks if pod contains label value that either matches templateGeneration or hash
func IsPodUpdated(dsTemplateGeneration int64, pod *v1.Pod, hash string) bool {
// Compare with hash to see if the pod is updated, need to maintain backward compatibility of templateGeneration
templateMatches := pod.Labels[extensions.DaemonSetTemplateGenerationKey] == fmt.Sprint(dsTemplateGeneration)
hashMatches := len(hash) > 0 && pod.Labels[extensions.DefaultDaemonSetUniqueLabelKey] == hash
return hashMatches || templateMatches
}
// SplitByAvailablePods splits provided daemon set pods by availabilty

View File

@@ -47,46 +47,118 @@ func newPod(podName string, nodeName string, label map[string]string) *v1.Pod {
}
func TestIsPodUpdated(t *testing.T) {
templateGeneration := int64(12345)
hash := "55555"
labels := map[string]string{extensions.DaemonSetTemplateGenerationKey: fmt.Sprint(templateGeneration), extensions.DefaultDaemonSetUniqueLabelKey: hash}
labelsNoHash := map[string]string{extensions.DaemonSetTemplateGenerationKey: fmt.Sprint(templateGeneration)}
tests := []struct {
test string
templateGeneration int64
pod *v1.Pod
hash string
isUpdated bool
}{
{
int64(12345),
newPod("pod1", "node1", map[string]string{extensions.DaemonSetTemplateGenerationKey: "12345"}),
"templateGeneration and hash both match",
templateGeneration,
newPod("pod1", "node1", labels),
hash,
true,
},
{
int64(12355),
newPod("pod1", "node1", map[string]string{extensions.DaemonSetTemplateGenerationKey: "12345"}),
"templateGeneration matches, hash doesn't",
templateGeneration,
newPod("pod1", "node1", labels),
hash + "123",
true,
},
{
"templateGeneration matches, no hash label, has hash",
templateGeneration,
newPod("pod1", "node1", labelsNoHash),
hash,
true,
},
{
"templateGeneration matches, no hash label, no hash",
templateGeneration,
newPod("pod1", "node1", labelsNoHash),
"",
true,
},
{
"templateGeneration matches, has hash label, no hash",
templateGeneration,
newPod("pod1", "node1", labels),
"",
true,
},
{
"templateGeneration doesn't match, hash does",
templateGeneration + 1,
newPod("pod1", "node1", labels),
hash,
true,
},
{
"templateGeneration and hash don't match",
templateGeneration + 1,
newPod("pod1", "node1", labels),
hash + "123",
false,
},
{
int64(12355),
"empty labels, no hash",
templateGeneration,
newPod("pod1", "node1", map[string]string{}),
"",
false,
},
{
int64(12355),
"empty labels",
templateGeneration,
newPod("pod1", "node1", map[string]string{}),
hash,
false,
},
{
"no labels",
templateGeneration,
newPod("pod1", "node1", nil),
hash,
false,
},
}
for _, test := range tests {
updated := IsPodUpdated(test.templateGeneration, test.pod)
updated := IsPodUpdated(test.templateGeneration, test.pod, test.hash)
if updated != test.isUpdated {
t.Errorf("IsPodUpdated returned wrong value. Expected %t, got %t. TemplateGeneration: %d", test.isUpdated, updated, test.templateGeneration)
t.Errorf("%s: IsPodUpdated returned wrong value. Expected %t, got %t", test.test, test.isUpdated, updated)
}
}
}
func TestGetPodTemplateWithGeneration(t *testing.T) {
generation := int64(1)
func TestCreatePodTemplate(t *testing.T) {
tests := []struct {
templateGeneration int64
hash string
expectUniqueLabel bool
}{
{int64(1), "", false},
{int64(2), "3242341807", true},
}
for _, test := range tests {
podTemplateSpec := v1.PodTemplateSpec{}
newPodTemplate := GetPodTemplateWithGeneration(podTemplateSpec, generation)
label, exists := newPodTemplate.ObjectMeta.Labels[extensions.DaemonSetTemplateGenerationKey]
if !exists || label != fmt.Sprint(generation) {
t.Errorf("Error in getting podTemplateSpec with label generation. Exists: %t, label: %s", exists, label)
newPodTemplate := CreatePodTemplate(podTemplateSpec, test.templateGeneration, test.hash)
val, exists := newPodTemplate.ObjectMeta.Labels[extensions.DaemonSetTemplateGenerationKey]
if !exists || val != fmt.Sprint(test.templateGeneration) {
t.Errorf("Expected podTemplateSpec to have generation label value: %d, got: %s", test.templateGeneration, val)
}
val, exists = newPodTemplate.ObjectMeta.Labels[extensions.DefaultDaemonSetUniqueLabelKey]
if test.expectUniqueLabel && (!exists || val != test.hash) {
t.Errorf("Expected podTemplateSpec to have hash label value: %s, got: %s", test.hash, val)
}
if !test.expectUniqueLabel && exists {
t.Errorf("Expected podTemplateSpec to have no hash label, got: %s", val)
}
}
}

View File

@@ -288,7 +288,7 @@ func (dc *DeploymentController) getNewReplicaSet(d *extensions.Deployment, rsLis
return nil, err
}
newRSTemplate := templateCopy.(v1.PodTemplateSpec)
podTemplateSpecHash := fmt.Sprintf("%d", deploymentutil.GetPodTemplateSpecHash(&newRSTemplate, d.Status.CollisionCount))
podTemplateSpecHash := fmt.Sprintf("%d", controller.ComputeHash(&newRSTemplate, d.Status.CollisionCount))
newRSTemplate.Labels = labelsutil.CloneAndAddLabel(d.Spec.Template.Labels, extensions.DefaultDeploymentUniqueLabelKey, podTemplateSpecHash)
// Add podTemplateHash label to selector.
newRSSelector := labelsutil.CloneSelectorAndAddLabel(d.Spec.Selector, extensions.DefaultDeploymentUniqueLabelKey, podTemplateSpecHash)

View File

@@ -28,7 +28,6 @@ go_library(
"//pkg/client/listers/extensions/v1beta1:go_default_library",
"//pkg/client/retry:go_default_library",
"//pkg/controller:go_default_library",
"//pkg/util/hash:go_default_library",
"//pkg/util/labels:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
@@ -48,7 +47,6 @@ go_test(
srcs = [
"deployment_util_test.go",
"hash_test.go",
"pod_util_test.go",
],
library = ":go_default_library",
tags = ["automanaged"],

View File

@@ -24,6 +24,7 @@ import (
"testing"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/controller"
hashutil "k8s.io/kubernetes/pkg/util/hash"
)
@@ -110,7 +111,7 @@ func TestPodTemplateSpecHash(t *testing.T) {
specJson := strings.Replace(podSpec, "@@VERSION@@", strconv.Itoa(i), 1)
spec := v1.PodTemplateSpec{}
json.Unmarshal([]byte(specJson), &spec)
hash := GetPodTemplateSpecHash(&spec, nil)
hash := controller.ComputeHash(&spec, nil)
if v, ok := seenHashes[hash]; ok {
t.Errorf("Hash collision, old: %d new: %d", v, i)
break
@@ -139,6 +140,6 @@ func BenchmarkFnv(b *testing.B) {
json.Unmarshal([]byte(podSpec), &spec)
for i := 0; i < b.N; i++ {
GetPodTemplateSpecHash(&spec, nil)
controller.ComputeHash(&spec, nil)
}
}

View File

@@ -17,9 +17,6 @@ limitations under the License.
package util
import (
"encoding/binary"
"hash/fnv"
"github.com/golang/glog"
errorsutil "k8s.io/apimachinery/pkg/util/errors"
@@ -28,23 +25,8 @@ import (
v1core "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/core/v1"
corelisters "k8s.io/kubernetes/pkg/client/listers/core/v1"
"k8s.io/kubernetes/pkg/client/retry"
hashutil "k8s.io/kubernetes/pkg/util/hash"
)
func GetPodTemplateSpecHash(template *v1.PodTemplateSpec, uniquifier *int64) uint32 {
podTemplateSpecHasher := fnv.New32a()
hashutil.DeepHashObject(podTemplateSpecHasher, *template)
// Add uniquifier in the hash if it exists.
if uniquifier != nil {
uniquifierBytes := make([]byte, 8)
binary.LittleEndian.PutUint64(uniquifierBytes, uint64(*uniquifier))
podTemplateSpecHasher.Write(uniquifierBytes)
}
return podTemplateSpecHasher.Sum32()
}
// TODO: use client library instead when it starts to support update retries
// see https://github.com/kubernetes/kubernetes/issues/21479
type updatePodFunc func(pod *v1.Pod) error

View File

@@ -1,59 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package util
import (
"math"
"testing"
"k8s.io/kubernetes/pkg/api/v1"
)
func int64P(num int64) *int64 {
return &num
}
func TestGetPodTemplateSpecHash(t *testing.T) {
tests := []struct {
name string
template *v1.PodTemplateSpec
collisionCount *int64
otherCollisionCount *int64
}{
{
name: "simple",
template: &v1.PodTemplateSpec{},
collisionCount: int64P(1),
otherCollisionCount: int64P(2),
},
{
name: "using math.MaxInt64",
template: &v1.PodTemplateSpec{},
collisionCount: nil,
otherCollisionCount: int64P(int64(math.MaxInt64)),
},
}
for _, test := range tests {
hash := GetPodTemplateSpecHash(test.template, test.collisionCount)
otherHash := GetPodTemplateSpecHash(test.template, test.otherCollisionCount)
if hash == otherHash {
t.Errorf("expected different hashes but got the same: %d", hash)
}
}
}

View File

@@ -28,6 +28,7 @@ import (
unversionedextensions "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/extensions/v1beta1"
extensionslisters "k8s.io/kubernetes/pkg/client/listers/extensions/v1beta1"
"k8s.io/kubernetes/pkg/client/retry"
"k8s.io/kubernetes/pkg/controller"
labelsutil "k8s.io/kubernetes/pkg/util/labels"
)
@@ -76,5 +77,5 @@ func GetReplicaSetHash(rs *extensions.ReplicaSet, uniquifier *int64) (string, er
}
rsTemplate := template.(v1.PodTemplateSpec)
rsTemplate.Labels = labelsutil.CloneAndRemoveLabel(rsTemplate.Labels, extensions.DefaultDeploymentUniqueLabelKey)
return fmt.Sprintf("%d", GetPodTemplateSpecHash(&rsTemplate, uniquifier)), nil
return fmt.Sprintf("%d", controller.ComputeHash(&rsTemplate, uniquifier)), nil
}

View File

@@ -86,6 +86,7 @@ func init() {
rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
rbac.NewRule("list", "watch", "create", "delete", "patch").Groups(legacyGroup).Resources("pods").RuleOrDie(),
rbac.NewRule("create").Groups(legacyGroup).Resources("pods/binding").RuleOrDie(),
rbac.NewRule("list", "watch", "create", "delete", "update", "patch").Groups(appsGroup).Resources("controllerrevisions").RuleOrDie(),
eventsRule(),
},
})

View File

@@ -180,6 +180,17 @@ items:
- pods/binding
verbs:
- create
- apiGroups:
- apps
resources:
- controllerrevisions
verbs:
- create
- delete
- list
- patch
- update
- watch
- apiGroups:
- ""
resources:

View File

@@ -28,6 +28,7 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
"//vendor/k8s.io/client-go/pkg/api/v1:go_default_library",
"//vendor/k8s.io/client-go/pkg/apis/apps/v1beta1:go_default_library",
"//vendor/k8s.io/client-go/pkg/apis/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/client-go/tools/cache:go_default_library",
],

View File

@@ -22,6 +22,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/pkg/api/v1"
apps "k8s.io/client-go/pkg/apis/apps/v1beta1"
"k8s.io/client-go/pkg/apis/extensions/v1beta1"
)
@@ -29,6 +30,7 @@ import (
// DaemonSetLister.
type DaemonSetListerExpansion interface {
GetPodDaemonSets(pod *v1.Pod) ([]*v1beta1.DaemonSet, error)
GetHistoryDaemonSets(history *apps.ControllerRevision) ([]*v1beta1.DaemonSet, error)
}
// DaemonSetNamespaceListerExpansion allows custom methods to be added to
@@ -76,3 +78,37 @@ func (s *daemonSetLister) GetPodDaemonSets(pod *v1.Pod) ([]*v1beta1.DaemonSet, e
return daemonSets, nil
}
// GetHistoryDaemonSets returns a list of DaemonSets that potentially
// match a ControllerRevision. Only the one specified in the ControllerRevision's ControllerRef
// will actually manage it.
// Returns an error only if no matching DaemonSets are found.
func (s *daemonSetLister) GetHistoryDaemonSets(history *apps.ControllerRevision) ([]*v1beta1.DaemonSet, error) {
if len(history.Labels) == 0 {
return nil, fmt.Errorf("no DaemonSet found for ControllerRevision %s because it has no labels", history.Name)
}
list, err := s.DaemonSets(history.Namespace).List(labels.Everything())
if err != nil {
return nil, err
}
var daemonSets []*v1beta1.DaemonSet
for _, ds := range list {
selector, err := metav1.LabelSelectorAsSelector(ds.Spec.Selector)
if err != nil {
return nil, fmt.Errorf("invalid label selector: %v", err)
}
// If a DaemonSet with a nil or empty selector creeps in, it should match nothing, not everything.
if selector.Empty() || !selector.Matches(labels.Set(history.Labels)) {
continue
}
daemonSets = append(daemonSets, ds)
}
if len(daemonSets) == 0 {
return nil, fmt.Errorf("could not find DaemonSets for ControllerRevision %s in namespace %s with labels: %v", history.Name, history.Namespace, history.Labels)
}
return daemonSets, nil
}

View File

@@ -386,7 +386,7 @@ type DaemonSetUpdateStrategy struct {
// Rolling update config params. Present only if type = "RollingUpdate".
//---
// TODO: Update this to follow our convention for oneOf, whatever we decide it
// to be. Same as DeploymentStrategy.RollingUpdate.
// to be. Same as Deployment `strategy.rollingUpdate`.
// See https://github.com/kubernetes/kubernetes/issues/35345
// +optional
RollingUpdate *RollingUpdateDaemonSet
@@ -449,10 +449,17 @@ type DaemonSetSpec struct {
// +optional
MinReadySeconds int32
// DEPRECATED.
// A sequence number representing a specific generation of the template.
// Populated by the system. It can be set only during the creation.
// +optional
TemplateGeneration int64
// The number of old history to retain to allow rollback.
// This is a pointer to distinguish between explicit zero and not specified.
// Defaults to 10.
// +optional
RevisionHistoryLimit *int32
}
// DaemonSetStatus represents the current status of a daemon set.
@@ -492,6 +499,12 @@ type DaemonSetStatus struct {
// (ready for at least spec.minReadySeconds)
// +optional
NumberUnavailable int32
// Count of hash collisions for the DaemonSet. The DaemonSet controller
// uses this field as a collision avoidance mechanism when it needs to
// create the name for the newest ControllerRevision.
// +optional
CollisionCount *int64
}
// +genclient=true
@@ -519,10 +532,16 @@ type DaemonSet struct {
}
const (
// DEPRECATED: DefaultDaemonSetUniqueLabelKey is used instead.
// DaemonSetTemplateGenerationKey is the key of the labels that is added
// to daemon set pods to distinguish between old and new pod templates
// during DaemonSet template update.
DaemonSetTemplateGenerationKey string = "pod-template-generation"
// DefaultDaemonSetUniqueLabelKey is the default label key that is added
// to existing DaemonSet pods to distinguish between old and new
// DaemonSet pods during DaemonSet template updates.
DefaultDaemonSetUniqueLabelKey string = "daemonset-controller-hash"
)
// DaemonSetList is a collection of daemon sets.

View File

@@ -56,6 +56,10 @@ func SetDefaults_DaemonSet(obj *DaemonSet) {
updateStrategy.RollingUpdate.MaxUnavailable = &maxUnavailable
}
}
if obj.Spec.RevisionHistoryLimit == nil {
obj.Spec.RevisionHistoryLimit = new(int32)
*obj.Spec.RevisionHistoryLimit = 10
}
}
func SetDefaults_Deployment(obj *Deployment) {

View File

@@ -689,6 +689,11 @@ func (m *DaemonSetSpec) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0x28
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.TemplateGeneration))
if m.RevisionHistoryLimit != nil {
dAtA[i] = 0x30
i++
i = encodeVarintGenerated(dAtA, i, uint64(*m.RevisionHistoryLimit))
}
return i, nil
}
@@ -731,6 +736,11 @@ func (m *DaemonSetStatus) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0x40
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.NumberUnavailable))
if m.CollisionCount != nil {
dAtA[i] = 0x48
i++
i = encodeVarintGenerated(dAtA, i, uint64(*m.CollisionCount))
}
return i, nil
}
@@ -2795,6 +2805,9 @@ func (m *DaemonSetSpec) Size() (n int) {
n += 1 + l + sovGenerated(uint64(l))
n += 1 + sovGenerated(uint64(m.MinReadySeconds))
n += 1 + sovGenerated(uint64(m.TemplateGeneration))
if m.RevisionHistoryLimit != nil {
n += 1 + sovGenerated(uint64(*m.RevisionHistoryLimit))
}
return n
}
@@ -2809,6 +2822,9 @@ func (m *DaemonSetStatus) Size() (n int) {
n += 1 + sovGenerated(uint64(m.UpdatedNumberScheduled))
n += 1 + sovGenerated(uint64(m.NumberAvailable))
n += 1 + sovGenerated(uint64(m.NumberUnavailable))
if m.CollisionCount != nil {
n += 1 + sovGenerated(uint64(*m.CollisionCount))
}
return n
}
@@ -3605,6 +3621,7 @@ func (this *DaemonSetSpec) String() string {
`UpdateStrategy:` + strings.Replace(strings.Replace(this.UpdateStrategy.String(), "DaemonSetUpdateStrategy", "DaemonSetUpdateStrategy", 1), `&`, ``, 1) + `,`,
`MinReadySeconds:` + fmt.Sprintf("%v", this.MinReadySeconds) + `,`,
`TemplateGeneration:` + fmt.Sprintf("%v", this.TemplateGeneration) + `,`,
`RevisionHistoryLimit:` + valueToStringGenerated(this.RevisionHistoryLimit) + `,`,
`}`,
}, "")
return s
@@ -3622,6 +3639,7 @@ func (this *DaemonSetStatus) String() string {
`UpdatedNumberScheduled:` + fmt.Sprintf("%v", this.UpdatedNumberScheduled) + `,`,
`NumberAvailable:` + fmt.Sprintf("%v", this.NumberAvailable) + `,`,
`NumberUnavailable:` + fmt.Sprintf("%v", this.NumberUnavailable) + `,`,
`CollisionCount:` + valueToStringGenerated(this.CollisionCount) + `,`,
`}`,
}, "")
return s
@@ -5102,6 +5120,26 @@ func (m *DaemonSetSpec) Unmarshal(dAtA []byte) error {
break
}
}
case 6:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field RevisionHistoryLimit", wireType)
}
var v int32
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= (int32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.RevisionHistoryLimit = &v
default:
iNdEx = preIndex
skippy, err := skipGenerated(dAtA[iNdEx:])
@@ -5304,6 +5342,26 @@ func (m *DaemonSetStatus) Unmarshal(dAtA []byte) error {
break
}
}
case 9:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field CollisionCount", wireType)
}
var v int64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.CollisionCount = &v
default:
iNdEx = preIndex
skippy, err := skipGenerated(dAtA[iNdEx:])
@@ -11873,219 +11931,220 @@ func init() {
}
var fileDescriptorGenerated = []byte{
// 3412 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x5b, 0xdd, 0x6f, 0x1c, 0x57,
0x15, 0xcf, 0x78, 0xbd, 0xf1, 0xfa, 0x6c, 0x6c, 0xc7, 0xd7, 0xae, 0xb3, 0x75, 0x5b, 0x3b, 0x1d,
0x44, 0x9b, 0x42, 0xbb, 0xa6, 0x29, 0x29, 0x6d, 0xda, 0xa6, 0xf5, 0xda, 0xf9, 0x30, 0xb2, 0x9d,
0xed, 0xdd, 0x75, 0x44, 0xd3, 0x2f, 0xc6, 0xbb, 0xd7, 0xeb, 0x49, 0xe6, 0xab, 0x33, 0x77, 0x5c,
0xaf, 0x2a, 0xa0, 0x12, 0xa2, 0x0f, 0x3c, 0x20, 0x78, 0x41, 0x45, 0x82, 0x47, 0x1e, 0x78, 0x81,
0xf6, 0x01, 0x0a, 0x7f, 0x01, 0x79, 0x40, 0xa8, 0x48, 0x20, 0x55, 0xa8, 0x58, 0xc4, 0x15, 0xfd,
0x07, 0xa0, 0x2f, 0x79, 0x42, 0xf7, 0xce, 0x9d, 0xef, 0x19, 0x27, 0xbb, 0x4e, 0x56, 0x48, 0xbc,
0xed, 0xdc, 0x7b, 0xce, 0xef, 0x7c, 0xdc, 0x73, 0xcf, 0x3d, 0xf7, 0x63, 0xe1, 0x85, 0xeb, 0xcf,
0x38, 0x55, 0xd5, 0x5c, 0xb8, 0xee, 0x6e, 0x12, 0xdb, 0x20, 0x94, 0x38, 0x0b, 0xd6, 0xf5, 0xce,
0x82, 0x62, 0xa9, 0xce, 0x02, 0xd9, 0xa5, 0xc4, 0x70, 0x54, 0xd3, 0x70, 0x16, 0x76, 0x9e, 0xdc,
0x24, 0x54, 0x79, 0x72, 0xa1, 0x43, 0x0c, 0x62, 0x2b, 0x94, 0xb4, 0xab, 0x96, 0x6d, 0x52, 0x13,
0x3d, 0xe1, 0xb1, 0x57, 0x43, 0xf6, 0xaa, 0x75, 0xbd, 0x53, 0x65, 0xec, 0xd5, 0x90, 0xbd, 0x2a,
0xd8, 0x67, 0x9f, 0xe8, 0xa8, 0x74, 0xdb, 0xdd, 0xac, 0xb6, 0x4c, 0x7d, 0xa1, 0x63, 0x76, 0xcc,
0x05, 0x8e, 0xb2, 0xe9, 0x6e, 0xf1, 0x2f, 0xfe, 0xc1, 0x7f, 0x79, 0xe8, 0xb3, 0x5f, 0x17, 0xca,
0x29, 0x96, 0xaa, 0x2b, 0xad, 0x6d, 0xd5, 0x20, 0x76, 0xd7, 0x57, 0x6f, 0xc1, 0x26, 0x8e, 0xe9,
0xda, 0x2d, 0x92, 0xd4, 0xe9, 0x40, 0x2e, 0x67, 0x41, 0x27, 0x54, 0x59, 0xd8, 0x49, 0x59, 0x32,
0xbb, 0x90, 0xc7, 0x65, 0xbb, 0x06, 0x55, 0xf5, 0xb4, 0x98, 0xa7, 0x6f, 0xc7, 0xe0, 0xb4, 0xb6,
0x89, 0xae, 0xa4, 0xf8, 0x9e, 0xca, 0xe3, 0x73, 0xa9, 0xaa, 0x2d, 0xa8, 0x06, 0x75, 0xa8, 0x9d,
0x62, 0x7a, 0x3c, 0x77, 0x98, 0xb2, 0x6c, 0x79, 0xf6, 0x80, 0x41, 0xb5, 0x4c, 0x4d, 0x6d, 0x75,
0xf3, 0x06, 0x54, 0xae, 0x02, 0x2c, 0xd6, 0x57, 0xae, 0x10, 0x9b, 0x0d, 0x1c, 0x3a, 0x09, 0xc3,
0x86, 0xa2, 0x93, 0x8a, 0x74, 0x52, 0x3a, 0x35, 0x5a, 0x3b, 0x76, 0x63, 0x6f, 0xfe, 0xc8, 0xfe,
0xde, 0xfc, 0xf0, 0xba, 0xa2, 0x13, 0xcc, 0x7b, 0xe4, 0x9f, 0x49, 0x70, 0xff, 0x92, 0xeb, 0x50,
0x53, 0x5f, 0x23, 0xd4, 0x56, 0x5b, 0x4b, 0xae, 0x6d, 0x13, 0x83, 0x36, 0xa8, 0x42, 0x5d, 0xe7,
0xf6, 0xfc, 0xe8, 0x2a, 0x14, 0x77, 0x14, 0xcd, 0x25, 0x95, 0xa1, 0x93, 0xd2, 0xa9, 0xf2, 0xe9,
0x6a, 0x55, 0x04, 0x54, 0xd4, 0x3b, 0x7e, 0x48, 0x55, 0xfd, 0x21, 0xaf, 0xbe, 0xec, 0x2a, 0x06,
0x55, 0x69, 0xb7, 0x36, 0x2d, 0x20, 0x8f, 0x09, 0xb9, 0x57, 0x18, 0x16, 0xf6, 0x20, 0xe5, 0x1f,
0x49, 0xf0, 0x50, 0xae, 0x6e, 0xab, 0xaa, 0x43, 0x91, 0x0e, 0x45, 0x95, 0x12, 0xdd, 0xa9, 0x48,
0x27, 0x0b, 0xa7, 0xca, 0xa7, 0x2f, 0x55, 0x7b, 0x0a, 0xe7, 0x6a, 0x2e, 0x78, 0x6d, 0x4c, 0xe8,
0x55, 0x5c, 0x61, 0xf0, 0xd8, 0x93, 0x22, 0xff, 0x44, 0x02, 0x14, 0xe5, 0x69, 0x2a, 0x76, 0x87,
0xd0, 0x3b, 0xf0, 0xd2, 0x2b, 0x87, 0xf3, 0xd2, 0x94, 0x80, 0x2c, 0x7b, 0x02, 0x63, 0x4e, 0x7a,
0x57, 0x82, 0x99, 0xb4, 0x4e, 0xdc, 0x3b, 0x5b, 0x71, 0xef, 0x2c, 0x1e, 0xc2, 0x3b, 0x1e, 0x6a,
0x8e, 0x5b, 0x7e, 0x3b, 0x04, 0xa3, 0xcb, 0x0a, 0xd1, 0x4d, 0xa3, 0x41, 0x28, 0xfa, 0x36, 0x94,
0xd8, 0x1c, 0x6d, 0x2b, 0x54, 0xe1, 0x1e, 0x29, 0x9f, 0xfe, 0xda, 0x41, 0xe6, 0x3a, 0x55, 0x46,
0x5d, 0xdd, 0x79, 0xb2, 0x7a, 0x79, 0xf3, 0x1a, 0x69, 0xd1, 0x35, 0x42, 0x95, 0x1a, 0x12, 0x72,
0x20, 0x6c, 0xc3, 0x01, 0x2a, 0x7a, 0x03, 0x86, 0x1d, 0x8b, 0xb4, 0x84, 0x33, 0x9f, 0xef, 0xd1,
0xac, 0x40, 0xd3, 0x86, 0x45, 0x5a, 0xe1, 0x68, 0xb1, 0x2f, 0xcc, 0x71, 0xd1, 0x16, 0x1c, 0x75,
0x78, 0x18, 0x54, 0x0a, 0x5c, 0xc2, 0xb9, 0xbe, 0x25, 0x78, 0xc1, 0x34, 0x2e, 0x64, 0x1c, 0xf5,
0xbe, 0xb1, 0x40, 0x97, 0xff, 0x24, 0xc1, 0x58, 0x40, 0xcb, 0x47, 0xec, 0xb5, 0x94, 0xef, 0xaa,
0x77, 0xe6, 0x3b, 0xc6, 0xcd, 0x3d, 0x77, 0x5c, 0xc8, 0x2a, 0xf9, 0x2d, 0x11, 0xbf, 0xbd, 0xee,
0xc7, 0xc3, 0x10, 0x8f, 0x87, 0x67, 0xfa, 0x35, 0x2b, 0x27, 0x0c, 0x3e, 0x2b, 0x44, 0xcc, 0x61,
0xee, 0x44, 0xaf, 0x43, 0xc9, 0x21, 0x1a, 0x69, 0x51, 0xd3, 0x16, 0xe6, 0x3c, 0x75, 0x87, 0xe6,
0x28, 0x9b, 0x44, 0x6b, 0x08, 0xd6, 0xda, 0x31, 0x66, 0x8f, 0xff, 0x85, 0x03, 0x48, 0xf4, 0x2a,
0x94, 0x28, 0xd1, 0x2d, 0x4d, 0xa1, 0xfe, 0xc4, 0x7a, 0x22, 0xdf, 0x24, 0x06, 0x5b, 0x37, 0xdb,
0x4d, 0xc1, 0xc0, 0x07, 0x3f, 0x70, 0x96, 0xdf, 0x8a, 0x03, 0x40, 0xf4, 0x9e, 0x04, 0xe3, 0xae,
0xd5, 0x66, 0xa4, 0x94, 0x25, 0xd8, 0x4e, 0x57, 0x44, 0xc3, 0x85, 0x7e, 0xdd, 0xb6, 0x11, 0x43,
0xab, 0xcd, 0x08, 0xe1, 0xe3, 0xf1, 0x76, 0x9c, 0x90, 0x8a, 0x16, 0x61, 0x42, 0x57, 0x0d, 0x4c,
0x94, 0x76, 0xb7, 0x41, 0x5a, 0xa6, 0xd1, 0x76, 0x2a, 0xc3, 0x27, 0xa5, 0x53, 0xc5, 0xda, 0x09,
0x01, 0x30, 0xb1, 0x16, 0xef, 0xc6, 0x49, 0x7a, 0xf4, 0x4d, 0x40, 0xbe, 0x5d, 0x17, 0xbd, 0xf5,
0x42, 0x35, 0x8d, 0x4a, 0xf1, 0xa4, 0x74, 0xaa, 0x50, 0x9b, 0x15, 0x28, 0xa8, 0x99, 0xa2, 0xc0,
0x19, 0x5c, 0xf2, 0x7f, 0x86, 0x61, 0x22, 0x11, 0xe0, 0xe8, 0x0a, 0xcc, 0xb4, 0xbc, 0xf4, 0xb9,
0xee, 0xea, 0x9b, 0xc4, 0x6e, 0xb4, 0xb6, 0x49, 0xdb, 0xd5, 0x48, 0x9b, 0x8f, 0x7a, 0xb1, 0x36,
0x27, 0x64, 0xcc, 0x2c, 0x65, 0x52, 0xe1, 0x1c, 0x6e, 0xa6, 0xb7, 0xc1, 0x9b, 0xd6, 0x54, 0xc7,
0x09, 0x30, 0x87, 0x38, 0x66, 0xa0, 0xf7, 0x7a, 0x8a, 0x02, 0x67, 0x70, 0x31, 0x1d, 0xdb, 0xc4,
0x51, 0x6d, 0xd2, 0x4e, 0xea, 0x58, 0x88, 0xeb, 0xb8, 0x9c, 0x49, 0x85, 0x73, 0xb8, 0xd1, 0x19,
0x28, 0x7b, 0xd2, 0xb8, 0xc7, 0xc5, 0xd0, 0x04, 0x09, 0x7b, 0x3d, 0xec, 0xc2, 0x51, 0x3a, 0x66,
0x9a, 0xb9, 0xe9, 0x10, 0x7b, 0x87, 0xb4, 0xf3, 0x87, 0xe4, 0x72, 0x8a, 0x02, 0x67, 0x70, 0x31,
0xd3, 0xbc, 0x98, 0x49, 0x99, 0x76, 0x34, 0x6e, 0xda, 0x46, 0x26, 0x15, 0xce, 0xe1, 0x66, 0x91,
0xe7, 0xa9, 0xbc, 0xb8, 0xa3, 0xa8, 0x9a, 0xb2, 0xa9, 0x91, 0xca, 0x48, 0x3c, 0xf2, 0xd6, 0xe3,
0xdd, 0x38, 0x49, 0x8f, 0x2e, 0xc2, 0xa4, 0xd7, 0xb4, 0x61, 0x28, 0x01, 0x48, 0x89, 0x83, 0xdc,
0x2f, 0x40, 0x26, 0xd7, 0x93, 0x04, 0x38, 0xcd, 0x23, 0xff, 0x5d, 0x82, 0x13, 0x39, 0x33, 0x09,
0xbd, 0x08, 0xc3, 0xb4, 0x6b, 0xf9, 0xeb, 0xef, 0x57, 0xfd, 0x8c, 0xde, 0xec, 0x5a, 0xe4, 0xd6,
0xde, 0xfc, 0x03, 0x39, 0x6c, 0xac, 0x1b, 0x73, 0x46, 0xf4, 0x5d, 0x18, 0xb3, 0x4d, 0x4d, 0x53,
0x8d, 0x8e, 0x47, 0x22, 0xb2, 0xc9, 0xf9, 0x1e, 0x67, 0x3a, 0x8e, 0x62, 0x84, 0xd9, 0x72, 0x72,
0x7f, 0x6f, 0x7e, 0x2c, 0xd6, 0x87, 0xe3, 0xe2, 0xe4, 0xdf, 0x0f, 0x01, 0x2c, 0x13, 0x4b, 0x33,
0xbb, 0x3a, 0x31, 0x06, 0xb1, 0x82, 0xbe, 0x19, 0x5b, 0x41, 0x5f, 0xe8, 0x35, 0xa3, 0x05, 0xaa,
0xe6, 0x2e, 0xa1, 0x9d, 0xc4, 0x12, 0xfa, 0x62, 0xff, 0x22, 0x0e, 0x5e, 0x43, 0x6f, 0x16, 0x60,
0x2a, 0x24, 0x5e, 0x32, 0x8d, 0xb6, 0xca, 0xe7, 0xc4, 0x73, 0xb1, 0x98, 0x78, 0x34, 0x11, 0x13,
0x27, 0x32, 0x58, 0x22, 0xf1, 0x70, 0x25, 0xd0, 0x7e, 0x88, 0xb3, 0x9f, 0x8b, 0x0b, 0xbf, 0xb5,
0x37, 0x7f, 0x60, 0x3d, 0x5f, 0x0d, 0x30, 0xe3, 0xca, 0xa2, 0x47, 0xe0, 0xa8, 0x4d, 0x14, 0xc7,
0x34, 0x78, 0x9a, 0x18, 0x0d, 0x8d, 0xc2, 0xbc, 0x15, 0x8b, 0x5e, 0xf4, 0x18, 0x8c, 0xe8, 0xc4,
0x71, 0x94, 0x0e, 0xe1, 0x19, 0x61, 0xb4, 0x36, 0x21, 0x08, 0x47, 0xd6, 0xbc, 0x66, 0xec, 0xf7,
0xa3, 0x6b, 0x30, 0xae, 0x29, 0x8e, 0x08, 0xed, 0xa6, 0xaa, 0x13, 0x3e, 0xe7, 0xcb, 0xa7, 0xbf,
0x72, 0x67, 0x11, 0xc3, 0x38, 0xc2, 0x95, 0x68, 0x35, 0x86, 0x84, 0x13, 0xc8, 0x68, 0x07, 0x10,
0x6b, 0x69, 0xda, 0x8a, 0xe1, 0x78, 0x2e, 0x63, 0xf2, 0x46, 0x7a, 0x96, 0x17, 0xe4, 0xb7, 0xd5,
0x14, 0x1a, 0xce, 0x90, 0x20, 0xff, 0x59, 0x82, 0xf1, 0x70, 0xc0, 0x06, 0x50, 0x28, 0xbd, 0x11,
0x2f, 0x94, 0x9e, 0xed, 0x3b, 0x78, 0x73, 0x2a, 0xa5, 0xf7, 0x0b, 0x80, 0x42, 0x22, 0x96, 0x1a,
0x36, 0x95, 0xd6, 0xf5, 0x3b, 0xd8, 0x47, 0xfc, 0x52, 0x02, 0x24, 0x92, 0xf5, 0xa2, 0x61, 0x98,
0x94, 0xe7, 0x7f, 0x5f, 0xcd, 0x57, 0xfa, 0x56, 0xd3, 0xd7, 0xa0, 0xba, 0x91, 0xc2, 0x3e, 0x6f,
0x50, 0xbb, 0x1b, 0x8e, 0x58, 0x9a, 0x00, 0x67, 0x28, 0x84, 0xde, 0x02, 0xb0, 0x05, 0x66, 0xd3,
0x14, 0x29, 0xe0, 0x85, 0x3e, 0xb2, 0x29, 0x03, 0x58, 0x32, 0x8d, 0x2d, 0xb5, 0x13, 0x26, 0x34,
0x1c, 0x00, 0xe3, 0x88, 0x90, 0xd9, 0xf3, 0x70, 0x22, 0x47, 0x7b, 0x74, 0x1c, 0x0a, 0xd7, 0x49,
0xd7, 0x73, 0x2b, 0x66, 0x3f, 0xd1, 0x74, 0x74, 0x3f, 0x36, 0x2a, 0xb6, 0x52, 0x67, 0x87, 0x9e,
0x91, 0xe4, 0xcf, 0x8b, 0xd1, 0x58, 0xe3, 0x55, 0xec, 0x29, 0x28, 0xd9, 0xc4, 0xd2, 0xd4, 0x96,
0xe2, 0x88, 0x7a, 0x86, 0x17, 0xa4, 0x58, 0xb4, 0xe1, 0xa0, 0x37, 0x56, 0xef, 0x0e, 0xdd, 0xdb,
0x7a, 0xb7, 0x70, 0xb7, 0xeb, 0x5d, 0x13, 0x4a, 0x8e, 0x5f, 0xe8, 0x0e, 0x73, 0xf0, 0xc5, 0x43,
0xe4, 0x6c, 0x51, 0xe3, 0x06, 0x02, 0x83, 0xea, 0x36, 0x10, 0x92, 0x55, 0xd7, 0x16, 0x7b, 0xac,
0x6b, 0x57, 0x61, 0xda, 0x26, 0x3b, 0x2a, 0x53, 0xe3, 0x92, 0xea, 0x50, 0xd3, 0xee, 0xae, 0xaa,
0xba, 0x4a, 0x45, 0xd9, 0x53, 0xd9, 0xdf, 0x9b, 0x9f, 0xc6, 0x19, 0xfd, 0x38, 0x93, 0x8b, 0x65,
0x67, 0x4b, 0x71, 0x1d, 0xd2, 0xe6, 0x29, 0xad, 0x14, 0x66, 0xe7, 0x3a, 0x6f, 0xc5, 0xa2, 0x17,
0xe9, 0xb1, 0xe0, 0x2e, 0xdd, 0x8d, 0xe0, 0x1e, 0xcf, 0x0f, 0x6c, 0xb4, 0x01, 0x27, 0x2c, 0xdb,
0xec, 0xd8, 0xc4, 0x71, 0x96, 0x89, 0xd2, 0xd6, 0x54, 0x83, 0xf8, 0xfe, 0x1a, 0xe5, 0x76, 0x3e,
0xb0, 0xbf, 0x37, 0x7f, 0xa2, 0x9e, 0x4d, 0x82, 0xf3, 0x78, 0xe5, 0x4f, 0x86, 0xe1, 0x78, 0x72,
0x95, 0xcd, 0xa9, 0x4a, 0xa5, 0xbe, 0xaa, 0xd2, 0xc7, 0x23, 0xd3, 0xc6, 0x2b, 0xd9, 0x83, 0x68,
0xc8, 0x98, 0x3a, 0x8b, 0x30, 0x21, 0xf2, 0x88, 0xdf, 0x29, 0xea, 0xf2, 0x20, 0x1a, 0x36, 0xe2,
0xdd, 0x38, 0x49, 0xcf, 0x6a, 0xcd, 0xb0, 0x84, 0xf4, 0x41, 0x86, 0xe3, 0xb5, 0xe6, 0x62, 0x92,
0x00, 0xa7, 0x79, 0xd0, 0x1a, 0x4c, 0xb9, 0x46, 0x1a, 0xca, 0x8b, 0xce, 0x07, 0x04, 0xd4, 0xd4,
0x46, 0x9a, 0x04, 0x67, 0xf1, 0xa1, 0x1d, 0x80, 0x96, 0x5f, 0x10, 0x38, 0x95, 0xa3, 0x3c, 0x57,
0xd7, 0xfa, 0x9e, 0x5b, 0x41, 0x6d, 0x11, 0x66, 0xc4, 0xa0, 0xc9, 0xc1, 0x11, 0x49, 0xe8, 0x39,
0x18, 0xb3, 0xf9, 0xc6, 0xc3, 0x37, 0xc0, 0x2b, 0xde, 0xef, 0x13, 0x6c, 0x63, 0x38, 0xda, 0x89,
0xe3, 0xb4, 0xe8, 0x2c, 0x8c, 0xb7, 0x58, 0x8d, 0xca, 0xd4, 0x58, 0x32, 0x5d, 0x83, 0xf2, 0x40,
0x2f, 0xd4, 0x10, 0xab, 0x13, 0x96, 0x62, 0x3d, 0x38, 0x41, 0x29, 0xff, 0x45, 0x8a, 0x2e, 0x6f,
0x41, 0x99, 0x7e, 0x36, 0x56, 0x92, 0x3d, 0x92, 0x28, 0xc9, 0x66, 0xd2, 0x1c, 0x91, 0x8a, 0xec,
0x7b, 0xd9, 0x15, 0xfa, 0x85, 0x43, 0x55, 0xe8, 0xe1, 0x32, 0x7d, 0xfb, 0x12, 0xfd, 0x43, 0x09,
0x66, 0x2e, 0x34, 0x2e, 0xda, 0xa6, 0x6b, 0xf9, 0xea, 0x5d, 0xb6, 0x3c, 0x3f, 0x7f, 0x03, 0x86,
0x6d, 0x57, 0xf3, 0xed, 0xfa, 0x92, 0x6f, 0x17, 0x76, 0x35, 0x66, 0xd7, 0x54, 0x82, 0xcb, 0x33,
0x8a, 0x31, 0xa0, 0x37, 0xe0, 0xa8, 0xad, 0x18, 0x1d, 0xe2, 0x2f, 0xe0, 0x4f, 0xf7, 0x68, 0xcd,
0xca, 0x32, 0x66, 0xec, 0x91, 0x32, 0x92, 0xa3, 0x61, 0x81, 0x2a, 0xff, 0x42, 0x82, 0x89, 0x4b,
0xcd, 0x66, 0x7d, 0xc5, 0xe0, 0x19, 0xa0, 0xae, 0xd0, 0x6d, 0x56, 0x63, 0x58, 0x0a, 0xdd, 0x4e,
0xd6, 0x18, 0xac, 0x0f, 0xf3, 0x1e, 0xb4, 0x0d, 0x23, 0x2c, 0xf3, 0x10, 0xa3, 0xdd, 0xe7, 0xf6,
0x40, 0x88, 0xab, 0x79, 0x20, 0x61, 0xed, 0x2a, 0x1a, 0xb0, 0x0f, 0x2f, 0xbf, 0x03, 0xd3, 0x11,
0xf5, 0x98, 0xbf, 0xf8, 0xc9, 0x26, 0x6a, 0x41, 0x91, 0x69, 0xe2, 0x9f, 0x5b, 0xf6, 0x7a, 0xfc,
0x96, 0x30, 0x39, 0xac, 0xc1, 0xd8, 0x97, 0x83, 0x3d, 0x6c, 0x79, 0x0d, 0xc6, 0x2e, 0x99, 0x0e,
0xad, 0x9b, 0x36, 0xe5, 0x6e, 0x43, 0x0f, 0x41, 0x41, 0x57, 0x0d, 0xb1, 0xc2, 0x97, 0x05, 0x4f,
0x81, 0xad, 0x41, 0xac, 0x9d, 0x77, 0x2b, 0xbb, 0x22, 0x93, 0x85, 0xdd, 0xca, 0x2e, 0x66, 0xed,
0xf2, 0x45, 0x18, 0x11, 0xc3, 0x11, 0x05, 0x2a, 0x1c, 0x0c, 0x54, 0xc8, 0x00, 0xfa, 0xcd, 0x10,
0x8c, 0x08, 0xed, 0x07, 0xb0, 0x11, 0x7c, 0x2d, 0xb6, 0x11, 0x3c, 0xdb, 0xdf, 0x48, 0xe7, 0xee,
0x02, 0xdb, 0x89, 0x5d, 0xe0, 0xf3, 0x7d, 0xe2, 0x1f, 0xbc, 0x05, 0xfc, 0x40, 0x82, 0xf1, 0x78,
0xcc, 0xa1, 0x33, 0x50, 0x66, 0xeb, 0x91, 0xda, 0x22, 0xeb, 0x61, 0x41, 0x1d, 0x1c, 0xca, 0x34,
0xc2, 0x2e, 0x1c, 0xa5, 0x43, 0x9d, 0x80, 0x8d, 0x85, 0x85, 0x70, 0x4a, 0xbe, 0xcb, 0x5d, 0xaa,
0x6a, 0x55, 0xef, 0xc2, 0xa7, 0xba, 0x62, 0xd0, 0xcb, 0x76, 0x83, 0xda, 0xaa, 0xd1, 0x49, 0x09,
0xe2, 0x31, 0x16, 0x45, 0x96, 0x6f, 0x48, 0x50, 0x16, 0x2a, 0x0f, 0x60, 0x3b, 0xf3, 0x6a, 0x7c,
0x3b, 0xf3, 0x74, 0x9f, 0xf3, 0x39, 0x7b, 0x2f, 0xf3, 0x51, 0x68, 0x0a, 0x9b, 0xc1, 0x2c, 0xc1,
0x6c, 0x9b, 0x0e, 0x4d, 0x26, 0x18, 0x36, 0xd7, 0x30, 0xef, 0x41, 0x3f, 0x90, 0xe0, 0xb8, 0x9a,
0x98, 0xf3, 0xc2, 0xd7, 0x2f, 0xf6, 0xa7, 0x5a, 0x00, 0x53, 0xab, 0x08, 0x79, 0xc7, 0x93, 0x3d,
0x38, 0x25, 0x52, 0x76, 0x21, 0x45, 0x85, 0x14, 0x18, 0xde, 0xa6, 0xd4, 0x12, 0x83, 0xb0, 0xd4,
0x7f, 0xe6, 0x09, 0x55, 0x2a, 0x71, 0xf3, 0x9b, 0xcd, 0x3a, 0xe6, 0xd0, 0xf2, 0xaf, 0x87, 0x02,
0x87, 0x35, 0xbc, 0x49, 0x12, 0xe4, 0x5b, 0xe9, 0x6e, 0xe4, 0xdb, 0x72, 0x56, 0xae, 0x45, 0xdf,
0x82, 0x02, 0xd5, 0xfa, 0xdd, 0xd0, 0x0a, 0x09, 0xcd, 0xd5, 0x46, 0x98, 0xb0, 0x9a, 0xab, 0x0d,
0xcc, 0x20, 0xd1, 0x9b, 0x50, 0x64, 0xab, 0x19, 0x9b, 0xe3, 0x85, 0xfe, 0x73, 0x08, 0xf3, 0x57,
0x18, 0x61, 0xec, 0xcb, 0xc1, 0x1e, 0xae, 0xfc, 0x0e, 0x8c, 0xc5, 0x12, 0x01, 0xba, 0x06, 0xc7,
0x34, 0x53, 0x69, 0xd7, 0x14, 0x4d, 0x31, 0x5a, 0xc4, 0x4e, 0xa6, 0xc6, 0xec, 0xbd, 0xd0, 0x6a,
0x84, 0x43, 0x24, 0x94, 0xe0, 0xf2, 0x31, 0xda, 0x87, 0x63, 0xd8, 0xb2, 0x02, 0x10, 0x5a, 0x8f,
0xe6, 0xa1, 0xc8, 0x42, 0xd8, 0x5b, 0x99, 0x46, 0x6b, 0xa3, 0x4c, 0x57, 0x16, 0xd9, 0x0e, 0xf6,
0xda, 0xd1, 0x69, 0x00, 0x87, 0xb4, 0x6c, 0x42, 0x79, 0xde, 0xf1, 0x4e, 0x8f, 0x82, 0x0c, 0xdc,
0x08, 0x7a, 0x70, 0x84, 0x4a, 0xfe, 0x9b, 0x04, 0x63, 0xeb, 0x84, 0xbe, 0x6d, 0xda, 0xd7, 0xeb,
0xfc, 0x72, 0x77, 0x00, 0x79, 0x7f, 0x33, 0x96, 0xf7, 0x5f, 0xea, 0x71, 0xcc, 0x62, 0xda, 0xe6,
0x65, 0x7f, 0xf9, 0x5f, 0x12, 0x54, 0x62, 0x94, 0xd1, 0x34, 0x41, 0xa0, 0x68, 0x99, 0x36, 0xf5,
0xd7, 0xf8, 0x43, 0x69, 0xc0, 0x52, 0x6a, 0x64, 0x95, 0x67, 0xb0, 0xd8, 0x43, 0x67, 0x76, 0x6e,
0xd9, 0xa6, 0x2e, 0xe2, 0xfe, 0x70, 0x52, 0x08, 0xb1, 0x43, 0x3b, 0x2f, 0xd8, 0xa6, 0x8e, 0x39,
0xb6, 0xfc, 0x57, 0x09, 0x26, 0x63, 0x94, 0x03, 0x48, 0xe9, 0x4a, 0x3c, 0xa5, 0x3f, 0x7f, 0x18,
0xc3, 0x72, 0x12, 0xfb, 0x17, 0x49, 0xb3, 0x98, 0x03, 0xd0, 0x16, 0x94, 0x2d, 0xb3, 0xdd, 0xb8,
0x0b, 0xb7, 0x7a, 0x13, 0x6c, 0x85, 0xac, 0x87, 0x58, 0x38, 0x0a, 0x8c, 0x76, 0x61, 0xd2, 0x50,
0x74, 0xe2, 0x58, 0x4a, 0x8b, 0x34, 0xee, 0xc2, 0x99, 0xca, 0x7d, 0xfc, 0xa6, 0x21, 0x89, 0x88,
0xd3, 0x42, 0xe4, 0xdf, 0xa5, 0xec, 0x36, 0x6d, 0x8a, 0x5e, 0x86, 0x12, 0x7f, 0x60, 0xd1, 0x32,
0x35, 0xb1, 0xb4, 0x9d, 0x61, 0x43, 0x53, 0x17, 0x6d, 0xb7, 0xf6, 0xe6, 0xbf, 0x7c, 0xe0, 0x91,
0xb0, 0x4f, 0x88, 0x03, 0x18, 0xb4, 0x0e, 0xc3, 0xd6, 0x61, 0xca, 0x0c, 0xbe, 0xb0, 0xf0, 0xda,
0x82, 0xe3, 0xc8, 0xff, 0x4e, 0x2a, 0xce, 0x97, 0x97, 0x6b, 0x77, 0x6d, 0xc0, 0x82, 0xb2, 0x26,
0x77, 0xd0, 0x6c, 0x18, 0x11, 0xab, 0xac, 0x88, 0xcb, 0x8b, 0x87, 0x89, 0xcb, 0xe8, 0xca, 0x10,
0x6c, 0x22, 0xfc, 0x46, 0x5f, 0x90, 0xfc, 0x0f, 0x09, 0x26, 0xb9, 0x42, 0x2d, 0xd7, 0x56, 0x69,
0x77, 0x60, 0x19, 0x74, 0x2b, 0x96, 0x41, 0x97, 0x7b, 0x34, 0x34, 0xa5, 0x71, 0x6e, 0x16, 0xfd,
0x54, 0x82, 0xfb, 0x52, 0xd4, 0x03, 0xc8, 0x30, 0x24, 0x9e, 0x61, 0x5e, 0x3a, 0xac, 0x81, 0x39,
0x59, 0xe6, 0x87, 0xe5, 0x0c, 0xf3, 0x78, 0xe0, 0x9e, 0x06, 0xb0, 0x6c, 0x75, 0x47, 0xd5, 0x48,
0x47, 0x5c, 0x24, 0x97, 0xc2, 0x21, 0xa9, 0x07, 0x3d, 0x38, 0x42, 0x85, 0xbe, 0x03, 0x33, 0x6d,
0xb2, 0xa5, 0xb8, 0x1a, 0x5d, 0x6c, 0xb7, 0x97, 0x14, 0x4b, 0xd9, 0x54, 0x35, 0x95, 0xaa, 0x62,
0x87, 0x3d, 0x5a, 0x3b, 0xef, 0x5d, 0xf0, 0x66, 0x51, 0xdc, 0xda, 0x9b, 0x7f, 0xf4, 0xe0, 0x4b,
0x1d, 0x9f, 0xb8, 0x8b, 0x73, 0x84, 0xa0, 0xef, 0x4b, 0x50, 0xb1, 0xc9, 0x5b, 0xae, 0x6a, 0x93,
0xf6, 0xb2, 0x6d, 0x5a, 0x31, 0x0d, 0x0a, 0x5c, 0x83, 0x8b, 0xfb, 0x7b, 0xf3, 0x15, 0x9c, 0x43,
0xd3, 0x8b, 0x0e, 0xb9, 0x82, 0x10, 0x85, 0x29, 0x45, 0xd3, 0xcc, 0xb7, 0x49, 0xdc, 0x03, 0xc3,
0x5c, 0x7e, 0x6d, 0x7f, 0x6f, 0x7e, 0x6a, 0x31, 0xdd, 0xdd, 0x8b, 0xe8, 0x2c, 0x78, 0xb4, 0x00,
0x23, 0x3b, 0xa6, 0xe6, 0xea, 0xc4, 0xa9, 0x14, 0xb9, 0x24, 0x96, 0x71, 0x47, 0xae, 0x78, 0x4d,
0xb7, 0xf6, 0xe6, 0x8f, 0x5e, 0x68, 0xf0, 0xa3, 0x0f, 0x9f, 0x8a, 0xed, 0xd1, 0x58, 0xcd, 0x24,
0xa6, 0x3c, 0x3f, 0xb3, 0x2d, 0x85, 0x39, 0xe6, 0x52, 0xd8, 0x85, 0xa3, 0x74, 0x48, 0x87, 0xd1,
0x6d, 0xb1, 0x6f, 0x77, 0x2a, 0x23, 0x7d, 0xad, 0x7e, 0xb1, 0x7d, 0x7f, 0x6d, 0x52, 0x88, 0x1c,
0xf5, 0x9b, 0x1d, 0x1c, 0x4a, 0x40, 0x8f, 0xc1, 0x08, 0xff, 0x58, 0x59, 0xe6, 0x07, 0x60, 0xa5,
0x30, 0x13, 0x5d, 0xf2, 0x9a, 0xb1, 0xdf, 0xef, 0x93, 0xae, 0xd4, 0x97, 0xf8, 0xc1, 0x6c, 0x82,
0x74, 0xa5, 0xbe, 0x84, 0xfd, 0x7e, 0x64, 0xc1, 0x88, 0x43, 0x56, 0x55, 0xc3, 0xdd, 0xad, 0x40,
0x5f, 0x57, 0xcd, 0x8d, 0xf3, 0x9c, 0x3b, 0x71, 0x14, 0x15, 0x4a, 0x14, 0xfd, 0xd8, 0x17, 0x83,
0x76, 0x61, 0xd4, 0x76, 0x8d, 0x45, 0x67, 0xc3, 0x21, 0x76, 0xa5, 0xcc, 0x65, 0xf6, 0x9a, 0x9c,
0xb1, 0xcf, 0x9f, 0x94, 0x1a, 0x78, 0x30, 0xa0, 0xc0, 0xa1, 0x30, 0xf4, 0x73, 0x09, 0x90, 0xe3,
0x5a, 0x96, 0x46, 0x74, 0x62, 0x50, 0x45, 0xe3, 0xa7, 0x61, 0x4e, 0xe5, 0x18, 0xd7, 0xa1, 0xde,
0xab, 0xdd, 0x29, 0xa0, 0xa4, 0x32, 0xc1, 0x31, 0x75, 0x9a, 0x14, 0x67, 0xe8, 0xc1, 0x86, 0x62,
0xcb, 0xe1, 0xbf, 0x2b, 0x63, 0x7d, 0x0d, 0x45, 0xf6, 0xa9, 0x60, 0x38, 0x14, 0xa2, 0x1f, 0xfb,
0x62, 0xd0, 0x15, 0x98, 0xb1, 0x89, 0xd2, 0xbe, 0x6c, 0x68, 0x5d, 0x6c, 0x9a, 0xf4, 0x82, 0xaa,
0x11, 0xa7, 0xeb, 0x50, 0xa2, 0x57, 0xc6, 0x79, 0xd8, 0x04, 0xcf, 0x35, 0x70, 0x26, 0x15, 0xce,
0xe1, 0x46, 0x2f, 0xc1, 0x71, 0x31, 0x31, 0x79, 0x68, 0xf2, 0x13, 0xb4, 0x09, 0x3e, 0x15, 0xa7,
0xd9, 0x8e, 0x78, 0x31, 0xd1, 0x87, 0x53, 0xd4, 0xfc, 0x1d, 0x82, 0x38, 0x01, 0x1e, 0xcc, 0x4b,
0xbe, 0xc3, 0xbd, 0x43, 0x08, 0x55, 0xbd, 0x67, 0xef, 0x10, 0x22, 0x22, 0x0e, 0x3e, 0x84, 0xfa,
0x62, 0x08, 0xa6, 0x42, 0xe2, 0x3b, 0x7e, 0x87, 0x90, 0xc1, 0x32, 0x80, 0x77, 0x08, 0xd9, 0x17,
0xf9, 0x85, 0x7b, 0x7d, 0x91, 0x7f, 0x0f, 0xde, 0x3f, 0xf0, 0xb7, 0x01, 0xa1, 0x13, 0xff, 0xf7,
0xdf, 0x06, 0x84, 0xba, 0xe6, 0x14, 0x44, 0x7f, 0x18, 0x8a, 0x1a, 0xf4, 0x7f, 0x74, 0x01, 0x7d,
0xf8, 0x77, 0x8e, 0xf2, 0xa7, 0x05, 0x38, 0x9e, 0x9c, 0xb1, 0xb1, 0x7b, 0x48, 0xe9, 0xb6, 0xf7,
0x90, 0x75, 0x98, 0xde, 0x72, 0x35, 0xad, 0xcb, 0x1d, 0x12, 0xb9, 0x8c, 0xf4, 0xce, 0xfd, 0x1f,
0x14, 0x9c, 0xd3, 0x17, 0x32, 0x68, 0x70, 0x26, 0x67, 0xce, 0x9d, 0x6a, 0xa1, 0xaf, 0x3b, 0xd5,
0xd4, 0x95, 0xde, 0x70, 0x0f, 0x57, 0x7a, 0x99, 0xf7, 0xa3, 0xc5, 0x3e, 0xee, 0x47, 0xef, 0xc6,
0x85, 0x66, 0x46, 0xe2, 0xbb, 0xdd, 0x85, 0xa6, 0xfc, 0x20, 0xcc, 0x0a, 0x36, 0xca, 0xef, 0x1a,
0x0d, 0x6a, 0x9b, 0x9a, 0x46, 0xec, 0x65, 0x57, 0xd7, 0xbb, 0xf2, 0x39, 0x18, 0x8f, 0xdf, 0xaa,
0x7b, 0x23, 0xef, 0x5d, 0xf4, 0x8b, 0xdb, 0x98, 0xc8, 0xc8, 0x7b, 0xed, 0x38, 0xa0, 0x90, 0xdf,
0x93, 0x60, 0x26, 0xfb, 0x05, 0x1f, 0xd2, 0x60, 0x5c, 0x57, 0x76, 0xa3, 0x4f, 0x18, 0xa5, 0x3e,
0xf7, 0xec, 0xfc, 0xfa, 0x74, 0x2d, 0x86, 0x85, 0x13, 0xd8, 0xf2, 0x67, 0x12, 0x9c, 0xc8, 0xb9,
0xa8, 0x1c, 0xac, 0x26, 0xe8, 0x2a, 0x94, 0x74, 0x65, 0xb7, 0xe1, 0xda, 0x1d, 0xd2, 0xf7, 0x29,
0x05, 0xcf, 0x25, 0x6b, 0x02, 0x05, 0x07, 0x78, 0xf2, 0x87, 0x12, 0x54, 0xf2, 0x2a, 0x4a, 0x74,
0x26, 0x76, 0xa5, 0xfa, 0x70, 0xe2, 0x4a, 0x75, 0x32, 0xc5, 0x37, 0xa0, 0x0b, 0xd5, 0x8f, 0x24,
0x98, 0xc9, 0xae, 0xbc, 0xd1, 0x53, 0x31, 0x8d, 0xe7, 0x13, 0x1a, 0x4f, 0x24, 0xb8, 0x84, 0xbe,
0xdb, 0x30, 0x2e, 0xea, 0x73, 0x01, 0x23, 0xbc, 0xfc, 0xf8, 0xc1, 0x59, 0x55, 0x80, 0xf9, 0x95,
0x26, 0x1f, 0xc9, 0x78, 0x1b, 0x4e, 0xe0, 0xca, 0xbf, 0x1a, 0x82, 0x62, 0xa3, 0xa5, 0x68, 0x64,
0x00, 0x45, 0xdd, 0xd5, 0x58, 0x51, 0xd7, 0xeb, 0xbf, 0x0c, 0xb8, 0x96, 0xb9, 0xf5, 0xdc, 0x66,
0xa2, 0x9e, 0x3b, 0xdb, 0x17, 0xfa, 0xc1, 0xa5, 0xdc, 0xb3, 0x30, 0x1a, 0x28, 0xd1, 0xdb, 0xea,
0x21, 0x7f, 0x30, 0x04, 0xe5, 0x88, 0x88, 0x1e, 0xd7, 0x9e, 0x9d, 0xd8, 0xea, 0xdd, 0xcf, 0x1f,
0x9a, 0x22, 0xb2, 0xab, 0xfe, 0xfa, 0xed, 0xbd, 0xe0, 0x0b, 0x5f, 0x62, 0xa5, 0x97, 0xf5, 0x73,
0x30, 0x4e, 0xf9, 0xff, 0x7b, 0x82, 0x53, 0xc2, 0x02, 0x8f, 0xe2, 0xe0, 0x5d, 0x68, 0x33, 0xd6,
0x8b, 0x13, 0xd4, 0xb3, 0xcf, 0xc1, 0x58, 0x4c, 0x58, 0x4f, 0x0f, 0xee, 0xfe, 0x28, 0xc1, 0xc3,
0xb7, 0xdd, 0xd5, 0xa1, 0x5a, 0x6c, 0x7a, 0x55, 0x13, 0xd3, 0x6b, 0x2e, 0x1f, 0x60, 0x80, 0xcf,
0x2d, 0x7e, 0x3a, 0x04, 0xa8, 0xb9, 0xad, 0xda, 0xed, 0xba, 0x62, 0xd3, 0x2e, 0x16, 0xff, 0xe2,
0x1a, 0xc0, 0x84, 0x3b, 0x03, 0xe5, 0x36, 0x71, 0x5a, 0xb6, 0xca, 0x9d, 0x25, 0xf6, 0x0a, 0xc1,
0x49, 0xca, 0x72, 0xd8, 0x85, 0xa3, 0x74, 0xa8, 0x03, 0xa5, 0x1d, 0xef, 0x7f, 0x82, 0xfe, 0xdd,
0x5d, 0xaf, 0xc5, 0x6c, 0xf8, 0x4f, 0xc3, 0x30, 0xbe, 0x44, 0x83, 0x83, 0x03, 0x70, 0xf9, 0x7d,
0x09, 0x66, 0xd2, 0x8e, 0x59, 0x66, 0xaa, 0xdf, 0x7b, 0xe7, 0x3c, 0x08, 0xc3, 0x1c, 0x9d, 0x79,
0xe5, 0x98, 0x77, 0x66, 0xce, 0x24, 0x63, 0xde, 0x2a, 0x7f, 0x2e, 0xc1, 0x6c, 0xb6, 0x6a, 0x03,
0xd8, 0x4a, 0x5c, 0x8b, 0x6f, 0x25, 0x7a, 0x3d, 0x78, 0xc8, 0xd6, 0x3b, 0x67, 0x5b, 0xb1, 0x97,
0x39, 0x06, 0x03, 0x30, 0x72, 0x2b, 0x6e, 0xe4, 0xe2, 0xa1, 0x8d, 0xcc, 0x36, 0xb0, 0xf6, 0xd8,
0x8d, 0x9b, 0x73, 0x47, 0x3e, 0xbe, 0x39, 0x77, 0xe4, 0x93, 0x9b, 0x73, 0x47, 0xde, 0xdd, 0x9f,
0x93, 0x6e, 0xec, 0xcf, 0x49, 0x1f, 0xef, 0xcf, 0x49, 0xff, 0xdc, 0x9f, 0x93, 0x7e, 0xfc, 0xd9,
0xdc, 0x91, 0xab, 0x23, 0x02, 0xf3, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x6d, 0x3f, 0x0c, 0xbe,
0x34, 0x3d, 0x00, 0x00,
// 3427 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x5b, 0xcd, 0x6f, 0x1c, 0xc7,
0x95, 0x57, 0x73, 0x38, 0xe4, 0xf0, 0x8d, 0x48, 0x8a, 0x45, 0x9a, 0x1a, 0xd3, 0x36, 0x29, 0xf7,
0x62, 0x6d, 0x79, 0xd7, 0x1e, 0xae, 0xe5, 0x95, 0xd7, 0x96, 0x6d, 0xd9, 0x1c, 0x52, 0x1f, 0x5c,
0x90, 0xd4, 0xb8, 0x66, 0x28, 0xac, 0xe5, 0xaf, 0x6d, 0xce, 0x14, 0x87, 0x2d, 0xf5, 0x97, 0xbb,
0xab, 0x69, 0x0e, 0x8c, 0xdd, 0x35, 0xb0, 0x88, 0x0f, 0x39, 0x04, 0xc9, 0x25, 0x70, 0x80, 0xe4,
0x98, 0x43, 0x2e, 0x89, 0x7d, 0x48, 0x9c, 0xfc, 0x05, 0xd1, 0x21, 0x08, 0x1c, 0x20, 0x01, 0x8c,
0xc0, 0x21, 0x22, 0x1a, 0xf1, 0x3f, 0x10, 0xf8, 0xa2, 0x53, 0x50, 0xd5, 0xd5, 0xdf, 0xdd, 0x94,
0x66, 0x48, 0x0d, 0x02, 0xe4, 0x36, 0x5d, 0xf5, 0xde, 0xef, 0x7d, 0xd4, 0xab, 0x57, 0xaf, 0x3e,
0x06, 0x5e, 0xb9, 0xf5, 0x82, 0x53, 0x55, 0xcd, 0xc5, 0x5b, 0xee, 0x16, 0xb1, 0x0d, 0x42, 0x89,
0xb3, 0x68, 0xdd, 0xea, 0x2c, 0x2a, 0x96, 0xea, 0x2c, 0x92, 0x3d, 0x4a, 0x0c, 0x47, 0x35, 0x0d,
0x67, 0x71, 0xf7, 0xd9, 0x2d, 0x42, 0x95, 0x67, 0x17, 0x3b, 0xc4, 0x20, 0xb6, 0x42, 0x49, 0xbb,
0x6a, 0xd9, 0x26, 0x35, 0xd1, 0x33, 0x1e, 0x7b, 0x35, 0x64, 0xaf, 0x5a, 0xb7, 0x3a, 0x55, 0xc6,
0x5e, 0x0d, 0xd9, 0xab, 0x82, 0x7d, 0xee, 0x99, 0x8e, 0x4a, 0x77, 0xdc, 0xad, 0x6a, 0xcb, 0xd4,
0x17, 0x3b, 0x66, 0xc7, 0x5c, 0xe4, 0x28, 0x5b, 0xee, 0x36, 0xff, 0xe2, 0x1f, 0xfc, 0x97, 0x87,
0x3e, 0xf7, 0xef, 0x42, 0x39, 0xc5, 0x52, 0x75, 0xa5, 0xb5, 0xa3, 0x1a, 0xc4, 0xee, 0xfa, 0xea,
0x2d, 0xda, 0xc4, 0x31, 0x5d, 0xbb, 0x45, 0x92, 0x3a, 0x1d, 0xca, 0xe5, 0x2c, 0xea, 0x84, 0x2a,
0x8b, 0xbb, 0x29, 0x4b, 0xe6, 0x16, 0xf3, 0xb8, 0x6c, 0xd7, 0xa0, 0xaa, 0x9e, 0x16, 0xf3, 0xfc,
0xbd, 0x18, 0x9c, 0xd6, 0x0e, 0xd1, 0x95, 0x14, 0xdf, 0x73, 0x79, 0x7c, 0x2e, 0x55, 0xb5, 0x45,
0xd5, 0xa0, 0x0e, 0xb5, 0x53, 0x4c, 0x4f, 0xe7, 0x0e, 0x53, 0x96, 0x2d, 0x2f, 0x1e, 0x32, 0xa8,
0x96, 0xa9, 0xa9, 0xad, 0x6e, 0xde, 0x80, 0xca, 0x55, 0x80, 0xa5, 0xfa, 0xea, 0x75, 0x62, 0xb3,
0x81, 0x43, 0x67, 0x60, 0xd8, 0x50, 0x74, 0x52, 0x91, 0xce, 0x48, 0x67, 0xc7, 0x6a, 0x27, 0x6f,
0xef, 0x2f, 0x9c, 0x38, 0xd8, 0x5f, 0x18, 0xde, 0x50, 0x74, 0x82, 0x79, 0x8f, 0xfc, 0x03, 0x09,
0x1e, 0x5e, 0x76, 0x1d, 0x6a, 0xea, 0xeb, 0x84, 0xda, 0x6a, 0x6b, 0xd9, 0xb5, 0x6d, 0x62, 0xd0,
0x06, 0x55, 0xa8, 0xeb, 0xdc, 0x9b, 0x1f, 0xdd, 0x80, 0xe2, 0xae, 0xa2, 0xb9, 0xa4, 0x32, 0x74,
0x46, 0x3a, 0x5b, 0x3e, 0x57, 0xad, 0x8a, 0x80, 0x8a, 0x7a, 0xc7, 0x0f, 0xa9, 0xaa, 0x3f, 0xe4,
0xd5, 0xd7, 0x5d, 0xc5, 0xa0, 0x2a, 0xed, 0xd6, 0x66, 0x04, 0xe4, 0x49, 0x21, 0xf7, 0x3a, 0xc3,
0xc2, 0x1e, 0xa4, 0xfc, 0x1d, 0x09, 0x1e, 0xcb, 0xd5, 0x6d, 0x4d, 0x75, 0x28, 0xd2, 0xa1, 0xa8,
0x52, 0xa2, 0x3b, 0x15, 0xe9, 0x4c, 0xe1, 0x6c, 0xf9, 0xdc, 0xd5, 0x6a, 0x4f, 0xe1, 0x5c, 0xcd,
0x05, 0xaf, 0x8d, 0x0b, 0xbd, 0x8a, 0xab, 0x0c, 0x1e, 0x7b, 0x52, 0xe4, 0xef, 0x49, 0x80, 0xa2,
0x3c, 0x4d, 0xc5, 0xee, 0x10, 0x7a, 0x1f, 0x5e, 0x7a, 0xe3, 0x68, 0x5e, 0x9a, 0x16, 0x90, 0x65,
0x4f, 0x60, 0xcc, 0x49, 0x1f, 0x4a, 0x30, 0x9b, 0xd6, 0x89, 0x7b, 0x67, 0x3b, 0xee, 0x9d, 0xa5,
0x23, 0x78, 0xc7, 0x43, 0xcd, 0x71, 0xcb, 0xcf, 0x87, 0x60, 0x6c, 0x45, 0x21, 0xba, 0x69, 0x34,
0x08, 0x45, 0xff, 0x0d, 0x25, 0x36, 0x47, 0xdb, 0x0a, 0x55, 0xb8, 0x47, 0xca, 0xe7, 0xfe, 0xed,
0x30, 0x73, 0x9d, 0x2a, 0xa3, 0xae, 0xee, 0x3e, 0x5b, 0xbd, 0xb6, 0x75, 0x93, 0xb4, 0xe8, 0x3a,
0xa1, 0x4a, 0x0d, 0x09, 0x39, 0x10, 0xb6, 0xe1, 0x00, 0x15, 0xbd, 0x03, 0xc3, 0x8e, 0x45, 0x5a,
0xc2, 0x99, 0x2f, 0xf7, 0x68, 0x56, 0xa0, 0x69, 0xc3, 0x22, 0xad, 0x70, 0xb4, 0xd8, 0x17, 0xe6,
0xb8, 0x68, 0x1b, 0x46, 0x1c, 0x1e, 0x06, 0x95, 0x02, 0x97, 0x70, 0xb1, 0x6f, 0x09, 0x5e, 0x30,
0x4d, 0x08, 0x19, 0x23, 0xde, 0x37, 0x16, 0xe8, 0xf2, 0x6f, 0x24, 0x18, 0x0f, 0x68, 0xf9, 0x88,
0xbd, 0x95, 0xf2, 0x5d, 0xf5, 0xfe, 0x7c, 0xc7, 0xb8, 0xb9, 0xe7, 0x4e, 0x09, 0x59, 0x25, 0xbf,
0x25, 0xe2, 0xb7, 0xb7, 0xfd, 0x78, 0x18, 0xe2, 0xf1, 0xf0, 0x42, 0xbf, 0x66, 0xe5, 0x84, 0xc1,
0xa7, 0xc3, 0x11, 0x73, 0x98, 0x3b, 0xd1, 0xdb, 0x50, 0x72, 0x88, 0x46, 0x5a, 0xd4, 0xb4, 0x85,
0x39, 0xcf, 0xdd, 0xa7, 0x39, 0xca, 0x16, 0xd1, 0x1a, 0x82, 0xb5, 0x76, 0x92, 0xd9, 0xe3, 0x7f,
0xe1, 0x00, 0x12, 0xbd, 0x09, 0x25, 0x4a, 0x74, 0x4b, 0x53, 0xa8, 0x3f, 0xb1, 0x9e, 0xc9, 0x37,
0x89, 0xc1, 0xd6, 0xcd, 0x76, 0x53, 0x30, 0xf0, 0xc1, 0x0f, 0x9c, 0xe5, 0xb7, 0xe2, 0x00, 0x10,
0x7d, 0x24, 0xc1, 0x84, 0x6b, 0xb5, 0x19, 0x29, 0x65, 0x09, 0xb6, 0xd3, 0x15, 0xd1, 0x70, 0xb9,
0x5f, 0xb7, 0x6d, 0xc6, 0xd0, 0x6a, 0xb3, 0x42, 0xf8, 0x44, 0xbc, 0x1d, 0x27, 0xa4, 0xa2, 0x25,
0x98, 0xd4, 0x55, 0x03, 0x13, 0xa5, 0xdd, 0x6d, 0x90, 0x96, 0x69, 0xb4, 0x9d, 0xca, 0xf0, 0x19,
0xe9, 0x6c, 0xb1, 0x76, 0x5a, 0x00, 0x4c, 0xae, 0xc7, 0xbb, 0x71, 0x92, 0x1e, 0xfd, 0x27, 0x20,
0xdf, 0xae, 0x2b, 0xde, 0x7a, 0xa1, 0x9a, 0x46, 0xa5, 0x78, 0x46, 0x3a, 0x5b, 0xa8, 0xcd, 0x09,
0x14, 0xd4, 0x4c, 0x51, 0xe0, 0x0c, 0x2e, 0xb4, 0x06, 0x33, 0x36, 0xd9, 0x55, 0x99, 0x8d, 0x57,
0x55, 0x87, 0x9a, 0x76, 0x77, 0x4d, 0xd5, 0x55, 0x5a, 0x19, 0xe1, 0x3a, 0x55, 0x0e, 0xf6, 0x17,
0x66, 0x70, 0x46, 0x3f, 0xce, 0xe4, 0x92, 0x3f, 0x29, 0xc2, 0x64, 0x62, 0xba, 0xa0, 0xeb, 0x30,
0xdb, 0xf2, 0x92, 0xf1, 0x86, 0xab, 0x6f, 0x11, 0xbb, 0xd1, 0xda, 0x21, 0x6d, 0x57, 0x23, 0x6d,
0x1e, 0x43, 0xc5, 0xda, 0xbc, 0xd0, 0x78, 0x76, 0x39, 0x93, 0x0a, 0xe7, 0x70, 0x33, 0x2f, 0x18,
0xbc, 0x69, 0x5d, 0x75, 0x9c, 0x00, 0x73, 0x88, 0x63, 0x06, 0x5e, 0xd8, 0x48, 0x51, 0xe0, 0x0c,
0x2e, 0xa6, 0x63, 0x9b, 0x38, 0xaa, 0x4d, 0xda, 0x49, 0x1d, 0x0b, 0x71, 0x1d, 0x57, 0x32, 0xa9,
0x70, 0x0e, 0x37, 0x3a, 0x0f, 0x65, 0x4f, 0x1a, 0x1f, 0x3f, 0x31, 0xd0, 0x41, 0xfa, 0xdf, 0x08,
0xbb, 0x70, 0x94, 0x8e, 0x99, 0x66, 0x6e, 0x39, 0xc4, 0xde, 0x25, 0xed, 0xfc, 0x01, 0xbe, 0x96,
0xa2, 0xc0, 0x19, 0x5c, 0xcc, 0x34, 0x2f, 0x02, 0x53, 0xa6, 0x8d, 0xc4, 0x4d, 0xdb, 0xcc, 0xa4,
0xc2, 0x39, 0xdc, 0x2c, 0x8e, 0x3d, 0x95, 0x97, 0x76, 0x15, 0x55, 0x53, 0xb6, 0x34, 0x52, 0x19,
0x8d, 0xc7, 0xf1, 0x46, 0xbc, 0x1b, 0x27, 0xe9, 0xd1, 0x15, 0x98, 0xf2, 0x9a, 0x36, 0x0d, 0x25,
0x00, 0x29, 0x71, 0x90, 0x87, 0x05, 0xc8, 0xd4, 0x46, 0x92, 0x00, 0xa7, 0x79, 0xd0, 0x05, 0x98,
0x68, 0x99, 0x9a, 0xc6, 0xe3, 0x71, 0xd9, 0x74, 0x0d, 0x5a, 0x19, 0xe3, 0xbe, 0x42, 0x6c, 0x3e,
0x2e, 0xc7, 0x7a, 0x70, 0x82, 0x52, 0xfe, 0xa3, 0x04, 0xa7, 0x73, 0xe6, 0x34, 0x7a, 0x15, 0x86,
0x69, 0xd7, 0xf2, 0x2b, 0x81, 0x7f, 0xf5, 0xd7, 0x96, 0x66, 0xd7, 0x22, 0x77, 0xf7, 0x17, 0x1e,
0xc9, 0x61, 0x63, 0xdd, 0x98, 0x33, 0xa2, 0xff, 0x85, 0x71, 0x9b, 0x89, 0x33, 0x3a, 0x1e, 0x89,
0xc8, 0x6b, 0x97, 0x7a, 0xcc, 0x39, 0x38, 0x8a, 0x11, 0xe6, 0xed, 0xa9, 0x83, 0xfd, 0x85, 0xf1,
0x58, 0x1f, 0x8e, 0x8b, 0x93, 0x7f, 0x39, 0x04, 0xb0, 0x42, 0x2c, 0xcd, 0xec, 0xea, 0xc4, 0x18,
0xc4, 0x5a, 0xfe, 0x6e, 0x6c, 0x2d, 0x7f, 0xa5, 0xd7, 0xdc, 0x1a, 0xa8, 0x9a, 0xbb, 0x98, 0x77,
0x12, 0x8b, 0xf9, 0xab, 0xfd, 0x8b, 0x38, 0x7c, 0x35, 0xbf, 0x53, 0x80, 0xe9, 0x90, 0x78, 0xd9,
0x34, 0xda, 0x2a, 0x9f, 0x4f, 0x2f, 0xc5, 0x62, 0xe2, 0xc9, 0x44, 0x4c, 0x9c, 0xce, 0x60, 0x89,
0xc4, 0xc3, 0xf5, 0x40, 0xfb, 0x21, 0xce, 0x7e, 0x31, 0x2e, 0xfc, 0xee, 0xfe, 0xc2, 0xa1, 0x3b,
0x8b, 0x6a, 0x80, 0x19, 0x57, 0x16, 0x3d, 0x01, 0x23, 0x36, 0x51, 0x1c, 0xd3, 0xe0, 0x29, 0x66,
0x2c, 0x34, 0x0a, 0xf3, 0x56, 0x2c, 0x7a, 0xd1, 0x53, 0x30, 0xaa, 0x13, 0xc7, 0x51, 0x3a, 0x84,
0x67, 0x93, 0xb1, 0xda, 0xa4, 0x20, 0x1c, 0x5d, 0xf7, 0x9a, 0xb1, 0xdf, 0x8f, 0x6e, 0xc2, 0x84,
0xa6, 0x38, 0x22, 0xb4, 0x9b, 0xaa, 0x4e, 0x78, 0xbe, 0x28, 0x9f, 0xfb, 0x97, 0xfb, 0x8b, 0x18,
0xc6, 0x11, 0xae, 0x89, 0x6b, 0x31, 0x24, 0x9c, 0x40, 0x46, 0xbb, 0x80, 0x58, 0x4b, 0xd3, 0x56,
0x0c, 0xc7, 0x73, 0x19, 0x93, 0x37, 0xda, 0xb3, 0xbc, 0x20, 0x37, 0xae, 0xa5, 0xd0, 0x70, 0x86,
0x04, 0xf9, 0xb7, 0x12, 0x4c, 0x84, 0x03, 0x36, 0x80, 0x92, 0xed, 0x9d, 0x78, 0xc9, 0xf6, 0x62,
0xdf, 0xc1, 0x9b, 0x53, 0xb3, 0x7d, 0x5c, 0x00, 0x14, 0x12, 0xb1, 0xd4, 0xb0, 0xa5, 0xb4, 0x6e,
0xdd, 0xc7, 0x8e, 0xe6, 0xc7, 0x12, 0x20, 0x91, 0xe8, 0x97, 0x0c, 0xc3, 0xa4, 0x7c, 0xed, 0xf0,
0xd5, 0x7c, 0xa3, 0x6f, 0x35, 0x7d, 0x0d, 0xaa, 0x9b, 0x29, 0xec, 0x4b, 0x06, 0xb5, 0xbb, 0xe1,
0x88, 0xa5, 0x09, 0x70, 0x86, 0x42, 0xe8, 0x3d, 0x00, 0x5b, 0x60, 0x36, 0x4d, 0x91, 0x02, 0x5e,
0xe9, 0x23, 0x9b, 0x32, 0x80, 0x65, 0xd3, 0xd8, 0x56, 0x3b, 0x61, 0x42, 0xc3, 0x01, 0x30, 0x8e,
0x08, 0x99, 0xbb, 0x04, 0xa7, 0x73, 0xb4, 0x47, 0xa7, 0xa0, 0x70, 0x8b, 0x74, 0x3d, 0xb7, 0x62,
0xf6, 0x13, 0xcd, 0x44, 0x77, 0x86, 0x63, 0x62, 0x53, 0x77, 0x61, 0xe8, 0x05, 0x49, 0xfe, 0xba,
0x18, 0x8d, 0x35, 0x5e, 0x4f, 0x9f, 0x85, 0x92, 0x4d, 0x2c, 0x4d, 0x6d, 0x29, 0x8e, 0xa8, 0x85,
0x78, 0x69, 0x8c, 0x45, 0x1b, 0x0e, 0x7a, 0x63, 0x95, 0xf7, 0xd0, 0x83, 0xad, 0xbc, 0x0b, 0xc7,
0x5d, 0x79, 0x9b, 0x50, 0x72, 0xfc, 0x92, 0x7b, 0x98, 0x83, 0x2f, 0x1d, 0x21, 0x67, 0x8b, 0x6a,
0x3b, 0x10, 0x18, 0xd4, 0xd9, 0x81, 0x90, 0xac, 0x0a, 0xbb, 0xd8, 0x63, 0x85, 0x7d, 0xac, 0x55,
0x31, 0xcb, 0xce, 0x96, 0xe2, 0x3a, 0xa4, 0xcd, 0x53, 0x5a, 0x29, 0xcc, 0xce, 0x75, 0xde, 0x8a,
0x45, 0x2f, 0xd2, 0x63, 0xc1, 0x5d, 0x3a, 0x8e, 0xe0, 0x9e, 0xc8, 0x0f, 0x6c, 0xb4, 0x09, 0xa7,
0x2d, 0xdb, 0xec, 0xd8, 0xc4, 0x71, 0x56, 0x88, 0xd2, 0xd6, 0x54, 0x83, 0xf8, 0xfe, 0x1a, 0xe3,
0x76, 0x3e, 0x72, 0xb0, 0xbf, 0x70, 0xba, 0x9e, 0x4d, 0x82, 0xf3, 0x78, 0xe5, 0x2f, 0x86, 0xe1,
0x54, 0x72, 0x95, 0xcd, 0xa9, 0x68, 0xa5, 0xbe, 0x2a, 0xda, 0xa7, 0x23, 0xd3, 0xc6, 0x2b, 0xf7,
0x83, 0x68, 0xc8, 0x98, 0x3a, 0x4b, 0x30, 0x29, 0xf2, 0x88, 0xdf, 0x29, 0x6a, 0xfa, 0x20, 0x1a,
0x36, 0xe3, 0xdd, 0x38, 0x49, 0xcf, 0xea, 0xd4, 0xb0, 0xfc, 0xf4, 0x41, 0x86, 0xe3, 0x75, 0xea,
0x52, 0x92, 0x00, 0xa7, 0x79, 0xd0, 0x3a, 0x4c, 0xbb, 0x46, 0x1a, 0xca, 0x8b, 0xce, 0x47, 0x04,
0xd4, 0xf4, 0x66, 0x9a, 0x04, 0x67, 0xf1, 0xa1, 0x5d, 0x80, 0x96, 0x5f, 0x10, 0x38, 0x95, 0x11,
0x9e, 0xab, 0x6b, 0x7d, 0xcf, 0xad, 0xa0, 0xb6, 0x08, 0x33, 0x62, 0xd0, 0xe4, 0xe0, 0x88, 0x24,
0xf4, 0x12, 0x8c, 0xdb, 0x7c, 0xd3, 0xe2, 0x1b, 0xe0, 0x15, 0xfe, 0x0f, 0x09, 0xb6, 0x71, 0x1c,
0xed, 0xc4, 0x71, 0xda, 0x8c, 0x5a, 0xbd, 0x74, 0xdf, 0xb5, 0xfa, 0xef, 0xa4, 0xe8, 0xf2, 0x16,
0x94, 0xe9, 0x17, 0x62, 0x25, 0xd9, 0x13, 0x89, 0x92, 0x6c, 0x36, 0xcd, 0x11, 0xa9, 0xc8, 0xfe,
0x2f, 0xbb, 0x42, 0xbf, 0x7c, 0xa4, 0x0a, 0x3d, 0x5c, 0xa6, 0xef, 0x5d, 0xa2, 0x7f, 0x2a, 0xc1,
0xec, 0xe5, 0xc6, 0x15, 0xdb, 0x74, 0x2d, 0x5f, 0xbd, 0x6b, 0x96, 0xe7, 0xe7, 0xff, 0x80, 0x61,
0xdb, 0xd5, 0x7c, 0xbb, 0xfe, 0xc9, 0xb7, 0x0b, 0xbb, 0x1a, 0xb3, 0x6b, 0x3a, 0xc1, 0xe5, 0x19,
0xc5, 0x18, 0xd0, 0x3b, 0x30, 0x62, 0x2b, 0x46, 0x87, 0xf8, 0x0b, 0xf8, 0xf3, 0x3d, 0x5a, 0xb3,
0xba, 0x82, 0x19, 0x7b, 0xa4, 0x8c, 0xe4, 0x68, 0x58, 0xa0, 0xca, 0x3f, 0x92, 0x60, 0xf2, 0x6a,
0xb3, 0x59, 0x5f, 0x35, 0x78, 0x06, 0xa8, 0x2b, 0x74, 0x87, 0xd5, 0x18, 0x96, 0x42, 0x77, 0x92,
0x35, 0x06, 0xeb, 0xc3, 0xbc, 0x07, 0xed, 0xc0, 0x28, 0xcb, 0x3c, 0xc4, 0x68, 0xf7, 0xb9, 0x3d,
0x10, 0xe2, 0x6a, 0x1e, 0x48, 0x58, 0xbb, 0x8a, 0x06, 0xec, 0xc3, 0xcb, 0x1f, 0xc0, 0x4c, 0x44,
0x3d, 0xe6, 0x2f, 0x7e, 0xc6, 0x8a, 0x5a, 0x50, 0x64, 0x9a, 0xf8, 0x27, 0xa8, 0xbd, 0x1e, 0x04,
0x26, 0x4c, 0x0e, 0x6b, 0x30, 0xf6, 0xe5, 0x60, 0x0f, 0x5b, 0x5e, 0x87, 0xf1, 0xab, 0xa6, 0x43,
0xeb, 0xa6, 0x4d, 0xb9, 0xdb, 0xd0, 0x63, 0x50, 0xd0, 0x55, 0x43, 0xac, 0xf0, 0x65, 0xc1, 0x53,
0x60, 0x6b, 0x10, 0x6b, 0xe7, 0xdd, 0xca, 0x9e, 0xc8, 0x64, 0x61, 0xb7, 0xb2, 0x87, 0x59, 0xbb,
0x7c, 0x05, 0x46, 0xc5, 0x70, 0x44, 0x81, 0x0a, 0x87, 0x03, 0x15, 0x32, 0x80, 0x7e, 0x36, 0x04,
0xa3, 0x42, 0xfb, 0x01, 0x6c, 0x04, 0xdf, 0x8a, 0x6d, 0x04, 0x2f, 0xf4, 0x37, 0xd2, 0xb9, 0xbb,
0xc0, 0x76, 0x62, 0x17, 0xf8, 0x72, 0x9f, 0xf8, 0x87, 0x6f, 0x01, 0x3f, 0x91, 0x60, 0x22, 0x1e,
0x73, 0xe8, 0x3c, 0x94, 0xd9, 0x7a, 0xa4, 0xb6, 0xc8, 0x46, 0x58, 0x50, 0x07, 0x07, 0x3a, 0x8d,
0xb0, 0x0b, 0x47, 0xe9, 0x50, 0x27, 0x60, 0x63, 0x61, 0x21, 0x9c, 0x92, 0xef, 0x72, 0x97, 0xaa,
0x5a, 0xd5, 0xbb, 0x7a, 0xaa, 0xae, 0x1a, 0xf4, 0x9a, 0xdd, 0xa0, 0xb6, 0x6a, 0x74, 0x52, 0x82,
0x78, 0x8c, 0x45, 0x91, 0xe5, 0xdb, 0x12, 0x94, 0x85, 0xca, 0x03, 0xd8, 0xce, 0xbc, 0x19, 0xdf,
0xce, 0x3c, 0xdf, 0xe7, 0x7c, 0xce, 0xde, 0xcb, 0x7c, 0x16, 0x9a, 0xc2, 0x66, 0x30, 0x4b, 0x30,
0x3b, 0xa6, 0x43, 0x93, 0x09, 0x86, 0xcd, 0x35, 0xcc, 0x7b, 0xd0, 0xb7, 0x24, 0x38, 0xa5, 0x26,
0xe6, 0xbc, 0xf0, 0xf5, 0xab, 0xfd, 0xa9, 0x16, 0xc0, 0xd4, 0x2a, 0x42, 0xde, 0xa9, 0x64, 0x0f,
0x4e, 0x89, 0x94, 0x5d, 0x48, 0x51, 0x21, 0x05, 0x86, 0x77, 0x28, 0xb5, 0xc4, 0x20, 0x2c, 0xf7,
0x9f, 0x79, 0x42, 0x95, 0x4a, 0xdc, 0xfc, 0x66, 0xb3, 0x8e, 0x39, 0xb4, 0xfc, 0xd3, 0xa1, 0xc0,
0x61, 0x0d, 0x6f, 0x92, 0x04, 0xf9, 0x56, 0x3a, 0x8e, 0x7c, 0x5b, 0xce, 0xca, 0xb5, 0xe8, 0xbf,
0xa0, 0x40, 0xb5, 0x7e, 0x37, 0xb4, 0x42, 0x42, 0x73, 0xad, 0x11, 0x26, 0xac, 0xe6, 0x5a, 0x03,
0x33, 0x48, 0xf4, 0x2e, 0x14, 0xd9, 0x6a, 0xc6, 0xe6, 0x78, 0xa1, 0xff, 0x1c, 0xc2, 0xfc, 0x15,
0x46, 0x18, 0xfb, 0x72, 0xb0, 0x87, 0x2b, 0x7f, 0x00, 0xe3, 0xb1, 0x44, 0x80, 0x6e, 0xc2, 0x49,
0xcd, 0x54, 0xda, 0x35, 0x45, 0x53, 0x8c, 0x16, 0xb1, 0x93, 0xa9, 0x31, 0x7b, 0x2f, 0xb4, 0x16,
0xe1, 0x10, 0x09, 0x25, 0xb8, 0x06, 0x8d, 0xf6, 0xe1, 0x18, 0xb6, 0xac, 0x00, 0x84, 0xd6, 0xa3,
0x05, 0x28, 0xb2, 0x10, 0xf6, 0x56, 0xa6, 0xb1, 0xda, 0x18, 0xd3, 0x95, 0x45, 0xb6, 0x83, 0xbd,
0x76, 0x74, 0x0e, 0xc0, 0x21, 0x2d, 0x9b, 0x50, 0x9e, 0x77, 0xbc, 0xd3, 0xa3, 0x20, 0x03, 0x37,
0x82, 0x1e, 0x1c, 0xa1, 0x92, 0xff, 0x20, 0xc1, 0xf8, 0x06, 0xa1, 0xef, 0x9b, 0xf6, 0xad, 0x3a,
0xbf, 0x66, 0x1e, 0x40, 0xde, 0xdf, 0x8a, 0xe5, 0xfd, 0xd7, 0x7a, 0x1c, 0xb3, 0x98, 0xb6, 0x79,
0xd9, 0x5f, 0xfe, 0x8b, 0x04, 0x95, 0x18, 0x65, 0x34, 0x4d, 0x10, 0x28, 0x5a, 0xa6, 0x4d, 0xfd,
0x35, 0xfe, 0x48, 0x1a, 0xb0, 0x94, 0x1a, 0x59, 0xe5, 0x19, 0x2c, 0xf6, 0xd0, 0x99, 0x9d, 0xdb,
0xb6, 0xa9, 0x8b, 0xb8, 0x3f, 0x9a, 0x14, 0x42, 0xec, 0xd0, 0xce, 0xcb, 0xb6, 0xa9, 0x63, 0x8e,
0x2d, 0xff, 0x5e, 0x82, 0xa9, 0x18, 0xe5, 0x00, 0x52, 0xba, 0x12, 0x4f, 0xe9, 0x2f, 0x1f, 0xc5,
0xb0, 0x9c, 0xc4, 0xfe, 0x4d, 0xd2, 0x2c, 0xe6, 0x00, 0xb4, 0x0d, 0x65, 0xcb, 0x6c, 0x37, 0x8e,
0xe1, 0x7e, 0x71, 0x92, 0xad, 0x90, 0xf5, 0x10, 0x0b, 0x47, 0x81, 0xd1, 0x1e, 0x4c, 0x19, 0x8a,
0x4e, 0x1c, 0x4b, 0x69, 0x91, 0xc6, 0x31, 0x9c, 0xa9, 0x3c, 0xc4, 0x6f, 0x29, 0x92, 0x88, 0x38,
0x2d, 0x44, 0xfe, 0x45, 0xca, 0x6e, 0xd3, 0xa6, 0xe8, 0x75, 0x28, 0xf1, 0xa7, 0x1e, 0x2d, 0x53,
0x13, 0x4b, 0xdb, 0x79, 0x36, 0x34, 0x75, 0xd1, 0x76, 0x77, 0x7f, 0xe1, 0x9f, 0x0f, 0x3d, 0x12,
0xf6, 0x09, 0x71, 0x00, 0x83, 0x36, 0x60, 0xd8, 0x3a, 0x4a, 0x99, 0xc1, 0x17, 0x16, 0x5e, 0x5b,
0x70, 0x1c, 0xf9, 0xaf, 0x49, 0xc5, 0xf9, 0xf2, 0x72, 0xf3, 0xd8, 0x06, 0x2c, 0x28, 0x6b, 0x72,
0x07, 0xcd, 0x86, 0x51, 0xb1, 0xca, 0x8a, 0xb8, 0xbc, 0x72, 0x94, 0xb8, 0x8c, 0xae, 0x0c, 0xc1,
0x26, 0xc2, 0x6f, 0xf4, 0x05, 0xc9, 0x7f, 0x92, 0x60, 0x8a, 0x2b, 0xd4, 0x72, 0x6d, 0x95, 0x76,
0x07, 0x96, 0x41, 0xb7, 0x63, 0x19, 0x74, 0xa5, 0x47, 0x43, 0x53, 0x1a, 0xe7, 0x66, 0xd1, 0x2f,
0x25, 0x78, 0x28, 0x45, 0x3d, 0x80, 0x0c, 0x43, 0xe2, 0x19, 0xe6, 0xb5, 0xa3, 0x1a, 0x98, 0x93,
0x65, 0xbe, 0x5d, 0xce, 0x30, 0x8f, 0x07, 0xee, 0x39, 0x00, 0xcb, 0x56, 0x77, 0x55, 0x8d, 0x74,
0xc4, 0x25, 0x74, 0x29, 0x1c, 0x92, 0x7a, 0xd0, 0x83, 0x23, 0x54, 0xe8, 0x7f, 0x60, 0xb6, 0x4d,
0xb6, 0x15, 0x57, 0xa3, 0x4b, 0xed, 0xf6, 0xb2, 0x62, 0x29, 0x5b, 0xaa, 0xa6, 0x52, 0x55, 0xec,
0xb0, 0xc7, 0x6a, 0x97, 0xbc, 0xcb, 0xe1, 0x2c, 0x8a, 0xbb, 0xfb, 0x0b, 0x4f, 0x1e, 0x7e, 0xa9,
0xe3, 0x13, 0x77, 0x71, 0x8e, 0x10, 0xf4, 0xff, 0x12, 0x54, 0x6c, 0xf2, 0x9e, 0xab, 0xda, 0xa4,
0xbd, 0x62, 0x9b, 0x56, 0x4c, 0x83, 0x02, 0xd7, 0xe0, 0xca, 0xc1, 0xfe, 0x42, 0x05, 0xe7, 0xd0,
0xf4, 0xa2, 0x43, 0xae, 0x20, 0x44, 0x61, 0x5a, 0xd1, 0x34, 0xf3, 0x7d, 0x12, 0xf7, 0xc0, 0x30,
0x97, 0x5f, 0x3b, 0xd8, 0x5f, 0x98, 0x5e, 0x4a, 0x77, 0xf7, 0x22, 0x3a, 0x0b, 0x1e, 0x2d, 0xc2,
0xe8, 0xae, 0xa9, 0xb9, 0x3a, 0x71, 0x2a, 0x45, 0x2e, 0x89, 0x65, 0xdc, 0xd1, 0xeb, 0x5e, 0xd3,
0xdd, 0xfd, 0x85, 0x91, 0xcb, 0x0d, 0x7e, 0xf4, 0xe1, 0x53, 0xb1, 0x3d, 0x1a, 0xab, 0x99, 0xc4,
0x94, 0xe7, 0x67, 0xb6, 0xa5, 0x30, 0xc7, 0x5c, 0x0d, 0xbb, 0x70, 0x94, 0x0e, 0xe9, 0x30, 0xb6,
0x23, 0xf6, 0xed, 0x4e, 0x65, 0xb4, 0xaf, 0xd5, 0x2f, 0xb6, 0xef, 0xaf, 0x4d, 0x09, 0x91, 0x63,
0x7e, 0xb3, 0x83, 0x43, 0x09, 0xe8, 0x29, 0x18, 0xe5, 0x1f, 0xab, 0x2b, 0xfc, 0x00, 0xac, 0x14,
0x66, 0xa2, 0xab, 0x5e, 0x33, 0xf6, 0xfb, 0x7d, 0xd2, 0xd5, 0xfa, 0x32, 0x3f, 0x98, 0x4d, 0x90,
0xae, 0xd6, 0x97, 0xb1, 0xdf, 0x8f, 0x2c, 0x18, 0x75, 0xc8, 0x9a, 0x6a, 0xb8, 0x7b, 0x15, 0xe8,
0xeb, 0xaa, 0xb9, 0x71, 0x89, 0x73, 0x27, 0x8e, 0xa2, 0x42, 0x89, 0xa2, 0x1f, 0xfb, 0x62, 0xd0,
0x1e, 0x8c, 0xd9, 0xae, 0xb1, 0xe4, 0x6c, 0x3a, 0xc4, 0xae, 0x94, 0xb9, 0xcc, 0x5e, 0x93, 0x33,
0xf6, 0xf9, 0x93, 0x52, 0x03, 0x0f, 0x06, 0x14, 0x38, 0x14, 0x86, 0x7e, 0x28, 0x01, 0x72, 0x5c,
0xcb, 0xd2, 0x88, 0x4e, 0x0c, 0xaa, 0x68, 0xfc, 0x34, 0xcc, 0xa9, 0x9c, 0xe4, 0x3a, 0xd4, 0x7b,
0xb5, 0x3b, 0x05, 0x94, 0x54, 0x26, 0x38, 0xa6, 0x4e, 0x93, 0xe2, 0x0c, 0x3d, 0xd8, 0x50, 0x6c,
0x3b, 0xfc, 0x77, 0x65, 0xbc, 0xaf, 0xa1, 0xc8, 0x3e, 0x15, 0x0c, 0x87, 0x42, 0xf4, 0x63, 0x5f,
0x0c, 0xba, 0x0e, 0xb3, 0x36, 0x51, 0xda, 0xd7, 0x0c, 0xad, 0x8b, 0x4d, 0x93, 0x5e, 0x56, 0x35,
0xe2, 0x74, 0x1d, 0x4a, 0xf4, 0xca, 0x04, 0x0f, 0x9b, 0xe0, 0xa9, 0x07, 0xce, 0xa4, 0xc2, 0x39,
0xdc, 0xe8, 0x35, 0x38, 0x25, 0x26, 0x26, 0x0f, 0x4d, 0x7e, 0x82, 0x36, 0xc9, 0xa7, 0xe2, 0x0c,
0xdb, 0x11, 0x2f, 0x25, 0xfa, 0x70, 0x8a, 0x9a, 0xbf, 0x43, 0x10, 0x27, 0xc0, 0x83, 0x79, 0x53,
0x78, 0xb4, 0x77, 0x08, 0xa1, 0xaa, 0x0f, 0xec, 0x1d, 0x42, 0x44, 0xc4, 0xe1, 0x87, 0x50, 0xdf,
0x0c, 0xc1, 0x74, 0x48, 0x7c, 0xdf, 0xef, 0x10, 0x32, 0x58, 0x06, 0xf0, 0x0e, 0x21, 0xfb, 0x22,
0xbf, 0xf0, 0xa0, 0x2f, 0xf2, 0x1f, 0xc0, 0xfb, 0x07, 0xfe, 0x36, 0x20, 0x74, 0xe2, 0xdf, 0xff,
0xdb, 0x80, 0x50, 0xd7, 0x9c, 0x82, 0xe8, 0x57, 0x43, 0x51, 0x83, 0xfe, 0x81, 0x2e, 0xa0, 0x8f,
0xfe, 0xe2, 0x52, 0xfe, 0xb2, 0x00, 0xa7, 0x92, 0x33, 0x36, 0x76, 0x0f, 0x29, 0xdd, 0xf3, 0x1e,
0xb2, 0x0e, 0x33, 0xdb, 0xae, 0xa6, 0x75, 0xb9, 0x43, 0x22, 0x97, 0x91, 0xde, 0xb9, 0xff, 0xa3,
0x82, 0x73, 0xe6, 0x72, 0x06, 0x0d, 0xce, 0xe4, 0xcc, 0xb9, 0x53, 0x2d, 0xf4, 0x75, 0xa7, 0x9a,
0xba, 0xd2, 0x1b, 0xee, 0xe1, 0x4a, 0x2f, 0xf3, 0x7e, 0xb4, 0xd8, 0xc7, 0xfd, 0xe8, 0x71, 0x5c,
0x68, 0x66, 0x24, 0xbe, 0x7b, 0x5d, 0x68, 0xca, 0x8f, 0xc2, 0x9c, 0x60, 0xa3, 0xfc, 0xae, 0xd1,
0xa0, 0xb6, 0xa9, 0x69, 0xc4, 0x5e, 0x71, 0x75, 0xbd, 0x2b, 0x5f, 0x84, 0x89, 0xf8, 0xad, 0xba,
0x37, 0xf2, 0xde, 0x45, 0xbf, 0xb8, 0x8d, 0x89, 0x8c, 0xbc, 0xd7, 0x8e, 0x03, 0x0a, 0xf9, 0x23,
0x09, 0x66, 0xb3, 0x5f, 0xf0, 0x21, 0x0d, 0x26, 0x74, 0x65, 0x2f, 0xfa, 0xfc, 0x51, 0xea, 0x73,
0xcf, 0xce, 0xaf, 0x4f, 0xd7, 0x63, 0x58, 0x38, 0x81, 0x2d, 0x7f, 0x25, 0xc1, 0xe9, 0x9c, 0x8b,
0xca, 0xc1, 0x6a, 0x82, 0x6e, 0x40, 0x49, 0x57, 0xf6, 0x1a, 0xae, 0xdd, 0x21, 0x7d, 0x9f, 0x52,
0xf0, 0x5c, 0xb2, 0x2e, 0x50, 0x70, 0x80, 0x27, 0x7f, 0x2a, 0x41, 0x25, 0xaf, 0xa2, 0x44, 0xe7,
0x63, 0x57, 0xaa, 0x8f, 0x27, 0xae, 0x54, 0xa7, 0x52, 0x7c, 0x03, 0xba, 0x50, 0xfd, 0x4c, 0x82,
0xd9, 0xec, 0xca, 0x1b, 0x3d, 0x17, 0xd3, 0x78, 0x21, 0xa1, 0xf1, 0x64, 0x82, 0x4b, 0xe8, 0xbb,
0x03, 0x13, 0xa2, 0x3e, 0x17, 0x30, 0xc2, 0xcb, 0x4f, 0x1f, 0x9e, 0x55, 0x05, 0x98, 0x5f, 0x69,
0xf2, 0x91, 0x8c, 0xb7, 0xe1, 0x04, 0xae, 0xfc, 0x93, 0x21, 0x28, 0x36, 0x5a, 0x8a, 0x46, 0x06,
0x50, 0xd4, 0xdd, 0x88, 0x15, 0x75, 0xbd, 0xfe, 0xdf, 0x81, 0x6b, 0x99, 0x5b, 0xcf, 0x6d, 0x25,
0xea, 0xb9, 0x0b, 0x7d, 0xa1, 0x1f, 0x5e, 0xca, 0xbd, 0x08, 0x63, 0x81, 0x12, 0xbd, 0xad, 0x1e,
0xf2, 0x27, 0x43, 0x50, 0x8e, 0x88, 0xe8, 0x71, 0xed, 0xd9, 0x8d, 0xad, 0xde, 0xfd, 0xfc, 0xb5,
0x2a, 0x22, 0xbb, 0xea, 0xaf, 0xdf, 0xde, 0x0b, 0xbe, 0xf0, 0x25, 0x56, 0x7a, 0x59, 0xbf, 0x08,
0x13, 0x94, 0xff, 0xd3, 0x28, 0x38, 0x25, 0x2c, 0xf0, 0x28, 0x0e, 0xde, 0x85, 0x36, 0x63, 0xbd,
0x38, 0x41, 0x3d, 0xf7, 0x12, 0x8c, 0xc7, 0x84, 0xf5, 0xf4, 0xe0, 0xee, 0xd7, 0x12, 0x3c, 0x7e,
0xcf, 0x5d, 0x1d, 0xaa, 0xc5, 0xa6, 0x57, 0x35, 0x31, 0xbd, 0xe6, 0xf3, 0x01, 0x06, 0xf8, 0xdc,
0xe2, 0xfb, 0x43, 0x80, 0x9a, 0x3b, 0xaa, 0xdd, 0xae, 0x2b, 0x36, 0xed, 0x62, 0xf1, 0x7f, 0xb2,
0x01, 0x4c, 0xb8, 0xf3, 0x50, 0x6e, 0x13, 0xa7, 0x65, 0xab, 0xdc, 0x59, 0x62, 0xaf, 0x10, 0x9c,
0xa4, 0xac, 0x84, 0x5d, 0x38, 0x4a, 0x87, 0x3a, 0x50, 0xda, 0xf5, 0xfe, 0xb1, 0xe8, 0xdf, 0xdd,
0xf5, 0x5a, 0xcc, 0x86, 0xff, 0x79, 0x0c, 0xe3, 0x4b, 0x34, 0x38, 0x38, 0x00, 0x97, 0x3f, 0x96,
0x60, 0x36, 0xed, 0x98, 0x15, 0xa6, 0xfa, 0x83, 0x77, 0xce, 0xa3, 0x30, 0xcc, 0xd1, 0x99, 0x57,
0x4e, 0x7a, 0x67, 0xe6, 0x4c, 0x32, 0xe6, 0xad, 0xf2, 0xd7, 0x12, 0xcc, 0x65, 0xab, 0x36, 0x80,
0xad, 0xc4, 0xcd, 0xf8, 0x56, 0xa2, 0xd7, 0x83, 0x87, 0x6c, 0xbd, 0x73, 0xb6, 0x15, 0xfb, 0x99,
0x63, 0x30, 0x00, 0x23, 0xb7, 0xe3, 0x46, 0x2e, 0x1d, 0xd9, 0xc8, 0x6c, 0x03, 0x6b, 0x4f, 0xdd,
0xbe, 0x33, 0x7f, 0xe2, 0xf3, 0x3b, 0xf3, 0x27, 0xbe, 0xb8, 0x33, 0x7f, 0xe2, 0xc3, 0x83, 0x79,
0xe9, 0xf6, 0xc1, 0xbc, 0xf4, 0xf9, 0xc1, 0xbc, 0xf4, 0xe7, 0x83, 0x79, 0xe9, 0xbb, 0x5f, 0xcd,
0x9f, 0xb8, 0x31, 0x2a, 0x30, 0xff, 0x16, 0x00, 0x00, 0xff, 0xff, 0x9e, 0x01, 0x30, 0x7b, 0xbe,
0x3d, 0x00, 0x00,
}

View File

@@ -123,10 +123,17 @@ message DaemonSetSpec {
// +optional
optional int32 minReadySeconds = 4;
// DEPRECATED.
// A sequence number representing a specific generation of the template.
// Populated by the system. It can be set only during the creation.
// +optional
optional int64 templateGeneration = 5;
// The number of old history to retain to allow rollback.
// This is a pointer to distinguish between explicit zero and not specified.
// Defaults to 10.
// +optional
optional int32 revisionHistoryLimit = 6;
}
// DaemonSetStatus represents the current status of a daemon set.
@@ -169,6 +176,12 @@ message DaemonSetStatus {
// (ready for at least spec.minReadySeconds)
// +optional
optional int32 numberUnavailable = 8;
// Count of hash collisions for the DaemonSet. The DaemonSet controller
// uses this field as a collision avoidance mechanism when it needs to
// create the name for the newest ControllerRevision.
// +optional
optional int64 collisionCount = 9;
}
message DaemonSetUpdateStrategy {
@@ -180,7 +193,7 @@ message DaemonSetUpdateStrategy {
// Rolling update config params. Present only if type = "RollingUpdate".
// ---
// TODO: Update this to follow our convention for oneOf, whatever we decide it
// to be. Same as DeploymentStrategy.RollingUpdate.
// to be. Same as Deployment `strategy.rollingUpdate`.
// See https://github.com/kubernetes/kubernetes/issues/35345
// +optional
optional RollingUpdateDaemonSet rollingUpdate = 2;

View File

@@ -7552,16 +7552,17 @@ func (x *DaemonSetSpec) CodecEncodeSelf(e *codec1978.Encoder) {
} else {
yysep2 := !z.EncBinary()
yy2arr2 := z.EncBasicHandle().StructToArray
var yyq2 [5]bool
var yyq2 [6]bool
_, _, _ = yysep2, yyq2, yy2arr2
const yyr2 bool = false
yyq2[0] = x.Selector != nil
yyq2[2] = true
yyq2[3] = x.MinReadySeconds != 0
yyq2[4] = x.TemplateGeneration != 0
yyq2[5] = x.RevisionHistoryLimit != nil
var yynn2 int
if yyr2 || yy2arr2 {
r.EncodeArrayStart(5)
r.EncodeArrayStart(6)
} else {
yynn2 = 1
for _, b := range yyq2 {
@@ -7685,6 +7686,41 @@ func (x *DaemonSetSpec) CodecEncodeSelf(e *codec1978.Encoder) {
}
}
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
if yyq2[5] {
if x.RevisionHistoryLimit == nil {
r.EncodeNil()
} else {
yy23 := *x.RevisionHistoryLimit
yym24 := z.EncBinary()
_ = yym24
if false {
} else {
r.EncodeInt(int64(yy23))
}
}
} else {
r.EncodeNil()
}
} else {
if yyq2[5] {
z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("revisionHistoryLimit"))
z.EncSendContainerState(codecSelfer_containerMapValue1234)
if x.RevisionHistoryLimit == nil {
r.EncodeNil()
} else {
yy25 := *x.RevisionHistoryLimit
yym26 := z.EncBinary()
_ = yym26
if false {
} else {
r.EncodeInt(int64(yy25))
}
}
}
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
} else {
@@ -7801,6 +7837,22 @@ func (x *DaemonSetSpec) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
*((*int64)(yyv10)) = int64(r.DecodeInt(64))
}
}
case "revisionHistoryLimit":
if r.TryDecodeAsNil() {
if x.RevisionHistoryLimit != nil {
x.RevisionHistoryLimit = nil
}
} else {
if x.RevisionHistoryLimit == nil {
x.RevisionHistoryLimit = new(int32)
}
yym13 := z.DecBinary()
_ = yym13
if false {
} else {
*((*int32)(x.RevisionHistoryLimit)) = int32(r.DecodeInt(32))
}
}
default:
z.DecStructFieldNotFound(-1, yys3)
} // end switch yys3
@@ -7812,16 +7864,16 @@ func (x *DaemonSetSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r
var yyj12 int
var yyb12 bool
var yyhl12 bool = l >= 0
yyj12++
if yyhl12 {
yyb12 = yyj12 > l
var yyj14 int
var yyb14 bool
var yyhl14 bool = l >= 0
yyj14++
if yyhl14 {
yyb14 = yyj14 > l
} else {
yyb12 = r.CheckBreak()
yyb14 = r.CheckBreak()
}
if yyb12 {
if yyb14 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
@@ -7834,21 +7886,21 @@ func (x *DaemonSetSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
if x.Selector == nil {
x.Selector = new(pkg1_v1.LabelSelector)
}
yym14 := z.DecBinary()
_ = yym14
yym16 := z.DecBinary()
_ = yym16
if false {
} else if z.HasExtensions() && z.DecExt(x.Selector) {
} else {
z.DecFallback(x.Selector, false)
}
}
yyj12++
if yyhl12 {
yyb12 = yyj12 > l
yyj14++
if yyhl14 {
yyb14 = yyj14 > l
} else {
yyb12 = r.CheckBreak()
yyb14 = r.CheckBreak()
}
if yyb12 {
if yyb14 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
@@ -7856,16 +7908,16 @@ func (x *DaemonSetSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
if r.TryDecodeAsNil() {
x.Template = pkg4_v1.PodTemplateSpec{}
} else {
yyv15 := &x.Template
yyv15.CodecDecodeSelf(d)
yyv17 := &x.Template
yyv17.CodecDecodeSelf(d)
}
yyj12++
if yyhl12 {
yyb12 = yyj12 > l
yyj14++
if yyhl14 {
yyb14 = yyj14 > l
} else {
yyb12 = r.CheckBreak()
yyb14 = r.CheckBreak()
}
if yyb12 {
if yyb14 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
@@ -7873,16 +7925,16 @@ func (x *DaemonSetSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
if r.TryDecodeAsNil() {
x.UpdateStrategy = DaemonSetUpdateStrategy{}
} else {
yyv16 := &x.UpdateStrategy
yyv16.CodecDecodeSelf(d)
yyv18 := &x.UpdateStrategy
yyv18.CodecDecodeSelf(d)
}
yyj12++
if yyhl12 {
yyb12 = yyj12 > l
yyj14++
if yyhl14 {
yyb14 = yyj14 > l
} else {
yyb12 = r.CheckBreak()
yyb14 = r.CheckBreak()
}
if yyb12 {
if yyb14 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
@@ -7890,21 +7942,21 @@ func (x *DaemonSetSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
if r.TryDecodeAsNil() {
x.MinReadySeconds = 0
} else {
yyv17 := &x.MinReadySeconds
yym18 := z.DecBinary()
_ = yym18
yyv19 := &x.MinReadySeconds
yym20 := z.DecBinary()
_ = yym20
if false {
} else {
*((*int32)(yyv17)) = int32(r.DecodeInt(32))
*((*int32)(yyv19)) = int32(r.DecodeInt(32))
}
}
yyj12++
if yyhl12 {
yyb12 = yyj12 > l
yyj14++
if yyhl14 {
yyb14 = yyj14 > l
} else {
yyb12 = r.CheckBreak()
yyb14 = r.CheckBreak()
}
if yyb12 {
if yyb14 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
@@ -7912,26 +7964,52 @@ func (x *DaemonSetSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
if r.TryDecodeAsNil() {
x.TemplateGeneration = 0
} else {
yyv19 := &x.TemplateGeneration
yym20 := z.DecBinary()
_ = yym20
yyv21 := &x.TemplateGeneration
yym22 := z.DecBinary()
_ = yym22
if false {
} else {
*((*int64)(yyv19)) = int64(r.DecodeInt(64))
*((*int64)(yyv21)) = int64(r.DecodeInt(64))
}
}
yyj14++
if yyhl14 {
yyb14 = yyj14 > l
} else {
yyb14 = r.CheckBreak()
}
if yyb14 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
if x.RevisionHistoryLimit != nil {
x.RevisionHistoryLimit = nil
}
} else {
if x.RevisionHistoryLimit == nil {
x.RevisionHistoryLimit = new(int32)
}
yym24 := z.DecBinary()
_ = yym24
if false {
} else {
*((*int32)(x.RevisionHistoryLimit)) = int32(r.DecodeInt(32))
}
}
for {
yyj12++
if yyhl12 {
yyb12 = yyj12 > l
yyj14++
if yyhl14 {
yyb14 = yyj14 > l
} else {
yyb12 = r.CheckBreak()
yyb14 = r.CheckBreak()
}
if yyb12 {
if yyb14 {
break
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
z.DecStructFieldNotFound(yyj12-1, "")
z.DecStructFieldNotFound(yyj14-1, "")
}
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
}
@@ -7950,16 +8028,17 @@ func (x *DaemonSetStatus) CodecEncodeSelf(e *codec1978.Encoder) {
} else {
yysep2 := !z.EncBinary()
yy2arr2 := z.EncBasicHandle().StructToArray
var yyq2 [8]bool
var yyq2 [9]bool
_, _, _ = yysep2, yyq2, yy2arr2
const yyr2 bool = false
yyq2[4] = x.ObservedGeneration != 0
yyq2[5] = x.UpdatedNumberScheduled != 0
yyq2[6] = x.NumberAvailable != 0
yyq2[7] = x.NumberUnavailable != 0
yyq2[8] = x.CollisionCount != nil
var yynn2 int
if yyr2 || yy2arr2 {
r.EncodeArrayStart(8)
r.EncodeArrayStart(9)
} else {
yynn2 = 4
for _, b := range yyq2 {
@@ -8146,6 +8225,41 @@ func (x *DaemonSetStatus) CodecEncodeSelf(e *codec1978.Encoder) {
}
}
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
if yyq2[8] {
if x.CollisionCount == nil {
r.EncodeNil()
} else {
yy28 := *x.CollisionCount
yym29 := z.EncBinary()
_ = yym29
if false {
} else {
r.EncodeInt(int64(yy28))
}
}
} else {
r.EncodeNil()
}
} else {
if yyq2[8] {
z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("collisionCount"))
z.EncSendContainerState(codecSelfer_containerMapValue1234)
if x.CollisionCount == nil {
r.EncodeNil()
} else {
yy30 := *x.CollisionCount
yym31 := z.EncBinary()
_ = yym31
if false {
} else {
r.EncodeInt(int64(yy30))
}
}
}
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
} else {
@@ -8303,6 +8417,22 @@ func (x *DaemonSetStatus) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
*((*int32)(yyv18)) = int32(r.DecodeInt(32))
}
}
case "collisionCount":
if r.TryDecodeAsNil() {
if x.CollisionCount != nil {
x.CollisionCount = nil
}
} else {
if x.CollisionCount == nil {
x.CollisionCount = new(int64)
}
yym21 := z.DecBinary()
_ = yym21
if false {
} else {
*((*int64)(x.CollisionCount)) = int64(r.DecodeInt(64))
}
}
default:
z.DecStructFieldNotFound(-1, yys3)
} // end switch yys3
@@ -8314,16 +8444,16 @@ func (x *DaemonSetStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r
var yyj20 int
var yyb20 bool
var yyhl20 bool = l >= 0
yyj20++
if yyhl20 {
yyb20 = yyj20 > l
var yyj22 int
var yyb22 bool
var yyhl22 bool = l >= 0
yyj22++
if yyhl22 {
yyb22 = yyj22 > l
} else {
yyb20 = r.CheckBreak()
yyb22 = r.CheckBreak()
}
if yyb20 {
if yyb22 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
@@ -8331,29 +8461,7 @@ func (x *DaemonSetStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
if r.TryDecodeAsNil() {
x.CurrentNumberScheduled = 0
} else {
yyv21 := &x.CurrentNumberScheduled
yym22 := z.DecBinary()
_ = yym22
if false {
} else {
*((*int32)(yyv21)) = int32(r.DecodeInt(32))
}
}
yyj20++
if yyhl20 {
yyb20 = yyj20 > l
} else {
yyb20 = r.CheckBreak()
}
if yyb20 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.NumberMisscheduled = 0
} else {
yyv23 := &x.NumberMisscheduled
yyv23 := &x.CurrentNumberScheduled
yym24 := z.DecBinary()
_ = yym24
if false {
@@ -8361,21 +8469,21 @@ func (x *DaemonSetStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
*((*int32)(yyv23)) = int32(r.DecodeInt(32))
}
}
yyj20++
if yyhl20 {
yyb20 = yyj20 > l
yyj22++
if yyhl22 {
yyb22 = yyj22 > l
} else {
yyb20 = r.CheckBreak()
yyb22 = r.CheckBreak()
}
if yyb20 {
if yyb22 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.DesiredNumberScheduled = 0
x.NumberMisscheduled = 0
} else {
yyv25 := &x.DesiredNumberScheduled
yyv25 := &x.NumberMisscheduled
yym26 := z.DecBinary()
_ = yym26
if false {
@@ -8383,21 +8491,21 @@ func (x *DaemonSetStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
*((*int32)(yyv25)) = int32(r.DecodeInt(32))
}
}
yyj20++
if yyhl20 {
yyb20 = yyj20 > l
yyj22++
if yyhl22 {
yyb22 = yyj22 > l
} else {
yyb20 = r.CheckBreak()
yyb22 = r.CheckBreak()
}
if yyb20 {
if yyb22 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.NumberReady = 0
x.DesiredNumberScheduled = 0
} else {
yyv27 := &x.NumberReady
yyv27 := &x.DesiredNumberScheduled
yym28 := z.DecBinary()
_ = yym28
if false {
@@ -8405,13 +8513,35 @@ func (x *DaemonSetStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
*((*int32)(yyv27)) = int32(r.DecodeInt(32))
}
}
yyj20++
if yyhl20 {
yyb20 = yyj20 > l
yyj22++
if yyhl22 {
yyb22 = yyj22 > l
} else {
yyb20 = r.CheckBreak()
yyb22 = r.CheckBreak()
}
if yyb20 {
if yyb22 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.NumberReady = 0
} else {
yyv29 := &x.NumberReady
yym30 := z.DecBinary()
_ = yym30
if false {
} else {
*((*int32)(yyv29)) = int32(r.DecodeInt(32))
}
}
yyj22++
if yyhl22 {
yyb22 = yyj22 > l
} else {
yyb22 = r.CheckBreak()
}
if yyb22 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
@@ -8419,21 +8549,21 @@ func (x *DaemonSetStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
if r.TryDecodeAsNil() {
x.ObservedGeneration = 0
} else {
yyv29 := &x.ObservedGeneration
yym30 := z.DecBinary()
_ = yym30
yyv31 := &x.ObservedGeneration
yym32 := z.DecBinary()
_ = yym32
if false {
} else {
*((*int64)(yyv29)) = int64(r.DecodeInt(64))
*((*int64)(yyv31)) = int64(r.DecodeInt(64))
}
}
yyj20++
if yyhl20 {
yyb20 = yyj20 > l
yyj22++
if yyhl22 {
yyb22 = yyj22 > l
} else {
yyb20 = r.CheckBreak()
yyb22 = r.CheckBreak()
}
if yyb20 {
if yyb22 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
@@ -8441,29 +8571,7 @@ func (x *DaemonSetStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
if r.TryDecodeAsNil() {
x.UpdatedNumberScheduled = 0
} else {
yyv31 := &x.UpdatedNumberScheduled
yym32 := z.DecBinary()
_ = yym32
if false {
} else {
*((*int32)(yyv31)) = int32(r.DecodeInt(32))
}
}
yyj20++
if yyhl20 {
yyb20 = yyj20 > l
} else {
yyb20 = r.CheckBreak()
}
if yyb20 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.NumberAvailable = 0
} else {
yyv33 := &x.NumberAvailable
yyv33 := &x.UpdatedNumberScheduled
yym34 := z.DecBinary()
_ = yym34
if false {
@@ -8471,21 +8579,21 @@ func (x *DaemonSetStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
*((*int32)(yyv33)) = int32(r.DecodeInt(32))
}
}
yyj20++
if yyhl20 {
yyb20 = yyj20 > l
yyj22++
if yyhl22 {
yyb22 = yyj22 > l
} else {
yyb20 = r.CheckBreak()
yyb22 = r.CheckBreak()
}
if yyb20 {
if yyb22 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.NumberUnavailable = 0
x.NumberAvailable = 0
} else {
yyv35 := &x.NumberUnavailable
yyv35 := &x.NumberAvailable
yym36 := z.DecBinary()
_ = yym36
if false {
@@ -8493,18 +8601,66 @@ func (x *DaemonSetStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
*((*int32)(yyv35)) = int32(r.DecodeInt(32))
}
}
for {
yyj20++
if yyhl20 {
yyb20 = yyj20 > l
yyj22++
if yyhl22 {
yyb22 = yyj22 > l
} else {
yyb20 = r.CheckBreak()
yyb22 = r.CheckBreak()
}
if yyb20 {
if yyb22 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.NumberUnavailable = 0
} else {
yyv37 := &x.NumberUnavailable
yym38 := z.DecBinary()
_ = yym38
if false {
} else {
*((*int32)(yyv37)) = int32(r.DecodeInt(32))
}
}
yyj22++
if yyhl22 {
yyb22 = yyj22 > l
} else {
yyb22 = r.CheckBreak()
}
if yyb22 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
if x.CollisionCount != nil {
x.CollisionCount = nil
}
} else {
if x.CollisionCount == nil {
x.CollisionCount = new(int64)
}
yym40 := z.DecBinary()
_ = yym40
if false {
} else {
*((*int64)(x.CollisionCount)) = int64(r.DecodeInt(64))
}
}
for {
yyj22++
if yyhl22 {
yyb22 = yyj22 > l
} else {
yyb22 = r.CheckBreak()
}
if yyb22 {
break
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
z.DecStructFieldNotFound(yyj20-1, "")
z.DecStructFieldNotFound(yyj22-1, "")
}
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
}
@@ -19917,7 +20073,7 @@ func (x codecSelfer1234) decSliceDaemonSet(v *[]DaemonSet, d *codec1978.Decoder)
yyrg1 := len(yyv1) > 0
yyv21 := yyv1
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 912)
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 928)
if yyrt1 {
if yyrl1 <= cap(yyv1) {
yyv1 = yyv1[:yyrl1]

View File

@@ -386,7 +386,7 @@ type DaemonSetUpdateStrategy struct {
// Rolling update config params. Present only if type = "RollingUpdate".
//---
// TODO: Update this to follow our convention for oneOf, whatever we decide it
// to be. Same as DeploymentStrategy.RollingUpdate.
// to be. Same as Deployment `strategy.rollingUpdate`.
// See https://github.com/kubernetes/kubernetes/issues/35345
// +optional
RollingUpdate *RollingUpdateDaemonSet `json:"rollingUpdate,omitempty" protobuf:"bytes,2,opt,name=rollingUpdate"`
@@ -449,10 +449,17 @@ type DaemonSetSpec struct {
// +optional
MinReadySeconds int32 `json:"minReadySeconds,omitempty" protobuf:"varint,4,opt,name=minReadySeconds"`
// DEPRECATED.
// A sequence number representing a specific generation of the template.
// Populated by the system. It can be set only during the creation.
// +optional
TemplateGeneration int64 `json:"templateGeneration,omitempty" protobuf:"varint,5,opt,name=templateGeneration"`
// The number of old history to retain to allow rollback.
// This is a pointer to distinguish between explicit zero and not specified.
// Defaults to 10.
// +optional
RevisionHistoryLimit *int32 `json:"revisionHistoryLimit,omitempty" protobuf:"varint,6,opt,name=revisionHistoryLimit"`
}
// DaemonSetStatus represents the current status of a daemon set.
@@ -495,6 +502,12 @@ type DaemonSetStatus struct {
// (ready for at least spec.minReadySeconds)
// +optional
NumberUnavailable int32 `json:"numberUnavailable,omitempty" protobuf:"varint,8,opt,name=numberUnavailable"`
// Count of hash collisions for the DaemonSet. The DaemonSet controller
// uses this field as a collision avoidance mechanism when it needs to
// create the name for the newest ControllerRevision.
// +optional
CollisionCount *int64 `json:"collisionCount,omitempty" protobuf:"varint,9,opt,name=collisionCount"`
}
// +genclient=true
@@ -522,10 +535,16 @@ type DaemonSet struct {
}
const (
// DEPRECATED: DefaultDaemonSetUniqueLabelKey is used instead.
// DaemonSetTemplateGenerationKey is the key of the labels that is added
// to daemon set pods to distinguish between old and new pod templates
// during DaemonSet template update.
DaemonSetTemplateGenerationKey string = "pod-template-generation"
// DefaultDaemonSetUniqueLabelKey is the default label key that is added
// to existing DaemonSet pods to distinguish between old and new
// DaemonSet pods during DaemonSet template updates.
DefaultDaemonSetUniqueLabelKey string = "daemonset-controller-hash"
)
// DaemonSetList is a collection of daemon sets.

View File

@@ -82,7 +82,8 @@ var map_DaemonSetSpec = map[string]string{
"template": "An object that describes the pod that will be created. The DaemonSet will create exactly one copy of this pod on every node that matches the template's node selector (or on every node if no node selector is specified). More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#pod-template",
"updateStrategy": "An update strategy to replace existing DaemonSet pods with new pods.",
"minReadySeconds": "The minimum number of seconds for which a newly created DaemonSet pod should be ready without any of its container crashing, for it to be considered available. Defaults to 0 (pod will be considered available as soon as it is ready).",
"templateGeneration": "A sequence number representing a specific generation of the template. Populated by the system. It can be set only during the creation.",
"templateGeneration": "DEPRECATED. A sequence number representing a specific generation of the template. Populated by the system. It can be set only during the creation.",
"revisionHistoryLimit": "The number of old history to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 10.",
}
func (DaemonSetSpec) SwaggerDoc() map[string]string {
@@ -99,6 +100,7 @@ var map_DaemonSetStatus = map[string]string{
"updatedNumberScheduled": "The total number of nodes that are running updated daemon pod",
"numberAvailable": "The number of nodes that should be running the daemon pod and have one or more of the daemon pod running and available (ready for at least spec.minReadySeconds)",
"numberUnavailable": "The number of nodes that should be running the daemon pod and have none of the daemon pod running and available (ready for at least spec.minReadySeconds)",
"collisionCount": "Count of hash collisions for the DaemonSet. The DaemonSet controller uses this field as a collision avoidance mechanism when it needs to create the name for the newest ControllerRevision.",
}
func (DaemonSetStatus) SwaggerDoc() map[string]string {

View File

@@ -352,6 +352,7 @@ func autoConvert_v1beta1_DaemonSetSpec_To_extensions_DaemonSetSpec(in *DaemonSet
}
out.MinReadySeconds = in.MinReadySeconds
out.TemplateGeneration = in.TemplateGeneration
out.RevisionHistoryLimit = (*int32)(unsafe.Pointer(in.RevisionHistoryLimit))
return nil
}
@@ -370,6 +371,7 @@ func autoConvert_extensions_DaemonSetSpec_To_v1beta1_DaemonSetSpec(in *extension
}
out.MinReadySeconds = in.MinReadySeconds
out.TemplateGeneration = in.TemplateGeneration
out.RevisionHistoryLimit = (*int32)(unsafe.Pointer(in.RevisionHistoryLimit))
return nil
}
@@ -387,6 +389,7 @@ func autoConvert_v1beta1_DaemonSetStatus_To_extensions_DaemonSetStatus(in *Daemo
out.UpdatedNumberScheduled = in.UpdatedNumberScheduled
out.NumberAvailable = in.NumberAvailable
out.NumberUnavailable = in.NumberUnavailable
out.CollisionCount = (*int64)(unsafe.Pointer(in.CollisionCount))
return nil
}
@@ -404,6 +407,7 @@ func autoConvert_extensions_DaemonSetStatus_To_v1beta1_DaemonSetStatus(in *exten
out.UpdatedNumberScheduled = in.UpdatedNumberScheduled
out.NumberAvailable = in.NumberAvailable
out.NumberUnavailable = in.NumberUnavailable
out.CollisionCount = (*int64)(unsafe.Pointer(in.CollisionCount))
return nil
}

View File

@@ -182,6 +182,9 @@ func DeepCopy_v1beta1_DaemonSet(in interface{}, out interface{}, c *conversion.C
if err := DeepCopy_v1beta1_DaemonSetSpec(&in.Spec, &out.Spec, c); err != nil {
return err
}
if err := DeepCopy_v1beta1_DaemonSetStatus(&in.Status, &out.Status, c); err != nil {
return err
}
return nil
}
}
@@ -225,6 +228,11 @@ func DeepCopy_v1beta1_DaemonSetSpec(in interface{}, out interface{}, c *conversi
if err := DeepCopy_v1beta1_DaemonSetUpdateStrategy(&in.UpdateStrategy, &out.UpdateStrategy, c); err != nil {
return err
}
if in.RevisionHistoryLimit != nil {
in, out := &in.RevisionHistoryLimit, &out.RevisionHistoryLimit
*out = new(int32)
**out = **in
}
return nil
}
}
@@ -235,6 +243,11 @@ func DeepCopy_v1beta1_DaemonSetStatus(in interface{}, out interface{}, c *conver
in := in.(*DaemonSetStatus)
out := out.(*DaemonSetStatus)
*out = *in
if in.CollisionCount != nil {
in, out := &in.CollisionCount, &out.CollisionCount
*out = new(int64)
**out = **in
}
return nil
}
}

View File

@@ -183,6 +183,9 @@ func DeepCopy_extensions_DaemonSet(in interface{}, out interface{}, c *conversio
if err := DeepCopy_extensions_DaemonSetSpec(&in.Spec, &out.Spec, c); err != nil {
return err
}
if err := DeepCopy_extensions_DaemonSetStatus(&in.Status, &out.Status, c); err != nil {
return err
}
return nil
}
}
@@ -226,6 +229,11 @@ func DeepCopy_extensions_DaemonSetSpec(in interface{}, out interface{}, c *conve
if err := DeepCopy_extensions_DaemonSetUpdateStrategy(&in.UpdateStrategy, &out.UpdateStrategy, c); err != nil {
return err
}
if in.RevisionHistoryLimit != nil {
in, out := &in.RevisionHistoryLimit, &out.RevisionHistoryLimit
*out = new(int32)
**out = **in
}
return nil
}
}
@@ -236,6 +244,11 @@ func DeepCopy_extensions_DaemonSetStatus(in interface{}, out interface{}, c *con
in := in.(*DaemonSetStatus)
out := out.(*DaemonSetStatus)
*out = *in
if in.CollisionCount != nil {
in, out := &in.CollisionCount, &out.CollisionCount
*out = new(int64)
**out = **in
}
return nil
}
}

View File

@@ -31,6 +31,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/v1"
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
apps "k8s.io/kubernetes/pkg/apis/apps/v1beta1"
extensionsinternal "k8s.io/kubernetes/pkg/apis/extensions"
extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
@@ -260,9 +261,19 @@ var _ = framework.KubeDescribe("Daemon set [Serial]", func() {
Expect(err).NotTo(HaveOccurred(), "error waiting for daemon pod to start")
By("Make sure all daemon pods have correct template generation 1")
templateGeneration := "1"
err = checkDaemonPodsTemplateGeneration(c, ns, label, "1")
Expect(err).NotTo(HaveOccurred())
// Check history and labels
ds, err = c.Extensions().DaemonSets(ns).Get(ds.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
first := curHistory(listDaemonHistories(c, ns, label), &ds.Spec.Template)
firstHash := ds.Labels[extensions.DefaultDaemonSetUniqueLabelKey]
Expect(first.Labels[extensions.DefaultDaemonSetUniqueLabelKey]).To(Equal(firstHash))
Expect(first.Revision).To(Equal(int64(1)))
checkDaemonSetPodsLabels(listDaemonPods(c, ns, label), firstHash, templateGeneration)
By("Update daemon pods image.")
patch := getDaemonSetImagePatch(ds.Spec.Template.Spec.Containers[0].Name, redisImage)
ds, err = c.Extensions().DaemonSets(ns).Patch(dsName, types.StrategicMergePatchType, []byte(patch))
@@ -274,12 +285,21 @@ var _ = framework.KubeDescribe("Daemon set [Serial]", func() {
Expect(err).NotTo(HaveOccurred())
By("Make sure all daemon pods have correct template generation 1")
err = checkDaemonPodsTemplateGeneration(c, ns, label, "1")
err = checkDaemonPodsTemplateGeneration(c, ns, label, templateGeneration)
Expect(err).NotTo(HaveOccurred())
By("Check that daemon pods are still running on every node of the cluster.")
err = wait.PollImmediate(dsRetryPeriod, dsRetryTimeout, checkRunningOnAllNodes(f, ds))
Expect(err).NotTo(HaveOccurred(), "error waiting for daemon pod to start")
// Check history and labels
ds, err = c.Extensions().DaemonSets(ns).Get(ds.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
cur := curHistory(listDaemonHistories(c, ns, label), &ds.Spec.Template)
curHash := ds.Labels[extensions.DefaultDaemonSetUniqueLabelKey]
Expect(cur.Labels[extensions.DefaultDaemonSetUniqueLabelKey]).To(Equal(curHash))
Expect(cur.Revision).To(Equal(int64(2)))
checkDaemonSetPodsLabels(listDaemonPods(c, ns, label), firstHash, templateGeneration)
})
It("Should update pod when spec was updated and update strategy is RollingUpdate", func() {
@@ -302,23 +322,42 @@ var _ = framework.KubeDescribe("Daemon set [Serial]", func() {
err = checkDaemonPodsTemplateGeneration(c, ns, label, fmt.Sprint(templateGeneration))
Expect(err).NotTo(HaveOccurred())
// Check history and labels
ds, err = c.Extensions().DaemonSets(ns).Get(ds.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
cur := curHistory(listDaemonHistories(c, ns, label), &ds.Spec.Template)
hash := ds.Labels[extensions.DefaultDaemonSetUniqueLabelKey]
Expect(cur.Labels[extensions.DefaultDaemonSetUniqueLabelKey]).To(Equal(hash))
Expect(cur.Revision).To(Equal(int64(1)))
checkDaemonSetPodsLabels(listDaemonPods(c, ns, label), hash, fmt.Sprint(templateGeneration))
By("Update daemon pods image.")
patch := getDaemonSetImagePatch(ds.Spec.Template.Spec.Containers[0].Name, redisImage)
ds, err = c.Extensions().DaemonSets(ns).Patch(dsName, types.StrategicMergePatchType, []byte(patch))
Expect(err).NotTo(HaveOccurred())
Expect(ds.Spec.TemplateGeneration).To(Equal(templateGeneration + 1))
templateGeneration++
Expect(ds.Spec.TemplateGeneration).To(Equal(templateGeneration))
By("Check that daemon pods images are updated.")
err = wait.PollImmediate(dsRetryPeriod, dsRetryTimeout, checkDaemonPodsImageAndAvailability(c, ds, redisImage, 1))
Expect(err).NotTo(HaveOccurred())
By(fmt.Sprintf("Make sure all daemon pods have correct template generation %d", templateGeneration+1))
err = checkDaemonPodsTemplateGeneration(c, ns, label, fmt.Sprint(templateGeneration+1))
By(fmt.Sprintf("Make sure all daemon pods have correct template generation %d", templateGeneration))
err = checkDaemonPodsTemplateGeneration(c, ns, label, fmt.Sprint(templateGeneration))
Expect(err).NotTo(HaveOccurred())
By("Check that daemon pods are still running on every node of the cluster.")
err = wait.PollImmediate(dsRetryPeriod, dsRetryTimeout, checkRunningOnAllNodes(f, ds))
Expect(err).NotTo(HaveOccurred(), "error waiting for daemon pod to start")
// Check history and labels
ds, err = c.Extensions().DaemonSets(ns).Get(ds.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
cur = curHistory(listDaemonHistories(c, ns, label), &ds.Spec.Template)
hash = ds.Labels[extensions.DefaultDaemonSetUniqueLabelKey]
Expect(cur.Labels[extensions.DefaultDaemonSetUniqueLabelKey]).To(Equal(hash))
Expect(cur.Revision).To(Equal(int64(2)))
checkDaemonSetPodsLabels(listDaemonPods(c, ns, label), hash, fmt.Sprint(templateGeneration))
})
It("Should adopt or recreate existing pods when creating a RollingUpdate DaemonSet with matching or mismatching templateGeneration", func() {
@@ -698,3 +737,44 @@ func checkDaemonSetPodsName(c clientset.Interface, ns, prefix string, label map[
}
return nil
}
func checkDaemonSetPodsLabels(podList *v1.PodList, hash, templateGeneration string) {
for _, pod := range podList.Items {
podHash := pod.Labels[extensions.DefaultDaemonSetUniqueLabelKey]
podTemplate := pod.Labels[extensions.DaemonSetTemplateGenerationKey]
Expect(len(podHash)).To(BeNumerically(">", 0))
if len(hash) > 0 {
Expect(podHash).To(Equal(hash))
}
Expect(len(podTemplate)).To(BeNumerically(">", 0))
Expect(podTemplate).To(Equal(templateGeneration))
}
}
func listDaemonHistories(c clientset.Interface, ns string, label map[string]string) *apps.ControllerRevisionList {
selector := labels.Set(label).AsSelector()
options := metav1.ListOptions{LabelSelector: selector.String()}
historyList, err := c.Apps().ControllerRevisions(ns).List(options)
Expect(err).NotTo(HaveOccurred())
Expect(len(historyList.Items)).To(BeNumerically(">", 0))
return historyList
}
func curHistory(historyList *apps.ControllerRevisionList, template *v1.PodTemplateSpec) *apps.ControllerRevision {
var curHistory *apps.ControllerRevision
foundCurHistories := 0
for i := range historyList.Items {
history := &historyList.Items[i]
// Every history should have the hash label
Expect(len(history.Labels[extensions.DefaultDaemonSetUniqueLabelKey])).To(BeNumerically(">", 0))
match, err := daemon.Match(template, history)
Expect(err).NotTo(HaveOccurred())
if match {
curHistory = history
foundCurHistories++
}
}
Expect(foundCurHistories).To(Equal(1))
Expect(curHistory).NotTo(BeNil())
return curHistory
}