diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index 7450953e313..87532880f35 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -41439,6 +41439,11 @@ "template" ], "properties": { + "minReadySeconds": { + "description": "MinReadySeconds 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).", + "type": "integer", + "format": "int32" + }, "selector": { "description": "Selector is 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: http://kubernetes.io/docs/user-guide/labels#label-selectors", "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector" @@ -41446,6 +41451,15 @@ "template": { "description": "Template is the 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: http://kubernetes.io/docs/user-guide/replication-controller#pod-template", "$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.", + "type": "integer", + "format": "int64" + }, + "updateStrategy": { + "description": "UpdateStrategy to replace existing DaemonSet pods with new pods.", + "$ref": "#/definitions/io.k8s.kubernetes.pkg.apis.extensions.v1beta1.DaemonSetUpdateStrategy" } } }, @@ -41468,6 +41482,11 @@ "type": "integer", "format": "int32" }, + "numberAvailable": { + "description": "NumberAvailable is 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 minReadySeconds)", + "type": "integer", + "format": "int32" + }, "numberMisscheduled": { "description": "NumberMisscheduled is the number of nodes that are running the daemon pod, but are not supposed to run the daemon pod. More info: http://releases.k8s.io/HEAD/docs/admin/daemons.md", "type": "integer", @@ -41478,10 +41497,32 @@ "type": "integer", "format": "int32" }, + "numberUnavailable": { + "description": "NumberUnavailable is 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 minReadySeconds)", + "type": "integer", + "format": "int32" + }, "observedGeneration": { "description": "ObservedGeneration is the most recent generation observed by the daemon set controller.", "type": "integer", "format": "int64" + }, + "updatedNumberScheduled": { + "description": "UpdatedNumberScheduled is the total number of nodes that are running updated daemon pod", + "type": "integer", + "format": "int32" + } + } + }, + "io.k8s.kubernetes.pkg.apis.extensions.v1beta1.DaemonSetUpdateStrategy": { + "properties": { + "rollingUpdate": { + "description": "Rolling update config params. Present only if DaemonSetUpdateStrategy = RollingUpdate.", + "$ref": "#/definitions/io.k8s.kubernetes.pkg.apis.extensions.v1beta1.RollingUpdateDaemonSet" + }, + "type": { + "description": "Type of daemon set update. Can be \"RollingUpdate\" or \"OnDelete\". Default is OnDelete.", + "type": "string" } } }, @@ -42387,6 +42428,15 @@ } } }, + "io.k8s.kubernetes.pkg.apis.extensions.v1beta1.RollingUpdateDaemonSet": { + "description": "Spec to control the desired behavior of daemon set rolling update.", + "properties": { + "maxUnavailable": { + "description": "The maximum number of DaemonSet pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of total number of DaemonSet pods at the start of the update (ex: 10%). Absolute number is calculated from percentage by rounding up. This cannot be 0. Default value is 1. Example: when this is set to 30%, 30% of the currently running DaemonSet pods can be stopped for an update at any given time. The update starts by stopping at most 30% of the currently running DaemonSet pods and then brings up new DaemonSet pods in their place. Once the new pods are ready, it then proceeds onto other DaemonSet pods, thus ensuring that at least 70% of original number of DaemonSet pods are available at all times during the update.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString" + } + } + }, "io.k8s.kubernetes.pkg.apis.extensions.v1beta1.RollingUpdateDeployment": { "description": "Spec to control the desired behavior of rolling update.", "properties": { diff --git a/api/swagger-spec/extensions_v1beta1.json b/api/swagger-spec/extensions_v1beta1.json index 4548189708e..8c1350510e9 100644 --- a/api/swagger-spec/extensions_v1beta1.json +++ b/api/swagger-spec/extensions_v1beta1.json @@ -6612,6 +6612,20 @@ "template": { "$ref": "v1.PodTemplateSpec", "description": "Template is the 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: http://kubernetes.io/docs/user-guide/replication-controller#pod-template" + }, + "updateStrategy": { + "$ref": "v1beta1.DaemonSetUpdateStrategy", + "description": "UpdateStrategy to replace existing DaemonSet pods with new pods." + }, + "minReadySeconds": { + "type": "integer", + "format": "int32", + "description": "MinReadySeconds 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": { + "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." } } }, @@ -8439,6 +8453,29 @@ } } }, + "v1beta1.DaemonSetUpdateStrategy": { + "id": "v1beta1.DaemonSetUpdateStrategy", + "properties": { + "type": { + "type": "string", + "description": "Type of daemon set update. Can be \"RollingUpdate\" or \"OnDelete\". Default is OnDelete." + }, + "rollingUpdate": { + "$ref": "v1beta1.RollingUpdateDaemonSet", + "description": "Rolling update config params. Present only if DaemonSetUpdateStrategy = RollingUpdate." + } + } + }, + "v1beta1.RollingUpdateDaemonSet": { + "id": "v1beta1.RollingUpdateDaemonSet", + "description": "Spec to control the desired behavior of daemon set rolling update.", + "properties": { + "maxUnavailable": { + "type": "string", + "description": "The maximum number of DaemonSet pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of total number of DaemonSet pods at the start of the update (ex: 10%). Absolute number is calculated from percentage by rounding up. This cannot be 0. Default value is 1. Example: when this is set to 30%, 30% of the currently running DaemonSet pods can be stopped for an update at any given time. The update starts by stopping at most 30% of the currently running DaemonSet pods and then brings up new DaemonSet pods in their place. Once the new pods are ready, it then proceeds onto other DaemonSet pods, thus ensuring that at least 70% of original number of DaemonSet pods are available at all times during the update." + } + } + }, "v1beta1.DaemonSetStatus": { "id": "v1beta1.DaemonSetStatus", "description": "DaemonSetStatus represents the current status of a daemon set.", @@ -8473,6 +8510,21 @@ "type": "integer", "format": "int64", "description": "ObservedGeneration is the most recent generation observed by the daemon set controller." + }, + "updatedNumberScheduled": { + "type": "integer", + "format": "int32", + "description": "UpdatedNumberScheduled is the total number of nodes that are running updated daemon pod" + }, + "numberAvailable": { + "type": "integer", + "format": "int32", + "description": "NumberAvailable is 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 minReadySeconds)" + }, + "numberUnavailable": { + "type": "integer", + "format": "int32", + "description": "NumberUnavailable is 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 minReadySeconds)" } } }, diff --git a/docs/api-reference/extensions/v1beta1/definitions.html b/docs/api-reference/extensions/v1beta1/definitions.html index 968f226477d..8d5ff553424 100755 --- a/docs/api-reference/extensions/v1beta1/definitions.html +++ b/docs/api-reference/extensions/v1beta1/definitions.html @@ -661,6 +661,27 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

integer (int64)

+ +

updatedNumberScheduled

+

UpdatedNumberScheduled is the total number of nodes that are running updated daemon pod

+

false

+

integer (int32)

+ + + +

numberAvailable

+

NumberAvailable is 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 minReadySeconds)

+

false

+

integer (int32)

+ + + +

numberUnavailable

+

NumberUnavailable is 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 minReadySeconds)

+

false

+

integer (int32)

+ + @@ -1892,6 +1913,40 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; } + +
+

v1beta1.RollingUpdateDaemonSet

+
+

Spec to control the desired behavior of daemon set rolling update.

+
+ +++++++ + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

maxUnavailable

The maximum number of DaemonSet pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of total number of DaemonSet pods at the start of the update (ex: 10%). Absolute number is calculated from percentage by rounding up. This cannot be 0. Default value is 1. Example: when this is set to 30%, 30% of the currently running DaemonSet pods can be stopped for an update at any given time. The update starts by stopping at most 30% of the currently running DaemonSet pods and then brings up new DaemonSet pods in their place. Once the new pods are ready, it then proceeds onto other DaemonSet pods, thus ensuring that at least 70% of original number of DaemonSet pods are available at all times during the update.

false

string

+

v1.ObjectMeta

@@ -2131,6 +2186,27 @@ Populated by the system when a graceful deletion is requested. Read-only. More i

v1.PodTemplateSpec

+ +

updateStrategy

+

UpdateStrategy to replace existing DaemonSet pods with new pods.

+

false

+

v1beta1.DaemonSetUpdateStrategy

+ + + +

minReadySeconds

+

MinReadySeconds 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).

+

false

+

integer (int32)

+ + + +

templateGeneration

+

A sequence number representing a specific generation of the template. Populated by the system. It can be set only during the creation.

+

false

+

integer (int64)

+ + @@ -3221,6 +3297,44 @@ Populated by the system when a graceful deletion is requested. Read-only. More i +
+
+

v1beta1.DaemonSetUpdateStrategy

+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

type

Type of daemon set update. Can be "RollingUpdate" or "OnDelete". Default is OnDelete.

false

string

rollingUpdate

Rolling update config params. Present only if DaemonSetUpdateStrategy = RollingUpdate.

false

v1beta1.RollingUpdateDaemonSet

+

v1.VsphereVirtualDiskVolumeSource

@@ -7612,7 +7726,7 @@ Both these may change in the future. Incoming requests are matched against the h
diff --git a/federation/apis/openapi-spec/swagger.json b/federation/apis/openapi-spec/swagger.json index 4a06768d4e9..cddf935a7ae 100644 --- a/federation/apis/openapi-spec/swagger.json +++ b/federation/apis/openapi-spec/swagger.json @@ -13810,6 +13810,11 @@ "template" ], "properties": { + "minReadySeconds": { + "description": "MinReadySeconds 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).", + "type": "integer", + "format": "int32" + }, "selector": { "description": "Selector is 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: http://kubernetes.io/docs/user-guide/labels#label-selectors", "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector" @@ -13817,6 +13822,15 @@ "template": { "description": "Template is the 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: http://kubernetes.io/docs/user-guide/replication-controller#pod-template", "$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.", + "type": "integer", + "format": "int64" + }, + "updateStrategy": { + "description": "UpdateStrategy to replace existing DaemonSet pods with new pods.", + "$ref": "#/definitions/io.k8s.kubernetes.pkg.apis.extensions.v1beta1.DaemonSetUpdateStrategy" } } }, @@ -13839,6 +13853,11 @@ "type": "integer", "format": "int32" }, + "numberAvailable": { + "description": "NumberAvailable is 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 minReadySeconds)", + "type": "integer", + "format": "int32" + }, "numberMisscheduled": { "description": "NumberMisscheduled is the number of nodes that are running the daemon pod, but are not supposed to run the daemon pod. More info: http://releases.k8s.io/HEAD/docs/admin/daemons.md", "type": "integer", @@ -13849,10 +13868,32 @@ "type": "integer", "format": "int32" }, + "numberUnavailable": { + "description": "NumberUnavailable is 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 minReadySeconds)", + "type": "integer", + "format": "int32" + }, "observedGeneration": { "description": "ObservedGeneration is the most recent generation observed by the daemon set controller.", "type": "integer", "format": "int64" + }, + "updatedNumberScheduled": { + "description": "UpdatedNumberScheduled is the total number of nodes that are running updated daemon pod", + "type": "integer", + "format": "int32" + } + } + }, + "io.k8s.kubernetes.pkg.apis.extensions.v1beta1.DaemonSetUpdateStrategy": { + "properties": { + "rollingUpdate": { + "description": "Rolling update config params. Present only if DaemonSetUpdateStrategy = RollingUpdate.", + "$ref": "#/definitions/io.k8s.kubernetes.pkg.apis.extensions.v1beta1.RollingUpdateDaemonSet" + }, + "type": { + "description": "Type of daemon set update. Can be \"RollingUpdate\" or \"OnDelete\". Default is OnDelete.", + "type": "string" } } }, @@ -14438,6 +14479,15 @@ } } }, + "io.k8s.kubernetes.pkg.apis.extensions.v1beta1.RollingUpdateDaemonSet": { + "description": "Spec to control the desired behavior of daemon set rolling update.", + "properties": { + "maxUnavailable": { + "description": "The maximum number of DaemonSet pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of total number of DaemonSet pods at the start of the update (ex: 10%). Absolute number is calculated from percentage by rounding up. This cannot be 0. Default value is 1. Example: when this is set to 30%, 30% of the currently running DaemonSet pods can be stopped for an update at any given time. The update starts by stopping at most 30% of the currently running DaemonSet pods and then brings up new DaemonSet pods in their place. Once the new pods are ready, it then proceeds onto other DaemonSet pods, thus ensuring that at least 70% of original number of DaemonSet pods are available at all times during the update.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString" + } + } + }, "io.k8s.kubernetes.pkg.apis.extensions.v1beta1.RollingUpdateDeployment": { "description": "Spec to control the desired behavior of rolling update.", "properties": { diff --git a/pkg/api/testing/fuzzer.go b/pkg/api/testing/fuzzer.go index 8ad142d8709..58429422d0b 100644 --- a/pkg/api/testing/fuzzer.go +++ b/pkg/api/testing/fuzzer.go @@ -518,6 +518,25 @@ func extensionFuncs(t apitesting.TestingCommon) []interface{} { } } }, + 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. + strategyTypes := []extensions.DaemonSetUpdateStrategyType{extensions.RollingUpdateDaemonSetStrategyType, extensions.OnDeleteDaemonSetStrategyType} + j.Type = strategyTypes[c.Rand.Intn(len(strategyTypes))] + if j.Type != extensions.RollingUpdateDaemonSetStrategyType { + j.RollingUpdate = nil + } else { + rollingUpdate := extensions.RollingUpdateDaemonSet{} + if c.RandBool() { + if c.RandBool() { + rollingUpdate.MaxUnavailable = intstr.FromInt(1 + int(c.Rand.Int31())) + } else { + rollingUpdate.MaxUnavailable = intstr.FromString(fmt.Sprintf("%d%%", 1+c.Rand.Int31())) + } + } + j.RollingUpdate = &rollingUpdate + } + }, } } diff --git a/pkg/apis/extensions/types.go b/pkg/apis/extensions/types.go index f2aa644f7c7..d12a9d59854 100644 --- a/pkg/apis/extensions/types.go +++ b/pkg/apis/extensions/types.go @@ -370,11 +370,10 @@ type DeploymentList struct { Items []Deployment } -// TODO(madhusudancs): Uncomment while implementing DaemonSet updates. -/* Commenting out for v1.2. We are planning to bring these types back with a more robust DaemonSet update implementation in v1.3, hence not deleting but just commenting the types out. type DaemonSetUpdateStrategy struct { - // Type of daemon set update. Only "RollingUpdate" is supported at this time. Default is RollingUpdate. -// +optional + // Type of daemon set update. Can be "RollingUpdate" or "OnDelete". + // Default is OnDelete. + // +optional Type DaemonSetUpdateStrategyType // Rolling update config params. Present only if DaemonSetUpdateStrategy = @@ -382,7 +381,8 @@ type DaemonSetUpdateStrategy struct { //--- // TODO: Update this to follow our convention for oneOf, whatever we decide it // to be. Same as DeploymentStrategy.RollingUpdate. -// +optional + // See https://github.com/kubernetes/kubernetes/issues/35345 + // +optional RollingUpdate *RollingUpdateDaemonSet } @@ -391,6 +391,9 @@ type DaemonSetUpdateStrategyType string const ( // Replace the old daemons by new ones using rolling update i.e replace them on each node one after the other. RollingUpdateDaemonSetStrategyType DaemonSetUpdateStrategyType = "RollingUpdate" + + // Replace the old daemons only when it's killed + OnDeleteDaemonSetStrategyType DaemonSetUpdateStrategyType = "OnDelete" ) // Spec to control the desired behavior of daemon set rolling update. @@ -408,17 +411,9 @@ type RollingUpdateDaemonSet struct { // it then proceeds onto other DaemonSet pods, thus ensuring that at least // 70% of original number of DaemonSet pods are available at all times // during the update. -// +optional + // +optional MaxUnavailable intstr.IntOrString - - // 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). -// +optional - MinReadySeconds int } -*/ // DaemonSetSpec is the specification of a daemon set. type DaemonSetSpec struct { @@ -436,31 +431,23 @@ type DaemonSetSpec struct { // More info: http://kubernetes.io/docs/user-guide/replication-controller#pod-template Template api.PodTemplateSpec - // TODO(madhusudancs): Uncomment while implementing DaemonSet updates. - /* Commenting out for v1.2. We are planning to bring these fields back with a more robust DaemonSet update implementation in v1.3, hence not deleting but just commenting these fields out. - // Update strategy to replace existing DaemonSet pods with new pods. + // UpdateStrategy to replace existing DaemonSet pods with new pods. // +optional - UpdateStrategy DaemonSetUpdateStrategy + UpdateStrategy DaemonSetUpdateStrategy - // Label key that is added to DaemonSet pods to distinguish between old and - // new pod templates during DaemonSet update. - // Users can set this to an empty string to indicate that the system should - // not add any label. If unspecified, system uses - // DefaultDaemonSetUniqueLabelKey("daemonset.kubernetes.io/podTemplateHash"). - // Value of this key is hash of DaemonSetSpec.PodTemplateSpec. - // No label is added if this is set to empty string. + // MinReadySeconds 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). // +optional - UniqueLabelKey string - */ + MinReadySeconds int32 + + // 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 } -const ( - // DefaultDaemonSetUniqueLabelKey is the default key of the labels that is added - // to daemon set pods to distinguish between old and new pod templates during - // DaemonSet update. See DaemonSetSpec's UniqueLabelKey field for more information. - DefaultDaemonSetUniqueLabelKey string = "daemonset.kubernetes.io/podTemplateHash" -) - // DaemonSetStatus represents the current status of a daemon set. type DaemonSetStatus struct { // CurrentNumberScheduled is the number of nodes that are running at least 1 @@ -482,6 +469,23 @@ type DaemonSetStatus struct { // ObservedGeneration is the most recent generation observed by the daemon set controller. // +optional ObservedGeneration int64 + + // UpdatedNumberScheduled is the total number of nodes that are running updated + // daemon pod + // +optional + UpdatedNumberScheduled int32 + + // NumberAvailable is 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 minReadySeconds) + // +optional + NumberAvailable int32 + + // NumberUnavailable is 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 minReadySeconds) + // +optional + NumberUnavailable int32 } // +genclient=true @@ -508,6 +512,13 @@ type DaemonSet struct { Status DaemonSetStatus } +const ( + // 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" +) + // DaemonSetList is a collection of daemon sets. type DaemonSetList struct { metav1.TypeMeta diff --git a/pkg/apis/extensions/v1beta1/conversion.go b/pkg/apis/extensions/v1beta1/conversion.go index a28055655a1..38b8c2ac8f8 100644 --- a/pkg/apis/extensions/v1beta1/conversion.go +++ b/pkg/apis/extensions/v1beta1/conversion.go @@ -38,6 +38,8 @@ func addConversionFuncs(scheme *runtime.Scheme) error { Convert_v1beta1_DeploymentStrategy_To_extensions_DeploymentStrategy, Convert_extensions_RollingUpdateDeployment_To_v1beta1_RollingUpdateDeployment, Convert_v1beta1_RollingUpdateDeployment_To_extensions_RollingUpdateDeployment, + Convert_extensions_RollingUpdateDaemonSet_To_v1beta1_RollingUpdateDaemonSet, + Convert_v1beta1_RollingUpdateDaemonSet_To_extensions_RollingUpdateDaemonSet, Convert_extensions_ReplicaSetSpec_To_v1beta1_ReplicaSetSpec, Convert_v1beta1_ReplicaSetSpec_To_extensions_ReplicaSetSpec, ) @@ -219,6 +221,23 @@ func Convert_v1beta1_RollingUpdateDeployment_To_extensions_RollingUpdateDeployme return nil } +func Convert_extensions_RollingUpdateDaemonSet_To_v1beta1_RollingUpdateDaemonSet(in *extensions.RollingUpdateDaemonSet, out *RollingUpdateDaemonSet, s conversion.Scope) error { + if out.MaxUnavailable == nil { + out.MaxUnavailable = &intstr.IntOrString{} + } + if err := s.Convert(&in.MaxUnavailable, out.MaxUnavailable, 0); err != nil { + return err + } + return nil +} + +func Convert_v1beta1_RollingUpdateDaemonSet_To_extensions_RollingUpdateDaemonSet(in *RollingUpdateDaemonSet, out *extensions.RollingUpdateDaemonSet, s conversion.Scope) error { + if err := s.Convert(in.MaxUnavailable, &out.MaxUnavailable, 0); err != nil { + return err + } + return nil +} + func Convert_extensions_ReplicaSetSpec_To_v1beta1_ReplicaSetSpec(in *extensions.ReplicaSetSpec, out *ReplicaSetSpec, s conversion.Scope) error { out.Replicas = new(int32) *out.Replicas = int32(in.Replicas) diff --git a/pkg/apis/extensions/v1beta1/defaults.go b/pkg/apis/extensions/v1beta1/defaults.go index a78c17ee745..5f14d8160ed 100644 --- a/pkg/apis/extensions/v1beta1/defaults.go +++ b/pkg/apis/extensions/v1beta1/defaults.go @@ -47,6 +47,21 @@ func SetDefaults_DaemonSet(obj *DaemonSet) { obj.Labels = labels } } + updateStrategy := &obj.Spec.UpdateStrategy + if updateStrategy.Type == "" { + updateStrategy.Type = OnDeleteDaemonSetStrategyType + } + if updateStrategy.Type == RollingUpdateDaemonSetStrategyType { + if updateStrategy.RollingUpdate == nil { + rollingUpdate := RollingUpdateDaemonSet{} + updateStrategy.RollingUpdate = &rollingUpdate + } + if updateStrategy.RollingUpdate.MaxUnavailable == nil { + // Set default MaxUnavailable as 1 by default. + maxUnavailable := intstr.FromInt(1) + updateStrategy.RollingUpdate.MaxUnavailable = &maxUnavailable + } + } } func SetDefaults_Deployment(obj *Deployment) { diff --git a/pkg/apis/extensions/v1beta1/defaults_test.go b/pkg/apis/extensions/v1beta1/defaults_test.go index e8149be3adb..6072b667241 100644 --- a/pkg/apis/extensions/v1beta1/defaults_test.go +++ b/pkg/apis/extensions/v1beta1/defaults_test.go @@ -74,6 +74,9 @@ func TestSetDefaultDaemonSet(t *testing.T) { MatchLabels: defaultLabels, }, Template: defaultTemplate, + UpdateStrategy: DaemonSetUpdateStrategy{ + Type: OnDeleteDaemonSetStrategyType, + }, }, }, }, @@ -99,6 +102,9 @@ func TestSetDefaultDaemonSet(t *testing.T) { MatchLabels: defaultLabels, }, Template: defaultTemplate, + UpdateStrategy: DaemonSetUpdateStrategy{ + Type: OnDeleteDaemonSetStrategyType, + }, }, }, }, @@ -107,6 +113,9 @@ func TestSetDefaultDaemonSet(t *testing.T) { expected: &DaemonSet{ Spec: DaemonSetSpec{ Template: templateNoLabel, + UpdateStrategy: DaemonSetUpdateStrategy{ + Type: OnDeleteDaemonSetStrategyType, + }, }, }, }, @@ -117,6 +126,9 @@ func TestSetDefaultDaemonSet(t *testing.T) { expected: &DaemonSet{ Spec: DaemonSetSpec{ Template: templateNoLabel, + UpdateStrategy: DaemonSetUpdateStrategy{ + Type: OnDeleteDaemonSetStrategyType, + }, }, }, }, @@ -127,6 +139,9 @@ func TestSetDefaultDaemonSet(t *testing.T) { expected: &DaemonSet{ Spec: DaemonSetSpec{ Template: templateNoLabel, + UpdateStrategy: DaemonSetUpdateStrategy{ + Type: OnDeleteDaemonSetStrategyType, + }, }, }, }, diff --git a/pkg/apis/extensions/v1beta1/generated.pb.go b/pkg/apis/extensions/v1beta1/generated.pb.go index ce3741fffd2..053cf10dbf3 100644 --- a/pkg/apis/extensions/v1beta1/generated.pb.go +++ b/pkg/apis/extensions/v1beta1/generated.pb.go @@ -34,6 +34,7 @@ limitations under the License. DaemonSetList DaemonSetSpec DaemonSetStatus + DaemonSetUpdateStrategy Deployment DeploymentCondition DeploymentList @@ -70,6 +71,7 @@ limitations under the License. ReplicaSetStatus ReplicationControllerDummy RollbackConfig + RollingUpdateDaemonSet RollingUpdateDeployment RunAsUserStrategyOptions SELinuxStrategyOptions @@ -149,205 +151,213 @@ func (m *DaemonSetStatus) Reset() { *m = DaemonSetStatus{} } func (*DaemonSetStatus) ProtoMessage() {} func (*DaemonSetStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{8} } +func (m *DaemonSetUpdateStrategy) Reset() { *m = DaemonSetUpdateStrategy{} } +func (*DaemonSetUpdateStrategy) ProtoMessage() {} +func (*DaemonSetUpdateStrategy) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{9} } + func (m *Deployment) Reset() { *m = Deployment{} } func (*Deployment) ProtoMessage() {} -func (*Deployment) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{9} } +func (*Deployment) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{10} } func (m *DeploymentCondition) Reset() { *m = DeploymentCondition{} } func (*DeploymentCondition) ProtoMessage() {} -func (*DeploymentCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{10} } +func (*DeploymentCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{11} } func (m *DeploymentList) Reset() { *m = DeploymentList{} } func (*DeploymentList) ProtoMessage() {} -func (*DeploymentList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{11} } +func (*DeploymentList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{12} } func (m *DeploymentRollback) Reset() { *m = DeploymentRollback{} } func (*DeploymentRollback) ProtoMessage() {} -func (*DeploymentRollback) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{12} } +func (*DeploymentRollback) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{13} } func (m *DeploymentSpec) Reset() { *m = DeploymentSpec{} } func (*DeploymentSpec) ProtoMessage() {} -func (*DeploymentSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{13} } +func (*DeploymentSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{14} } func (m *DeploymentStatus) Reset() { *m = DeploymentStatus{} } func (*DeploymentStatus) ProtoMessage() {} -func (*DeploymentStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{14} } +func (*DeploymentStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{15} } func (m *DeploymentStrategy) Reset() { *m = DeploymentStrategy{} } func (*DeploymentStrategy) ProtoMessage() {} -func (*DeploymentStrategy) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{15} } +func (*DeploymentStrategy) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{16} } func (m *FSGroupStrategyOptions) Reset() { *m = FSGroupStrategyOptions{} } func (*FSGroupStrategyOptions) ProtoMessage() {} -func (*FSGroupStrategyOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{16} } +func (*FSGroupStrategyOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{17} } func (m *HTTPIngressPath) Reset() { *m = HTTPIngressPath{} } func (*HTTPIngressPath) ProtoMessage() {} -func (*HTTPIngressPath) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{17} } +func (*HTTPIngressPath) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{18} } func (m *HTTPIngressRuleValue) Reset() { *m = HTTPIngressRuleValue{} } func (*HTTPIngressRuleValue) ProtoMessage() {} -func (*HTTPIngressRuleValue) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{18} } +func (*HTTPIngressRuleValue) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{19} } func (m *HostPortRange) Reset() { *m = HostPortRange{} } func (*HostPortRange) ProtoMessage() {} -func (*HostPortRange) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{19} } +func (*HostPortRange) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{20} } func (m *IDRange) Reset() { *m = IDRange{} } func (*IDRange) ProtoMessage() {} -func (*IDRange) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{20} } +func (*IDRange) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{21} } func (m *Ingress) Reset() { *m = Ingress{} } func (*Ingress) ProtoMessage() {} -func (*Ingress) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{21} } +func (*Ingress) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{22} } func (m *IngressBackend) Reset() { *m = IngressBackend{} } func (*IngressBackend) ProtoMessage() {} -func (*IngressBackend) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{22} } +func (*IngressBackend) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{23} } func (m *IngressList) Reset() { *m = IngressList{} } func (*IngressList) ProtoMessage() {} -func (*IngressList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{23} } +func (*IngressList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{24} } func (m *IngressRule) Reset() { *m = IngressRule{} } func (*IngressRule) ProtoMessage() {} -func (*IngressRule) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{24} } +func (*IngressRule) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{25} } func (m *IngressRuleValue) Reset() { *m = IngressRuleValue{} } func (*IngressRuleValue) ProtoMessage() {} -func (*IngressRuleValue) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{25} } +func (*IngressRuleValue) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{26} } func (m *IngressSpec) Reset() { *m = IngressSpec{} } func (*IngressSpec) ProtoMessage() {} -func (*IngressSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{26} } +func (*IngressSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{27} } func (m *IngressStatus) Reset() { *m = IngressStatus{} } func (*IngressStatus) ProtoMessage() {} -func (*IngressStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{27} } +func (*IngressStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{28} } func (m *IngressTLS) Reset() { *m = IngressTLS{} } func (*IngressTLS) ProtoMessage() {} -func (*IngressTLS) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{28} } +func (*IngressTLS) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{29} } func (m *NetworkPolicy) Reset() { *m = NetworkPolicy{} } func (*NetworkPolicy) ProtoMessage() {} -func (*NetworkPolicy) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{29} } +func (*NetworkPolicy) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{30} } func (m *NetworkPolicyIngressRule) Reset() { *m = NetworkPolicyIngressRule{} } func (*NetworkPolicyIngressRule) ProtoMessage() {} func (*NetworkPolicyIngressRule) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{30} + return fileDescriptorGenerated, []int{31} } func (m *NetworkPolicyList) Reset() { *m = NetworkPolicyList{} } func (*NetworkPolicyList) ProtoMessage() {} -func (*NetworkPolicyList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{31} } +func (*NetworkPolicyList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{32} } func (m *NetworkPolicyPeer) Reset() { *m = NetworkPolicyPeer{} } func (*NetworkPolicyPeer) ProtoMessage() {} -func (*NetworkPolicyPeer) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{32} } +func (*NetworkPolicyPeer) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{33} } func (m *NetworkPolicyPort) Reset() { *m = NetworkPolicyPort{} } func (*NetworkPolicyPort) ProtoMessage() {} -func (*NetworkPolicyPort) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{33} } +func (*NetworkPolicyPort) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{34} } func (m *NetworkPolicySpec) Reset() { *m = NetworkPolicySpec{} } func (*NetworkPolicySpec) ProtoMessage() {} -func (*NetworkPolicySpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{34} } +func (*NetworkPolicySpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{35} } func (m *PodSecurityPolicy) Reset() { *m = PodSecurityPolicy{} } func (*PodSecurityPolicy) ProtoMessage() {} -func (*PodSecurityPolicy) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{35} } +func (*PodSecurityPolicy) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{36} } func (m *PodSecurityPolicyList) Reset() { *m = PodSecurityPolicyList{} } func (*PodSecurityPolicyList) ProtoMessage() {} -func (*PodSecurityPolicyList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{36} } +func (*PodSecurityPolicyList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{37} } func (m *PodSecurityPolicySpec) Reset() { *m = PodSecurityPolicySpec{} } func (*PodSecurityPolicySpec) ProtoMessage() {} -func (*PodSecurityPolicySpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{37} } +func (*PodSecurityPolicySpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{38} } func (m *ReplicaSet) Reset() { *m = ReplicaSet{} } func (*ReplicaSet) ProtoMessage() {} -func (*ReplicaSet) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{38} } +func (*ReplicaSet) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{39} } func (m *ReplicaSetCondition) Reset() { *m = ReplicaSetCondition{} } func (*ReplicaSetCondition) ProtoMessage() {} -func (*ReplicaSetCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{39} } +func (*ReplicaSetCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{40} } func (m *ReplicaSetList) Reset() { *m = ReplicaSetList{} } func (*ReplicaSetList) ProtoMessage() {} -func (*ReplicaSetList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{40} } +func (*ReplicaSetList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{41} } func (m *ReplicaSetSpec) Reset() { *m = ReplicaSetSpec{} } func (*ReplicaSetSpec) ProtoMessage() {} -func (*ReplicaSetSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{41} } +func (*ReplicaSetSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{42} } func (m *ReplicaSetStatus) Reset() { *m = ReplicaSetStatus{} } func (*ReplicaSetStatus) ProtoMessage() {} -func (*ReplicaSetStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{42} } +func (*ReplicaSetStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{43} } func (m *ReplicationControllerDummy) Reset() { *m = ReplicationControllerDummy{} } func (*ReplicationControllerDummy) ProtoMessage() {} func (*ReplicationControllerDummy) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{43} + return fileDescriptorGenerated, []int{44} } func (m *RollbackConfig) Reset() { *m = RollbackConfig{} } func (*RollbackConfig) ProtoMessage() {} -func (*RollbackConfig) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{44} } +func (*RollbackConfig) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{45} } + +func (m *RollingUpdateDaemonSet) Reset() { *m = RollingUpdateDaemonSet{} } +func (*RollingUpdateDaemonSet) ProtoMessage() {} +func (*RollingUpdateDaemonSet) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{46} } func (m *RollingUpdateDeployment) Reset() { *m = RollingUpdateDeployment{} } func (*RollingUpdateDeployment) ProtoMessage() {} func (*RollingUpdateDeployment) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{45} + return fileDescriptorGenerated, []int{47} } func (m *RunAsUserStrategyOptions) Reset() { *m = RunAsUserStrategyOptions{} } func (*RunAsUserStrategyOptions) ProtoMessage() {} func (*RunAsUserStrategyOptions) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{46} + return fileDescriptorGenerated, []int{48} } func (m *SELinuxStrategyOptions) Reset() { *m = SELinuxStrategyOptions{} } func (*SELinuxStrategyOptions) ProtoMessage() {} -func (*SELinuxStrategyOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{47} } +func (*SELinuxStrategyOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{49} } func (m *Scale) Reset() { *m = Scale{} } func (*Scale) ProtoMessage() {} -func (*Scale) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{48} } +func (*Scale) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{50} } func (m *ScaleSpec) Reset() { *m = ScaleSpec{} } func (*ScaleSpec) ProtoMessage() {} -func (*ScaleSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{49} } +func (*ScaleSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{51} } func (m *ScaleStatus) Reset() { *m = ScaleStatus{} } func (*ScaleStatus) ProtoMessage() {} -func (*ScaleStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{50} } +func (*ScaleStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{52} } func (m *SupplementalGroupsStrategyOptions) Reset() { *m = SupplementalGroupsStrategyOptions{} } func (*SupplementalGroupsStrategyOptions) ProtoMessage() {} func (*SupplementalGroupsStrategyOptions) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{51} + return fileDescriptorGenerated, []int{53} } func (m *ThirdPartyResource) Reset() { *m = ThirdPartyResource{} } func (*ThirdPartyResource) ProtoMessage() {} -func (*ThirdPartyResource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{52} } +func (*ThirdPartyResource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{54} } func (m *ThirdPartyResourceData) Reset() { *m = ThirdPartyResourceData{} } func (*ThirdPartyResourceData) ProtoMessage() {} -func (*ThirdPartyResourceData) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{53} } +func (*ThirdPartyResourceData) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{55} } func (m *ThirdPartyResourceDataList) Reset() { *m = ThirdPartyResourceDataList{} } func (*ThirdPartyResourceDataList) ProtoMessage() {} func (*ThirdPartyResourceDataList) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{54} + return fileDescriptorGenerated, []int{56} } func (m *ThirdPartyResourceList) Reset() { *m = ThirdPartyResourceList{} } func (*ThirdPartyResourceList) ProtoMessage() {} -func (*ThirdPartyResourceList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{55} } +func (*ThirdPartyResourceList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{57} } func init() { proto.RegisterType((*APIVersion)(nil), "k8s.io.kubernetes.pkg.apis.extensions.v1beta1.APIVersion") @@ -359,6 +369,7 @@ func init() { proto.RegisterType((*DaemonSetList)(nil), "k8s.io.kubernetes.pkg.apis.extensions.v1beta1.DaemonSetList") proto.RegisterType((*DaemonSetSpec)(nil), "k8s.io.kubernetes.pkg.apis.extensions.v1beta1.DaemonSetSpec") proto.RegisterType((*DaemonSetStatus)(nil), "k8s.io.kubernetes.pkg.apis.extensions.v1beta1.DaemonSetStatus") + proto.RegisterType((*DaemonSetUpdateStrategy)(nil), "k8s.io.kubernetes.pkg.apis.extensions.v1beta1.DaemonSetUpdateStrategy") proto.RegisterType((*Deployment)(nil), "k8s.io.kubernetes.pkg.apis.extensions.v1beta1.Deployment") proto.RegisterType((*DeploymentCondition)(nil), "k8s.io.kubernetes.pkg.apis.extensions.v1beta1.DeploymentCondition") proto.RegisterType((*DeploymentList)(nil), "k8s.io.kubernetes.pkg.apis.extensions.v1beta1.DeploymentList") @@ -395,6 +406,7 @@ func init() { proto.RegisterType((*ReplicaSetStatus)(nil), "k8s.io.kubernetes.pkg.apis.extensions.v1beta1.ReplicaSetStatus") proto.RegisterType((*ReplicationControllerDummy)(nil), "k8s.io.kubernetes.pkg.apis.extensions.v1beta1.ReplicationControllerDummy") proto.RegisterType((*RollbackConfig)(nil), "k8s.io.kubernetes.pkg.apis.extensions.v1beta1.RollbackConfig") + proto.RegisterType((*RollingUpdateDaemonSet)(nil), "k8s.io.kubernetes.pkg.apis.extensions.v1beta1.RollingUpdateDaemonSet") proto.RegisterType((*RollingUpdateDeployment)(nil), "k8s.io.kubernetes.pkg.apis.extensions.v1beta1.RollingUpdateDeployment") proto.RegisterType((*RunAsUserStrategyOptions)(nil), "k8s.io.kubernetes.pkg.apis.extensions.v1beta1.RunAsUserStrategyOptions") proto.RegisterType((*SELinuxStrategyOptions)(nil), "k8s.io.kubernetes.pkg.apis.extensions.v1beta1.SELinuxStrategyOptions") @@ -662,6 +674,20 @@ func (m *DaemonSetSpec) MarshalTo(data []byte) (int, error) { return 0, err } i += n8 + data[i] = 0x1a + i++ + i = encodeVarintGenerated(data, i, uint64(m.UpdateStrategy.Size())) + n9, err := m.UpdateStrategy.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n9 + data[i] = 0x20 + i++ + i = encodeVarintGenerated(data, i, uint64(m.MinReadySeconds)) + data[i] = 0x28 + i++ + i = encodeVarintGenerated(data, i, uint64(m.TemplateGeneration)) return i, nil } @@ -695,6 +721,47 @@ func (m *DaemonSetStatus) MarshalTo(data []byte) (int, error) { data[i] = 0x28 i++ i = encodeVarintGenerated(data, i, uint64(m.ObservedGeneration)) + data[i] = 0x30 + i++ + i = encodeVarintGenerated(data, i, uint64(m.UpdatedNumberScheduled)) + data[i] = 0x38 + i++ + i = encodeVarintGenerated(data, i, uint64(m.NumberAvailable)) + data[i] = 0x40 + i++ + i = encodeVarintGenerated(data, i, uint64(m.NumberUnavailable)) + return i, nil +} + +func (m *DaemonSetUpdateStrategy) Marshal() (data []byte, err error) { + size := m.Size() + data = make([]byte, size) + n, err := m.MarshalTo(data) + if err != nil { + return nil, err + } + return data[:n], nil +} + +func (m *DaemonSetUpdateStrategy) MarshalTo(data []byte) (int, error) { + var i int + _ = i + var l int + _ = l + data[i] = 0xa + i++ + i = encodeVarintGenerated(data, i, uint64(len(m.Type))) + i += copy(data[i:], m.Type) + if m.RollingUpdate != nil { + data[i] = 0x12 + i++ + i = encodeVarintGenerated(data, i, uint64(m.RollingUpdate.Size())) + n10, err := m.RollingUpdate.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n10 + } return i, nil } @@ -716,27 +783,27 @@ func (m *Deployment) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintGenerated(data, i, uint64(m.ObjectMeta.Size())) - n9, err := m.ObjectMeta.MarshalTo(data[i:]) - if err != nil { - return 0, err - } - i += n9 - data[i] = 0x12 - i++ - i = encodeVarintGenerated(data, i, uint64(m.Spec.Size())) - n10, err := m.Spec.MarshalTo(data[i:]) - if err != nil { - return 0, err - } - i += n10 - data[i] = 0x1a - i++ - i = encodeVarintGenerated(data, i, uint64(m.Status.Size())) - n11, err := m.Status.MarshalTo(data[i:]) + n11, err := m.ObjectMeta.MarshalTo(data[i:]) if err != nil { return 0, err } i += n11 + data[i] = 0x12 + i++ + i = encodeVarintGenerated(data, i, uint64(m.Spec.Size())) + n12, err := m.Spec.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n12 + data[i] = 0x1a + i++ + i = encodeVarintGenerated(data, i, uint64(m.Status.Size())) + n13, err := m.Status.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n13 return i, nil } @@ -774,19 +841,19 @@ func (m *DeploymentCondition) MarshalTo(data []byte) (int, error) { data[i] = 0x32 i++ i = encodeVarintGenerated(data, i, uint64(m.LastUpdateTime.Size())) - n12, err := m.LastUpdateTime.MarshalTo(data[i:]) + n14, err := m.LastUpdateTime.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n12 + i += n14 data[i] = 0x3a i++ i = encodeVarintGenerated(data, i, uint64(m.LastTransitionTime.Size())) - n13, err := m.LastTransitionTime.MarshalTo(data[i:]) + n15, err := m.LastTransitionTime.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n13 + i += n15 return i, nil } @@ -808,11 +875,11 @@ func (m *DeploymentList) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintGenerated(data, i, uint64(m.ListMeta.Size())) - n14, err := m.ListMeta.MarshalTo(data[i:]) + n16, err := m.ListMeta.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n14 + i += n16 if len(m.Items) > 0 { for _, msg := range m.Items { data[i] = 0x12 @@ -867,11 +934,11 @@ func (m *DeploymentRollback) MarshalTo(data []byte) (int, error) { data[i] = 0x1a i++ i = encodeVarintGenerated(data, i, uint64(m.RollbackTo.Size())) - n15, err := m.RollbackTo.MarshalTo(data[i:]) + n17, err := m.RollbackTo.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n15 + i += n17 return i, nil } @@ -899,28 +966,28 @@ func (m *DeploymentSpec) MarshalTo(data []byte) (int, error) { data[i] = 0x12 i++ i = encodeVarintGenerated(data, i, uint64(m.Selector.Size())) - n16, err := m.Selector.MarshalTo(data[i:]) + n18, err := m.Selector.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n16 + i += n18 } data[i] = 0x1a i++ i = encodeVarintGenerated(data, i, uint64(m.Template.Size())) - n17, err := m.Template.MarshalTo(data[i:]) + n19, err := m.Template.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n17 + i += n19 data[i] = 0x22 i++ i = encodeVarintGenerated(data, i, uint64(m.Strategy.Size())) - n18, err := m.Strategy.MarshalTo(data[i:]) + n20, err := m.Strategy.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n18 + i += n20 data[i] = 0x28 i++ i = encodeVarintGenerated(data, i, uint64(m.MinReadySeconds)) @@ -941,11 +1008,11 @@ func (m *DeploymentSpec) MarshalTo(data []byte) (int, error) { data[i] = 0x42 i++ i = encodeVarintGenerated(data, i, uint64(m.RollbackTo.Size())) - n19, err := m.RollbackTo.MarshalTo(data[i:]) + n21, err := m.RollbackTo.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n19 + i += n21 } if m.ProgressDeadlineSeconds != nil { data[i] = 0x48 @@ -1026,11 +1093,11 @@ func (m *DeploymentStrategy) MarshalTo(data []byte) (int, error) { data[i] = 0x12 i++ i = encodeVarintGenerated(data, i, uint64(m.RollingUpdate.Size())) - n20, err := m.RollingUpdate.MarshalTo(data[i:]) + n22, err := m.RollingUpdate.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n20 + i += n22 } return i, nil } @@ -1091,11 +1158,11 @@ func (m *HTTPIngressPath) MarshalTo(data []byte) (int, error) { data[i] = 0x12 i++ i = encodeVarintGenerated(data, i, uint64(m.Backend.Size())) - n21, err := m.Backend.MarshalTo(data[i:]) + n23, err := m.Backend.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n21 + i += n23 return i, nil } @@ -1195,27 +1262,27 @@ func (m *Ingress) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintGenerated(data, i, uint64(m.ObjectMeta.Size())) - n22, err := m.ObjectMeta.MarshalTo(data[i:]) - if err != nil { - return 0, err - } - i += n22 - data[i] = 0x12 - i++ - i = encodeVarintGenerated(data, i, uint64(m.Spec.Size())) - n23, err := m.Spec.MarshalTo(data[i:]) - if err != nil { - return 0, err - } - i += n23 - data[i] = 0x1a - i++ - i = encodeVarintGenerated(data, i, uint64(m.Status.Size())) - n24, err := m.Status.MarshalTo(data[i:]) + n24, err := m.ObjectMeta.MarshalTo(data[i:]) if err != nil { return 0, err } i += n24 + data[i] = 0x12 + i++ + i = encodeVarintGenerated(data, i, uint64(m.Spec.Size())) + n25, err := m.Spec.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n25 + data[i] = 0x1a + i++ + i = encodeVarintGenerated(data, i, uint64(m.Status.Size())) + n26, err := m.Status.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n26 return i, nil } @@ -1241,11 +1308,11 @@ func (m *IngressBackend) MarshalTo(data []byte) (int, error) { data[i] = 0x12 i++ i = encodeVarintGenerated(data, i, uint64(m.ServicePort.Size())) - n25, err := m.ServicePort.MarshalTo(data[i:]) + n27, err := m.ServicePort.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n25 + i += n27 return i, nil } @@ -1267,11 +1334,11 @@ func (m *IngressList) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintGenerated(data, i, uint64(m.ListMeta.Size())) - n26, err := m.ListMeta.MarshalTo(data[i:]) + n28, err := m.ListMeta.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n26 + i += n28 if len(m.Items) > 0 { for _, msg := range m.Items { data[i] = 0x12 @@ -1309,11 +1376,11 @@ func (m *IngressRule) MarshalTo(data []byte) (int, error) { data[i] = 0x12 i++ i = encodeVarintGenerated(data, i, uint64(m.IngressRuleValue.Size())) - n27, err := m.IngressRuleValue.MarshalTo(data[i:]) + n29, err := m.IngressRuleValue.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n27 + i += n29 return i, nil } @@ -1336,11 +1403,11 @@ func (m *IngressRuleValue) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintGenerated(data, i, uint64(m.HTTP.Size())) - n28, err := m.HTTP.MarshalTo(data[i:]) + n30, err := m.HTTP.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n28 + i += n30 } return i, nil } @@ -1364,11 +1431,11 @@ func (m *IngressSpec) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintGenerated(data, i, uint64(m.Backend.Size())) - n29, err := m.Backend.MarshalTo(data[i:]) + n31, err := m.Backend.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n29 + i += n31 } if len(m.TLS) > 0 { for _, msg := range m.TLS { @@ -1415,11 +1482,11 @@ func (m *IngressStatus) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintGenerated(data, i, uint64(m.LoadBalancer.Size())) - n30, err := m.LoadBalancer.MarshalTo(data[i:]) + n32, err := m.LoadBalancer.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n30 + i += n32 return i, nil } @@ -1478,19 +1545,19 @@ func (m *NetworkPolicy) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintGenerated(data, i, uint64(m.ObjectMeta.Size())) - n31, err := m.ObjectMeta.MarshalTo(data[i:]) + n33, err := m.ObjectMeta.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n31 + i += n33 data[i] = 0x12 i++ i = encodeVarintGenerated(data, i, uint64(m.Spec.Size())) - n32, err := m.Spec.MarshalTo(data[i:]) + n34, err := m.Spec.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n32 + i += n34 return i, nil } @@ -1554,11 +1621,11 @@ func (m *NetworkPolicyList) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintGenerated(data, i, uint64(m.ListMeta.Size())) - n33, err := m.ListMeta.MarshalTo(data[i:]) + n35, err := m.ListMeta.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n33 + i += n35 if len(m.Items) > 0 { for _, msg := range m.Items { data[i] = 0x12 @@ -1593,21 +1660,21 @@ func (m *NetworkPolicyPeer) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintGenerated(data, i, uint64(m.PodSelector.Size())) - n34, err := m.PodSelector.MarshalTo(data[i:]) + n36, err := m.PodSelector.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n34 + i += n36 } if m.NamespaceSelector != nil { data[i] = 0x12 i++ i = encodeVarintGenerated(data, i, uint64(m.NamespaceSelector.Size())) - n35, err := m.NamespaceSelector.MarshalTo(data[i:]) + n37, err := m.NamespaceSelector.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n35 + i += n37 } return i, nil } @@ -1637,11 +1704,11 @@ func (m *NetworkPolicyPort) MarshalTo(data []byte) (int, error) { data[i] = 0x12 i++ i = encodeVarintGenerated(data, i, uint64(m.Port.Size())) - n36, err := m.Port.MarshalTo(data[i:]) + n38, err := m.Port.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n36 + i += n38 } return i, nil } @@ -1664,11 +1731,11 @@ func (m *NetworkPolicySpec) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintGenerated(data, i, uint64(m.PodSelector.Size())) - n37, err := m.PodSelector.MarshalTo(data[i:]) + n39, err := m.PodSelector.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n37 + i += n39 if len(m.Ingress) > 0 { for _, msg := range m.Ingress { data[i] = 0x12 @@ -1702,19 +1769,19 @@ func (m *PodSecurityPolicy) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintGenerated(data, i, uint64(m.ObjectMeta.Size())) - n38, err := m.ObjectMeta.MarshalTo(data[i:]) + n40, err := m.ObjectMeta.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n38 + i += n40 data[i] = 0x12 i++ i = encodeVarintGenerated(data, i, uint64(m.Spec.Size())) - n39, err := m.Spec.MarshalTo(data[i:]) + n41, err := m.Spec.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n39 + i += n41 return i, nil } @@ -1736,11 +1803,11 @@ func (m *PodSecurityPolicyList) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintGenerated(data, i, uint64(m.ListMeta.Size())) - n40, err := m.ListMeta.MarshalTo(data[i:]) + n42, err := m.ListMeta.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n40 + i += n42 if len(m.Items) > 0 { for _, msg := range m.Items { data[i] = 0x12 @@ -1878,35 +1945,35 @@ func (m *PodSecurityPolicySpec) MarshalTo(data []byte) (int, error) { data[i] = 0x52 i++ i = encodeVarintGenerated(data, i, uint64(m.SELinux.Size())) - n41, err := m.SELinux.MarshalTo(data[i:]) - if err != nil { - return 0, err - } - i += n41 - data[i] = 0x5a - i++ - i = encodeVarintGenerated(data, i, uint64(m.RunAsUser.Size())) - n42, err := m.RunAsUser.MarshalTo(data[i:]) - if err != nil { - return 0, err - } - i += n42 - data[i] = 0x62 - i++ - i = encodeVarintGenerated(data, i, uint64(m.SupplementalGroups.Size())) - n43, err := m.SupplementalGroups.MarshalTo(data[i:]) + n43, err := m.SELinux.MarshalTo(data[i:]) if err != nil { return 0, err } i += n43 - data[i] = 0x6a + data[i] = 0x5a i++ - i = encodeVarintGenerated(data, i, uint64(m.FSGroup.Size())) - n44, err := m.FSGroup.MarshalTo(data[i:]) + i = encodeVarintGenerated(data, i, uint64(m.RunAsUser.Size())) + n44, err := m.RunAsUser.MarshalTo(data[i:]) if err != nil { return 0, err } i += n44 + data[i] = 0x62 + i++ + i = encodeVarintGenerated(data, i, uint64(m.SupplementalGroups.Size())) + n45, err := m.SupplementalGroups.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n45 + data[i] = 0x6a + i++ + i = encodeVarintGenerated(data, i, uint64(m.FSGroup.Size())) + n46, err := m.FSGroup.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n46 data[i] = 0x70 i++ if m.ReadOnlyRootFilesystem { @@ -1936,27 +2003,27 @@ func (m *ReplicaSet) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintGenerated(data, i, uint64(m.ObjectMeta.Size())) - n45, err := m.ObjectMeta.MarshalTo(data[i:]) - if err != nil { - return 0, err - } - i += n45 - data[i] = 0x12 - i++ - i = encodeVarintGenerated(data, i, uint64(m.Spec.Size())) - n46, err := m.Spec.MarshalTo(data[i:]) - if err != nil { - return 0, err - } - i += n46 - data[i] = 0x1a - i++ - i = encodeVarintGenerated(data, i, uint64(m.Status.Size())) - n47, err := m.Status.MarshalTo(data[i:]) + n47, err := m.ObjectMeta.MarshalTo(data[i:]) if err != nil { return 0, err } i += n47 + data[i] = 0x12 + i++ + i = encodeVarintGenerated(data, i, uint64(m.Spec.Size())) + n48, err := m.Spec.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n48 + data[i] = 0x1a + i++ + i = encodeVarintGenerated(data, i, uint64(m.Status.Size())) + n49, err := m.Status.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n49 return i, nil } @@ -1986,11 +2053,11 @@ func (m *ReplicaSetCondition) MarshalTo(data []byte) (int, error) { data[i] = 0x1a i++ i = encodeVarintGenerated(data, i, uint64(m.LastTransitionTime.Size())) - n48, err := m.LastTransitionTime.MarshalTo(data[i:]) + n50, err := m.LastTransitionTime.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n48 + i += n50 data[i] = 0x22 i++ i = encodeVarintGenerated(data, i, uint64(len(m.Reason))) @@ -2020,11 +2087,11 @@ func (m *ReplicaSetList) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintGenerated(data, i, uint64(m.ListMeta.Size())) - n49, err := m.ListMeta.MarshalTo(data[i:]) + n51, err := m.ListMeta.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n49 + i += n51 if len(m.Items) > 0 { for _, msg := range m.Items { data[i] = 0x12 @@ -2064,20 +2131,20 @@ func (m *ReplicaSetSpec) MarshalTo(data []byte) (int, error) { data[i] = 0x12 i++ i = encodeVarintGenerated(data, i, uint64(m.Selector.Size())) - n50, err := m.Selector.MarshalTo(data[i:]) + n52, err := m.Selector.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n50 + i += n52 } data[i] = 0x1a i++ i = encodeVarintGenerated(data, i, uint64(m.Template.Size())) - n51, err := m.Template.MarshalTo(data[i:]) + n53, err := m.Template.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n51 + i += n53 data[i] = 0x20 i++ i = encodeVarintGenerated(data, i, uint64(m.MinReadySeconds)) @@ -2168,6 +2235,34 @@ func (m *RollbackConfig) MarshalTo(data []byte) (int, error) { return i, nil } +func (m *RollingUpdateDaemonSet) Marshal() (data []byte, err error) { + size := m.Size() + data = make([]byte, size) + n, err := m.MarshalTo(data) + if err != nil { + return nil, err + } + return data[:n], nil +} + +func (m *RollingUpdateDaemonSet) MarshalTo(data []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.MaxUnavailable != nil { + data[i] = 0xa + i++ + i = encodeVarintGenerated(data, i, uint64(m.MaxUnavailable.Size())) + n54, err := m.MaxUnavailable.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n54 + } + return i, nil +} + func (m *RollingUpdateDeployment) Marshal() (data []byte, err error) { size := m.Size() data = make([]byte, size) @@ -2187,21 +2282,21 @@ func (m *RollingUpdateDeployment) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintGenerated(data, i, uint64(m.MaxUnavailable.Size())) - n52, err := m.MaxUnavailable.MarshalTo(data[i:]) + n55, err := m.MaxUnavailable.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n52 + i += n55 } if m.MaxSurge != nil { data[i] = 0x12 i++ i = encodeVarintGenerated(data, i, uint64(m.MaxSurge.Size())) - n53, err := m.MaxSurge.MarshalTo(data[i:]) + n56, err := m.MaxSurge.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n53 + i += n56 } return i, nil } @@ -2263,11 +2358,11 @@ func (m *SELinuxStrategyOptions) MarshalTo(data []byte) (int, error) { data[i] = 0x12 i++ i = encodeVarintGenerated(data, i, uint64(m.SELinuxOptions.Size())) - n54, err := m.SELinuxOptions.MarshalTo(data[i:]) + n57, err := m.SELinuxOptions.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n54 + i += n57 } return i, nil } @@ -2290,27 +2385,27 @@ func (m *Scale) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintGenerated(data, i, uint64(m.ObjectMeta.Size())) - n55, err := m.ObjectMeta.MarshalTo(data[i:]) + n58, err := m.ObjectMeta.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n55 + i += n58 data[i] = 0x12 i++ i = encodeVarintGenerated(data, i, uint64(m.Spec.Size())) - n56, err := m.Spec.MarshalTo(data[i:]) + n59, err := m.Spec.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n56 + i += n59 data[i] = 0x1a i++ i = encodeVarintGenerated(data, i, uint64(m.Status.Size())) - n57, err := m.Status.MarshalTo(data[i:]) + n60, err := m.Status.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n57 + i += n60 return i, nil } @@ -2429,11 +2524,11 @@ func (m *ThirdPartyResource) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintGenerated(data, i, uint64(m.ObjectMeta.Size())) - n58, err := m.ObjectMeta.MarshalTo(data[i:]) + n61, err := m.ObjectMeta.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n58 + i += n61 data[i] = 0x12 i++ i = encodeVarintGenerated(data, i, uint64(len(m.Description))) @@ -2471,11 +2566,11 @@ func (m *ThirdPartyResourceData) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintGenerated(data, i, uint64(m.ObjectMeta.Size())) - n59, err := m.ObjectMeta.MarshalTo(data[i:]) + n62, err := m.ObjectMeta.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n59 + i += n62 if m.Data != nil { data[i] = 0x12 i++ @@ -2503,11 +2598,11 @@ func (m *ThirdPartyResourceDataList) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintGenerated(data, i, uint64(m.ListMeta.Size())) - n60, err := m.ListMeta.MarshalTo(data[i:]) + n63, err := m.ListMeta.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n60 + i += n63 if len(m.Items) > 0 { for _, msg := range m.Items { data[i] = 0x12 @@ -2541,11 +2636,11 @@ func (m *ThirdPartyResourceList) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintGenerated(data, i, uint64(m.ListMeta.Size())) - n61, err := m.ListMeta.MarshalTo(data[i:]) + n64, err := m.ListMeta.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n61 + i += n64 if len(m.Items) > 0 { for _, msg := range m.Items { data[i] = 0x12 @@ -2675,6 +2770,10 @@ func (m *DaemonSetSpec) Size() (n int) { } l = m.Template.Size() n += 1 + l + sovGenerated(uint64(l)) + l = m.UpdateStrategy.Size() + n += 1 + l + sovGenerated(uint64(l)) + n += 1 + sovGenerated(uint64(m.MinReadySeconds)) + n += 1 + sovGenerated(uint64(m.TemplateGeneration)) return n } @@ -2686,6 +2785,21 @@ func (m *DaemonSetStatus) Size() (n int) { n += 1 + sovGenerated(uint64(m.DesiredNumberScheduled)) n += 1 + sovGenerated(uint64(m.NumberReady)) n += 1 + sovGenerated(uint64(m.ObservedGeneration)) + n += 1 + sovGenerated(uint64(m.UpdatedNumberScheduled)) + n += 1 + sovGenerated(uint64(m.NumberAvailable)) + n += 1 + sovGenerated(uint64(m.NumberUnavailable)) + return n +} + +func (m *DaemonSetUpdateStrategy) Size() (n int) { + var l int + _ = l + l = len(m.Type) + n += 1 + l + sovGenerated(uint64(l)) + if m.RollingUpdate != nil { + l = m.RollingUpdate.Size() + n += 1 + l + sovGenerated(uint64(l)) + } return n } @@ -3207,6 +3321,16 @@ func (m *RollbackConfig) Size() (n int) { return n } +func (m *RollingUpdateDaemonSet) Size() (n int) { + var l int + _ = l + if m.MaxUnavailable != nil { + l = m.MaxUnavailable.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + return n +} + func (m *RollingUpdateDeployment) Size() (n int) { var l int _ = l @@ -3448,6 +3572,9 @@ func (this *DaemonSetSpec) String() string { s := strings.Join([]string{`&DaemonSetSpec{`, `Selector:` + strings.Replace(fmt.Sprintf("%v", this.Selector), "LabelSelector", "k8s_io_apimachinery_pkg_apis_meta_v1.LabelSelector", 1) + `,`, `Template:` + strings.Replace(strings.Replace(this.Template.String(), "PodTemplateSpec", "k8s_io_kubernetes_pkg_api_v1.PodTemplateSpec", 1), `&`, ``, 1) + `,`, + `UpdateStrategy:` + strings.Replace(strings.Replace(this.UpdateStrategy.String(), "DaemonSetUpdateStrategy", "DaemonSetUpdateStrategy", 1), `&`, ``, 1) + `,`, + `MinReadySeconds:` + fmt.Sprintf("%v", this.MinReadySeconds) + `,`, + `TemplateGeneration:` + fmt.Sprintf("%v", this.TemplateGeneration) + `,`, `}`, }, "") return s @@ -3462,6 +3589,20 @@ func (this *DaemonSetStatus) String() string { `DesiredNumberScheduled:` + fmt.Sprintf("%v", this.DesiredNumberScheduled) + `,`, `NumberReady:` + fmt.Sprintf("%v", this.NumberReady) + `,`, `ObservedGeneration:` + fmt.Sprintf("%v", this.ObservedGeneration) + `,`, + `UpdatedNumberScheduled:` + fmt.Sprintf("%v", this.UpdatedNumberScheduled) + `,`, + `NumberAvailable:` + fmt.Sprintf("%v", this.NumberAvailable) + `,`, + `NumberUnavailable:` + fmt.Sprintf("%v", this.NumberUnavailable) + `,`, + `}`, + }, "") + return s +} +func (this *DaemonSetUpdateStrategy) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&DaemonSetUpdateStrategy{`, + `Type:` + fmt.Sprintf("%v", this.Type) + `,`, + `RollingUpdate:` + strings.Replace(fmt.Sprintf("%v", this.RollingUpdate), "RollingUpdateDaemonSet", "RollingUpdateDaemonSet", 1) + `,`, `}`, }, "") return s @@ -3908,6 +4049,16 @@ func (this *RollbackConfig) String() string { }, "") return s } +func (this *RollingUpdateDaemonSet) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&RollingUpdateDaemonSet{`, + `MaxUnavailable:` + strings.Replace(fmt.Sprintf("%v", this.MaxUnavailable), "IntOrString", "k8s_io_apimachinery_pkg_util_intstr.IntOrString", 1) + `,`, + `}`, + }, "") + return s +} func (this *RollingUpdateDeployment) String() string { if this == nil { return "nil" @@ -4851,6 +5002,74 @@ func (m *DaemonSetSpec) Unmarshal(data []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UpdateStrategy", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.UpdateStrategy.Unmarshal(data[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MinReadySeconds", wireType) + } + m.MinReadySeconds = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + m.MinReadySeconds |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TemplateGeneration", wireType) + } + m.TemplateGeneration = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + m.TemplateGeneration |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipGenerated(data[iNdEx:]) @@ -4996,6 +5215,175 @@ func (m *DaemonSetStatus) Unmarshal(data []byte) error { break } } + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field UpdatedNumberScheduled", wireType) + } + m.UpdatedNumberScheduled = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + m.UpdatedNumberScheduled |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field NumberAvailable", wireType) + } + m.NumberAvailable = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + m.NumberAvailable |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field NumberUnavailable", wireType) + } + m.NumberUnavailable = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + m.NumberUnavailable |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipGenerated(data[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *DaemonSetUpdateStrategy) Unmarshal(data []byte) error { + l := len(data) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: DaemonSetUpdateStrategy: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: DaemonSetUpdateStrategy: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Type = DaemonSetUpdateStrategyType(data[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RollingUpdate", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.RollingUpdate == nil { + m.RollingUpdate = &RollingUpdateDaemonSet{} + } + if err := m.RollingUpdate.Unmarshal(data[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(data[iNdEx:]) @@ -9862,6 +10250,89 @@ func (m *RollbackConfig) Unmarshal(data []byte) error { } return nil } +func (m *RollingUpdateDaemonSet) Unmarshal(data []byte) error { + l := len(data) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RollingUpdateDaemonSet: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RollingUpdateDaemonSet: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxUnavailable", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.MaxUnavailable == nil { + m.MaxUnavailable = &k8s_io_apimachinery_pkg_util_intstr.IntOrString{} + } + if err := m.MaxUnavailable.Unmarshal(data[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(data[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *RollingUpdateDeployment) Unmarshal(data []byte) error { l := len(data) iNdEx := 0 @@ -11307,208 +11778,216 @@ var ( ) var fileDescriptorGenerated = []byte{ - // 3238 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe4, 0x5b, 0xdd, 0x6f, 0x1b, 0xc7, - 0xb5, 0xf7, 0x92, 0xa2, 0x45, 0x1d, 0x59, 0x92, 0x35, 0x72, 0x64, 0x46, 0x49, 0x24, 0x67, 0x2f, - 0x6e, 0xe2, 0x5c, 0x24, 0xd4, 0x8d, 0x73, 0x9d, 0x9b, 0x38, 0x89, 0x13, 0x51, 0xf2, 0x87, 0x0a, - 0x49, 0x66, 0x86, 0xb4, 0xd1, 0x38, 0x5f, 0x5d, 0x91, 0x23, 0x6a, 0xed, 0xfd, 0xca, 0xec, 0xac, - 0x22, 0x22, 0x28, 0x1a, 0xa0, 0xe8, 0x6b, 0x91, 0xbe, 0x14, 0x29, 0x90, 0x3e, 0xf6, 0xa1, 0x2f, - 0x6d, 0xf2, 0xd0, 0xa6, 0xfd, 0x0b, 0x6a, 0xa0, 0x45, 0x91, 0x02, 0x2d, 0xd0, 0x87, 0x54, 0xa8, - 0x15, 0x34, 0xff, 0x40, 0x91, 0x17, 0x3f, 0x15, 0x33, 0x3b, 0xfb, 0xc9, 0x5d, 0xd9, 0xa4, 0x6c, - 0xa2, 0x40, 0xdf, 0xc4, 0x99, 0x73, 0x7e, 0xe7, 0x63, 0x66, 0xce, 0x39, 0x33, 0x67, 0x05, 0xaf, - 0xdc, 0x7c, 0xc1, 0xad, 0xea, 0xf6, 0xe2, 0x4d, 0x6f, 0x93, 0x50, 0x8b, 0x30, 0xe2, 0x2e, 0x3a, - 0x37, 0x3b, 0x8b, 0x9a, 0xa3, 0xbb, 0x8b, 0x64, 0x97, 0x11, 0xcb, 0xd5, 0x6d, 0xcb, 0x5d, 0xdc, - 0x79, 0x76, 0x93, 0x30, 0xed, 0xd9, 0xc5, 0x0e, 0xb1, 0x08, 0xd5, 0x18, 0x69, 0x57, 0x1d, 0x6a, - 0x33, 0x1b, 0x3d, 0xe3, 0xb3, 0x57, 0x23, 0xf6, 0xaa, 0x73, 0xb3, 0x53, 0xe5, 0xec, 0xd5, 0x88, - 0xbd, 0x2a, 0xd9, 0xe7, 0x9e, 0xe9, 0xe8, 0x6c, 0xdb, 0xdb, 0xac, 0xb6, 0x6c, 0x73, 0xb1, 0x63, - 0x77, 0xec, 0x45, 0x81, 0xb2, 0xe9, 0x6d, 0x89, 0x5f, 0xe2, 0x87, 0xf8, 0xcb, 0x47, 0x9f, 0xfb, - 0x3f, 0xa9, 0x9c, 0xe6, 0xe8, 0xa6, 0xd6, 0xda, 0xd6, 0x2d, 0x42, 0xbb, 0x81, 0x7a, 0x8b, 0x94, - 0xb8, 0xb6, 0x47, 0x5b, 0x24, 0xad, 0xd3, 0x81, 0x5c, 0xee, 0xa2, 0x49, 0x98, 0xb6, 0xb8, 0xd3, - 0x63, 0xc9, 0xdc, 0x62, 0x1e, 0x17, 0xf5, 0x2c, 0xa6, 0x9b, 0xbd, 0x62, 0x9e, 0xbf, 0x1b, 0x83, - 0xdb, 0xda, 0x26, 0xa6, 0xd6, 0xc3, 0xf7, 0x5c, 0x1e, 0x9f, 0xc7, 0x74, 0x63, 0x51, 0xb7, 0x98, - 0xcb, 0xe8, 0x41, 0x36, 0xb9, 0x84, 0xee, 0x10, 0x1a, 0x5f, 0x25, 0xcd, 0x74, 0x0c, 0x92, 0x65, - 0xd3, 0xd3, 0xb9, 0x8b, 0x9b, 0x41, 0xad, 0x56, 0x01, 0x96, 0xea, 0xab, 0xd7, 0x08, 0xe5, 0x6b, - 0x86, 0x4e, 0xc1, 0x88, 0xa5, 0x99, 0xa4, 0xa2, 0x9c, 0x52, 0x4e, 0x8f, 0xd5, 0x8e, 0xdd, 0xda, - 0x5b, 0x38, 0xb2, 0xbf, 0xb7, 0x30, 0xb2, 0xa1, 0x99, 0x04, 0x8b, 0x19, 0xf5, 0x27, 0x0a, 0x3c, - 0xbc, 0xec, 0xb9, 0xcc, 0x36, 0xd7, 0x09, 0xa3, 0x7a, 0x6b, 0xd9, 0xa3, 0x94, 0x58, 0xac, 0xc1, - 0x34, 0xe6, 0xb9, 0x77, 0xe7, 0x47, 0xd7, 0xa1, 0xb4, 0xa3, 0x19, 0x1e, 0xa9, 0x14, 0x4e, 0x29, - 0xa7, 0xc7, 0xcf, 0x54, 0xab, 0x72, 0x2f, 0xc5, 0x1d, 0x13, 0xec, 0xa6, 0x6a, 0xb0, 0xda, 0xd5, - 0xd7, 0x3d, 0xcd, 0x62, 0x3a, 0xeb, 0xd6, 0x4e, 0x48, 0xc8, 0x63, 0x52, 0xee, 0x35, 0x8e, 0x85, - 0x7d, 0x48, 0xf5, 0x87, 0x0a, 0x3c, 0x96, 0xab, 0xdb, 0x9a, 0xee, 0x32, 0x64, 0x42, 0x49, 0x67, - 0xc4, 0x74, 0x2b, 0xca, 0xa9, 0xe2, 0xe9, 0xf1, 0x33, 0x97, 0xab, 0x7d, 0xed, 0xe4, 0x6a, 0x2e, - 0x78, 0x6d, 0x42, 0xea, 0x55, 0x5a, 0xe5, 0xf0, 0xd8, 0x97, 0xa2, 0xfe, 0x48, 0x01, 0x14, 0xe7, - 0x69, 0x6a, 0xb4, 0x43, 0xd8, 0x3d, 0x78, 0xe9, 0x8d, 0xc3, 0x79, 0x69, 0x46, 0x42, 0x8e, 0xfb, - 0x02, 0x13, 0x4e, 0xfa, 0x50, 0x81, 0xd9, 0x5e, 0x9d, 0x84, 0x77, 0xb6, 0x92, 0xde, 0x59, 0x3a, - 0x84, 0x77, 0x7c, 0xd4, 0x1c, 0xb7, 0xfc, 0xaa, 0x00, 0x63, 0x2b, 0x1a, 0x31, 0x6d, 0xab, 0x41, - 0x18, 0xfa, 0x0e, 0x94, 0xf9, 0xf1, 0x6c, 0x6b, 0x4c, 0x13, 0x1e, 0x19, 0x3f, 0xf3, 0xbf, 0x07, - 0x99, 0xeb, 0x56, 0x39, 0x75, 0x75, 0xe7, 0xd9, 0xea, 0x95, 0xcd, 0x1b, 0xa4, 0xc5, 0xd6, 0x09, - 0xd3, 0x6a, 0x48, 0xca, 0x81, 0x68, 0x0c, 0x87, 0xa8, 0xe8, 0x1d, 0x18, 0x71, 0x1d, 0xd2, 0x92, - 0xce, 0x7c, 0xb9, 0x4f, 0xb3, 0x42, 0x4d, 0x1b, 0x0e, 0x69, 0x45, 0xab, 0xc5, 0x7f, 0x61, 0x81, - 0x8b, 0xb6, 0xe0, 0xa8, 0x2b, 0xb6, 0x41, 0xa5, 0x28, 0x24, 0x9c, 0x1f, 0x58, 0x82, 0xbf, 0x99, - 0x26, 0xa5, 0x8c, 0xa3, 0xfe, 0x6f, 0x2c, 0xd1, 0xd5, 0x3f, 0x28, 0x30, 0x11, 0xd2, 0x8a, 0x15, - 0x7b, 0xab, 0xc7, 0x77, 0xd5, 0x7b, 0xf3, 0x1d, 0xe7, 0x16, 0x9e, 0x3b, 0x2e, 0x65, 0x95, 0x83, - 0x91, 0x98, 0xdf, 0xde, 0x0e, 0xf6, 0x43, 0x41, 0xec, 0x87, 0x17, 0x06, 0x35, 0x2b, 0x67, 0x1b, - 0xfc, 0x3e, 0x6e, 0x0e, 0x77, 0x27, 0x7a, 0x1b, 0xca, 0x2e, 0x31, 0x48, 0x8b, 0xd9, 0x54, 0x9a, - 0xf3, 0xdc, 0x3d, 0x9a, 0xa3, 0x6d, 0x12, 0xa3, 0x21, 0x59, 0x6b, 0xc7, 0xb8, 0x3d, 0xc1, 0x2f, - 0x1c, 0x42, 0xa2, 0x37, 0xa1, 0xcc, 0x88, 0xe9, 0x18, 0x1a, 0x0b, 0x0e, 0xd6, 0x33, 0xf9, 0x26, - 0x71, 0xd8, 0xba, 0xdd, 0x6e, 0x4a, 0x06, 0xb1, 0xf8, 0xa1, 0xb3, 0x82, 0x51, 0x1c, 0x02, 0xaa, - 0x1f, 0x15, 0x61, 0x2a, 0xb5, 0x90, 0xe8, 0x1a, 0xcc, 0xb6, 0xfc, 0x30, 0xb1, 0xe1, 0x99, 0x9b, - 0x84, 0x36, 0x5a, 0xdb, 0xa4, 0xed, 0x19, 0xa4, 0x2d, 0xac, 0x2b, 0xd5, 0xe6, 0x25, 0xde, 0xec, - 0x72, 0x26, 0x15, 0xce, 0xe1, 0x46, 0xdf, 0x02, 0x64, 0x89, 0xa1, 0x75, 0xdd, 0x75, 0x43, 0xcc, - 0x82, 0xc0, 0x9c, 0x93, 0x98, 0x68, 0xa3, 0x87, 0x02, 0x67, 0x70, 0x71, 0x1d, 0xdb, 0xc4, 0xd5, - 0x29, 0x69, 0xa7, 0x75, 0x2c, 0x26, 0x75, 0x5c, 0xc9, 0xa4, 0xc2, 0x39, 0xdc, 0xe8, 0x2c, 0x8c, - 0xfb, 0xd2, 0x30, 0xd1, 0xda, 0xdd, 0xca, 0x88, 0x00, 0x0b, 0x03, 0xd3, 0x46, 0x34, 0x85, 0xe3, - 0x74, 0xdc, 0x34, 0x7b, 0x53, 0x64, 0xbb, 0xf6, 0x25, 0x3f, 0x55, 0xe9, 0xb6, 0x55, 0x29, 0x9d, - 0x52, 0x4e, 0x17, 0x23, 0xd3, 0xae, 0xf4, 0x50, 0xe0, 0x0c, 0x2e, 0xf5, 0x37, 0x05, 0x80, 0x15, - 0xe2, 0x18, 0x76, 0xd7, 0x24, 0xd6, 0x30, 0x02, 0xcd, 0xbb, 0x89, 0x40, 0xf3, 0x4a, 0xbf, 0xe7, - 0x25, 0x54, 0x35, 0x37, 0xd2, 0x74, 0x52, 0x91, 0xe6, 0xd5, 0xc1, 0x45, 0x1c, 0x1c, 0x6a, 0x6e, - 0x17, 0x61, 0x26, 0x22, 0x5e, 0xb6, 0xad, 0xb6, 0xce, 0x5d, 0x8a, 0x5e, 0x82, 0x11, 0xd6, 0x75, - 0x82, 0xd4, 0xf5, 0x64, 0xa0, 0x62, 0xb3, 0xeb, 0x90, 0x3b, 0x7b, 0x0b, 0x27, 0x33, 0x58, 0xf8, - 0x14, 0x16, 0x4c, 0xe8, 0x5a, 0xa8, 0x7d, 0x41, 0xb0, 0x9f, 0x4f, 0x0a, 0xbf, 0xb3, 0xb7, 0x70, - 0x60, 0xed, 0x52, 0x0d, 0x31, 0x93, 0xca, 0xa2, 0x27, 0xe0, 0x28, 0x25, 0x9a, 0x6b, 0x5b, 0x62, - 0x97, 0x8d, 0x45, 0x46, 0x61, 0x31, 0x8a, 0xe5, 0x2c, 0x7a, 0x0a, 0x46, 0x4d, 0xe2, 0xba, 0x5a, - 0x87, 0x88, 0x0d, 0x35, 0x56, 0x9b, 0x92, 0x84, 0xa3, 0xeb, 0xfe, 0x30, 0x0e, 0xe6, 0xd1, 0x0d, - 0x98, 0x34, 0x34, 0x97, 0x5d, 0x75, 0xda, 0x1a, 0x23, 0x4d, 0xdd, 0x24, 0x95, 0xa3, 0xc2, 0xe1, - 0xff, 0x73, 0x6f, 0x3b, 0x86, 0x73, 0xd4, 0x66, 0x25, 0xfa, 0xe4, 0x5a, 0x02, 0x09, 0xa7, 0x90, - 0xd1, 0x0e, 0x20, 0x3e, 0xd2, 0xa4, 0x9a, 0xe5, 0xfa, 0x2e, 0xe3, 0xf2, 0x46, 0xfb, 0x96, 0x17, - 0x1e, 0x8f, 0xb5, 0x1e, 0x34, 0x9c, 0x21, 0x41, 0xfd, 0xa3, 0x02, 0x93, 0xd1, 0x82, 0x0d, 0x21, - 0x9f, 0xbc, 0x93, 0xcc, 0x27, 0x2f, 0x0e, 0xbc, 0x79, 0x73, 0x12, 0xca, 0xc7, 0x45, 0x40, 0x11, - 0x11, 0xb6, 0x0d, 0x63, 0x53, 0x6b, 0xdd, 0xbc, 0x87, 0x72, 0xeb, 0x67, 0x0a, 0x20, 0x4f, 0x2c, - 0x48, 0x7b, 0xc9, 0xb2, 0x6c, 0x26, 0xc2, 0x47, 0xa0, 0xe6, 0x1b, 0x03, 0xab, 0x19, 0x68, 0x50, - 0xbd, 0xda, 0x83, 0x7d, 0xc1, 0x62, 0xb4, 0x1b, 0xad, 0x58, 0x2f, 0x01, 0xce, 0x50, 0x08, 0xbd, - 0x07, 0x40, 0x25, 0x66, 0xd3, 0x96, 0x21, 0xa0, 0xdf, 0x28, 0x13, 0x28, 0xb5, 0x6c, 0x5b, 0x5b, - 0x7a, 0x27, 0x0a, 0x68, 0x38, 0x04, 0xc6, 0x31, 0x21, 0x73, 0x17, 0xe0, 0x64, 0x8e, 0xf6, 0xe8, - 0x38, 0x14, 0x6f, 0x92, 0xae, 0xef, 0x56, 0xcc, 0xff, 0x44, 0x27, 0xe2, 0x65, 0xeb, 0x98, 0xac, - 0x38, 0xcf, 0x15, 0x5e, 0x50, 0xd4, 0xaf, 0x4b, 0xf1, 0xbd, 0x26, 0x92, 0xfd, 0x69, 0x28, 0x53, - 0xe2, 0x18, 0x7a, 0x4b, 0x73, 0x65, 0x3a, 0x14, 0x79, 0x1b, 0xcb, 0x31, 0x1c, 0xce, 0x26, 0xca, - 0x82, 0xc2, 0x83, 0x2d, 0x0b, 0x8a, 0xf7, 0xb9, 0x2c, 0x40, 0x36, 0x94, 0x5d, 0xc6, 0x2f, 0x5c, - 0x1d, 0x3f, 0x07, 0xf6, 0x5f, 0x56, 0xc7, 0x63, 0xb6, 0x0f, 0x14, 0x09, 0x0c, 0x46, 0x70, 0x28, - 0x04, 0x2d, 0xc1, 0x94, 0xa9, 0x5b, 0x22, 0x99, 0x36, 0x48, 0xcb, 0xb6, 0xda, 0xae, 0x08, 0x76, - 0xa5, 0xda, 0x49, 0xc9, 0x34, 0xb5, 0x9e, 0x9c, 0xc6, 0x69, 0x7a, 0xb4, 0x06, 0x27, 0x28, 0xd9, - 0xd1, 0xb9, 0x1a, 0x97, 0x75, 0x97, 0xd9, 0xb4, 0xbb, 0xa6, 0x9b, 0x3a, 0x13, 0x21, 0xb0, 0x54, - 0xab, 0xec, 0xef, 0x2d, 0x9c, 0xc0, 0x19, 0xf3, 0x38, 0x93, 0x8b, 0x47, 0x67, 0x47, 0xf3, 0x5c, - 0xd2, 0x16, 0x21, 0xad, 0x1c, 0x45, 0xe7, 0xba, 0x18, 0xc5, 0x72, 0x16, 0x99, 0x89, 0xcd, 0x5d, - 0xbe, 0x1f, 0x9b, 0x7b, 0x32, 0x7f, 0x63, 0xa3, 0xab, 0x70, 0xd2, 0xa1, 0x76, 0x87, 0x12, 0xd7, - 0x5d, 0x21, 0x5a, 0xdb, 0xd0, 0x2d, 0x12, 0xf8, 0x6b, 0x4c, 0xd8, 0xf9, 0xc8, 0xfe, 0xde, 0xc2, - 0xc9, 0x7a, 0x36, 0x09, 0xce, 0xe3, 0x55, 0x3f, 0x19, 0x81, 0xe3, 0xe9, 0x2c, 0x9b, 0x53, 0xd4, - 0x28, 0x83, 0x14, 0x35, 0xe8, 0xe9, 0xd8, 0xb1, 0xf1, 0x2b, 0xbe, 0x70, 0x37, 0x64, 0x1c, 0x9d, - 0x25, 0x98, 0x92, 0x71, 0x24, 0x98, 0x94, 0x65, 0x5d, 0xb8, 0x1b, 0xae, 0x26, 0xa7, 0x71, 0x9a, - 0x1e, 0x5d, 0x82, 0x69, 0x6d, 0x47, 0xd3, 0x0d, 0x6d, 0xd3, 0x20, 0x21, 0x88, 0x5f, 0xce, 0x3d, - 0x2c, 0x41, 0xa6, 0x97, 0xd2, 0x04, 0xb8, 0x97, 0x07, 0xad, 0xc3, 0x8c, 0x67, 0xf5, 0x42, 0xf9, - 0xbb, 0xf3, 0x11, 0x09, 0x35, 0x73, 0xb5, 0x97, 0x04, 0x67, 0xf1, 0xa1, 0x1d, 0x80, 0x56, 0x50, - 0x10, 0xb8, 0x95, 0xa3, 0x22, 0x56, 0xd7, 0x06, 0x3e, 0x5b, 0x61, 0x6d, 0x11, 0x45, 0xc4, 0x70, - 0xc8, 0xc5, 0x31, 0x49, 0xe8, 0x25, 0x98, 0xa0, 0xa2, 0x6e, 0x0d, 0x0c, 0x18, 0x15, 0x06, 0x3c, - 0x24, 0xd9, 0x26, 0x70, 0x7c, 0x12, 0x27, 0x69, 0xd5, 0x3f, 0x29, 0xf1, 0x14, 0x15, 0x1c, 0x5f, - 0x74, 0x2e, 0x51, 0x56, 0x3d, 0x91, 0x2a, 0xab, 0x66, 0x7b, 0x39, 0x62, 0x55, 0xd5, 0xf7, 0x60, - 0x82, 0x6f, 0x6b, 0xdd, 0xea, 0xf8, 0x4b, 0x29, 0x43, 0xe4, 0xc5, 0x01, 0x8e, 0x4e, 0x88, 0x11, - 0x4b, 0xb5, 0xd3, 0xc2, 0xa6, 0xf8, 0x24, 0x4e, 0xca, 0x53, 0x3f, 0x53, 0x60, 0xf6, 0x62, 0xe3, - 0x12, 0xb5, 0x3d, 0x27, 0x50, 0xef, 0x8a, 0xe3, 0xfb, 0xea, 0xff, 0x61, 0x84, 0x7a, 0x46, 0x60, - 0xd7, 0x7f, 0x05, 0x76, 0x61, 0xcf, 0xe0, 0x76, 0xcd, 0xa4, 0xb8, 0x7c, 0xa3, 0x38, 0x03, 0x7a, - 0x07, 0x8e, 0x52, 0xcd, 0xea, 0x90, 0x20, 0x09, 0x3f, 0xdf, 0xa7, 0x35, 0xab, 0x2b, 0x98, 0xb3, - 0xc7, 0x4a, 0x41, 0x81, 0x86, 0x25, 0xaa, 0xfa, 0x53, 0x05, 0xa6, 0x2e, 0x37, 0x9b, 0xf5, 0x55, - 0x4b, 0x9c, 0xe2, 0xba, 0xc6, 0xb6, 0x79, 0x9d, 0xe0, 0x68, 0x6c, 0x3b, 0x5d, 0x27, 0xf0, 0x39, - 0x2c, 0x66, 0xd0, 0x36, 0x8c, 0xf2, 0xe8, 0x41, 0xac, 0xf6, 0x80, 0x25, 0xbe, 0x14, 0x57, 0xf3, - 0x41, 0xa2, 0xfa, 0x53, 0x0e, 0xe0, 0x00, 0x5e, 0xfd, 0x00, 0x4e, 0xc4, 0xd4, 0xe3, 0xfe, 0x12, - 0x8f, 0x38, 0xa8, 0x05, 0x25, 0xae, 0x49, 0xf0, 0x44, 0xd3, 0xef, 0x4b, 0x43, 0xca, 0xe4, 0xa8, - 0x8e, 0xe2, 0xbf, 0x5c, 0xec, 0x63, 0xab, 0xeb, 0x30, 0x71, 0xd9, 0x76, 0x59, 0xdd, 0xa6, 0x4c, - 0xb8, 0x0d, 0x3d, 0x06, 0x45, 0x53, 0xb7, 0x64, 0x96, 0x1e, 0x97, 0x3c, 0x45, 0x9e, 0x47, 0xf8, - 0xb8, 0x98, 0xd6, 0x76, 0x65, 0x34, 0x8a, 0xa6, 0xb5, 0x5d, 0xcc, 0xc7, 0xd5, 0x4b, 0x30, 0x2a, - 0x97, 0x23, 0x0e, 0x54, 0x3c, 0x18, 0xa8, 0x98, 0x01, 0xf4, 0xcb, 0x02, 0x8c, 0x4a, 0xed, 0x87, - 0x70, 0x99, 0x7b, 0x2b, 0x71, 0x99, 0x3b, 0x37, 0xd8, 0x4a, 0xe7, 0xde, 0xe4, 0xda, 0xa9, 0x9b, - 0xdc, 0xcb, 0x03, 0xe2, 0x1f, 0x7c, 0x8d, 0xfb, 0x54, 0x81, 0xc9, 0xe4, 0x9e, 0xe3, 0xf7, 0x72, - 0x9e, 0x53, 0xf4, 0x16, 0xd9, 0x88, 0x8a, 0xe2, 0xf0, 0x5e, 0xde, 0x88, 0xa6, 0x70, 0x9c, 0x0e, - 0x75, 0x42, 0x36, 0xbe, 0x2d, 0xa4, 0x53, 0xf2, 0x5d, 0xee, 0x31, 0xdd, 0xa8, 0xfa, 0xcf, 0xda, - 0xd5, 0x55, 0x8b, 0x5d, 0xa1, 0x0d, 0x46, 0x75, 0xab, 0xd3, 0x23, 0x48, 0xec, 0xb1, 0x38, 0xb2, - 0x7a, 0x4b, 0x81, 0x71, 0xa9, 0xf2, 0x10, 0xae, 0x24, 0x6f, 0x26, 0xaf, 0x24, 0xcf, 0x0f, 0x78, - 0x9e, 0xb3, 0xef, 0x23, 0x9f, 0x47, 0xa6, 0xf0, 0x13, 0xcc, 0x03, 0xcc, 0xb6, 0xed, 0xb2, 0x74, - 0x80, 0xe1, 0x67, 0x0d, 0x8b, 0x19, 0xf4, 0x03, 0x05, 0x8e, 0xeb, 0xa9, 0x33, 0x2f, 0x7d, 0xfd, - 0xea, 0x60, 0xaa, 0x85, 0x30, 0xb5, 0x8a, 0x94, 0x77, 0x3c, 0x3d, 0x83, 0x7b, 0x44, 0xaa, 0x1e, - 0xf4, 0x50, 0x21, 0x0d, 0x46, 0xb6, 0x19, 0x73, 0xe4, 0x22, 0x2c, 0x0f, 0x1e, 0x79, 0x22, 0x95, - 0xca, 0xc2, 0xfc, 0x66, 0xb3, 0x8e, 0x05, 0xb4, 0xfa, 0x8b, 0x42, 0xe8, 0xb0, 0x86, 0x7f, 0x48, - 0xc2, 0x78, 0xab, 0xdc, 0x8f, 0x78, 0x3b, 0x9e, 0x15, 0x6b, 0xd1, 0xb7, 0xa1, 0xc8, 0x8c, 0x41, - 0x2f, 0xa5, 0x52, 0x42, 0x73, 0xad, 0x11, 0x05, 0xac, 0xe6, 0x5a, 0x03, 0x73, 0x48, 0xf4, 0x2e, - 0x94, 0x78, 0x36, 0xe3, 0x67, 0xbc, 0x38, 0x78, 0x0c, 0xe1, 0xfe, 0x8a, 0x76, 0x18, 0xff, 0xe5, - 0x62, 0x1f, 0x57, 0xfd, 0x00, 0x26, 0x12, 0x81, 0x00, 0xdd, 0x80, 0x63, 0x86, 0xad, 0xb5, 0x6b, - 0x9a, 0xa1, 0x59, 0x2d, 0x42, 0xd3, 0xa1, 0x31, 0xfb, 0x3e, 0xb3, 0x16, 0xe3, 0x90, 0x01, 0x25, - 0xec, 0xb3, 0xc4, 0xe7, 0x70, 0x02, 0x5b, 0xd5, 0x00, 0x22, 0xeb, 0xd1, 0x02, 0x94, 0xf8, 0x16, - 0xf6, 0x33, 0xd3, 0x58, 0x6d, 0x8c, 0xeb, 0xca, 0x77, 0xb6, 0x8b, 0xfd, 0x71, 0x74, 0x06, 0xc0, - 0x25, 0x2d, 0x4a, 0x98, 0x88, 0x3b, 0xfe, 0x0b, 0x50, 0x18, 0x81, 0x1b, 0xe1, 0x0c, 0x8e, 0x51, - 0xa9, 0x7f, 0x51, 0x60, 0x62, 0x83, 0xb0, 0xf7, 0x6d, 0x7a, 0xb3, 0x6e, 0x1b, 0x7a, 0xab, 0x3b, - 0x84, 0xb8, 0xbf, 0x99, 0x88, 0xfb, 0xaf, 0xf5, 0xb9, 0x66, 0x09, 0x6d, 0xf3, 0xa2, 0xbf, 0xfa, - 0x0f, 0x05, 0x2a, 0x09, 0xca, 0x78, 0x98, 0x20, 0x50, 0x72, 0x6c, 0xca, 0x82, 0x1c, 0x7f, 0x28, - 0x0d, 0x78, 0x48, 0x8d, 0x65, 0x79, 0x0e, 0x8b, 0x7d, 0x74, 0x6e, 0xe7, 0x16, 0xb5, 0x4d, 0xb9, - 0xef, 0x0f, 0x27, 0x85, 0x10, 0x1a, 0xd9, 0x79, 0x91, 0xda, 0x26, 0x16, 0xd8, 0xea, 0x9f, 0x15, - 0x98, 0x4e, 0x50, 0x0e, 0x21, 0xa4, 0x6b, 0xc9, 0x90, 0xfe, 0xf2, 0x61, 0x0c, 0xcb, 0x09, 0xec, - 0xdf, 0xa4, 0xcd, 0xe2, 0x0e, 0x40, 0x5b, 0x30, 0xee, 0xd8, 0xed, 0xc6, 0x7d, 0x68, 0x60, 0x4c, - 0xf1, 0x0c, 0x59, 0x8f, 0xb0, 0x70, 0x1c, 0x18, 0xed, 0xc2, 0xb4, 0xa5, 0x99, 0xc4, 0x75, 0xb4, - 0x16, 0x69, 0xdc, 0x87, 0x77, 0x91, 0x87, 0xf8, 0x0d, 0x6e, 0x23, 0x8d, 0x88, 0x7b, 0x85, 0xa8, - 0xbf, 0xee, 0xb1, 0xdb, 0xa6, 0x0c, 0xbd, 0x0e, 0x65, 0xd1, 0x4b, 0x6e, 0xd9, 0x86, 0x4c, 0x6d, - 0x67, 0xf9, 0xd2, 0xd4, 0xe5, 0xd8, 0x9d, 0xbd, 0x85, 0xff, 0x3e, 0xf0, 0x59, 0x37, 0x20, 0xc4, - 0x21, 0x0c, 0xda, 0x80, 0x11, 0xe7, 0x30, 0x65, 0x86, 0x48, 0x2c, 0xa2, 0xb6, 0x10, 0x38, 0xea, - 0x3f, 0xd3, 0x8a, 0x8b, 0xf4, 0x72, 0xe3, 0xbe, 0x2d, 0x58, 0x58, 0xd6, 0xe4, 0x2e, 0x1a, 0x85, - 0x51, 0x99, 0x65, 0xe5, 0xbe, 0xbc, 0x74, 0x98, 0x7d, 0x19, 0xcf, 0x0c, 0xe1, 0x25, 0x22, 0x18, - 0x0c, 0x04, 0xa9, 0x7f, 0x53, 0x60, 0x5a, 0x28, 0xd4, 0xf2, 0xa8, 0xce, 0xba, 0x43, 0x8b, 0xa0, - 0x5b, 0x89, 0x08, 0xba, 0xd2, 0xa7, 0xa1, 0x3d, 0x1a, 0xe7, 0x46, 0xd1, 0x2f, 0x15, 0x78, 0xa8, - 0x87, 0x7a, 0x08, 0x11, 0x86, 0x24, 0x23, 0xcc, 0x6b, 0x87, 0x35, 0x30, 0x27, 0xca, 0xdc, 0x82, - 0x0c, 0xf3, 0xc4, 0xc6, 0x3d, 0x03, 0xe0, 0x50, 0x7d, 0x47, 0x37, 0x48, 0x47, 0xf6, 0x12, 0xcb, - 0xd1, 0x92, 0xd4, 0xc3, 0x19, 0x1c, 0xa3, 0x42, 0xdf, 0x85, 0xd9, 0x36, 0xd9, 0xd2, 0x3c, 0x83, - 0x2d, 0xb5, 0xdb, 0xcb, 0x9a, 0xa3, 0x6d, 0xea, 0x86, 0xce, 0x74, 0x79, 0xc3, 0x1e, 0xab, 0x5d, - 0xf0, 0x7b, 0x7c, 0x59, 0x14, 0x77, 0xf6, 0x16, 0x9e, 0x3c, 0xb8, 0x31, 0x13, 0x10, 0x77, 0x71, - 0x8e, 0x10, 0xf4, 0x7d, 0x05, 0x2a, 0x94, 0xbc, 0xe7, 0xe9, 0x94, 0xb4, 0x57, 0xa8, 0xed, 0x24, - 0x34, 0x28, 0x0a, 0x0d, 0x2e, 0xed, 0xef, 0x2d, 0x54, 0x70, 0x0e, 0x4d, 0x3f, 0x3a, 0xe4, 0x0a, - 0x42, 0x0c, 0x66, 0x34, 0xc3, 0xb0, 0xdf, 0x27, 0x49, 0x0f, 0x8c, 0x08, 0xf9, 0xb5, 0xfd, 0xbd, - 0x85, 0x99, 0xa5, 0xde, 0xe9, 0x7e, 0x44, 0x67, 0xc1, 0xa3, 0x45, 0x18, 0xdd, 0xb1, 0x0d, 0xcf, - 0x24, 0x6e, 0xa5, 0x24, 0x24, 0xf1, 0x88, 0x3b, 0x7a, 0xcd, 0x1f, 0xba, 0xb3, 0xb7, 0x70, 0xf4, - 0x62, 0x43, 0x3c, 0x7d, 0x04, 0x54, 0xfc, 0x8e, 0xc6, 0x6b, 0x26, 0x79, 0xe4, 0xc5, 0xbb, 0x6b, - 0x39, 0x8a, 0x31, 0x97, 0xa3, 0x29, 0x1c, 0xa7, 0x43, 0x26, 0x8c, 0x6d, 0xcb, 0x7b, 0xbb, 0x5b, - 0x19, 0x1d, 0x28, 0xfb, 0x25, 0xee, 0xfd, 0xb5, 0x69, 0x29, 0x72, 0x2c, 0x18, 0x76, 0x71, 0x24, - 0x01, 0x3d, 0x05, 0xa3, 0xe2, 0xc7, 0xea, 0x8a, 0x78, 0xad, 0x2d, 0x47, 0x91, 0xe8, 0xb2, 0x3f, - 0x8c, 0x83, 0xf9, 0x80, 0x74, 0xb5, 0xbe, 0x2c, 0x1e, 0x57, 0x53, 0xa4, 0xab, 0xf5, 0x65, 0x1c, - 0xcc, 0x23, 0x07, 0x46, 0x5d, 0xb2, 0xa6, 0x5b, 0xde, 0x6e, 0x05, 0xc4, 0xc9, 0xbd, 0xd0, 0xa7, - 0x09, 0x8d, 0x0b, 0x82, 0x3b, 0xf5, 0x14, 0x15, 0x49, 0x94, 0xf3, 0x38, 0x10, 0x83, 0x76, 0x61, - 0x8c, 0x7a, 0xd6, 0x92, 0x7b, 0xd5, 0x25, 0xb4, 0x32, 0x2e, 0x64, 0xf6, 0x1b, 0x9c, 0x71, 0xc0, - 0x9f, 0x96, 0x1a, 0x7a, 0x30, 0xa4, 0xc0, 0x91, 0x30, 0xf4, 0x89, 0x02, 0xc8, 0xf5, 0x1c, 0xc7, - 0x20, 0x26, 0xb1, 0x98, 0x66, 0x88, 0xd7, 0x30, 0xb7, 0x72, 0x4c, 0xe8, 0x50, 0xef, 0xd7, 0xee, - 0x1e, 0xa0, 0xb4, 0x32, 0xe1, 0x53, 0x73, 0x2f, 0x29, 0xce, 0xd0, 0x83, 0x2f, 0xc5, 0x96, 0x2b, - 0xfe, 0xae, 0x4c, 0x0c, 0xb4, 0x14, 0xd9, 0xaf, 0x82, 0xd1, 0x52, 0xc8, 0x79, 0x1c, 0x88, 0x41, - 0xd7, 0x60, 0x96, 0x12, 0xad, 0x7d, 0xc5, 0x32, 0xba, 0xd8, 0xb6, 0xd9, 0x45, 0xdd, 0x20, 0x6e, - 0xd7, 0x65, 0xc4, 0xac, 0x4c, 0x8a, 0x6d, 0x13, 0x7e, 0x8c, 0x80, 0x33, 0xa9, 0x70, 0x0e, 0xb7, - 0xf8, 0x12, 0x40, 0xbe, 0xc1, 0x0e, 0xe7, 0x93, 0xa3, 0xc3, 0x7d, 0x09, 0x10, 0xa9, 0xfa, 0xc0, - 0xbe, 0x04, 0x88, 0x89, 0x38, 0xf8, 0x09, 0xe9, 0x9b, 0x02, 0xcc, 0x44, 0xc4, 0xf7, 0xfc, 0x25, - 0x40, 0x06, 0xcb, 0x10, 0xbe, 0x04, 0xc8, 0x6e, 0xa5, 0x17, 0x1f, 0x74, 0x2b, 0xfd, 0x01, 0x7c, - 0x81, 0x20, 0xba, 0xf3, 0x91, 0x13, 0xff, 0xfd, 0xbb, 0xf3, 0x91, 0xae, 0x39, 0xe5, 0xcc, 0x6f, - 0x0b, 0x71, 0x83, 0xfe, 0x83, 0x5a, 0xc0, 0x19, 0x1d, 0xd9, 0x91, 0xfe, 0x3a, 0xb2, 0xea, 0x97, - 0x45, 0x38, 0x9e, 0x3e, 0xb1, 0x89, 0x4e, 0xa0, 0x72, 0xd7, 0x4e, 0x60, 0x1d, 0x4e, 0x6c, 0x79, - 0x86, 0xd1, 0x15, 0x0e, 0x89, 0xb5, 0x03, 0xfd, 0x57, 0xfb, 0x47, 0x25, 0xe7, 0x89, 0x8b, 0x19, - 0x34, 0x38, 0x93, 0x33, 0xa7, 0xab, 0x59, 0x1c, 0xa8, 0xab, 0xd9, 0xd3, 0x54, 0x1b, 0xb9, 0xf7, - 0xa6, 0x5a, 0x76, 0x87, 0xb2, 0x34, 0x40, 0x87, 0xf2, 0x7e, 0xb4, 0x14, 0x33, 0x02, 0xdf, 0xdd, - 0x5a, 0x8a, 0xea, 0xa3, 0x30, 0x27, 0xd9, 0xf8, 0xef, 0x65, 0xdb, 0x62, 0xd4, 0x36, 0x0c, 0x42, - 0x57, 0x3c, 0xd3, 0xec, 0xaa, 0xe7, 0x61, 0x32, 0xd9, 0xd7, 0xf6, 0x57, 0xde, 0x6f, 0xb5, 0xcb, - 0x5e, 0x4a, 0x6c, 0xe5, 0xfd, 0x71, 0x1c, 0x52, 0xa8, 0x5f, 0x29, 0x70, 0x32, 0xa7, 0xbb, 0x87, - 0x0c, 0x98, 0x34, 0xb5, 0xdd, 0x58, 0xcf, 0xf5, 0xae, 0xf9, 0x30, 0xef, 0xca, 0x8d, 0xf6, 0xf7, - 0x16, 0x26, 0xd7, 0x13, 0x58, 0x38, 0x85, 0x8d, 0xae, 0x43, 0xd9, 0xd4, 0x76, 0x1b, 0x1e, 0xed, - 0x90, 0x81, 0xaf, 0xf6, 0xe2, 0x08, 0xaf, 0x4b, 0x14, 0x1c, 0xe2, 0xa9, 0x9f, 0x29, 0x50, 0xc9, - 0x2b, 0xc3, 0xd0, 0xd9, 0x44, 0x1f, 0xf2, 0xf1, 0x54, 0x1f, 0x72, 0xba, 0x87, 0x6f, 0x48, 0x5d, - 0xc8, 0xcf, 0x15, 0x98, 0xcd, 0x2e, 0x57, 0xd1, 0x73, 0x09, 0x8d, 0x17, 0x52, 0x1a, 0x4f, 0xa5, - 0xb8, 0xa4, 0xbe, 0xdb, 0x30, 0x29, 0x8b, 0x5a, 0x09, 0x23, 0xbd, 0xfc, 0xf4, 0xc1, 0xc1, 0x4c, - 0x82, 0x05, 0xe5, 0x99, 0x58, 0xc9, 0xe4, 0x18, 0x4e, 0xe1, 0xaa, 0x3f, 0x2f, 0x40, 0xa9, 0xd1, - 0xd2, 0x0c, 0x32, 0x84, 0x5a, 0xea, 0x7a, 0xa2, 0x96, 0xea, 0xf7, 0x2b, 0x64, 0xa1, 0x65, 0x6e, - 0x19, 0xb5, 0x99, 0x2a, 0xa3, 0xce, 0x0d, 0x84, 0x7e, 0x70, 0x05, 0xf5, 0x22, 0x8c, 0x85, 0x4a, - 0xf4, 0x17, 0xb4, 0xd5, 0x4f, 0x0b, 0x30, 0x1e, 0x13, 0xd1, 0x67, 0xc8, 0xdf, 0x49, 0x24, 0xcd, - 0x41, 0xfe, 0xe1, 0x21, 0x26, 0xbb, 0x1a, 0xa4, 0x4d, 0xff, 0xd3, 0xb5, 0xe8, 0x13, 0xa4, 0xde, - 0x6c, 0x7a, 0x1e, 0x26, 0x99, 0xf8, 0xfe, 0x3f, 0x7c, 0x5a, 0x2b, 0x8a, 0x5d, 0x1c, 0x7e, 0x10, - 0xd9, 0x4c, 0xcc, 0xe2, 0x14, 0xf5, 0xdc, 0x4b, 0x30, 0x91, 0x10, 0xd6, 0xd7, 0x97, 0x66, 0xbf, - 0x53, 0xe0, 0xf1, 0xbb, 0x5e, 0x85, 0x50, 0x2d, 0x71, 0xbc, 0xaa, 0xa9, 0xe3, 0x35, 0x9f, 0x0f, - 0x30, 0xc4, 0x6f, 0x14, 0x7e, 0x5c, 0x00, 0xd4, 0xdc, 0xd6, 0x69, 0xbb, 0xae, 0x51, 0xd6, 0xc5, - 0xf2, 0xbf, 0x3c, 0x86, 0x70, 0xe0, 0xce, 0xc2, 0x78, 0x9b, 0xb8, 0x2d, 0xaa, 0x0b, 0x67, 0xc9, - 0x12, 0x3d, 0x7c, 0x7e, 0x58, 0x89, 0xa6, 0x70, 0x9c, 0x0e, 0x75, 0xa0, 0xbc, 0xe3, 0xff, 0x1f, - 0x51, 0xd0, 0xf0, 0xea, 0xb7, 0x86, 0x8c, 0xfe, 0x13, 0x29, 0xda, 0x5f, 0x72, 0xc0, 0xc5, 0x21, - 0xb8, 0xfa, 0xb1, 0x02, 0xb3, 0xbd, 0x8e, 0x59, 0xe1, 0xaa, 0x3f, 0x78, 0xe7, 0x3c, 0x0a, 0x23, - 0x02, 0x9d, 0x7b, 0xe5, 0x98, 0xff, 0xd0, 0xcc, 0x25, 0x63, 0x31, 0xaa, 0x7e, 0xad, 0xc0, 0x5c, - 0xb6, 0x6a, 0x43, 0xa8, 0xe0, 0x6f, 0x24, 0x2b, 0xf8, 0x7e, 0x6f, 0xeb, 0xd9, 0x7a, 0xe7, 0x54, - 0xf3, 0x7b, 0x99, 0x6b, 0x30, 0x04, 0x23, 0xb7, 0x92, 0x46, 0x2e, 0x1d, 0xda, 0xc8, 0x6c, 0x03, - 0x6b, 0x4f, 0xdd, 0xba, 0x3d, 0x7f, 0xe4, 0x8b, 0xdb, 0xf3, 0x47, 0xfe, 0x7a, 0x7b, 0xfe, 0xc8, - 0x87, 0xfb, 0xf3, 0xca, 0xad, 0xfd, 0x79, 0xe5, 0x8b, 0xfd, 0x79, 0xe5, 0xef, 0xfb, 0xf3, 0xca, - 0x47, 0x5f, 0xcd, 0x1f, 0xb9, 0x3e, 0x2a, 0x31, 0xff, 0x15, 0x00, 0x00, 0xff, 0xff, 0x11, 0x54, - 0x28, 0xa2, 0x4f, 0x39, 0x00, 0x00, + // 3369 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe4, 0x5b, 0xdb, 0x6f, 0x1b, 0xc7, + 0xd5, 0xf7, 0x8a, 0xa4, 0x45, 0x1d, 0x59, 0x92, 0x35, 0x72, 0x64, 0x46, 0x49, 0x44, 0x67, 0x3f, + 0x7c, 0x89, 0xf3, 0x7d, 0x09, 0xf5, 0xc5, 0xf9, 0x9c, 0x26, 0x4e, 0xe2, 0x44, 0x94, 0x7c, 0x51, + 0x21, 0xc9, 0xcc, 0x90, 0x32, 0x1a, 0xe7, 0xd6, 0x15, 0x39, 0xa2, 0xd6, 0xde, 0x5b, 0x76, 0x67, + 0x15, 0x11, 0x41, 0xdb, 0x00, 0x45, 0xf3, 0x58, 0xb4, 0x2f, 0x45, 0x0a, 0xa4, 0x8f, 0x7d, 0xe8, + 0x4b, 0x9b, 0x3c, 0xb4, 0x69, 0xff, 0x82, 0xfa, 0xa1, 0x28, 0x52, 0xa0, 0x05, 0x8a, 0x22, 0x15, + 0x6a, 0x05, 0xcd, 0x3f, 0xd0, 0xe6, 0xc5, 0x4f, 0xc5, 0xcc, 0xce, 0xde, 0x77, 0x65, 0x93, 0xb2, + 0x89, 0x02, 0x7d, 0xe3, 0xce, 0x9c, 0xf3, 0x3b, 0x97, 0x39, 0x73, 0xe6, 0xcc, 0x85, 0xf0, 0xd2, + 0x8d, 0xe7, 0x9c, 0x9a, 0x6a, 0x2e, 0xdc, 0x70, 0x37, 0x89, 0x6d, 0x10, 0x4a, 0x9c, 0x05, 0xeb, + 0x46, 0x77, 0x41, 0xb1, 0x54, 0x67, 0x81, 0xec, 0x52, 0x62, 0x38, 0xaa, 0x69, 0x38, 0x0b, 0x3b, + 0x4f, 0x6f, 0x12, 0xaa, 0x3c, 0xbd, 0xd0, 0x25, 0x06, 0xb1, 0x15, 0x4a, 0x3a, 0x35, 0xcb, 0x36, + 0xa9, 0x89, 0x9e, 0xf2, 0xd8, 0x6b, 0x21, 0x7b, 0xcd, 0xba, 0xd1, 0xad, 0x31, 0xf6, 0x5a, 0xc8, + 0x5e, 0x13, 0xec, 0x73, 0x4f, 0x75, 0x55, 0xba, 0xed, 0x6e, 0xd6, 0xda, 0xa6, 0xbe, 0xd0, 0x35, + 0xbb, 0xe6, 0x02, 0x47, 0xd9, 0x74, 0xb7, 0xf8, 0x17, 0xff, 0xe0, 0xbf, 0x3c, 0xf4, 0xb9, 0xff, + 0x17, 0xca, 0x29, 0x96, 0xaa, 0x2b, 0xed, 0x6d, 0xd5, 0x20, 0x76, 0xcf, 0x57, 0x6f, 0xc1, 0x26, + 0x8e, 0xe9, 0xda, 0x6d, 0x92, 0xd4, 0xe9, 0x40, 0x2e, 0x67, 0x41, 0x27, 0x54, 0x59, 0xd8, 0x49, + 0x59, 0x32, 0xb7, 0x90, 0xc7, 0x65, 0xbb, 0x06, 0x55, 0xf5, 0xb4, 0x98, 0x67, 0xef, 0xc4, 0xe0, + 0xb4, 0xb7, 0x89, 0xae, 0xa4, 0xf8, 0x9e, 0xc9, 0xe3, 0x73, 0xa9, 0xaa, 0x2d, 0xa8, 0x06, 0x75, + 0xa8, 0x7d, 0x90, 0x4d, 0x0e, 0xb1, 0x77, 0x88, 0x1d, 0x1d, 0x25, 0x45, 0xb7, 0x34, 0x92, 0x65, + 0xd3, 0x93, 0xb9, 0x83, 0x9b, 0x41, 0x2d, 0xd7, 0x00, 0x16, 0x1b, 0x2b, 0x57, 0x89, 0xcd, 0xc6, + 0x0c, 0x9d, 0x82, 0xa2, 0xa1, 0xe8, 0xa4, 0x22, 0x9d, 0x92, 0x4e, 0x8f, 0xd5, 0x8f, 0xdd, 0xdc, + 0xab, 0x1e, 0xd9, 0xdf, 0xab, 0x16, 0xd7, 0x15, 0x9d, 0x60, 0xde, 0x23, 0xff, 0x58, 0x82, 0x07, + 0x97, 0x5c, 0x87, 0x9a, 0xfa, 0x1a, 0xa1, 0xb6, 0xda, 0x5e, 0x72, 0x6d, 0x9b, 0x18, 0xb4, 0x49, + 0x15, 0xea, 0x3a, 0x77, 0xe6, 0x47, 0xd7, 0xa0, 0xb4, 0xa3, 0x68, 0x2e, 0xa9, 0x8c, 0x9c, 0x92, + 0x4e, 0x8f, 0x9f, 0xa9, 0xd5, 0x44, 0x2c, 0x45, 0x1d, 0xe3, 0x47, 0x53, 0xcd, 0x1f, 0xed, 0xda, + 0xab, 0xae, 0x62, 0x50, 0x95, 0xf6, 0xea, 0x27, 0x04, 0xe4, 0x31, 0x21, 0xf7, 0x2a, 0xc3, 0xc2, + 0x1e, 0xa4, 0xfc, 0x7d, 0x09, 0x1e, 0xc9, 0xd5, 0x6d, 0x55, 0x75, 0x28, 0xd2, 0xa1, 0xa4, 0x52, + 0xa2, 0x3b, 0x15, 0xe9, 0x54, 0xe1, 0xf4, 0xf8, 0x99, 0xcb, 0xb5, 0xbe, 0x22, 0xb9, 0x96, 0x0b, + 0x5e, 0x9f, 0x10, 0x7a, 0x95, 0x56, 0x18, 0x3c, 0xf6, 0xa4, 0xc8, 0x3f, 0x94, 0x00, 0x45, 0x79, + 0x5a, 0x8a, 0xdd, 0x25, 0xf4, 0x2e, 0xbc, 0xf4, 0xda, 0xe1, 0xbc, 0x34, 0x23, 0x20, 0xc7, 0x3d, + 0x81, 0x31, 0x27, 0xbd, 0x2f, 0xc1, 0x6c, 0x5a, 0x27, 0xee, 0x9d, 0xad, 0xb8, 0x77, 0x16, 0x0f, + 0xe1, 0x1d, 0x0f, 0x35, 0xc7, 0x2d, 0xbf, 0x1c, 0x81, 0xb1, 0x65, 0x85, 0xe8, 0xa6, 0xd1, 0x24, + 0x14, 0x7d, 0x13, 0xca, 0x6c, 0x7a, 0x76, 0x14, 0xaa, 0x70, 0x8f, 0x8c, 0x9f, 0xf9, 0xbf, 0x83, + 0xcc, 0x75, 0x6a, 0x8c, 0xba, 0xb6, 0xf3, 0x74, 0xed, 0xca, 0xe6, 0x75, 0xd2, 0xa6, 0x6b, 0x84, + 0x2a, 0x75, 0x24, 0xe4, 0x40, 0xd8, 0x86, 0x03, 0x54, 0xf4, 0x16, 0x14, 0x1d, 0x8b, 0xb4, 0x85, + 0x33, 0x5f, 0xec, 0xd3, 0xac, 0x40, 0xd3, 0xa6, 0x45, 0xda, 0xe1, 0x68, 0xb1, 0x2f, 0xcc, 0x71, + 0xd1, 0x16, 0x1c, 0x75, 0x78, 0x18, 0x54, 0x0a, 0x5c, 0xc2, 0xf9, 0x81, 0x25, 0x78, 0xc1, 0x34, + 0x29, 0x64, 0x1c, 0xf5, 0xbe, 0xb1, 0x40, 0x97, 0x7f, 0x27, 0xc1, 0x44, 0x40, 0xcb, 0x47, 0xec, + 0x8d, 0x94, 0xef, 0x6a, 0x77, 0xe7, 0x3b, 0xc6, 0xcd, 0x3d, 0x77, 0x5c, 0xc8, 0x2a, 0xfb, 0x2d, + 0x11, 0xbf, 0xbd, 0xe9, 0xc7, 0xc3, 0x08, 0x8f, 0x87, 0xe7, 0x06, 0x35, 0x2b, 0x27, 0x0c, 0xbe, + 0x28, 0x44, 0xcc, 0x61, 0xee, 0x44, 0x6f, 0x42, 0xd9, 0x21, 0x1a, 0x69, 0x53, 0xd3, 0x16, 0xe6, + 0x3c, 0x73, 0x97, 0xe6, 0x28, 0x9b, 0x44, 0x6b, 0x0a, 0xd6, 0xfa, 0x31, 0x66, 0x8f, 0xff, 0x85, + 0x03, 0x48, 0xf4, 0x3a, 0x94, 0x29, 0xd1, 0x2d, 0x4d, 0xa1, 0xfe, 0xc4, 0x7a, 0x2a, 0xdf, 0x24, + 0x06, 0xdb, 0x30, 0x3b, 0x2d, 0xc1, 0xc0, 0x07, 0x3f, 0x70, 0x96, 0xdf, 0x8a, 0x03, 0x40, 0xf4, + 0x81, 0x04, 0x93, 0xae, 0xd5, 0x61, 0xa4, 0x94, 0x25, 0xd8, 0x6e, 0x4f, 0x44, 0xc3, 0xc5, 0x41, + 0xdd, 0xb6, 0x11, 0x43, 0xab, 0xcf, 0x0a, 0xe1, 0x93, 0xf1, 0x76, 0x9c, 0x90, 0x8a, 0x16, 0x61, + 0x4a, 0x57, 0x0d, 0x4c, 0x94, 0x4e, 0xaf, 0x49, 0xda, 0xa6, 0xd1, 0x71, 0x2a, 0xc5, 0x53, 0xd2, + 0xe9, 0x52, 0xfd, 0xa4, 0x00, 0x98, 0x5a, 0x8b, 0x77, 0xe3, 0x24, 0x3d, 0xfa, 0x3a, 0x20, 0xdf, + 0xae, 0x4b, 0xde, 0x7a, 0xa1, 0x9a, 0x46, 0xa5, 0x74, 0x4a, 0x3a, 0x5d, 0xa8, 0xcf, 0x09, 0x14, + 0xd4, 0x4a, 0x51, 0xe0, 0x0c, 0x2e, 0xf9, 0x9f, 0x45, 0x98, 0x4a, 0x04, 0x38, 0xba, 0x0a, 0xb3, + 0x6d, 0x2f, 0x7d, 0xae, 0xbb, 0xfa, 0x26, 0xb1, 0x9b, 0xed, 0x6d, 0xd2, 0x71, 0x35, 0xd2, 0xe1, + 0xa3, 0x5e, 0xaa, 0xcf, 0x0b, 0x19, 0xb3, 0x4b, 0x99, 0x54, 0x38, 0x87, 0x9b, 0xe9, 0x6d, 0xf0, + 0xa6, 0x35, 0xd5, 0x71, 0x02, 0xcc, 0x11, 0x8e, 0x19, 0xe8, 0xbd, 0x9e, 0xa2, 0xc0, 0x19, 0x5c, + 0x4c, 0xc7, 0x0e, 0x71, 0x54, 0x9b, 0x74, 0x92, 0x3a, 0x16, 0xe2, 0x3a, 0x2e, 0x67, 0x52, 0xe1, + 0x1c, 0x6e, 0x74, 0x16, 0xc6, 0x3d, 0x69, 0xdc, 0xe3, 0x62, 0x68, 0x82, 0x84, 0xbd, 0x1e, 0x76, + 0xe1, 0x28, 0x1d, 0x33, 0xcd, 0xdc, 0xe4, 0x55, 0x40, 0x27, 0x7f, 0x48, 0xae, 0xa4, 0x28, 0x70, + 0x06, 0x17, 0x33, 0xcd, 0x8b, 0x99, 0x94, 0x69, 0x47, 0xe3, 0xa6, 0x6d, 0x64, 0x52, 0xe1, 0x1c, + 0x6e, 0x16, 0x79, 0x9e, 0xca, 0x8b, 0x3b, 0x8a, 0xaa, 0x29, 0x9b, 0x1a, 0xa9, 0x8c, 0xc6, 0x23, + 0x6f, 0x3d, 0xde, 0x8d, 0x93, 0xf4, 0xe8, 0x12, 0x4c, 0x7b, 0x4d, 0x1b, 0x86, 0x12, 0x80, 0x94, + 0x39, 0xc8, 0x83, 0x02, 0x64, 0x7a, 0x3d, 0x49, 0x80, 0xd3, 0x3c, 0xf2, 0x5f, 0x24, 0x38, 0x99, + 0x33, 0x93, 0xd0, 0xcb, 0x50, 0xa4, 0x3d, 0xcb, 0x5f, 0x7f, 0xff, 0xd7, 0xcf, 0xe8, 0xad, 0x9e, + 0x45, 0x6e, 0xef, 0x55, 0x1f, 0xca, 0x61, 0x63, 0xdd, 0x98, 0x33, 0xa2, 0x6f, 0xc3, 0x84, 0x6d, + 0x6a, 0x9a, 0x6a, 0x74, 0x3d, 0x12, 0x91, 0x4d, 0x2e, 0xf4, 0x39, 0xd3, 0x71, 0x14, 0x23, 0xcc, + 0x96, 0xd3, 0xfb, 0x7b, 0xd5, 0x89, 0x58, 0x1f, 0x8e, 0x8b, 0x93, 0x7f, 0x3d, 0x02, 0xb0, 0x4c, + 0x2c, 0xcd, 0xec, 0xe9, 0xc4, 0x18, 0xc6, 0x0a, 0xfa, 0x76, 0x6c, 0x05, 0x7d, 0xa9, 0xdf, 0x8c, + 0x16, 0xa8, 0x9a, 0xbb, 0x84, 0x76, 0x13, 0x4b, 0xe8, 0xcb, 0x83, 0x8b, 0x38, 0x78, 0x0d, 0xbd, + 0x55, 0x80, 0x99, 0x90, 0x78, 0xc9, 0x34, 0x3a, 0x2a, 0x9f, 0x13, 0x2f, 0xc4, 0x62, 0xe2, 0xf1, + 0x44, 0x4c, 0x9c, 0xcc, 0x60, 0x89, 0xc4, 0xc3, 0xd5, 0x40, 0xfb, 0x11, 0xce, 0x7e, 0x3e, 0x2e, + 0xfc, 0xf6, 0x5e, 0xf5, 0xc0, 0xa2, 0xbc, 0x16, 0x60, 0xc6, 0x95, 0x45, 0x8f, 0xc1, 0x51, 0x9b, + 0x28, 0x8e, 0x69, 0xf0, 0x34, 0x31, 0x16, 0x1a, 0x85, 0x79, 0x2b, 0x16, 0xbd, 0xe8, 0x09, 0x18, + 0xd5, 0x89, 0xe3, 0x28, 0x5d, 0xc2, 0x33, 0xc2, 0x58, 0x7d, 0x4a, 0x10, 0x8e, 0xae, 0x79, 0xcd, + 0xd8, 0xef, 0x47, 0xd7, 0x61, 0x52, 0x53, 0x1c, 0x11, 0xda, 0x2d, 0x55, 0x27, 0x7c, 0xce, 0x8f, + 0x9f, 0xf9, 0x9f, 0xbb, 0x8b, 0x18, 0xc6, 0x11, 0xae, 0x44, 0xab, 0x31, 0x24, 0x9c, 0x40, 0x46, + 0x3b, 0x80, 0x58, 0x4b, 0xcb, 0x56, 0x0c, 0xc7, 0x73, 0x19, 0x93, 0x37, 0xda, 0xb7, 0xbc, 0x20, + 0xbf, 0xad, 0xa6, 0xd0, 0x70, 0x86, 0x04, 0xf9, 0xf7, 0x12, 0x4c, 0x86, 0x03, 0x36, 0x84, 0x42, + 0xe9, 0xad, 0x78, 0xa1, 0xf4, 0xfc, 0xc0, 0xc1, 0x9b, 0x53, 0x29, 0x7d, 0x58, 0x00, 0x14, 0x12, + 0xb1, 0xd4, 0xb0, 0xa9, 0xb4, 0x6f, 0xdc, 0xc5, 0x3e, 0xe2, 0xa7, 0x12, 0x20, 0x91, 0xac, 0x17, + 0x0d, 0xc3, 0xa4, 0x3c, 0xff, 0xfb, 0x6a, 0xbe, 0x36, 0xb0, 0x9a, 0xbe, 0x06, 0xb5, 0x8d, 0x14, + 0xf6, 0x05, 0x83, 0xda, 0xbd, 0x70, 0xc4, 0xd2, 0x04, 0x38, 0x43, 0x21, 0xf4, 0x0e, 0x80, 0x2d, + 0x30, 0x5b, 0xa6, 0x48, 0x01, 0x2f, 0x0d, 0x90, 0x4d, 0x19, 0xc0, 0x92, 0x69, 0x6c, 0xa9, 0xdd, + 0x30, 0xa1, 0xe1, 0x00, 0x18, 0x47, 0x84, 0xcc, 0x5d, 0x80, 0x93, 0x39, 0xda, 0xa3, 0xe3, 0x50, + 0xb8, 0x41, 0x7a, 0x9e, 0x5b, 0x31, 0xfb, 0x89, 0x4e, 0x44, 0xf7, 0x63, 0x63, 0x62, 0x2b, 0x75, + 0x6e, 0xe4, 0x39, 0x49, 0xfe, 0xb2, 0x14, 0x8d, 0x35, 0x5e, 0xc5, 0x9e, 0x86, 0xb2, 0x4d, 0x2c, + 0x4d, 0x6d, 0x2b, 0x8e, 0xa8, 0x67, 0x78, 0x41, 0x8a, 0x45, 0x1b, 0x0e, 0x7a, 0x63, 0xf5, 0xee, + 0xc8, 0xfd, 0xad, 0x77, 0x0b, 0xf7, 0xba, 0xde, 0x35, 0xa1, 0xec, 0xf8, 0x85, 0x6e, 0x91, 0x83, + 0x2f, 0x1e, 0x22, 0x67, 0x8b, 0x1a, 0x37, 0x10, 0x18, 0x54, 0xb7, 0x81, 0x90, 0xac, 0xba, 0xb6, + 0xd4, 0x67, 0x5d, 0xbb, 0x0a, 0x27, 0x6c, 0xb2, 0xa3, 0x32, 0x35, 0x2e, 0xab, 0x0e, 0x35, 0xed, + 0xde, 0xaa, 0xaa, 0xab, 0x54, 0x94, 0x3d, 0x95, 0xfd, 0xbd, 0xea, 0x09, 0x9c, 0xd1, 0x8f, 0x33, + 0xb9, 0x58, 0x76, 0xb6, 0x14, 0xd7, 0x21, 0x1d, 0x9e, 0xd2, 0xca, 0x61, 0x76, 0x6e, 0xf0, 0x56, + 0x2c, 0x7a, 0x91, 0x1e, 0x0b, 0xee, 0xf2, 0xbd, 0x08, 0xee, 0xc9, 0xfc, 0xc0, 0x46, 0x1b, 0x70, + 0xd2, 0xb2, 0xcd, 0xae, 0x4d, 0x1c, 0x67, 0x99, 0x28, 0x1d, 0x4d, 0x35, 0x88, 0xef, 0xaf, 0x31, + 0x6e, 0xe7, 0x43, 0xfb, 0x7b, 0xd5, 0x93, 0x8d, 0x6c, 0x12, 0x9c, 0xc7, 0x2b, 0x7f, 0x54, 0x84, + 0xe3, 0xc9, 0x55, 0x36, 0xa7, 0x2a, 0x95, 0x06, 0xaa, 0x4a, 0x9f, 0x8c, 0x4c, 0x1b, 0xaf, 0x64, + 0x0f, 0xa2, 0x21, 0x63, 0xea, 0x2c, 0xc2, 0x94, 0xc8, 0x23, 0x7e, 0xa7, 0xa8, 0xcb, 0x83, 0x68, + 0xd8, 0x88, 0x77, 0xe3, 0x24, 0x3d, 0xab, 0x35, 0xc3, 0x12, 0xd2, 0x07, 0x29, 0xc6, 0x6b, 0xcd, + 0xc5, 0x24, 0x01, 0x4e, 0xf3, 0xa0, 0x35, 0x98, 0x71, 0x8d, 0x34, 0x94, 0x17, 0x9d, 0x0f, 0x09, + 0xa8, 0x99, 0x8d, 0x34, 0x09, 0xce, 0xe2, 0x43, 0x3b, 0x00, 0x6d, 0xbf, 0x20, 0x70, 0x2a, 0x47, + 0x79, 0xae, 0xae, 0x0f, 0x3c, 0xb7, 0x82, 0xda, 0x22, 0xcc, 0x88, 0x41, 0x93, 0x83, 0x23, 0x92, + 0xd0, 0x0b, 0x30, 0x61, 0xf3, 0x8d, 0x87, 0x6f, 0x80, 0x57, 0xbc, 0x3f, 0x20, 0xd8, 0x26, 0x70, + 0xb4, 0x13, 0xc7, 0x69, 0xe5, 0x3f, 0x48, 0xd1, 0x25, 0x2a, 0x28, 0xb5, 0xcf, 0xc5, 0xca, 0xaa, + 0xc7, 0x12, 0x65, 0xd5, 0x6c, 0x9a, 0x23, 0x52, 0x55, 0x7d, 0x27, 0xbb, 0xca, 0xbe, 0x78, 0xa8, + 0x2a, 0x3b, 0x5c, 0x6a, 0xef, 0x5c, 0x66, 0x7f, 0x22, 0xc1, 0xec, 0xc5, 0xe6, 0x25, 0xdb, 0x74, + 0x2d, 0x5f, 0xbd, 0x2b, 0x96, 0xe7, 0xab, 0xaf, 0x41, 0xd1, 0x76, 0x35, 0xdf, 0xae, 0xff, 0xf2, + 0xed, 0xc2, 0xae, 0xc6, 0xec, 0x9a, 0x49, 0x70, 0x79, 0x46, 0x31, 0x06, 0xf4, 0x16, 0x1c, 0xb5, + 0x15, 0xa3, 0x4b, 0xfc, 0x45, 0xf8, 0xd9, 0x3e, 0xad, 0x59, 0x59, 0xc6, 0x8c, 0x3d, 0x52, 0x0a, + 0x72, 0x34, 0x2c, 0x50, 0xe5, 0x9f, 0x48, 0x30, 0x75, 0xb9, 0xd5, 0x6a, 0xac, 0x18, 0x7c, 0x16, + 0x37, 0x14, 0xba, 0xcd, 0xea, 0x04, 0x4b, 0xa1, 0xdb, 0xc9, 0x3a, 0x81, 0xf5, 0x61, 0xde, 0x83, + 0xb6, 0x61, 0x94, 0x65, 0x0f, 0x62, 0x74, 0x06, 0x2c, 0xf1, 0x85, 0xb8, 0xba, 0x07, 0x12, 0xd6, + 0x9f, 0xa2, 0x01, 0xfb, 0xf0, 0xf2, 0x7b, 0x70, 0x22, 0xa2, 0x1e, 0xf3, 0x17, 0x3f, 0x9d, 0x44, + 0x6d, 0x28, 0x31, 0x4d, 0xfc, 0xb3, 0xc7, 0x7e, 0x8f, 0xd0, 0x12, 0x26, 0x87, 0x75, 0x14, 0xfb, + 0x72, 0xb0, 0x87, 0x2d, 0xaf, 0xc1, 0xc4, 0x65, 0xd3, 0xa1, 0x0d, 0xd3, 0xa6, 0xdc, 0x6d, 0xe8, + 0x11, 0x28, 0xe8, 0xaa, 0x21, 0x56, 0xe9, 0x71, 0xc1, 0x53, 0x60, 0xeb, 0x08, 0x6b, 0xe7, 0xdd, + 0xca, 0xae, 0xc8, 0x46, 0x61, 0xb7, 0xb2, 0x8b, 0x59, 0xbb, 0x7c, 0x09, 0x46, 0xc5, 0x70, 0x44, + 0x81, 0x0a, 0x07, 0x03, 0x15, 0x32, 0x80, 0x7e, 0x31, 0x02, 0xa3, 0x42, 0xfb, 0x21, 0x6c, 0xe6, + 0xde, 0x88, 0x6d, 0xe6, 0xce, 0x0d, 0x36, 0xd2, 0xb9, 0x3b, 0xb9, 0x4e, 0x62, 0x27, 0xf7, 0xe2, + 0x80, 0xf8, 0x07, 0x6f, 0xe3, 0x3e, 0x96, 0x60, 0x32, 0x1e, 0x73, 0xe8, 0x2c, 0x8c, 0xb3, 0x35, + 0x45, 0x6d, 0x93, 0xf5, 0xb0, 0x28, 0x0e, 0x0e, 0x56, 0x9a, 0x61, 0x17, 0x8e, 0xd2, 0xa1, 0x6e, + 0xc0, 0xc6, 0xc2, 0x42, 0x38, 0x25, 0xdf, 0xe5, 0x2e, 0x55, 0xb5, 0x9a, 0x77, 0x5f, 0x53, 0x5b, + 0x31, 0xe8, 0x15, 0xbb, 0x49, 0x6d, 0xd5, 0xe8, 0xa6, 0x04, 0xf1, 0x18, 0x8b, 0x22, 0xcb, 0x37, + 0x25, 0x18, 0x17, 0x2a, 0x0f, 0x61, 0x4b, 0xf2, 0x7a, 0x7c, 0x4b, 0xf2, 0xec, 0x80, 0xf3, 0x39, + 0x7b, 0x3f, 0xf2, 0x69, 0x68, 0x0a, 0x9b, 0xc1, 0x2c, 0xc1, 0x6c, 0x9b, 0x0e, 0x4d, 0x26, 0x18, + 0x36, 0xd7, 0x30, 0xef, 0x41, 0xdf, 0x93, 0xe0, 0xb8, 0x9a, 0x98, 0xf3, 0xc2, 0xd7, 0x2f, 0x0f, + 0xa6, 0x5a, 0x00, 0x53, 0xaf, 0x08, 0x79, 0xc7, 0x93, 0x3d, 0x38, 0x25, 0x52, 0x76, 0x21, 0x45, + 0x85, 0x14, 0x28, 0x6e, 0x53, 0x6a, 0x89, 0x41, 0x58, 0x1a, 0x3c, 0xf3, 0x84, 0x2a, 0x95, 0xb9, + 0xf9, 0xad, 0x56, 0x03, 0x73, 0x68, 0xf9, 0xe7, 0x23, 0x81, 0xc3, 0x9a, 0xde, 0x24, 0x09, 0xf2, + 0xad, 0x74, 0x2f, 0xf2, 0xed, 0x78, 0x56, 0xae, 0x45, 0xdf, 0x80, 0x02, 0xd5, 0x06, 0xdd, 0x94, + 0x0a, 0x09, 0xad, 0xd5, 0x66, 0x98, 0xb0, 0x5a, 0xab, 0x4d, 0xcc, 0x20, 0xd1, 0xdb, 0x50, 0x62, + 0xab, 0x19, 0x9b, 0xe3, 0x85, 0xc1, 0x73, 0x08, 0xf3, 0x57, 0x18, 0x61, 0xec, 0xcb, 0xc1, 0x1e, + 0xae, 0xfc, 0x1e, 0x4c, 0xc4, 0x12, 0x01, 0xba, 0x0e, 0xc7, 0x34, 0x53, 0xe9, 0xd4, 0x15, 0x4d, + 0x31, 0xda, 0xc4, 0x4e, 0xa6, 0xc6, 0xec, 0xfd, 0xcc, 0x6a, 0x84, 0x43, 0x24, 0x94, 0xe0, 0x02, + 0x31, 0xda, 0x87, 0x63, 0xd8, 0xb2, 0x02, 0x10, 0x5a, 0x8f, 0xaa, 0x50, 0x62, 0x21, 0xec, 0xad, + 0x4c, 0x63, 0xf5, 0x31, 0xa6, 0x2b, 0x8b, 0x6c, 0x07, 0x7b, 0xed, 0xe8, 0x0c, 0x80, 0x43, 0xda, + 0x36, 0xa1, 0x3c, 0xef, 0x78, 0x27, 0x40, 0x41, 0x06, 0x6e, 0x06, 0x3d, 0x38, 0x42, 0x25, 0xff, + 0x49, 0x82, 0x89, 0x75, 0x42, 0xdf, 0x35, 0xed, 0x1b, 0x0d, 0x53, 0x53, 0xdb, 0xbd, 0x21, 0xe4, + 0xfd, 0xcd, 0x58, 0xde, 0x7f, 0xa5, 0xcf, 0x31, 0x8b, 0x69, 0x9b, 0x97, 0xfd, 0xe5, 0xbf, 0x4b, + 0x50, 0x89, 0x51, 0x46, 0xd3, 0x04, 0x81, 0x92, 0x65, 0xda, 0xd4, 0x5f, 0xe3, 0x0f, 0xa5, 0x01, + 0x4b, 0xa9, 0x91, 0x55, 0x9e, 0xc1, 0x62, 0x0f, 0x9d, 0xd9, 0xb9, 0x65, 0x9b, 0xba, 0x88, 0xfb, + 0xc3, 0x49, 0x21, 0xc4, 0x0e, 0xed, 0xbc, 0x68, 0x9b, 0x3a, 0xe6, 0xd8, 0xf2, 0x1f, 0x25, 0x98, + 0x8e, 0x51, 0x0e, 0x21, 0xa5, 0x2b, 0xf1, 0x94, 0xfe, 0xe2, 0x61, 0x0c, 0xcb, 0x49, 0xec, 0x5f, + 0x25, 0xcd, 0x62, 0x0e, 0x40, 0x5b, 0x30, 0x6e, 0x99, 0x9d, 0xe6, 0x3d, 0xb8, 0x99, 0x9b, 0x62, + 0x2b, 0x64, 0x23, 0xc4, 0xc2, 0x51, 0x60, 0xb4, 0x0b, 0xd3, 0x86, 0xa2, 0x13, 0xc7, 0x52, 0xda, + 0xa4, 0x79, 0x0f, 0xce, 0x45, 0x1e, 0xe0, 0xb7, 0x05, 0x49, 0x44, 0x9c, 0x16, 0x22, 0xff, 0x2a, + 0x65, 0xb7, 0x69, 0x53, 0xf4, 0x2a, 0x94, 0xf9, 0x23, 0x89, 0xb6, 0xa9, 0x89, 0xa5, 0xed, 0x2c, + 0x1b, 0x9a, 0x86, 0x68, 0xbb, 0xbd, 0x57, 0xfd, 0xef, 0x03, 0x8f, 0x75, 0x7d, 0x42, 0x1c, 0xc0, + 0xa0, 0x75, 0x28, 0x5a, 0x87, 0x29, 0x33, 0xf8, 0xc2, 0xc2, 0x6b, 0x0b, 0x8e, 0x23, 0xff, 0x23, + 0xa9, 0x38, 0x5f, 0x5e, 0xae, 0xdf, 0xb3, 0x01, 0x0b, 0xca, 0x9a, 0xdc, 0x41, 0xb3, 0x61, 0x54, + 0xac, 0xb2, 0x22, 0x2e, 0x2f, 0x1d, 0x26, 0x2e, 0xa3, 0x2b, 0x43, 0xb0, 0x89, 0xf0, 0x1b, 0x7d, + 0x41, 0xf2, 0x5f, 0x25, 0x98, 0xe6, 0x0a, 0xb5, 0x5d, 0x5b, 0xa5, 0xbd, 0xa1, 0x65, 0xd0, 0xad, + 0x58, 0x06, 0x5d, 0xee, 0xd3, 0xd0, 0x94, 0xc6, 0xb9, 0x59, 0xf4, 0x73, 0x09, 0x1e, 0x48, 0x51, + 0x0f, 0x21, 0xc3, 0x90, 0x78, 0x86, 0x79, 0xe5, 0xb0, 0x06, 0xe6, 0x64, 0x99, 0x9b, 0x90, 0x61, + 0x1e, 0x0f, 0xdc, 0x33, 0x00, 0x96, 0xad, 0xee, 0xa8, 0x1a, 0xe9, 0x8a, 0xcb, 0xe0, 0x72, 0x38, + 0x24, 0x8d, 0xa0, 0x07, 0x47, 0xa8, 0xd0, 0xb7, 0x60, 0xb6, 0x43, 0xb6, 0x14, 0x57, 0xa3, 0x8b, + 0x9d, 0xce, 0x92, 0x62, 0x29, 0x9b, 0xaa, 0xa6, 0x52, 0x55, 0xec, 0xb0, 0xc7, 0xea, 0x17, 0xbc, + 0x4b, 0xda, 0x2c, 0x8a, 0xdb, 0x7b, 0xd5, 0xc7, 0x0f, 0xbe, 0x98, 0xf1, 0x89, 0x7b, 0x38, 0x47, + 0x08, 0xfa, 0xae, 0x04, 0x15, 0x9b, 0xbc, 0xe3, 0xaa, 0x36, 0xe9, 0x2c, 0xdb, 0xa6, 0x15, 0xd3, + 0xa0, 0xc0, 0x35, 0xb8, 0xb4, 0xbf, 0x57, 0xad, 0xe0, 0x1c, 0x9a, 0x7e, 0x74, 0xc8, 0x15, 0x84, + 0x28, 0xcc, 0x28, 0x9a, 0x66, 0xbe, 0x4b, 0xe2, 0x1e, 0x28, 0x72, 0xf9, 0xf5, 0xfd, 0xbd, 0xea, + 0xcc, 0x62, 0xba, 0xbb, 0x1f, 0xd1, 0x59, 0xf0, 0x68, 0x01, 0x46, 0x77, 0x4c, 0xcd, 0xd5, 0x89, + 0x53, 0x29, 0x71, 0x49, 0x2c, 0xe3, 0x8e, 0x5e, 0xf5, 0x9a, 0x6e, 0xef, 0x55, 0x8f, 0x5e, 0x6c, + 0xf2, 0xa3, 0x0f, 0x9f, 0x8a, 0xed, 0xd1, 0x58, 0xcd, 0x24, 0xa6, 0x3c, 0x3f, 0x77, 0x2d, 0x87, + 0x39, 0xe6, 0x72, 0xd8, 0x85, 0xa3, 0x74, 0x48, 0x87, 0xb1, 0x6d, 0xb1, 0x6f, 0x77, 0x2a, 0xa3, + 0x03, 0xad, 0x7e, 0xb1, 0x7d, 0x7f, 0x7d, 0x5a, 0x88, 0x1c, 0xf3, 0x9b, 0x1d, 0x1c, 0x4a, 0x40, + 0x4f, 0xc0, 0x28, 0xff, 0x58, 0x59, 0xe6, 0xa7, 0xb5, 0xe5, 0x30, 0x13, 0x5d, 0xf6, 0x9a, 0xb1, + 0xdf, 0xef, 0x93, 0xae, 0x34, 0x96, 0xf8, 0xe1, 0x6a, 0x82, 0x74, 0xa5, 0xb1, 0x84, 0xfd, 0x7e, + 0x64, 0xc1, 0xa8, 0x43, 0x56, 0x55, 0xc3, 0xdd, 0xad, 0xc0, 0x40, 0xd7, 0xc5, 0xcd, 0x0b, 0x9c, + 0x3b, 0x71, 0x14, 0x15, 0x4a, 0x14, 0xfd, 0xd8, 0x17, 0x83, 0x76, 0x61, 0xcc, 0x76, 0x8d, 0x45, + 0x67, 0xc3, 0x21, 0x76, 0x65, 0x9c, 0xcb, 0xec, 0x37, 0x39, 0x63, 0x9f, 0x3f, 0x29, 0x35, 0xf0, + 0x60, 0x40, 0x81, 0x43, 0x61, 0xe8, 0x23, 0x09, 0x90, 0xe3, 0x5a, 0x96, 0x46, 0x74, 0x62, 0x50, + 0x45, 0xe3, 0xa7, 0x61, 0x4e, 0xe5, 0x18, 0xd7, 0xa1, 0xd1, 0xaf, 0xdd, 0x29, 0xa0, 0xa4, 0x32, + 0xc1, 0x51, 0x73, 0x9a, 0x14, 0x67, 0xe8, 0xc1, 0x86, 0x62, 0xcb, 0xe1, 0xbf, 0x2b, 0x13, 0x03, + 0x0d, 0x45, 0xf6, 0xa9, 0x60, 0x38, 0x14, 0xa2, 0x1f, 0xfb, 0x62, 0xd0, 0x55, 0x98, 0xb5, 0x89, + 0xd2, 0xb9, 0x62, 0x68, 0x3d, 0x6c, 0x9a, 0xf4, 0xa2, 0xaa, 0x11, 0xa7, 0xe7, 0x50, 0xa2, 0x57, + 0x26, 0x79, 0xd8, 0x04, 0x4f, 0x2e, 0x70, 0x26, 0x15, 0xce, 0xe1, 0xe6, 0x2f, 0x01, 0xc4, 0x19, + 0xec, 0x70, 0xde, 0xd2, 0x1d, 0xee, 0x25, 0x40, 0xa8, 0xea, 0x7d, 0x7b, 0x09, 0x10, 0x11, 0x71, + 0xf0, 0x11, 0xd2, 0x57, 0x23, 0x30, 0x13, 0x12, 0xdf, 0xf5, 0x4b, 0x80, 0x0c, 0x96, 0x21, 0xbc, + 0x04, 0xc8, 0xbe, 0x4a, 0x2f, 0xdc, 0xef, 0xab, 0xf4, 0xfb, 0xf0, 0x02, 0x81, 0xdf, 0xce, 0x87, + 0x4e, 0xfc, 0xf7, 0xbf, 0x9d, 0x0f, 0x75, 0xcd, 0x29, 0x67, 0x7e, 0x33, 0x12, 0x35, 0xe8, 0x3f, + 0xe8, 0x0a, 0xf8, 0xf0, 0x2f, 0x0d, 0xe5, 0xcf, 0x0b, 0x70, 0x3c, 0x39, 0x63, 0x63, 0x37, 0x81, + 0xd2, 0x1d, 0x6f, 0x02, 0x1b, 0x70, 0x62, 0xcb, 0xd5, 0xb4, 0x1e, 0x77, 0x48, 0xe4, 0x3a, 0xd0, + 0x3b, 0xb5, 0x7f, 0x58, 0x70, 0x9e, 0xb8, 0x98, 0x41, 0x83, 0x33, 0x39, 0x73, 0x6e, 0x35, 0x0b, + 0x03, 0xdd, 0x6a, 0xa6, 0x2e, 0xd5, 0x8a, 0x77, 0x7f, 0xa9, 0x96, 0x7d, 0x43, 0x59, 0x1a, 0xe0, + 0x86, 0xf2, 0x5e, 0x5c, 0x29, 0x66, 0x24, 0xbe, 0x3b, 0x5d, 0x29, 0xca, 0x0f, 0xc3, 0x9c, 0x60, + 0x63, 0xdf, 0x4b, 0xa6, 0x41, 0x6d, 0x53, 0xd3, 0x88, 0xbd, 0xec, 0xea, 0x7a, 0x4f, 0x3e, 0x0f, + 0x93, 0xf1, 0x7b, 0x6d, 0x6f, 0xe4, 0xbd, 0xab, 0x76, 0x71, 0x97, 0x12, 0x19, 0x79, 0xaf, 0x1d, + 0x07, 0x14, 0xf2, 0x07, 0x12, 0xcc, 0x66, 0xbf, 0xa1, 0x43, 0x1a, 0x4c, 0xea, 0xca, 0x6e, 0xf4, + 0x11, 0xa1, 0x34, 0xe0, 0x8e, 0x1b, 0xed, 0xef, 0x55, 0x27, 0xd7, 0x62, 0x58, 0x38, 0x81, 0x2d, + 0x7f, 0x21, 0xc1, 0xc9, 0x9c, 0x6b, 0xc6, 0xe1, 0x6a, 0x82, 0xae, 0x41, 0x59, 0x57, 0x76, 0x9b, + 0xae, 0xdd, 0x25, 0x03, 0x9f, 0x31, 0xf0, 0x5c, 0xb2, 0x26, 0x50, 0x70, 0x80, 0x27, 0x7f, 0x22, + 0x41, 0x25, 0xaf, 0x1e, 0x44, 0x67, 0x63, 0x17, 0xa2, 0x8f, 0x26, 0x2e, 0x44, 0xa7, 0x53, 0x7c, + 0x43, 0xba, 0x0e, 0xfd, 0x54, 0x82, 0xd9, 0xec, 0xba, 0x19, 0x3d, 0x13, 0xd3, 0xb8, 0x9a, 0xd0, + 0x78, 0x2a, 0xc1, 0x25, 0xf4, 0xdd, 0x86, 0x49, 0x51, 0x5d, 0x0b, 0x18, 0xe1, 0xe5, 0x27, 0x0f, + 0xce, 0xaa, 0x02, 0xcc, 0xaf, 0x13, 0xf9, 0x48, 0xc6, 0xdb, 0x70, 0x02, 0x57, 0xfe, 0xd9, 0x08, + 0x94, 0x9a, 0x6d, 0x45, 0x23, 0x43, 0x28, 0xea, 0xae, 0xc5, 0x8a, 0xba, 0x7e, 0xdf, 0xf9, 0x73, + 0x2d, 0x73, 0xeb, 0xb9, 0xcd, 0x44, 0x3d, 0x77, 0x6e, 0x20, 0xf4, 0x83, 0x4b, 0xb9, 0xe7, 0x61, + 0x2c, 0x50, 0xa2, 0xbf, 0xd5, 0x43, 0xfe, 0x78, 0x04, 0xc6, 0x23, 0x22, 0xfa, 0x5c, 0x7b, 0x76, + 0x62, 0xab, 0xf7, 0x20, 0x7f, 0x29, 0x8a, 0xc8, 0xae, 0xf9, 0xeb, 0xb7, 0xf7, 0x86, 0x2e, 0x7c, + 0x0b, 0x95, 0x5e, 0xd6, 0xcf, 0xc3, 0x24, 0xe5, 0xff, 0xb0, 0x09, 0xce, 0xf8, 0x0a, 0x3c, 0x8a, + 0x83, 0x97, 0x99, 0xad, 0x58, 0x2f, 0x4e, 0x50, 0xcf, 0xbd, 0x00, 0x13, 0x31, 0x61, 0x7d, 0x3d, + 0x79, 0xfb, 0xad, 0x04, 0x8f, 0xde, 0x71, 0x4f, 0x86, 0xea, 0xb1, 0xe9, 0x55, 0x4b, 0x4c, 0xaf, + 0xf9, 0x7c, 0x80, 0x21, 0x3e, 0x96, 0xf8, 0xd1, 0x08, 0xa0, 0xd6, 0xb6, 0x6a, 0x77, 0x1a, 0x8a, + 0x4d, 0x7b, 0x58, 0xfc, 0x8f, 0x6a, 0x08, 0x13, 0xee, 0x2c, 0x8c, 0x77, 0x88, 0xd3, 0xb6, 0x55, + 0xee, 0x2c, 0xb1, 0x57, 0x08, 0xce, 0x41, 0x96, 0xc3, 0x2e, 0x1c, 0xa5, 0x43, 0x5d, 0x28, 0xef, + 0x78, 0xff, 0xd4, 0xf3, 0x6f, 0xde, 0xfa, 0x2d, 0x66, 0xc3, 0xff, 0xfa, 0x85, 0xf1, 0x25, 0x1a, + 0x1c, 0x1c, 0x80, 0xcb, 0x1f, 0x4a, 0x30, 0x9b, 0x76, 0xcc, 0x32, 0x53, 0xfd, 0xfe, 0x3b, 0xe7, + 0x61, 0x28, 0x72, 0x74, 0xe6, 0x95, 0x63, 0xde, 0x89, 0x37, 0x93, 0x8c, 0x79, 0xab, 0xfc, 0xa5, + 0x04, 0x73, 0xd9, 0xaa, 0x0d, 0x61, 0x2b, 0x71, 0x3d, 0xbe, 0x95, 0xe8, 0xf7, 0xd8, 0x20, 0x5b, + 0xef, 0x9c, 0x6d, 0xc5, 0x5e, 0xe6, 0x18, 0x0c, 0xc1, 0xc8, 0xad, 0xb8, 0x91, 0x8b, 0x87, 0x36, + 0x32, 0xdb, 0xc0, 0xfa, 0x13, 0x37, 0x6f, 0xcd, 0x1f, 0xf9, 0xec, 0xd6, 0xfc, 0x91, 0x3f, 0xdf, + 0x9a, 0x3f, 0xf2, 0xfe, 0xfe, 0xbc, 0x74, 0x73, 0x7f, 0x5e, 0xfa, 0x6c, 0x7f, 0x5e, 0xfa, 0xdb, + 0xfe, 0xbc, 0xf4, 0x83, 0x2f, 0xe6, 0x8f, 0x5c, 0x1b, 0x15, 0x98, 0xff, 0x0a, 0x00, 0x00, 0xff, + 0xff, 0x56, 0x18, 0xbd, 0xf5, 0xb1, 0x3c, 0x00, 0x00, } diff --git a/pkg/apis/extensions/v1beta1/generated.proto b/pkg/apis/extensions/v1beta1/generated.proto index 1e2ea2b55e4..93b7a57b845 100644 --- a/pkg/apis/extensions/v1beta1/generated.proto +++ b/pkg/apis/extensions/v1beta1/generated.proto @@ -111,6 +111,22 @@ message DaemonSetSpec { // selector is specified). // More info: http://kubernetes.io/docs/user-guide/replication-controller#pod-template optional k8s.io.kubernetes.pkg.api.v1.PodTemplateSpec template = 2; + + // UpdateStrategy to replace existing DaemonSet pods with new pods. + // +optional + optional DaemonSetUpdateStrategy updateStrategy = 3; + + // MinReadySeconds 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). + // +optional + optional int32 minReadySeconds = 4; + + // 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; } // DaemonSetStatus represents the current status of a daemon set. @@ -137,6 +153,39 @@ message DaemonSetStatus { // ObservedGeneration is the most recent generation observed by the daemon set controller. // +optional optional int64 observedGeneration = 5; + + // UpdatedNumberScheduled is the total number of nodes that are running updated + // daemon pod + // +optional + optional int32 updatedNumberScheduled = 6; + + // NumberAvailable is 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 minReadySeconds) + // +optional + optional int32 numberAvailable = 7; + + // NumberUnavailable is 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 minReadySeconds) + // +optional + optional int32 numberUnavailable = 8; +} + +message DaemonSetUpdateStrategy { + // Type of daemon set update. Can be "RollingUpdate" or "OnDelete". + // Default is OnDelete. + // +optional + optional string type = 1; + + // Rolling update config params. Present only if DaemonSetUpdateStrategy = + // RollingUpdate. + // --- + // TODO: Update this to follow our convention for oneOf, whatever we decide it + // to be. Same as DeploymentStrategy.RollingUpdate. + // See https://github.com/kubernetes/kubernetes/issues/35345 + // +optional + optional RollingUpdateDaemonSet rollingUpdate = 2; } // Deployment enables declarative updates for Pods and ReplicaSets. @@ -784,6 +833,25 @@ message RollbackConfig { optional int64 revision = 1; } +// Spec to control the desired behavior of daemon set rolling update. +message RollingUpdateDaemonSet { + // The maximum number of DaemonSet pods that can be unavailable during the + // update. Value can be an absolute number (ex: 5) or a percentage of total + // number of DaemonSet pods at the start of the update (ex: 10%). Absolute + // number is calculated from percentage by rounding up. + // This cannot be 0. + // Default value is 1. + // Example: when this is set to 30%, 30% of the currently running DaemonSet + // pods can be stopped for an update at any given time. The update starts + // by stopping at most 30% of the currently running DaemonSet pods and then + // brings up new DaemonSet pods in their place. Once the new pods are ready, + // it then proceeds onto other DaemonSet pods, thus ensuring that at least + // 70% of original number of DaemonSet pods are available at all times + // during the update. + // +optional + optional k8s.io.apimachinery.pkg.util.intstr.IntOrString maxUnavailable = 1; +} + // Spec to control the desired behavior of rolling update. message RollingUpdateDeployment { // The maximum number of pods that can be unavailable during the update. diff --git a/pkg/apis/extensions/v1beta1/types.generated.go b/pkg/apis/extensions/v1beta1/types.generated.go index 698ea412510..fc147e0ca0b 100644 --- a/pkg/apis/extensions/v1beta1/types.generated.go +++ b/pkg/apis/extensions/v1beta1/types.generated.go @@ -7008,7 +7008,7 @@ func (x *DeploymentList) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) } -func (x *DaemonSetSpec) CodecEncodeSelf(e *codec1978.Encoder) { +func (x *DaemonSetUpdateStrategy) CodecEncodeSelf(e *codec1978.Encoder) { var h codecSelfer1234 z, r := codec1978.GenHelperEncoder(e) _, _, _ = h, z, r @@ -7025,10 +7025,465 @@ func (x *DaemonSetSpec) CodecEncodeSelf(e *codec1978.Encoder) { var yyq2 [2]bool _, _, _ = yysep2, yyq2, yy2arr2 const yyr2 bool = false - yyq2[0] = x.Selector != nil + yyq2[0] = x.Type != "" + yyq2[1] = x.RollingUpdate != nil var yynn2 int if yyr2 || yy2arr2 { r.EncodeArrayStart(2) + } else { + yynn2 = 0 + for _, b := range yyq2 { + if b { + yynn2++ + } + } + r.EncodeMapStart(yynn2) + yynn2 = 0 + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[0] { + x.Type.CodecEncodeSelf(e) + } else { + r.EncodeString(codecSelferC_UTF81234, "") + } + } else { + if yyq2[0] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("type")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + x.Type.CodecEncodeSelf(e) + } + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[1] { + if x.RollingUpdate == nil { + r.EncodeNil() + } else { + x.RollingUpdate.CodecEncodeSelf(e) + } + } else { + r.EncodeNil() + } + } else { + if yyq2[1] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("rollingUpdate")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + if x.RollingUpdate == nil { + r.EncodeNil() + } else { + x.RollingUpdate.CodecEncodeSelf(e) + } + } + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayEnd1234) + } else { + z.EncSendContainerState(codecSelfer_containerMapEnd1234) + } + } + } +} + +func (x *DaemonSetUpdateStrategy) CodecDecodeSelf(d *codec1978.Decoder) { + var h codecSelfer1234 + z, r := codec1978.GenHelperDecoder(d) + _, _, _ = h, z, r + yym1 := z.DecBinary() + _ = yym1 + if false { + } else if z.HasExtensions() && z.DecExt(x) { + } else { + yyct2 := r.ContainerType() + if yyct2 == codecSelferValueTypeMap1234 { + yyl2 := r.ReadMapStart() + if yyl2 == 0 { + z.DecSendContainerState(codecSelfer_containerMapEnd1234) + } else { + x.codecDecodeSelfFromMap(yyl2, d) + } + } else if yyct2 == codecSelferValueTypeArray1234 { + yyl2 := r.ReadArrayStart() + if yyl2 == 0 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + } else { + x.codecDecodeSelfFromArray(yyl2, d) + } + } else { + panic(codecSelferOnlyMapOrArrayEncodeToStructErr1234) + } + } +} + +func (x *DaemonSetUpdateStrategy) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { + var h codecSelfer1234 + z, r := codec1978.GenHelperDecoder(d) + _, _, _ = h, z, r + var yys3Slc = z.DecScratchBuffer() // default slice to decode into + _ = yys3Slc + var yyhl3 bool = l >= 0 + for yyj3 := 0; ; yyj3++ { + if yyhl3 { + if yyj3 >= l { + break + } + } else { + if r.CheckBreak() { + break + } + } + z.DecSendContainerState(codecSelfer_containerMapKey1234) + yys3Slc = r.DecodeBytes(yys3Slc, true, true) + yys3 := string(yys3Slc) + z.DecSendContainerState(codecSelfer_containerMapValue1234) + switch yys3 { + case "type": + if r.TryDecodeAsNil() { + x.Type = "" + } else { + yyv4 := &x.Type + yyv4.CodecDecodeSelf(d) + } + case "rollingUpdate": + if r.TryDecodeAsNil() { + if x.RollingUpdate != nil { + x.RollingUpdate = nil + } + } else { + if x.RollingUpdate == nil { + x.RollingUpdate = new(RollingUpdateDaemonSet) + } + x.RollingUpdate.CodecDecodeSelf(d) + } + default: + z.DecStructFieldNotFound(-1, yys3) + } // end switch yys3 + } // end for yyj3 + z.DecSendContainerState(codecSelfer_containerMapEnd1234) +} + +func (x *DaemonSetUpdateStrategy) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { + var h codecSelfer1234 + z, r := codec1978.GenHelperDecoder(d) + _, _, _ = h, z, r + var yyj6 int + var yyb6 bool + var yyhl6 bool = l >= 0 + yyj6++ + if yyhl6 { + yyb6 = yyj6 > l + } else { + yyb6 = r.CheckBreak() + } + if yyb6 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + x.Type = "" + } else { + yyv7 := &x.Type + yyv7.CodecDecodeSelf(d) + } + yyj6++ + if yyhl6 { + yyb6 = yyj6 > l + } else { + yyb6 = r.CheckBreak() + } + if yyb6 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + if x.RollingUpdate != nil { + x.RollingUpdate = nil + } + } else { + if x.RollingUpdate == nil { + x.RollingUpdate = new(RollingUpdateDaemonSet) + } + x.RollingUpdate.CodecDecodeSelf(d) + } + for { + yyj6++ + if yyhl6 { + yyb6 = yyj6 > l + } else { + yyb6 = r.CheckBreak() + } + if yyb6 { + break + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + z.DecStructFieldNotFound(yyj6-1, "") + } + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) +} + +func (x DaemonSetUpdateStrategyType) CodecEncodeSelf(e *codec1978.Encoder) { + var h codecSelfer1234 + z, r := codec1978.GenHelperEncoder(e) + _, _, _ = h, z, r + yym1 := z.EncBinary() + _ = yym1 + if false { + } else if z.HasExtensions() && z.EncExt(x) { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x)) + } +} + +func (x *DaemonSetUpdateStrategyType) CodecDecodeSelf(d *codec1978.Decoder) { + var h codecSelfer1234 + z, r := codec1978.GenHelperDecoder(d) + _, _, _ = h, z, r + yym1 := z.DecBinary() + _ = yym1 + if false { + } else if z.HasExtensions() && z.DecExt(x) { + } else { + *((*string)(x)) = r.DecodeString() + } +} + +func (x *RollingUpdateDaemonSet) CodecEncodeSelf(e *codec1978.Encoder) { + var h codecSelfer1234 + z, r := codec1978.GenHelperEncoder(e) + _, _, _ = h, z, r + if x == nil { + r.EncodeNil() + } else { + yym1 := z.EncBinary() + _ = yym1 + if false { + } else if z.HasExtensions() && z.EncExt(x) { + } else { + yysep2 := !z.EncBinary() + yy2arr2 := z.EncBasicHandle().StructToArray + var yyq2 [1]bool + _, _, _ = yysep2, yyq2, yy2arr2 + const yyr2 bool = false + yyq2[0] = x.MaxUnavailable != nil + var yynn2 int + if yyr2 || yy2arr2 { + r.EncodeArrayStart(1) + } else { + yynn2 = 0 + for _, b := range yyq2 { + if b { + yynn2++ + } + } + r.EncodeMapStart(yynn2) + yynn2 = 0 + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[0] { + if x.MaxUnavailable == nil { + r.EncodeNil() + } else { + yym4 := z.EncBinary() + _ = yym4 + if false { + } else if z.HasExtensions() && z.EncExt(x.MaxUnavailable) { + } else if !yym4 && z.IsJSONHandle() { + z.EncJSONMarshal(x.MaxUnavailable) + } else { + z.EncFallback(x.MaxUnavailable) + } + } + } else { + r.EncodeNil() + } + } else { + if yyq2[0] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("maxUnavailable")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + if x.MaxUnavailable == nil { + r.EncodeNil() + } else { + yym5 := z.EncBinary() + _ = yym5 + if false { + } else if z.HasExtensions() && z.EncExt(x.MaxUnavailable) { + } else if !yym5 && z.IsJSONHandle() { + z.EncJSONMarshal(x.MaxUnavailable) + } else { + z.EncFallback(x.MaxUnavailable) + } + } + } + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayEnd1234) + } else { + z.EncSendContainerState(codecSelfer_containerMapEnd1234) + } + } + } +} + +func (x *RollingUpdateDaemonSet) CodecDecodeSelf(d *codec1978.Decoder) { + var h codecSelfer1234 + z, r := codec1978.GenHelperDecoder(d) + _, _, _ = h, z, r + yym1 := z.DecBinary() + _ = yym1 + if false { + } else if z.HasExtensions() && z.DecExt(x) { + } else { + yyct2 := r.ContainerType() + if yyct2 == codecSelferValueTypeMap1234 { + yyl2 := r.ReadMapStart() + if yyl2 == 0 { + z.DecSendContainerState(codecSelfer_containerMapEnd1234) + } else { + x.codecDecodeSelfFromMap(yyl2, d) + } + } else if yyct2 == codecSelferValueTypeArray1234 { + yyl2 := r.ReadArrayStart() + if yyl2 == 0 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + } else { + x.codecDecodeSelfFromArray(yyl2, d) + } + } else { + panic(codecSelferOnlyMapOrArrayEncodeToStructErr1234) + } + } +} + +func (x *RollingUpdateDaemonSet) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { + var h codecSelfer1234 + z, r := codec1978.GenHelperDecoder(d) + _, _, _ = h, z, r + var yys3Slc = z.DecScratchBuffer() // default slice to decode into + _ = yys3Slc + var yyhl3 bool = l >= 0 + for yyj3 := 0; ; yyj3++ { + if yyhl3 { + if yyj3 >= l { + break + } + } else { + if r.CheckBreak() { + break + } + } + z.DecSendContainerState(codecSelfer_containerMapKey1234) + yys3Slc = r.DecodeBytes(yys3Slc, true, true) + yys3 := string(yys3Slc) + z.DecSendContainerState(codecSelfer_containerMapValue1234) + switch yys3 { + case "maxUnavailable": + if r.TryDecodeAsNil() { + if x.MaxUnavailable != nil { + x.MaxUnavailable = nil + } + } else { + if x.MaxUnavailable == nil { + x.MaxUnavailable = new(pkg5_intstr.IntOrString) + } + yym5 := z.DecBinary() + _ = yym5 + if false { + } else if z.HasExtensions() && z.DecExt(x.MaxUnavailable) { + } else if !yym5 && z.IsJSONHandle() { + z.DecJSONUnmarshal(x.MaxUnavailable) + } else { + z.DecFallback(x.MaxUnavailable, false) + } + } + default: + z.DecStructFieldNotFound(-1, yys3) + } // end switch yys3 + } // end for yyj3 + z.DecSendContainerState(codecSelfer_containerMapEnd1234) +} + +func (x *RollingUpdateDaemonSet) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { + var h codecSelfer1234 + z, r := codec1978.GenHelperDecoder(d) + _, _, _ = h, z, r + var yyj6 int + var yyb6 bool + var yyhl6 bool = l >= 0 + yyj6++ + if yyhl6 { + yyb6 = yyj6 > l + } else { + yyb6 = r.CheckBreak() + } + if yyb6 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + if x.MaxUnavailable != nil { + x.MaxUnavailable = nil + } + } else { + if x.MaxUnavailable == nil { + x.MaxUnavailable = new(pkg5_intstr.IntOrString) + } + yym8 := z.DecBinary() + _ = yym8 + if false { + } else if z.HasExtensions() && z.DecExt(x.MaxUnavailable) { + } else if !yym8 && z.IsJSONHandle() { + z.DecJSONUnmarshal(x.MaxUnavailable) + } else { + z.DecFallback(x.MaxUnavailable, false) + } + } + for { + yyj6++ + if yyhl6 { + yyb6 = yyj6 > l + } else { + yyb6 = r.CheckBreak() + } + if yyb6 { + break + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + z.DecStructFieldNotFound(yyj6-1, "") + } + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) +} + +func (x *DaemonSetSpec) CodecEncodeSelf(e *codec1978.Encoder) { + var h codecSelfer1234 + z, r := codec1978.GenHelperEncoder(e) + _, _, _ = h, z, r + if x == nil { + r.EncodeNil() + } else { + yym1 := z.EncBinary() + _ = yym1 + if false { + } else if z.HasExtensions() && z.EncExt(x) { + } else { + yysep2 := !z.EncBinary() + yy2arr2 := z.EncBasicHandle().StructToArray + var yyq2 [5]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 + var yynn2 int + if yyr2 || yy2arr2 { + r.EncodeArrayStart(5) } else { yynn2 = 1 for _, b := range yyq2 { @@ -7085,6 +7540,73 @@ func (x *DaemonSetSpec) CodecEncodeSelf(e *codec1978.Encoder) { yy9 := &x.Template yy9.CodecEncodeSelf(e) } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[2] { + yy12 := &x.UpdateStrategy + yy12.CodecEncodeSelf(e) + } else { + r.EncodeNil() + } + } else { + if yyq2[2] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("updateStrategy")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + yy14 := &x.UpdateStrategy + yy14.CodecEncodeSelf(e) + } + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[3] { + yym17 := z.EncBinary() + _ = yym17 + if false { + } else { + r.EncodeInt(int64(x.MinReadySeconds)) + } + } else { + r.EncodeInt(0) + } + } else { + if yyq2[3] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("minReadySeconds")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + yym18 := z.EncBinary() + _ = yym18 + if false { + } else { + r.EncodeInt(int64(x.MinReadySeconds)) + } + } + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[4] { + yym20 := z.EncBinary() + _ = yym20 + if false { + } else { + r.EncodeInt(int64(x.TemplateGeneration)) + } + } else { + r.EncodeInt(0) + } + } else { + if yyq2[4] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("templateGeneration")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + yym21 := z.EncBinary() + _ = yym21 + if false { + } else { + r.EncodeInt(int64(x.TemplateGeneration)) + } + } + } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayEnd1234) } else { @@ -7170,6 +7692,37 @@ func (x *DaemonSetSpec) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { yyv6 := &x.Template yyv6.CodecDecodeSelf(d) } + case "updateStrategy": + if r.TryDecodeAsNil() { + x.UpdateStrategy = DaemonSetUpdateStrategy{} + } else { + yyv7 := &x.UpdateStrategy + yyv7.CodecDecodeSelf(d) + } + case "minReadySeconds": + if r.TryDecodeAsNil() { + x.MinReadySeconds = 0 + } else { + yyv8 := &x.MinReadySeconds + yym9 := z.DecBinary() + _ = yym9 + if false { + } else { + *((*int32)(yyv8)) = int32(r.DecodeInt(32)) + } + } + case "templateGeneration": + if r.TryDecodeAsNil() { + x.TemplateGeneration = 0 + } else { + yyv10 := &x.TemplateGeneration + yym11 := z.DecBinary() + _ = yym11 + if false { + } else { + *((*int64)(yyv10)) = int64(r.DecodeInt(64)) + } + } default: z.DecStructFieldNotFound(-1, yys3) } // end switch yys3 @@ -7181,16 +7734,16 @@ func (x *DaemonSetSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { var h codecSelfer1234 z, r := codec1978.GenHelperDecoder(d) _, _, _ = h, z, r - var yyj7 int - var yyb7 bool - var yyhl7 bool = l >= 0 - yyj7++ - if yyhl7 { - yyb7 = yyj7 > l + var yyj12 int + var yyb12 bool + var yyhl12 bool = l >= 0 + yyj12++ + if yyhl12 { + yyb12 = yyj12 > l } else { - yyb7 = r.CheckBreak() + yyb12 = r.CheckBreak() } - if yyb7 { + if yyb12 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -7203,21 +7756,21 @@ func (x *DaemonSetSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { if x.Selector == nil { x.Selector = new(pkg1_v1.LabelSelector) } - yym9 := z.DecBinary() - _ = yym9 + yym14 := z.DecBinary() + _ = yym14 if false { } else if z.HasExtensions() && z.DecExt(x.Selector) { } else { z.DecFallback(x.Selector, false) } } - yyj7++ - if yyhl7 { - yyb7 = yyj7 > l + yyj12++ + if yyhl12 { + yyb12 = yyj12 > l } else { - yyb7 = r.CheckBreak() + yyb12 = r.CheckBreak() } - if yyb7 { + if yyb12 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -7225,21 +7778,82 @@ func (x *DaemonSetSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { if r.TryDecodeAsNil() { x.Template = pkg4_v1.PodTemplateSpec{} } else { - yyv10 := &x.Template - yyv10.CodecDecodeSelf(d) + yyv15 := &x.Template + yyv15.CodecDecodeSelf(d) + } + yyj12++ + if yyhl12 { + yyb12 = yyj12 > l + } else { + yyb12 = r.CheckBreak() + } + if yyb12 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + x.UpdateStrategy = DaemonSetUpdateStrategy{} + } else { + yyv16 := &x.UpdateStrategy + yyv16.CodecDecodeSelf(d) + } + yyj12++ + if yyhl12 { + yyb12 = yyj12 > l + } else { + yyb12 = r.CheckBreak() + } + if yyb12 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + x.MinReadySeconds = 0 + } else { + yyv17 := &x.MinReadySeconds + yym18 := z.DecBinary() + _ = yym18 + if false { + } else { + *((*int32)(yyv17)) = int32(r.DecodeInt(32)) + } + } + yyj12++ + if yyhl12 { + yyb12 = yyj12 > l + } else { + yyb12 = r.CheckBreak() + } + if yyb12 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + x.TemplateGeneration = 0 + } else { + yyv19 := &x.TemplateGeneration + yym20 := z.DecBinary() + _ = yym20 + if false { + } else { + *((*int64)(yyv19)) = int64(r.DecodeInt(64)) + } } for { - yyj7++ - if yyhl7 { - yyb7 = yyj7 > l + yyj12++ + if yyhl12 { + yyb12 = yyj12 > l } else { - yyb7 = r.CheckBreak() + yyb12 = r.CheckBreak() } - if yyb7 { + if yyb12 { break } z.DecSendContainerState(codecSelfer_containerArrayElem1234) - z.DecStructFieldNotFound(yyj7-1, "") + z.DecStructFieldNotFound(yyj12-1, "") } z.DecSendContainerState(codecSelfer_containerArrayEnd1234) } @@ -7258,13 +7872,16 @@ func (x *DaemonSetStatus) CodecEncodeSelf(e *codec1978.Encoder) { } else { yysep2 := !z.EncBinary() yy2arr2 := z.EncBasicHandle().StructToArray - var yyq2 [5]bool + var yyq2 [8]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 var yynn2 int if yyr2 || yy2arr2 { - r.EncodeArrayStart(5) + r.EncodeArrayStart(8) } else { yynn2 = 4 for _, b := range yyq2 { @@ -7376,6 +7993,81 @@ func (x *DaemonSetStatus) CodecEncodeSelf(e *codec1978.Encoder) { } } } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[5] { + yym19 := z.EncBinary() + _ = yym19 + if false { + } else { + r.EncodeInt(int64(x.UpdatedNumberScheduled)) + } + } else { + r.EncodeInt(0) + } + } else { + if yyq2[5] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("updatedNumberScheduled")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + yym20 := z.EncBinary() + _ = yym20 + if false { + } else { + r.EncodeInt(int64(x.UpdatedNumberScheduled)) + } + } + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[6] { + yym22 := z.EncBinary() + _ = yym22 + if false { + } else { + r.EncodeInt(int64(x.NumberAvailable)) + } + } else { + r.EncodeInt(0) + } + } else { + if yyq2[6] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("numberAvailable")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + yym23 := z.EncBinary() + _ = yym23 + if false { + } else { + r.EncodeInt(int64(x.NumberAvailable)) + } + } + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[7] { + yym25 := z.EncBinary() + _ = yym25 + if false { + } else { + r.EncodeInt(int64(x.NumberUnavailable)) + } + } else { + r.EncodeInt(0) + } + } else { + if yyq2[7] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("numberUnavailable")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + yym26 := z.EncBinary() + _ = yym26 + if false { + } else { + r.EncodeInt(int64(x.NumberUnavailable)) + } + } + } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayEnd1234) } else { @@ -7497,6 +8189,42 @@ func (x *DaemonSetStatus) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { *((*int64)(yyv12)) = int64(r.DecodeInt(64)) } } + case "updatedNumberScheduled": + if r.TryDecodeAsNil() { + x.UpdatedNumberScheduled = 0 + } else { + yyv14 := &x.UpdatedNumberScheduled + yym15 := z.DecBinary() + _ = yym15 + if false { + } else { + *((*int32)(yyv14)) = int32(r.DecodeInt(32)) + } + } + case "numberAvailable": + if r.TryDecodeAsNil() { + x.NumberAvailable = 0 + } else { + yyv16 := &x.NumberAvailable + yym17 := z.DecBinary() + _ = yym17 + if false { + } else { + *((*int32)(yyv16)) = int32(r.DecodeInt(32)) + } + } + case "numberUnavailable": + if r.TryDecodeAsNil() { + x.NumberUnavailable = 0 + } else { + yyv18 := &x.NumberUnavailable + yym19 := z.DecBinary() + _ = yym19 + if false { + } else { + *((*int32)(yyv18)) = int32(r.DecodeInt(32)) + } + } default: z.DecStructFieldNotFound(-1, yys3) } // end switch yys3 @@ -7508,16 +8236,16 @@ func (x *DaemonSetStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) var h codecSelfer1234 z, r := codec1978.GenHelperDecoder(d) _, _, _ = h, z, r - var yyj14 int - var yyb14 bool - var yyhl14 bool = l >= 0 - yyj14++ - if yyhl14 { - yyb14 = yyj14 > l + var yyj20 int + var yyb20 bool + var yyhl20 bool = l >= 0 + yyj20++ + if yyhl20 { + yyb20 = yyj20 > l } else { - yyb14 = r.CheckBreak() + yyb20 = r.CheckBreak() } - if yyb14 { + if yyb20 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -7525,73 +8253,7 @@ func (x *DaemonSetStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) if r.TryDecodeAsNil() { x.CurrentNumberScheduled = 0 } else { - yyv15 := &x.CurrentNumberScheduled - yym16 := z.DecBinary() - _ = yym16 - if false { - } else { - *((*int32)(yyv15)) = int32(r.DecodeInt(32)) - } - } - yyj14++ - if yyhl14 { - yyb14 = yyj14 > l - } else { - yyb14 = r.CheckBreak() - } - if yyb14 { - z.DecSendContainerState(codecSelfer_containerArrayEnd1234) - return - } - z.DecSendContainerState(codecSelfer_containerArrayElem1234) - if r.TryDecodeAsNil() { - x.NumberMisscheduled = 0 - } else { - yyv17 := &x.NumberMisscheduled - yym18 := z.DecBinary() - _ = yym18 - if false { - } else { - *((*int32)(yyv17)) = int32(r.DecodeInt(32)) - } - } - yyj14++ - if yyhl14 { - yyb14 = yyj14 > l - } else { - yyb14 = r.CheckBreak() - } - if yyb14 { - z.DecSendContainerState(codecSelfer_containerArrayEnd1234) - return - } - z.DecSendContainerState(codecSelfer_containerArrayElem1234) - if r.TryDecodeAsNil() { - x.DesiredNumberScheduled = 0 - } else { - yyv19 := &x.DesiredNumberScheduled - yym20 := z.DecBinary() - _ = yym20 - if false { - } else { - *((*int32)(yyv19)) = int32(r.DecodeInt(32)) - } - } - yyj14++ - if yyhl14 { - yyb14 = yyj14 > l - } else { - yyb14 = r.CheckBreak() - } - if yyb14 { - z.DecSendContainerState(codecSelfer_containerArrayEnd1234) - return - } - z.DecSendContainerState(codecSelfer_containerArrayElem1234) - if r.TryDecodeAsNil() { - x.NumberReady = 0 - } else { - yyv21 := &x.NumberReady + yyv21 := &x.CurrentNumberScheduled yym22 := z.DecBinary() _ = yym22 if false { @@ -7599,13 +8261,79 @@ func (x *DaemonSetStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) *((*int32)(yyv21)) = int32(r.DecodeInt(32)) } } - yyj14++ - if yyhl14 { - yyb14 = yyj14 > l + yyj20++ + if yyhl20 { + yyb20 = yyj20 > l } else { - yyb14 = r.CheckBreak() + yyb20 = r.CheckBreak() } - if yyb14 { + if yyb20 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + x.NumberMisscheduled = 0 + } else { + yyv23 := &x.NumberMisscheduled + yym24 := z.DecBinary() + _ = yym24 + if false { + } else { + *((*int32)(yyv23)) = 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.DesiredNumberScheduled = 0 + } else { + yyv25 := &x.DesiredNumberScheduled + yym26 := z.DecBinary() + _ = yym26 + if false { + } else { + *((*int32)(yyv25)) = 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.NumberReady = 0 + } else { + yyv27 := &x.NumberReady + yym28 := z.DecBinary() + _ = yym28 + if false { + } else { + *((*int32)(yyv27)) = int32(r.DecodeInt(32)) + } + } + yyj20++ + if yyhl20 { + yyb20 = yyj20 > l + } else { + yyb20 = r.CheckBreak() + } + if yyb20 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -7613,26 +8341,92 @@ func (x *DaemonSetStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) if r.TryDecodeAsNil() { x.ObservedGeneration = 0 } else { - yyv23 := &x.ObservedGeneration - yym24 := z.DecBinary() - _ = yym24 + yyv29 := &x.ObservedGeneration + yym30 := z.DecBinary() + _ = yym30 if false { } else { - *((*int64)(yyv23)) = int64(r.DecodeInt(64)) + *((*int64)(yyv29)) = int64(r.DecodeInt(64)) + } + } + 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.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 + yym34 := z.DecBinary() + _ = yym34 + if false { + } else { + *((*int32)(yyv33)) = 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.NumberUnavailable = 0 + } else { + yyv35 := &x.NumberUnavailable + yym36 := z.DecBinary() + _ = yym36 + if false { + } else { + *((*int32)(yyv35)) = int32(r.DecodeInt(32)) } } for { - yyj14++ - if yyhl14 { - yyb14 = yyj14 > l + yyj20++ + if yyhl20 { + yyb20 = yyj20 > l } else { - yyb14 = r.CheckBreak() + yyb20 = r.CheckBreak() } - if yyb14 { + if yyb20 { break } z.DecSendContainerState(codecSelfer_containerArrayElem1234) - z.DecStructFieldNotFound(yyj14-1, "") + z.DecStructFieldNotFound(yyj20-1, "") } z.DecSendContainerState(codecSelfer_containerArrayEnd1234) } @@ -18977,7 +19771,7 @@ func (x codecSelfer1234) decSliceDaemonSet(v *[]DaemonSet, d *codec1978.Decoder) yyrg1 := len(yyv1) > 0 yyv21 := yyv1 - yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 816) + yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 872) if yyrt1 { if yyrl1 <= cap(yyv1) { yyv1 = yyv1[:yyrl1] diff --git a/pkg/apis/extensions/v1beta1/types.go b/pkg/apis/extensions/v1beta1/types.go index 13b4d934287..700957931c4 100644 --- a/pkg/apis/extensions/v1beta1/types.go +++ b/pkg/apis/extensions/v1beta1/types.go @@ -369,20 +369,20 @@ type DeploymentList struct { Items []Deployment `json:"items" protobuf:"bytes,2,rep,name=items"` } -// TODO(madhusudancs): Uncomment while implementing DaemonSet updates. -/* Commenting out for v1.2. We are planning to bring these types back with a more robust DaemonSet update implementation in v1.3, hence not deleting but just commenting the types out. type DaemonSetUpdateStrategy struct { - // Type of daemon set update. Only "RollingUpdate" is supported at this time. Default is RollingUpdate. -// +optional - Type DaemonSetUpdateStrategyType `json:"type,omitempty"` + // Type of daemon set update. Can be "RollingUpdate" or "OnDelete". + // Default is OnDelete. + // +optional + Type DaemonSetUpdateStrategyType `json:"type,omitempty" protobuf:"bytes,1,opt,name=type"` // Rolling update config params. Present only if DaemonSetUpdateStrategy = // RollingUpdate. //--- // TODO: Update this to follow our convention for oneOf, whatever we decide it // to be. Same as DeploymentStrategy.RollingUpdate. -// +optional - RollingUpdate *RollingUpdateDaemonSet `json:"rollingUpdate,omitempty"` + // See https://github.com/kubernetes/kubernetes/issues/35345 + // +optional + RollingUpdate *RollingUpdateDaemonSet `json:"rollingUpdate,omitempty" protobuf:"bytes,2,opt,name=rollingUpdate"` } type DaemonSetUpdateStrategyType string @@ -390,6 +390,9 @@ type DaemonSetUpdateStrategyType string const ( // Replace the old daemons by new ones using rolling update i.e replace them on each node one after the other. RollingUpdateDaemonSetStrategyType DaemonSetUpdateStrategyType = "RollingUpdate" + + // Replace the old daemons only when it's killed + OnDeleteDaemonSetStrategyType DaemonSetUpdateStrategyType = "OnDelete" ) // Spec to control the desired behavior of daemon set rolling update. @@ -407,17 +410,9 @@ type RollingUpdateDaemonSet struct { // it then proceeds onto other DaemonSet pods, thus ensuring that at least // 70% of original number of DaemonSet pods are available at all times // during the update. -// +optional - MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty"` - - // 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). -// +optional - MinReadySeconds int32 `json:"minReadySeconds,omitempty"` + // +optional + MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty" protobuf:"bytes,1,opt,name=maxUnavailable"` } -*/ // DaemonSetSpec is the specification of a daemon set. type DaemonSetSpec struct { @@ -435,31 +430,23 @@ type DaemonSetSpec struct { // More info: http://kubernetes.io/docs/user-guide/replication-controller#pod-template Template v1.PodTemplateSpec `json:"template" protobuf:"bytes,2,opt,name=template"` - // TODO(madhusudancs): Uncomment while implementing DaemonSet updates. - /* Commenting out for v1.2. We are planning to bring these fields back with a more robust DaemonSet update implementation in v1.3, hence not deleting but just commenting these fields out. - // Update strategy to replace existing DaemonSet pods with new pods. + // UpdateStrategy to replace existing DaemonSet pods with new pods. // +optional - UpdateStrategy DaemonSetUpdateStrategy `json:"updateStrategy,omitempty"` + UpdateStrategy DaemonSetUpdateStrategy `json:"updateStrategy,omitempty" protobuf:"bytes,3,opt,name=updateStrategy"` - // Label key that is added to DaemonSet pods to distinguish between old and - // new pod templates during DaemonSet update. - // Users can set this to an empty string to indicate that the system should - // not add any label. If unspecified, system uses - // DefaultDaemonSetUniqueLabelKey("daemonset.kubernetes.io/podTemplateHash"). - // Value of this key is hash of DaemonSetSpec.PodTemplateSpec. - // No label is added if this is set to empty string. + // MinReadySeconds 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). // +optional - UniqueLabelKey *string `json:"uniqueLabelKey,omitempty"` - */ + MinReadySeconds int32 `json:"minReadySeconds,omitempty" protobuf:"varint,4,opt,name=minReadySeconds"` + + // 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"` } -const ( - // DefaultDaemonSetUniqueLabelKey is the default key of the labels that is added - // to daemon set pods to distinguish between old and new pod templates during - // DaemonSet update. See DaemonSetSpec's UniqueLabelKey field for more information. - DefaultDaemonSetUniqueLabelKey string = "daemonset.kubernetes.io/podTemplateHash" -) - // DaemonSetStatus represents the current status of a daemon set. type DaemonSetStatus struct { // CurrentNumberScheduled is the number of nodes that are running at least 1 @@ -484,6 +471,23 @@ type DaemonSetStatus struct { // ObservedGeneration is the most recent generation observed by the daemon set controller. // +optional ObservedGeneration int64 `json:"observedGeneration,omitempty" protobuf:"varint,5,opt,name=observedGeneration"` + + // UpdatedNumberScheduled is the total number of nodes that are running updated + // daemon pod + // +optional + UpdatedNumberScheduled int32 `json:"updatedNumberScheduled,omitempty" protobuf:"varint,6,opt,name=updatedNumberScheduled"` + + // NumberAvailable is 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 minReadySeconds) + // +optional + NumberAvailable int32 `json:"numberAvailable,omitempty" protobuf:"varint,7,opt,name=numberAvailable"` + + // NumberUnavailable is 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 minReadySeconds) + // +optional + NumberUnavailable int32 `json:"numberUnavailable,omitempty" protobuf:"varint,8,opt,name=numberUnavailable"` } // +genclient=true @@ -510,6 +514,13 @@ type DaemonSet struct { Status DaemonSetStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"` } +const ( + // 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" +) + // DaemonSetList is a collection of daemon sets. type DaemonSetList struct { metav1.TypeMeta `json:",inline"` diff --git a/pkg/apis/extensions/v1beta1/types_swagger_doc_generated.go b/pkg/apis/extensions/v1beta1/types_swagger_doc_generated.go index 6c56702499b..dd8b41f5e0a 100644 --- a/pkg/apis/extensions/v1beta1/types_swagger_doc_generated.go +++ b/pkg/apis/extensions/v1beta1/types_swagger_doc_generated.go @@ -77,9 +77,12 @@ func (DaemonSetList) SwaggerDoc() map[string]string { } var map_DaemonSetSpec = map[string]string{ - "": "DaemonSetSpec is the specification of a daemon set.", - "selector": "Selector is 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: http://kubernetes.io/docs/user-guide/labels#label-selectors", - "template": "Template is the 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: http://kubernetes.io/docs/user-guide/replication-controller#pod-template", + "": "DaemonSetSpec is the specification of a daemon set.", + "selector": "Selector is 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: http://kubernetes.io/docs/user-guide/labels#label-selectors", + "template": "Template is the 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: http://kubernetes.io/docs/user-guide/replication-controller#pod-template", + "updateStrategy": "UpdateStrategy to replace existing DaemonSet pods with new pods.", + "minReadySeconds": "MinReadySeconds 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.", } func (DaemonSetSpec) SwaggerDoc() map[string]string { @@ -93,12 +96,24 @@ var map_DaemonSetStatus = map[string]string{ "desiredNumberScheduled": "DesiredNumberScheduled is the total number of nodes that should be running the daemon pod (including nodes correctly running the daemon pod). More info: http://releases.k8s.io/HEAD/docs/admin/daemons.md", "numberReady": "NumberReady is the number of nodes that should be running the daemon pod and have one or more of the daemon pod running and ready.", "observedGeneration": "ObservedGeneration is the most recent generation observed by the daemon set controller.", + "updatedNumberScheduled": "UpdatedNumberScheduled is the total number of nodes that are running updated daemon pod", + "numberAvailable": "NumberAvailable is 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 minReadySeconds)", + "numberUnavailable": "NumberUnavailable is 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 minReadySeconds)", } func (DaemonSetStatus) SwaggerDoc() map[string]string { return map_DaemonSetStatus } +var map_DaemonSetUpdateStrategy = map[string]string{ + "type": "Type of daemon set update. Can be \"RollingUpdate\" or \"OnDelete\". Default is OnDelete.", + "rollingUpdate": "Rolling update config params. Present only if DaemonSetUpdateStrategy = RollingUpdate.", +} + +func (DaemonSetUpdateStrategy) SwaggerDoc() map[string]string { + return map_DaemonSetUpdateStrategy +} + var map_Deployment = map[string]string{ "": "Deployment enables declarative updates for Pods and ReplicaSets.", "metadata": "Standard object metadata.", @@ -488,6 +503,15 @@ func (RollbackConfig) SwaggerDoc() map[string]string { return map_RollbackConfig } +var map_RollingUpdateDaemonSet = map[string]string{ + "": "Spec to control the desired behavior of daemon set rolling update.", + "maxUnavailable": "The maximum number of DaemonSet pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of total number of DaemonSet pods at the start of the update (ex: 10%). Absolute number is calculated from percentage by rounding up. This cannot be 0. Default value is 1. Example: when this is set to 30%, 30% of the currently running DaemonSet pods can be stopped for an update at any given time. The update starts by stopping at most 30% of the currently running DaemonSet pods and then brings up new DaemonSet pods in their place. Once the new pods are ready, it then proceeds onto other DaemonSet pods, thus ensuring that at least 70% of original number of DaemonSet pods are available at all times during the update.", +} + +func (RollingUpdateDaemonSet) SwaggerDoc() map[string]string { + return map_RollingUpdateDaemonSet +} + var map_RollingUpdateDeployment = map[string]string{ "": "Spec to control the desired behavior of rolling update.", "maxUnavailable": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. By default, a fixed value of 1 is used. Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old RC can be scaled down further, followed by scaling up the new RC, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", diff --git a/pkg/apis/extensions/v1beta1/zz_generated.conversion.go b/pkg/apis/extensions/v1beta1/zz_generated.conversion.go index c3e5d513e99..5af6a4ceb5a 100644 --- a/pkg/apis/extensions/v1beta1/zz_generated.conversion.go +++ b/pkg/apis/extensions/v1beta1/zz_generated.conversion.go @@ -57,6 +57,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_extensions_DaemonSetSpec_To_v1beta1_DaemonSetSpec, Convert_v1beta1_DaemonSetStatus_To_extensions_DaemonSetStatus, Convert_extensions_DaemonSetStatus_To_v1beta1_DaemonSetStatus, + Convert_v1beta1_DaemonSetUpdateStrategy_To_extensions_DaemonSetUpdateStrategy, + Convert_extensions_DaemonSetUpdateStrategy_To_v1beta1_DaemonSetUpdateStrategy, Convert_v1beta1_Deployment_To_extensions_Deployment, Convert_extensions_Deployment_To_v1beta1_Deployment, Convert_v1beta1_DeploymentCondition_To_extensions_DeploymentCondition, @@ -129,6 +131,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_extensions_ReplicationControllerDummy_To_v1beta1_ReplicationControllerDummy, Convert_v1beta1_RollbackConfig_To_extensions_RollbackConfig, Convert_extensions_RollbackConfig_To_v1beta1_RollbackConfig, + Convert_v1beta1_RollingUpdateDaemonSet_To_extensions_RollingUpdateDaemonSet, + Convert_extensions_RollingUpdateDaemonSet_To_v1beta1_RollingUpdateDaemonSet, Convert_v1beta1_RollingUpdateDeployment_To_extensions_RollingUpdateDeployment, Convert_extensions_RollingUpdateDeployment_To_v1beta1_RollingUpdateDeployment, Convert_v1beta1_RunAsUserStrategyOptions_To_extensions_RunAsUserStrategyOptions, @@ -323,6 +327,11 @@ func autoConvert_v1beta1_DaemonSetSpec_To_extensions_DaemonSetSpec(in *DaemonSet if err := api_v1.Convert_v1_PodTemplateSpec_To_api_PodTemplateSpec(&in.Template, &out.Template, s); err != nil { return err } + if err := Convert_v1beta1_DaemonSetUpdateStrategy_To_extensions_DaemonSetUpdateStrategy(&in.UpdateStrategy, &out.UpdateStrategy, s); err != nil { + return err + } + out.MinReadySeconds = in.MinReadySeconds + out.TemplateGeneration = in.TemplateGeneration return nil } @@ -335,6 +344,11 @@ func autoConvert_extensions_DaemonSetSpec_To_v1beta1_DaemonSetSpec(in *extension if err := api_v1.Convert_api_PodTemplateSpec_To_v1_PodTemplateSpec(&in.Template, &out.Template, s); err != nil { return err } + if err := Convert_extensions_DaemonSetUpdateStrategy_To_v1beta1_DaemonSetUpdateStrategy(&in.UpdateStrategy, &out.UpdateStrategy, s); err != nil { + return err + } + out.MinReadySeconds = in.MinReadySeconds + out.TemplateGeneration = in.TemplateGeneration return nil } @@ -348,6 +362,9 @@ func autoConvert_v1beta1_DaemonSetStatus_To_extensions_DaemonSetStatus(in *Daemo out.DesiredNumberScheduled = in.DesiredNumberScheduled out.NumberReady = in.NumberReady out.ObservedGeneration = in.ObservedGeneration + out.UpdatedNumberScheduled = in.UpdatedNumberScheduled + out.NumberAvailable = in.NumberAvailable + out.NumberUnavailable = in.NumberUnavailable return nil } @@ -361,6 +378,9 @@ func autoConvert_extensions_DaemonSetStatus_To_v1beta1_DaemonSetStatus(in *exten out.DesiredNumberScheduled = in.DesiredNumberScheduled out.NumberReady = in.NumberReady out.ObservedGeneration = in.ObservedGeneration + out.UpdatedNumberScheduled = in.UpdatedNumberScheduled + out.NumberAvailable = in.NumberAvailable + out.NumberUnavailable = in.NumberUnavailable return nil } @@ -368,6 +388,42 @@ func Convert_extensions_DaemonSetStatus_To_v1beta1_DaemonSetStatus(in *extension return autoConvert_extensions_DaemonSetStatus_To_v1beta1_DaemonSetStatus(in, out, s) } +func autoConvert_v1beta1_DaemonSetUpdateStrategy_To_extensions_DaemonSetUpdateStrategy(in *DaemonSetUpdateStrategy, out *extensions.DaemonSetUpdateStrategy, s conversion.Scope) error { + out.Type = extensions.DaemonSetUpdateStrategyType(in.Type) + if in.RollingUpdate != nil { + in, out := &in.RollingUpdate, &out.RollingUpdate + *out = new(extensions.RollingUpdateDaemonSet) + if err := Convert_v1beta1_RollingUpdateDaemonSet_To_extensions_RollingUpdateDaemonSet(*in, *out, s); err != nil { + return err + } + } else { + out.RollingUpdate = nil + } + return nil +} + +func Convert_v1beta1_DaemonSetUpdateStrategy_To_extensions_DaemonSetUpdateStrategy(in *DaemonSetUpdateStrategy, out *extensions.DaemonSetUpdateStrategy, s conversion.Scope) error { + return autoConvert_v1beta1_DaemonSetUpdateStrategy_To_extensions_DaemonSetUpdateStrategy(in, out, s) +} + +func autoConvert_extensions_DaemonSetUpdateStrategy_To_v1beta1_DaemonSetUpdateStrategy(in *extensions.DaemonSetUpdateStrategy, out *DaemonSetUpdateStrategy, s conversion.Scope) error { + out.Type = DaemonSetUpdateStrategyType(in.Type) + if in.RollingUpdate != nil { + in, out := &in.RollingUpdate, &out.RollingUpdate + *out = new(RollingUpdateDaemonSet) + if err := Convert_extensions_RollingUpdateDaemonSet_To_v1beta1_RollingUpdateDaemonSet(*in, *out, s); err != nil { + return err + } + } else { + out.RollingUpdate = nil + } + return nil +} + +func Convert_extensions_DaemonSetUpdateStrategy_To_v1beta1_DaemonSetUpdateStrategy(in *extensions.DaemonSetUpdateStrategy, out *DaemonSetUpdateStrategy, s conversion.Scope) error { + return autoConvert_extensions_DaemonSetUpdateStrategy_To_v1beta1_DaemonSetUpdateStrategy(in, out, s) +} + func autoConvert_v1beta1_Deployment_To_extensions_Deployment(in *Deployment, out *extensions.Deployment, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta if err := Convert_v1beta1_DeploymentSpec_To_extensions_DeploymentSpec(&in.Spec, &out.Spec, s); err != nil { @@ -1318,6 +1374,16 @@ func Convert_extensions_RollbackConfig_To_v1beta1_RollbackConfig(in *extensions. return autoConvert_extensions_RollbackConfig_To_v1beta1_RollbackConfig(in, out, s) } +func autoConvert_v1beta1_RollingUpdateDaemonSet_To_extensions_RollingUpdateDaemonSet(in *RollingUpdateDaemonSet, out *extensions.RollingUpdateDaemonSet, s conversion.Scope) error { + // WARNING: in.MaxUnavailable requires manual conversion: inconvertible types (*k8s.io/apimachinery/pkg/util/intstr.IntOrString vs k8s.io/apimachinery/pkg/util/intstr.IntOrString) + return nil +} + +func autoConvert_extensions_RollingUpdateDaemonSet_To_v1beta1_RollingUpdateDaemonSet(in *extensions.RollingUpdateDaemonSet, out *RollingUpdateDaemonSet, s conversion.Scope) error { + // WARNING: in.MaxUnavailable requires manual conversion: inconvertible types (k8s.io/apimachinery/pkg/util/intstr.IntOrString vs *k8s.io/apimachinery/pkg/util/intstr.IntOrString) + return nil +} + func autoConvert_v1beta1_RollingUpdateDeployment_To_extensions_RollingUpdateDeployment(in *RollingUpdateDeployment, out *extensions.RollingUpdateDeployment, s conversion.Scope) error { // WARNING: in.MaxUnavailable requires manual conversion: inconvertible types (*k8s.io/apimachinery/pkg/util/intstr.IntOrString vs k8s.io/apimachinery/pkg/util/intstr.IntOrString) // WARNING: in.MaxSurge requires manual conversion: inconvertible types (*k8s.io/apimachinery/pkg/util/intstr.IntOrString vs k8s.io/apimachinery/pkg/util/intstr.IntOrString) diff --git a/pkg/apis/extensions/v1beta1/zz_generated.deepcopy.go b/pkg/apis/extensions/v1beta1/zz_generated.deepcopy.go index af3a29d4fe6..5188d3ed764 100644 --- a/pkg/apis/extensions/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/extensions/v1beta1/zz_generated.deepcopy.go @@ -46,6 +46,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error { conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_DaemonSetList, InType: reflect.TypeOf(&DaemonSetList{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_DaemonSetSpec, InType: reflect.TypeOf(&DaemonSetSpec{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_DaemonSetStatus, InType: reflect.TypeOf(&DaemonSetStatus{})}, + conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_DaemonSetUpdateStrategy, InType: reflect.TypeOf(&DaemonSetUpdateStrategy{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_Deployment, InType: reflect.TypeOf(&Deployment{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_DeploymentCondition, InType: reflect.TypeOf(&DeploymentCondition{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_DeploymentList, InType: reflect.TypeOf(&DeploymentList{})}, @@ -82,6 +83,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error { conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_ReplicaSetStatus, InType: reflect.TypeOf(&ReplicaSetStatus{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_ReplicationControllerDummy, InType: reflect.TypeOf(&ReplicationControllerDummy{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_RollbackConfig, InType: reflect.TypeOf(&RollbackConfig{})}, + conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_RollingUpdateDaemonSet, InType: reflect.TypeOf(&RollingUpdateDaemonSet{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_RollingUpdateDeployment, InType: reflect.TypeOf(&RollingUpdateDeployment{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_RunAsUserStrategyOptions, InType: reflect.TypeOf(&RunAsUserStrategyOptions{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_SELinuxStrategyOptions, InType: reflect.TypeOf(&SELinuxStrategyOptions{})}, @@ -212,6 +214,9 @@ func DeepCopy_v1beta1_DaemonSetSpec(in interface{}, out interface{}, c *conversi if err := api_v1.DeepCopy_v1_PodTemplateSpec(&in.Template, &out.Template, c); err != nil { return err } + if err := DeepCopy_v1beta1_DaemonSetUpdateStrategy(&in.UpdateStrategy, &out.UpdateStrategy, c); err != nil { + return err + } return nil } } @@ -225,6 +230,22 @@ func DeepCopy_v1beta1_DaemonSetStatus(in interface{}, out interface{}, c *conver } } +func DeepCopy_v1beta1_DaemonSetUpdateStrategy(in interface{}, out interface{}, c *conversion.Cloner) error { + { + in := in.(*DaemonSetUpdateStrategy) + out := out.(*DaemonSetUpdateStrategy) + *out = *in + if in.RollingUpdate != nil { + in, out := &in.RollingUpdate, &out.RollingUpdate + *out = new(RollingUpdateDaemonSet) + if err := DeepCopy_v1beta1_RollingUpdateDaemonSet(*in, *out, c); err != nil { + return err + } + } + return nil + } +} + func DeepCopy_v1beta1_Deployment(in interface{}, out interface{}, c *conversion.Cloner) error { { in := in.(*Deployment) @@ -874,6 +895,20 @@ func DeepCopy_v1beta1_RollbackConfig(in interface{}, out interface{}, c *convers } } +func DeepCopy_v1beta1_RollingUpdateDaemonSet(in interface{}, out interface{}, c *conversion.Cloner) error { + { + in := in.(*RollingUpdateDaemonSet) + out := out.(*RollingUpdateDaemonSet) + *out = *in + if in.MaxUnavailable != nil { + in, out := &in.MaxUnavailable, &out.MaxUnavailable + *out = new(intstr.IntOrString) + **out = **in + } + return nil + } +} + func DeepCopy_v1beta1_RollingUpdateDeployment(in interface{}, out interface{}, c *conversion.Cloner) error { { in := in.(*RollingUpdateDeployment) diff --git a/pkg/apis/extensions/validation/validation.go b/pkg/apis/extensions/validation/validation.go index 5ca7a9b1073..3405a580ad7 100644 --- a/pkg/apis/extensions/validation/validation.go +++ b/pkg/apis/extensions/validation/validation.go @@ -110,6 +110,9 @@ func validateDaemonSetStatus(status *extensions.DaemonSetStatus, fldPath *field. allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.DesiredNumberScheduled), fldPath.Child("desiredNumberScheduled"))...) allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.NumberReady), fldPath.Child("numberReady"))...) allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(status.ObservedGeneration, fldPath.Child("observedGeneration"))...) + 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"))...) return allErrs } @@ -141,6 +144,40 @@ func ValidateDaemonSetSpec(spec *extensions.DaemonSetSpec, fldPath *field.Path) if spec.Template.Spec.RestartPolicy != api.RestartPolicyAlways { allErrs = append(allErrs, field.NotSupported(fldPath.Child("template", "spec", "restartPolicy"), spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyAlways)})) } + allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(spec.MinReadySeconds), fldPath.Child("minReadySeconds"))...) + allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(spec.TemplateGeneration), fldPath.Child("templateGeneration"))...) + + allErrs = append(allErrs, ValidateDaemonSetUpdateStrategy(&spec.UpdateStrategy, fldPath.Child("updateStrategy"))...) + return allErrs +} + +func ValidateRollingUpdateDaemonSet(rollingUpdate *extensions.RollingUpdateDaemonSet, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + allErrs = append(allErrs, ValidatePositiveIntOrPercent(rollingUpdate.MaxUnavailable, fldPath.Child("maxUnavailable"))...) + if getIntOrPercentValue(rollingUpdate.MaxUnavailable) == 0 { + // MaxUnavailable cannot be 0. + allErrs = append(allErrs, field.Invalid(fldPath.Child("maxUnavailable"), rollingUpdate.MaxUnavailable, "cannot be 0")) + } + // Validate that MaxUnavailable is not more than 100%. + allErrs = append(allErrs, IsNotMoreThan100Percent(rollingUpdate.MaxUnavailable, fldPath.Child("maxUnavailable"))...) + return allErrs +} + +func ValidateDaemonSetUpdateStrategy(strategy *extensions.DaemonSetUpdateStrategy, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + switch strategy.Type { + case extensions.OnDeleteDaemonSetStrategyType: + case extensions.RollingUpdateDaemonSetStrategyType: + // Make sure RollingUpdate field isn't nil. + if strategy.RollingUpdate == nil { + allErrs = append(allErrs, field.Required(fldPath.Child("rollingUpdate"), "")) + return allErrs + } + allErrs = append(allErrs, ValidateRollingUpdateDaemonSet(strategy.RollingUpdate, fldPath.Child("rollingUpdate"))...) + default: + validValues := []string{string(extensions.RollingUpdateDaemonSetStrategyType), string(extensions.OnDeleteDaemonSetStrategyType)} + allErrs = append(allErrs, field.NotSupported(fldPath, strategy, validValues)) + } return allErrs } diff --git a/pkg/apis/extensions/validation/validation_test.go b/pkg/apis/extensions/validation/validation_test.go index fafede1a6af..b04d3685974 100644 --- a/pkg/apis/extensions/validation/validation_test.go +++ b/pkg/apis/extensions/validation/validation_test.go @@ -46,6 +46,9 @@ func TestValidateDaemonSetStatusUpdate(t *testing.T) { NumberMisscheduled: 2, DesiredNumberScheduled: 3, NumberReady: 1, + UpdatedNumberScheduled: 1, + NumberAvailable: 1, + NumberUnavailable: 2, }, }, update: extensions.DaemonSet{ @@ -55,6 +58,9 @@ func TestValidateDaemonSetStatusUpdate(t *testing.T) { NumberMisscheduled: 1, DesiredNumberScheduled: 3, NumberReady: 1, + UpdatedNumberScheduled: 1, + NumberAvailable: 1, + NumberUnavailable: 2, }, }, }, @@ -81,6 +87,9 @@ func TestValidateDaemonSetStatusUpdate(t *testing.T) { DesiredNumberScheduled: 3, NumberReady: 1, ObservedGeneration: 3, + UpdatedNumberScheduled: 1, + NumberAvailable: 1, + NumberUnavailable: 2, }, }, update: extensions.DaemonSet{ @@ -95,6 +104,9 @@ func TestValidateDaemonSetStatusUpdate(t *testing.T) { DesiredNumberScheduled: -3, NumberReady: -1, ObservedGeneration: -3, + UpdatedNumberScheduled: -1, + NumberAvailable: -1, + NumberUnavailable: -2, }, }, }, @@ -111,6 +123,9 @@ func TestValidateDaemonSetStatusUpdate(t *testing.T) { DesiredNumberScheduled: 3, NumberReady: 1, ObservedGeneration: 3, + UpdatedNumberScheduled: 1, + NumberAvailable: 1, + NumberUnavailable: 2, }, }, update: extensions.DaemonSet{ @@ -125,6 +140,9 @@ func TestValidateDaemonSetStatusUpdate(t *testing.T) { DesiredNumberScheduled: 3, NumberReady: 1, ObservedGeneration: 3, + UpdatedNumberScheduled: 1, + NumberAvailable: 1, + NumberUnavailable: 2, }, }, }, @@ -141,6 +159,9 @@ func TestValidateDaemonSetStatusUpdate(t *testing.T) { DesiredNumberScheduled: 3, NumberReady: 1, ObservedGeneration: 3, + UpdatedNumberScheduled: 1, + NumberAvailable: 1, + NumberUnavailable: 2, }, }, update: extensions.DaemonSet{ @@ -155,6 +176,9 @@ func TestValidateDaemonSetStatusUpdate(t *testing.T) { DesiredNumberScheduled: 3, NumberReady: 1, ObservedGeneration: 3, + UpdatedNumberScheduled: 1, + NumberAvailable: 1, + NumberUnavailable: 2, }, }, }, @@ -171,6 +195,9 @@ func TestValidateDaemonSetStatusUpdate(t *testing.T) { DesiredNumberScheduled: 3, NumberReady: 1, ObservedGeneration: 3, + UpdatedNumberScheduled: 1, + NumberAvailable: 1, + NumberUnavailable: 2, }, }, update: extensions.DaemonSet{ @@ -185,6 +212,9 @@ func TestValidateDaemonSetStatusUpdate(t *testing.T) { DesiredNumberScheduled: -3, NumberReady: 1, ObservedGeneration: 3, + UpdatedNumberScheduled: 1, + NumberAvailable: 1, + NumberUnavailable: 2, }, }, }, @@ -201,6 +231,9 @@ func TestValidateDaemonSetStatusUpdate(t *testing.T) { DesiredNumberScheduled: 3, NumberReady: 1, ObservedGeneration: 3, + UpdatedNumberScheduled: 1, + NumberAvailable: 1, + NumberUnavailable: 2, }, }, update: extensions.DaemonSet{ @@ -215,6 +248,9 @@ func TestValidateDaemonSetStatusUpdate(t *testing.T) { DesiredNumberScheduled: 3, NumberReady: -1, ObservedGeneration: 3, + UpdatedNumberScheduled: 1, + NumberAvailable: 1, + NumberUnavailable: 2, }, }, }, @@ -231,6 +267,9 @@ func TestValidateDaemonSetStatusUpdate(t *testing.T) { DesiredNumberScheduled: 3, NumberReady: 1, ObservedGeneration: 3, + UpdatedNumberScheduled: 1, + NumberAvailable: 1, + NumberUnavailable: 2, }, }, update: extensions.DaemonSet{ @@ -245,6 +284,117 @@ func TestValidateDaemonSetStatusUpdate(t *testing.T) { DesiredNumberScheduled: 3, NumberReady: 1, ObservedGeneration: -3, + UpdatedNumberScheduled: 1, + NumberAvailable: 1, + NumberUnavailable: 2, + }, + }, + }, + "negative UpdatedNumberScheduled": { + old: extensions.DaemonSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "abc", + Namespace: metav1.NamespaceDefault, + ResourceVersion: "10", + }, + Status: extensions.DaemonSetStatus{ + CurrentNumberScheduled: 1, + NumberMisscheduled: 2, + DesiredNumberScheduled: 3, + NumberReady: 1, + ObservedGeneration: 3, + UpdatedNumberScheduled: 1, + NumberAvailable: 1, + NumberUnavailable: 2, + }, + }, + update: extensions.DaemonSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "abc", + Namespace: metav1.NamespaceDefault, + ResourceVersion: "10", + }, + Status: extensions.DaemonSetStatus{ + CurrentNumberScheduled: 1, + NumberMisscheduled: 1, + DesiredNumberScheduled: 3, + NumberReady: 1, + ObservedGeneration: 3, + UpdatedNumberScheduled: -1, + NumberAvailable: 1, + NumberUnavailable: 2, + }, + }, + }, + "negative NumberAvailable": { + old: extensions.DaemonSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "abc", + Namespace: metav1.NamespaceDefault, + ResourceVersion: "10", + }, + Status: extensions.DaemonSetStatus{ + CurrentNumberScheduled: 1, + NumberMisscheduled: 2, + DesiredNumberScheduled: 3, + NumberReady: 1, + ObservedGeneration: 3, + UpdatedNumberScheduled: 1, + NumberAvailable: 1, + NumberUnavailable: 2, + }, + }, + update: extensions.DaemonSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "abc", + Namespace: metav1.NamespaceDefault, + ResourceVersion: "10", + }, + Status: extensions.DaemonSetStatus{ + CurrentNumberScheduled: 1, + NumberMisscheduled: 1, + DesiredNumberScheduled: 3, + NumberReady: 1, + ObservedGeneration: 3, + UpdatedNumberScheduled: 1, + NumberAvailable: -1, + NumberUnavailable: 2, + }, + }, + }, + "negative NumberUnavailable": { + old: extensions.DaemonSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "abc", + Namespace: metav1.NamespaceDefault, + ResourceVersion: "10", + }, + Status: extensions.DaemonSetStatus{ + CurrentNumberScheduled: 1, + NumberMisscheduled: 2, + DesiredNumberScheduled: 3, + NumberReady: 1, + ObservedGeneration: 3, + UpdatedNumberScheduled: 1, + NumberAvailable: 1, + NumberUnavailable: 2, + }, + }, + update: extensions.DaemonSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "abc", + Namespace: metav1.NamespaceDefault, + ResourceVersion: "10", + }, + Status: extensions.DaemonSetStatus{ + CurrentNumberScheduled: 1, + NumberMisscheduled: 1, + DesiredNumberScheduled: 3, + NumberReady: 1, + ObservedGeneration: 3, + UpdatedNumberScheduled: 1, + NumberAvailable: 1, + NumberUnavailable: -2, }, }, }, @@ -349,6 +499,9 @@ func TestValidateDaemonSetUpdate(t *testing.T) { Spec: extensions.DaemonSetSpec{ Selector: &metav1.LabelSelector{MatchLabels: validSelector}, Template: validPodTemplateAbc.Template, + UpdateStrategy: extensions.DaemonSetUpdateStrategy{ + Type: extensions.OnDeleteDaemonSetStrategyType, + }, }, }, update: extensions.DaemonSet{ @@ -356,6 +509,9 @@ func TestValidateDaemonSetUpdate(t *testing.T) { Spec: extensions.DaemonSetSpec{ Selector: &metav1.LabelSelector{MatchLabels: validSelector}, Template: validPodTemplateAbc.Template, + UpdateStrategy: extensions.DaemonSetUpdateStrategy{ + Type: extensions.OnDeleteDaemonSetStrategyType, + }, }, }, }, @@ -365,6 +521,9 @@ func TestValidateDaemonSetUpdate(t *testing.T) { Spec: extensions.DaemonSetSpec{ Selector: &metav1.LabelSelector{MatchLabels: validSelector}, Template: validPodTemplateAbc.Template, + UpdateStrategy: extensions.DaemonSetUpdateStrategy{ + Type: extensions.OnDeleteDaemonSetStrategyType, + }, }, }, update: extensions.DaemonSet{ @@ -372,6 +531,9 @@ func TestValidateDaemonSetUpdate(t *testing.T) { Spec: extensions.DaemonSetSpec{ Selector: &metav1.LabelSelector{MatchLabels: validSelector2}, Template: validPodTemplateAbc2.Template, + UpdateStrategy: extensions.DaemonSetUpdateStrategy{ + Type: extensions.OnDeleteDaemonSetStrategyType, + }, }, }, }, @@ -381,6 +543,9 @@ func TestValidateDaemonSetUpdate(t *testing.T) { Spec: extensions.DaemonSetSpec{ Selector: &metav1.LabelSelector{MatchLabels: validSelector}, Template: validPodTemplateAbc.Template, + UpdateStrategy: extensions.DaemonSetUpdateStrategy{ + Type: extensions.OnDeleteDaemonSetStrategyType, + }, }, }, update: extensions.DaemonSet{ @@ -388,6 +553,9 @@ func TestValidateDaemonSetUpdate(t *testing.T) { Spec: extensions.DaemonSetSpec{ Selector: &metav1.LabelSelector{MatchLabels: validSelector}, Template: validPodTemplateNodeSelector.Template, + UpdateStrategy: extensions.DaemonSetUpdateStrategy{ + Type: extensions.OnDeleteDaemonSetStrategyType, + }, }, }, }, @@ -536,6 +704,9 @@ func TestValidateDaemonSet(t *testing.T) { Spec: extensions.DaemonSetSpec{ Selector: &metav1.LabelSelector{MatchLabels: validSelector}, Template: validPodTemplate.Template, + UpdateStrategy: extensions.DaemonSetUpdateStrategy{ + Type: extensions.OnDeleteDaemonSetStrategyType, + }, }, }, { @@ -543,6 +714,9 @@ func TestValidateDaemonSet(t *testing.T) { Spec: extensions.DaemonSetSpec{ Selector: &metav1.LabelSelector{MatchLabels: validSelector}, Template: validPodTemplate.Template, + UpdateStrategy: extensions.DaemonSetUpdateStrategy{ + Type: extensions.OnDeleteDaemonSetStrategyType, + }, }, }, } diff --git a/pkg/apis/extensions/zz_generated.deepcopy.go b/pkg/apis/extensions/zz_generated.deepcopy.go index d1920f9a420..d2187b5e42c 100644 --- a/pkg/apis/extensions/zz_generated.deepcopy.go +++ b/pkg/apis/extensions/zz_generated.deepcopy.go @@ -46,6 +46,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error { conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_extensions_DaemonSetList, InType: reflect.TypeOf(&DaemonSetList{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_extensions_DaemonSetSpec, InType: reflect.TypeOf(&DaemonSetSpec{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_extensions_DaemonSetStatus, InType: reflect.TypeOf(&DaemonSetStatus{})}, + conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_extensions_DaemonSetUpdateStrategy, InType: reflect.TypeOf(&DaemonSetUpdateStrategy{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_extensions_Deployment, InType: reflect.TypeOf(&Deployment{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_extensions_DeploymentCondition, InType: reflect.TypeOf(&DeploymentCondition{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_extensions_DeploymentList, InType: reflect.TypeOf(&DeploymentList{})}, @@ -82,6 +83,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error { conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_extensions_ReplicaSetStatus, InType: reflect.TypeOf(&ReplicaSetStatus{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_extensions_ReplicationControllerDummy, InType: reflect.TypeOf(&ReplicationControllerDummy{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_extensions_RollbackConfig, InType: reflect.TypeOf(&RollbackConfig{})}, + conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_extensions_RollingUpdateDaemonSet, InType: reflect.TypeOf(&RollingUpdateDaemonSet{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_extensions_RollingUpdateDeployment, InType: reflect.TypeOf(&RollingUpdateDeployment{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_extensions_RunAsUserStrategyOptions, InType: reflect.TypeOf(&RunAsUserStrategyOptions{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_extensions_SELinuxStrategyOptions, InType: reflect.TypeOf(&SELinuxStrategyOptions{})}, @@ -212,6 +214,9 @@ func DeepCopy_extensions_DaemonSetSpec(in interface{}, out interface{}, c *conve if err := api.DeepCopy_api_PodTemplateSpec(&in.Template, &out.Template, c); err != nil { return err } + if err := DeepCopy_extensions_DaemonSetUpdateStrategy(&in.UpdateStrategy, &out.UpdateStrategy, c); err != nil { + return err + } return nil } } @@ -225,6 +230,20 @@ func DeepCopy_extensions_DaemonSetStatus(in interface{}, out interface{}, c *con } } +func DeepCopy_extensions_DaemonSetUpdateStrategy(in interface{}, out interface{}, c *conversion.Cloner) error { + { + in := in.(*DaemonSetUpdateStrategy) + out := out.(*DaemonSetUpdateStrategy) + *out = *in + if in.RollingUpdate != nil { + in, out := &in.RollingUpdate, &out.RollingUpdate + *out = new(RollingUpdateDaemonSet) + **out = **in + } + return nil + } +} + func DeepCopy_extensions_Deployment(in interface{}, out interface{}, c *conversion.Cloner) error { { in := in.(*Deployment) @@ -862,6 +881,15 @@ func DeepCopy_extensions_RollbackConfig(in interface{}, out interface{}, c *conv } } +func DeepCopy_extensions_RollingUpdateDaemonSet(in interface{}, out interface{}, c *conversion.Cloner) error { + { + in := in.(*RollingUpdateDaemonSet) + out := out.(*RollingUpdateDaemonSet) + *out = *in + return nil + } +} + func DeepCopy_extensions_RollingUpdateDeployment(in interface{}, out interface{}, c *conversion.Cloner) error { { in := in.(*RollingUpdateDeployment) diff --git a/pkg/controller/daemon/BUILD b/pkg/controller/daemon/BUILD index d019a6d1e8e..29875a7c552 100644 --- a/pkg/controller/daemon/BUILD +++ b/pkg/controller/daemon/BUILD @@ -13,6 +13,7 @@ go_library( srcs = [ "daemoncontroller.go", "doc.go", + "update.go", ], tags = ["automanaged"], deps = [ @@ -26,6 +27,7 @@ go_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/util/metrics:go_default_library", "//plugin/pkg/scheduler/algorithm:go_default_library", "//plugin/pkg/scheduler/algorithm/predicates:go_default_library", @@ -35,6 +37,7 @@ go_library( "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", "//vendor:k8s.io/apimachinery/pkg/labels", "//vendor:k8s.io/apimachinery/pkg/util/errors", + "//vendor:k8s.io/apimachinery/pkg/util/intstr", "//vendor:k8s.io/apimachinery/pkg/util/runtime", "//vendor:k8s.io/apimachinery/pkg/util/wait", "//vendor:k8s.io/client-go/kubernetes/typed/core/v1", @@ -47,7 +50,10 @@ go_library( go_test( name = "go_default_test", - srcs = ["daemoncontroller_test.go"], + srcs = [ + "daemoncontroller_test.go", + "update_test.go", + ], library = ":go_default_library", tags = ["automanaged"], deps = [ @@ -62,6 +68,7 @@ go_test( "//vendor:k8s.io/apimachinery/pkg/api/resource", "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", "//vendor:k8s.io/apimachinery/pkg/runtime", + "//vendor:k8s.io/apimachinery/pkg/util/intstr", "//vendor:k8s.io/apiserver/pkg/storage/names", "//vendor:k8s.io/client-go/testing", "//vendor:k8s.io/client-go/tools/cache", @@ -78,6 +85,9 @@ filegroup( filegroup( name = "all-srcs", - srcs = [":package-srcs"], + srcs = [ + ":package-srcs", + "//pkg/controller/daemon/util:all-srcs", + ], tags = ["automanaged"], ) diff --git a/pkg/controller/daemon/daemoncontroller.go b/pkg/controller/daemon/daemoncontroller.go index 34876a72e51..aaf3f71d29c 100644 --- a/pkg/controller/daemon/daemoncontroller.go +++ b/pkg/controller/daemon/daemoncontroller.go @@ -44,6 +44,7 @@ import ( corelisters "k8s.io/kubernetes/pkg/client/listers/core/v1" extensionslisters "k8s.io/kubernetes/pkg/client/listers/extensions/v1beta1" "k8s.io/kubernetes/pkg/controller" + "k8s.io/kubernetes/pkg/controller/daemon/util" "k8s.io/kubernetes/pkg/util/metrics" "k8s.io/kubernetes/plugin/pkg/scheduler/algorithm" "k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/predicates" @@ -255,6 +256,17 @@ func (dsc *DaemonSetsController) enqueueDaemonSet(ds *extensions.DaemonSet) { dsc.queue.Add(key) } +func (dsc *DaemonSetsController) enqueueDaemonSetAfter(obj interface{}, after time.Duration) { + key, err := controller.KeyFunc(obj) + if err != nil { + utilruntime.HandleError(fmt.Errorf("Couldn't get key for object %+v: %v", obj, err)) + return + } + + // TODO: Handle overlapping controllers better. See comment in ReplicationManager. + dsc.queue.AddAfter(key, after) +} + func (dsc *DaemonSetsController) getPodDaemonSet(pod *v1.Pod) *extensions.DaemonSet { // look up in the cache, if cached and the cache is valid, just return cached value if obj, cached := dsc.lookupCache.GetMatchingObject(pod); cached { @@ -342,8 +354,14 @@ func (dsc *DaemonSetsController) updatePod(old, cur interface{}) { return } glog.V(4).Infof("Pod %s updated.", curPod.Name) + changedToReady := !v1.IsPodReady(oldPod) && v1.IsPodReady(curPod) if curDS := dsc.getPodDaemonSet(curPod); curDS != nil { dsc.enqueueDaemonSet(curDS) + + // See https://github.com/kubernetes/kubernetes/pull/38076 for more details + if changedToReady && curDS.Spec.MinReadySeconds > 0 { + dsc.enqueueDaemonSetAfter(curDS, time.Duration(curDS.Spec.MinReadySeconds)*time.Second) + } } // If the labels have not changed, then the daemon set responsible for // the pod is the same as it was before. In that case we have enqueued the daemon @@ -521,11 +539,23 @@ func (dsc *DaemonSetsController) manage(ds *extensions.DaemonSet) error { } } } + errors := dsc.syncNodes(ds, podsToDelete, nodesNeedingDaemonPods) + // 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 utilerrors.NewAggregate(errors) +} + +// syncNodes deletes given pods and creates new daemon set pods on the given node +// returns slice with erros if any +func (dsc *DaemonSetsController) syncNodes(ds *extensions.DaemonSet, podsToDelete, nodesNeedingDaemonPods []string) []error { // We need to set expectations before creating/deleting pods to avoid race conditions. dsKey, err := controller.KeyFunc(ds) if err != nil { - return fmt.Errorf("couldn't get key for object %#v: %v", ds, err) + return []error{fmt.Errorf("couldn't get key for object %#v: %v", ds, err)} } createDiff := len(nodesNeedingDaemonPods) @@ -546,10 +576,11 @@ func (dsc *DaemonSetsController) manage(ds *extensions.DaemonSet) error { 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) for i := 0; i < createDiff; i++ { go func(ix int) { defer createWait.Done() - if err := dsc.podControl.CreatePodsOnNode(nodesNeedingDaemonPods[ix], ds.Namespace, &ds.Spec.Template, ds); err != nil { + if err := dsc.podControl.CreatePodsOnNode(nodesNeedingDaemonPods[ix], ds.Namespace, &template, ds); err != nil { glog.V(2).Infof("Failed creation, decrementing expectations for set %q/%q", ds.Namespace, ds.Name) dsc.expectations.CreationObserved(dsKey) errCh <- err @@ -581,18 +612,17 @@ func (dsc *DaemonSetsController) manage(ds *extensions.DaemonSet) error { for err := range errCh { errors = append(errors, 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 utilerrors.NewAggregate(errors) + return errors } -func storeDaemonSetStatus(dsClient unversionedextensions.DaemonSetInterface, ds *extensions.DaemonSet, desiredNumberScheduled, currentNumberScheduled, numberMisscheduled, numberReady int) error { +func storeDaemonSetStatus(dsClient unversionedextensions.DaemonSetInterface, ds *extensions.DaemonSet, desiredNumberScheduled, currentNumberScheduled, numberMisscheduled, numberReady, updatedNumberScheduled, numberAvailable, numberUnavailable int) error { if int(ds.Status.DesiredNumberScheduled) == desiredNumberScheduled && int(ds.Status.CurrentNumberScheduled) == currentNumberScheduled && int(ds.Status.NumberMisscheduled) == numberMisscheduled && int(ds.Status.NumberReady) == numberReady && + int(ds.Status.UpdatedNumberScheduled) == updatedNumberScheduled && + int(ds.Status.NumberAvailable) == numberAvailable && + int(ds.Status.NumberUnavailable) == numberUnavailable && ds.Status.ObservedGeneration >= ds.Generation { return nil } @@ -611,6 +641,9 @@ func storeDaemonSetStatus(dsClient unversionedextensions.DaemonSetInterface, ds toUpdate.Status.CurrentNumberScheduled = int32(currentNumberScheduled) toUpdate.Status.NumberMisscheduled = int32(numberMisscheduled) toUpdate.Status.NumberReady = int32(numberReady) + toUpdate.Status.UpdatedNumberScheduled = int32(updatedNumberScheduled) + toUpdate.Status.NumberAvailable = int32(numberAvailable) + toUpdate.Status.NumberUnavailable = int32(numberUnavailable) if _, updateErr = dsClient.UpdateStatus(toUpdate); updateErr == nil { return nil @@ -638,7 +671,7 @@ func (dsc *DaemonSetsController) updateDaemonSetStatus(ds *extensions.DaemonSet) return fmt.Errorf("couldn't get list of nodes when updating daemon set %#v: %v", ds, err) } - var desiredNumberScheduled, currentNumberScheduled, numberMisscheduled, numberReady int + var desiredNumberScheduled, currentNumberScheduled, numberMisscheduled, numberReady, updatedNumberScheduled, numberAvailable int for i := range nodeList { node := nodeList[i] wantToRun, _, _, err := dsc.nodeShouldRunDaemonPod(node, ds) @@ -652,11 +685,18 @@ func (dsc *DaemonSetsController) updateDaemonSetStatus(ds *extensions.DaemonSet) desiredNumberScheduled++ if scheduled { currentNumberScheduled++ - // Sort the daemon pods by creation time, so the the oldest is first. + // Sort the daemon pods by creation time, so that the oldest is first. daemonPods, _ := nodeToDaemonPods[node.Name] sort.Sort(podByCreationTimestamp(daemonPods)) - if v1.IsPodReady(daemonPods[0]) { + pod := daemonPods[0] + if v1.IsPodReady(pod) { numberReady++ + if v1.IsPodAvailable(pod, ds.Spec.MinReadySeconds, metav1.Now()) { + numberAvailable++ + } + } + if util.IsPodUpdated(ds.Spec.TemplateGeneration, pod) { + updatedNumberScheduled++ } } } else { @@ -665,8 +705,9 @@ func (dsc *DaemonSetsController) updateDaemonSetStatus(ds *extensions.DaemonSet) } } } + numberUnavailable := desiredNumberScheduled - numberAvailable - err = storeDaemonSetStatus(dsc.kubeClient.Extensions().DaemonSets(ds.Namespace), ds, desiredNumberScheduled, currentNumberScheduled, numberMisscheduled, numberReady) + err = storeDaemonSetStatus(dsc.kubeClient.Extensions().DaemonSets(ds.Namespace), ds, desiredNumberScheduled, currentNumberScheduled, numberMisscheduled, numberReady, updatedNumberScheduled, numberAvailable, numberUnavailable) if err != nil { return fmt.Errorf("error storing status for daemon set %#v: %v", ds, err) } @@ -714,6 +755,17 @@ func (dsc *DaemonSetsController) syncDaemonSet(key string) error { } } + dsNeedsSync = dsc.expectations.SatisfiedExpectations(dsKey) + if dsNeedsSync && ds.DeletionTimestamp == nil { + switch ds.Spec.UpdateStrategy.Type { + case extensions.RollingUpdateDaemonSetStrategyType: + err = dsc.rollingUpdate(ds) + } + if err != nil { + return err + } + } + return dsc.updateDaemonSetStatus(ds) } diff --git a/pkg/controller/daemon/daemoncontroller_test.go b/pkg/controller/daemon/daemoncontroller_test.go index 4a348696995..faac5fdc79f 100644 --- a/pkg/controller/daemon/daemoncontroller_test.go +++ b/pkg/controller/daemon/daemoncontroller_test.go @@ -18,6 +18,7 @@ package daemon import ( "fmt" + "sync" "testing" "k8s.io/apimachinery/pkg/api/resource" @@ -166,6 +167,63 @@ func addFailedPods(podStore cache.Store, nodeName string, label map[string]strin } } +type fakePodControl struct { + sync.Mutex + *controller.FakePodControl + podStore cache.Store + podIDMap map[string]*v1.Pod +} + +func newFakePodControl() *fakePodControl { + podIDMap := make(map[string]*v1.Pod) + return &fakePodControl{ + FakePodControl: &controller.FakePodControl{}, + podIDMap: podIDMap} +} + +func (f *fakePodControl) CreatePodsOnNode(nodeName, namespace string, template *v1.PodTemplateSpec, object runtime.Object) error { + f.Lock() + defer f.Unlock() + if err := f.FakePodControl.CreatePodsOnNode(nodeName, namespace, template, object); err != nil { + return fmt.Errorf("failed to create pod on node %q", nodeName) + } + + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Labels: template.Labels, + Namespace: namespace, + GenerateName: fmt.Sprintf("%s-", nodeName), + }, + } + + if err := api.Scheme.Convert(&template.Spec, &pod.Spec, nil); err != nil { + return fmt.Errorf("unable to convert pod template: %v", err) + } + if len(nodeName) != 0 { + pod.Spec.NodeName = nodeName + } + pod.Name = names.SimpleNameGenerator.GenerateName(fmt.Sprintf("%s-", nodeName)) + + f.podStore.Update(pod) + f.podIDMap[pod.Name] = pod + return nil +} + +func (f *fakePodControl) DeletePod(namespace string, podID string, object runtime.Object) error { + f.Lock() + defer f.Unlock() + if err := f.FakePodControl.DeletePod(namespace, podID, object); err != nil { + return fmt.Errorf("failed to delete pod %q", podID) + } + pod, ok := f.podIDMap[podID] + if !ok { + return fmt.Errorf("pod %q does not exist", podID) + } + f.podStore.Delete(pod) + delete(f.podIDMap, podID) + return nil +} + type daemonSetsController struct { *DaemonSetsController @@ -174,7 +232,7 @@ type daemonSetsController struct { nodeStore cache.Store } -func newTestController(initialObjects ...runtime.Object) (*daemonSetsController, *controller.FakePodControl, *fake.Clientset) { +func newTestController(initialObjects ...runtime.Object) (*daemonSetsController, *fakePodControl, *fake.Clientset) { clientset := fake.NewSimpleClientset(initialObjects...) informerFactory := informers.NewSharedInformerFactory(clientset, controller.NoResyncPeriodFunc()) @@ -190,8 +248,9 @@ func newTestController(initialObjects ...runtime.Object) (*daemonSetsController, manager.podStoreSynced = alwaysReady manager.nodeStoreSynced = alwaysReady manager.dsStoreSynced = alwaysReady - podControl := &controller.FakePodControl{} + podControl := newFakePodControl() manager.podControl = podControl + podControl.podStore = informerFactory.Core().V1().Pods().Informer().GetStore() return &daemonSetsController{ manager, @@ -201,7 +260,7 @@ func newTestController(initialObjects ...runtime.Object) (*daemonSetsController, }, podControl, clientset } -func validateSyncDaemonSets(t *testing.T, fakePodControl *controller.FakePodControl, expectedCreates, expectedDeletes int) { +func validateSyncDaemonSets(t *testing.T, fakePodControl *fakePodControl, expectedCreates, expectedDeletes int) { if len(fakePodControl.Templates) != expectedCreates { t.Errorf("Unexpected number of creates. Expected %d, saw %d\n", expectedCreates, len(fakePodControl.Templates)) } @@ -210,7 +269,7 @@ func validateSyncDaemonSets(t *testing.T, fakePodControl *controller.FakePodCont } } -func syncAndValidateDaemonSets(t *testing.T, manager *daemonSetsController, ds *extensions.DaemonSet, podControl *controller.FakePodControl, expectedCreates, expectedDeletes int) { +func syncAndValidateDaemonSets(t *testing.T, manager *daemonSetsController, ds *extensions.DaemonSet, podControl *fakePodControl, expectedCreates, expectedDeletes int) { key, err := controller.KeyFunc(ds) if err != nil { t.Errorf("Could not get key for daemon.") @@ -219,6 +278,18 @@ func syncAndValidateDaemonSets(t *testing.T, manager *daemonSetsController, ds * validateSyncDaemonSets(t, podControl, expectedCreates, expectedDeletes) } +// clearExpectations copies the FakePodControl to PodStore and clears the create and delete expectations. +func clearExpectations(t *testing.T, manager *daemonSetsController, ds *extensions.DaemonSet, fakePodControl *fakePodControl) { + fakePodControl.Clear() + + key, err := controller.KeyFunc(ds) + if err != nil { + t.Errorf("Could not get key for daemon.") + return + } + manager.expectations.DeleteExpectations(key) +} + func TestDeleteFinalStateUnknown(t *testing.T) { manager, _, _ := newTestController() addNodes(manager.nodeStore, 0, 1, nil) @@ -231,6 +302,15 @@ func TestDeleteFinalStateUnknown(t *testing.T) { } } +func markPodsReady(store cache.Store) { + // mark pods as ready + for _, obj := range store.List() { + pod := obj.(*v1.Pod) + condition := v1.PodCondition{Type: v1.PodReady, Status: v1.ConditionTrue} + v1.UpdatePodCondition(&pod.Status, &condition) + } +} + // DaemonSets without node selectors should launch pods on every node. func TestSimpleDaemonSetLaunchesPods(t *testing.T) { manager, podControl, _ := newTestController() diff --git a/pkg/controller/daemon/update.go b/pkg/controller/daemon/update.go new file mode 100644 index 00000000000..f13afba8330 --- /dev/null +++ b/pkg/controller/daemon/update.go @@ -0,0 +1,137 @@ +/* +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 daemon + +import ( + "fmt" + + "github.com/golang/glog" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + intstrutil "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/kubernetes/pkg/api/v1" + extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" + "k8s.io/kubernetes/pkg/controller/daemon/util" +) + +// 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 { + newPods, oldPods, err := dsc.getAllDaemonSetPods(ds) + allPods := append(oldPods, newPods...) + + maxUnavailable, numUnavailable, err := dsc.getUnavailableNumbers(ds, allPods) + if err != nil { + return fmt.Errorf("Couldn't get unavailable numbers: %v", err) + } + oldAvailablePods, oldUnavailablePods := util.SplitByAvailablePods(ds.Spec.MinReadySeconds, oldPods) + + // for oldPods delete all not running pods + var podsToDelete []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 + if pod.DeletionTimestamp != nil { + continue + } + glog.V(4).Infof("Marking pod %s/%s for deletion", ds.Name, pod.Name) + podsToDelete = append(podsToDelete, pod.Name) + } + + glog.V(4).Infof("Marking old pods for deletion") + for _, pod := range oldAvailablePods { + if numUnavailable >= maxUnavailable { + glog.V(4).Infof("Number of unavailable DaemonSet pods: %d, is equal to or exceeds allowed maximum: %d", numUnavailable, maxUnavailable) + break + } + glog.V(4).Infof("Marking pod %s/%s for deletion", ds.Name, pod.Name) + podsToDelete = append(podsToDelete, pod.Name) + numUnavailable++ + } + errors := dsc.syncNodes(ds, podsToDelete, []string{}) + return utilerrors.NewAggregate(errors) +} + +func (dsc *DaemonSetsController) getAllDaemonSetPods(ds *extensions.DaemonSet) ([]*v1.Pod, []*v1.Pod, error) { + var newPods []*v1.Pod + var oldPods []*v1.Pod + + selector, err := metav1.LabelSelectorAsSelector(ds.Spec.Selector) + if err != nil { + return newPods, oldPods, err + } + daemonPods, err := dsc.podLister.Pods(ds.Namespace).List(selector) + if err != nil { + return newPods, oldPods, fmt.Errorf("Couldn't get list of pods for daemon set %#v: %v", ds, err) + } + for _, pod := range daemonPods { + if util.IsPodUpdated(ds.Spec.TemplateGeneration, pod) { + newPods = append(newPods, pod) + } else { + oldPods = append(oldPods, pod) + } + } + return newPods, oldPods, nil +} + +func (dsc *DaemonSetsController) getUnavailableNumbers(ds *extensions.DaemonSet, allPods []*v1.Pod) (int, int, error) { + glog.V(4).Infof("Getting unavailable numbers") + // TODO: get nodeList once in syncDaemonSet and pass it to other functions + nodeList, err := dsc.nodeLister.List(labels.Everything()) + if err != nil { + return -1, -1, fmt.Errorf("couldn't get list of nodes during rolling update of daemon set %#v: %v", ds, err) + } + + nodeToDaemonPods, err := dsc.getNodesToDaemonPods(ds) + if err != nil { + return -1, -1, fmt.Errorf("couldn't get node to daemon pods mapping for daemon set %#v: %v", ds, err) + } + + var numUnavailable, desiredNumberScheduled int + for i := range nodeList { + node := nodeList[i] + wantToRun, _, _, err := dsc.nodeShouldRunDaemonPod(node, ds) + if err != nil { + return -1, -1, err + } + if !wantToRun { + continue + } + desiredNumberScheduled++ + daemonPods, exists := nodeToDaemonPods[node.Name] + if !exists { + numUnavailable++ + continue + } + available := false + for _, pod := range daemonPods { + if v1.IsPodAvailable(pod, ds.Spec.MinReadySeconds, metav1.Now()) { + available = true + break + } + } + if !available { + numUnavailable++ + } + } + maxUnavailable, err := intstrutil.GetValueFromIntOrPercent(ds.Spec.UpdateStrategy.RollingUpdate.MaxUnavailable, desiredNumberScheduled, true) + if err != nil { + return -1, -1, fmt.Errorf("Invalid value for MaxUnavailable: %v", err) + } + return maxUnavailable, numUnavailable, nil +} diff --git a/pkg/controller/daemon/update_test.go b/pkg/controller/daemon/update_test.go new file mode 100644 index 00000000000..ea16f6fcbb0 --- /dev/null +++ b/pkg/controller/daemon/update_test.go @@ -0,0 +1,135 @@ +/* +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 daemon + +import ( + "testing" + + "k8s.io/apimachinery/pkg/util/intstr" + extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" +) + +func TestDaemonSetUpdatesPods(t *testing.T) { + manager, podControl, _ := newTestController() + maxUnavailable := 2 + addNodes(manager.nodeStore, 0, 5, nil) + ds := newDaemonSet("foo") + manager.dsStore.Add(ds) + syncAndValidateDaemonSets(t, manager, ds, podControl, 5, 0) + markPodsReady(podControl.podStore) + + ds.Spec.Template.Spec.Containers[0].Image = "foo2/bar2" + ds.Spec.UpdateStrategy.Type = extensions.RollingUpdateDaemonSetStrategyType + intStr := intstr.FromInt(maxUnavailable) + ds.Spec.UpdateStrategy.RollingUpdate = &extensions.RollingUpdateDaemonSet{MaxUnavailable: &intStr} + ds.Spec.TemplateGeneration++ + manager.dsStore.Update(ds) + + clearExpectations(t, manager, ds, podControl) + syncAndValidateDaemonSets(t, manager, ds, podControl, 0, maxUnavailable) + clearExpectations(t, manager, ds, podControl) + syncAndValidateDaemonSets(t, manager, ds, podControl, maxUnavailable, 0) + markPodsReady(podControl.podStore) + + clearExpectations(t, manager, ds, podControl) + syncAndValidateDaemonSets(t, manager, ds, podControl, 0, maxUnavailable) + clearExpectations(t, manager, ds, podControl) + syncAndValidateDaemonSets(t, manager, ds, podControl, maxUnavailable, 0) + markPodsReady(podControl.podStore) + + clearExpectations(t, manager, ds, podControl) + syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 1) + clearExpectations(t, manager, ds, podControl) + syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0) + markPodsReady(podControl.podStore) + + clearExpectations(t, manager, ds, podControl) + syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0) + clearExpectations(t, manager, ds, podControl) +} + +func TestDaemonSetUpdatesWhenNewPosIsNotReady(t *testing.T) { + manager, podControl, _ := newTestController() + maxUnavailable := 3 + addNodes(manager.nodeStore, 0, 5, nil) + ds := newDaemonSet("foo") + manager.dsStore.Add(ds) + syncAndValidateDaemonSets(t, manager, ds, podControl, 5, 0) + markPodsReady(podControl.podStore) + + ds.Spec.Template.Spec.Containers[0].Image = "foo2/bar2" + ds.Spec.UpdateStrategy.Type = extensions.RollingUpdateDaemonSetStrategyType + intStr := intstr.FromInt(maxUnavailable) + ds.Spec.UpdateStrategy.RollingUpdate = &extensions.RollingUpdateDaemonSet{MaxUnavailable: &intStr} + ds.Spec.TemplateGeneration++ + manager.dsStore.Update(ds) + + // new pods are not ready numUnavailable == maxUnavailable + clearExpectations(t, manager, ds, podControl) + syncAndValidateDaemonSets(t, manager, ds, podControl, 0, maxUnavailable) + clearExpectations(t, manager, ds, podControl) + syncAndValidateDaemonSets(t, manager, ds, podControl, maxUnavailable, 0) + + clearExpectations(t, manager, ds, podControl) + syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0) + clearExpectations(t, manager, ds, podControl) +} + +func TestDaemonSetUpdatesAllOldPodsNotReady(t *testing.T) { + manager, podControl, _ := newTestController() + maxUnavailable := 3 + addNodes(manager.nodeStore, 0, 5, nil) + ds := newDaemonSet("foo") + manager.dsStore.Add(ds) + syncAndValidateDaemonSets(t, manager, ds, podControl, 5, 0) + + ds.Spec.Template.Spec.Containers[0].Image = "foo2/bar2" + ds.Spec.UpdateStrategy.Type = extensions.RollingUpdateDaemonSetStrategyType + intStr := intstr.FromInt(maxUnavailable) + ds.Spec.UpdateStrategy.RollingUpdate = &extensions.RollingUpdateDaemonSet{MaxUnavailable: &intStr} + ds.Spec.TemplateGeneration++ + manager.dsStore.Update(ds) + + // all old pods are unavailable so should be removed + clearExpectations(t, manager, ds, podControl) + syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 5) + clearExpectations(t, manager, ds, podControl) + syncAndValidateDaemonSets(t, manager, ds, podControl, 5, 0) + + clearExpectations(t, manager, ds, podControl) + syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0) + clearExpectations(t, manager, ds, podControl) +} + +func TestDaemonSetUpdatesNoTemplateChanged(t *testing.T) { + manager, podControl, _ := newTestController() + maxUnavailable := 3 + addNodes(manager.nodeStore, 0, 5, nil) + ds := newDaemonSet("foo") + manager.dsStore.Add(ds) + syncAndValidateDaemonSets(t, manager, ds, podControl, 5, 0) + + ds.Spec.UpdateStrategy.Type = extensions.RollingUpdateDaemonSetStrategyType + intStr := intstr.FromInt(maxUnavailable) + ds.Spec.UpdateStrategy.RollingUpdate = &extensions.RollingUpdateDaemonSet{MaxUnavailable: &intStr} + manager.dsStore.Update(ds) + + // template is not changed no pod should be removed + clearExpectations(t, manager, ds, podControl) + syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0) + clearExpectations(t, manager, ds, podControl) +} diff --git a/pkg/controller/daemon/util/BUILD b/pkg/controller/daemon/util/BUILD new file mode 100644 index 00000000000..11eb61c5490 --- /dev/null +++ b/pkg/controller/daemon/util/BUILD @@ -0,0 +1,48 @@ +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_library( + name = "go_default_library", + srcs = ["daemonset_util.go"], + tags = ["automanaged"], + deps = [ + "//pkg/api:go_default_library", + "//pkg/api/v1:go_default_library", + "//pkg/apis/extensions/v1beta1:go_default_library", + "//pkg/util/labels:go_default_library", + "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) + +go_test( + name = "go_default_test", + srcs = ["daemonset_util_test.go"], + library = ":go_default_library", + tags = ["automanaged"], + deps = [ + "//pkg/api/testapi:go_default_library", + "//pkg/api/v1:go_default_library", + "//pkg/apis/extensions:go_default_library", + "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", + ], +) diff --git a/pkg/controller/daemon/util/daemonset_util.go b/pkg/controller/daemon/util/daemonset_util.go new file mode 100644 index 00000000000..2b1d71021d0 --- /dev/null +++ b/pkg/controller/daemon/util/daemonset_util.go @@ -0,0 +1,62 @@ +/* +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 ( + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/v1" + extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" + labelsutil "k8s.io/kubernetes/pkg/util/labels" +) + +// GetPodTemplateWithHash returns copy of provided template with additional +// label which contains hash of provided template +func GetPodTemplateWithGeneration(template v1.PodTemplateSpec, generation int64) v1.PodTemplateSpec { + obj, _ := api.Scheme.DeepCopy(template) + newTemplate := obj.(v1.PodTemplateSpec) + templateGenerationStr := fmt.Sprint(generation) + newTemplate.ObjectMeta.Labels = labelsutil.CloneAndAddLabel( + template.ObjectMeta.Labels, + extensions.DaemonSetTemplateGenerationKey, + templateGenerationStr, + ) + 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 +} + +// SplitByAvailablePods splits provided daemon set pods by availabilty +func SplitByAvailablePods(minReadySeconds int32, pods []*v1.Pod) ([]*v1.Pod, []*v1.Pod) { + unavailablePods := []*v1.Pod{} + availablePods := []*v1.Pod{} + for _, pod := range pods { + if v1.IsPodAvailable(pod, minReadySeconds, metav1.Now()) { + availablePods = append(availablePods, pod) + } else { + unavailablePods = append(unavailablePods, pod) + } + } + return availablePods, unavailablePods +} diff --git a/pkg/controller/daemon/util/daemonset_util_test.go b/pkg/controller/daemon/util/daemonset_util_test.go new file mode 100644 index 00000000000..630b60ebdd9 --- /dev/null +++ b/pkg/controller/daemon/util/daemonset_util_test.go @@ -0,0 +1,92 @@ +/* +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 ( + "fmt" + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/pkg/api/testapi" + "k8s.io/kubernetes/pkg/api/v1" + "k8s.io/kubernetes/pkg/apis/extensions" +) + +func newPod(podName string, nodeName string, label map[string]string) *v1.Pod { + pod := &v1.Pod{ + TypeMeta: metav1.TypeMeta{APIVersion: testapi.Extensions.GroupVersion().String()}, + ObjectMeta: metav1.ObjectMeta{ + Labels: label, + Namespace: metav1.NamespaceDefault, + }, + Spec: v1.PodSpec{ + NodeName: nodeName, + Containers: []v1.Container{ + { + Image: "foo/bar", + }, + }, + }, + } + pod.Name = podName + return pod +} + +func TestIsPodUpdated(t *testing.T) { + tests := []struct { + templateGeneration int64 + pod *v1.Pod + isUpdated bool + }{ + { + int64(12345), + newPod("pod1", "node1", map[string]string{extensions.DaemonSetTemplateGenerationKey: "12345"}), + true, + }, + { + int64(12355), + newPod("pod1", "node1", map[string]string{extensions.DaemonSetTemplateGenerationKey: "12345"}), + false, + }, + { + int64(12355), + newPod("pod1", "node1", map[string]string{}), + false, + }, + { + int64(12355), + newPod("pod1", "node1", nil), + false, + }, + } + for _, test := range tests { + updated := IsPodUpdated(test.templateGeneration, test.pod) + if updated != test.isUpdated { + t.Errorf("IsPodUpdated returned wrong value. Expected %t, got %t. TemplateGeneration: %d", test.isUpdated, updated, test.templateGeneration) + } + } +} + +func TestGetPodTemplateWithGeneration(t *testing.T) { + generation := int64(1) + 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) + } +} diff --git a/pkg/controller/deployment/util/pod_util.go b/pkg/controller/deployment/util/pod_util.go index b2d4e8464eb..5101e6fa05b 100644 --- a/pkg/controller/deployment/util/pod_util.go +++ b/pkg/controller/deployment/util/pod_util.go @@ -44,6 +44,8 @@ func GetInternalPodTemplateSpecHash(template api.PodTemplateSpec) uint32 { return podTemplateSpecHasher.Sum32() } +// TODO: move it to a better place. It's also used by DaemonSets +// Maybe to pkg/api/v1/resource_helpers.go func GetPodTemplateSpecHashFnv(template v1.PodTemplateSpec) uint32 { podTemplateSpecHasher := fnv.New32a() hashutil.DeepHashObject(podTemplateSpecHasher, template) diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 891c26a871c..417f6e70a82 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -12826,12 +12826,32 @@ func GetOpenAPIDefinitions(ref openapi.ReferenceCallback) map[string]openapi.Ope Ref: ref("k8s.io/kubernetes/pkg/api/v1.PodTemplateSpec"), }, }, + "updateStrategy": { + SchemaProps: spec.SchemaProps{ + Description: "UpdateStrategy to replace existing DaemonSet pods with new pods.", + Ref: ref("k8s.io/kubernetes/pkg/apis/extensions/v1beta1.DaemonSetUpdateStrategy"), + }, + }, + "minReadySeconds": { + SchemaProps: spec.SchemaProps{ + Description: "MinReadySeconds 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).", + Type: []string{"integer"}, + Format: "int32", + }, + }, + "templateGeneration": { + SchemaProps: spec.SchemaProps{ + Description: "A sequence number representing a specific generation of the template. Populated by the system. It can be set only during the creation.", + Type: []string{"integer"}, + Format: "int64", + }, + }, }, Required: []string{"template"}, }, }, Dependencies: []string{ - "k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector", "k8s.io/kubernetes/pkg/api/v1.PodTemplateSpec"}, + "k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector", "k8s.io/kubernetes/pkg/api/v1.PodTemplateSpec", "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.DaemonSetUpdateStrategy"}, }, "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.DaemonSetStatus": { Schema: spec.Schema{ @@ -12873,12 +12893,56 @@ func GetOpenAPIDefinitions(ref openapi.ReferenceCallback) map[string]openapi.Ope Format: "int64", }, }, + "updatedNumberScheduled": { + SchemaProps: spec.SchemaProps{ + Description: "UpdatedNumberScheduled is the total number of nodes that are running updated daemon pod", + Type: []string{"integer"}, + Format: "int32", + }, + }, + "numberAvailable": { + SchemaProps: spec.SchemaProps{ + Description: "NumberAvailable is 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 minReadySeconds)", + Type: []string{"integer"}, + Format: "int32", + }, + }, + "numberUnavailable": { + SchemaProps: spec.SchemaProps{ + Description: "NumberUnavailable is 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 minReadySeconds)", + Type: []string{"integer"}, + Format: "int32", + }, + }, }, Required: []string{"currentNumberScheduled", "numberMisscheduled", "desiredNumberScheduled", "numberReady"}, }, }, Dependencies: []string{}, }, + "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.DaemonSetUpdateStrategy": { + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Properties: map[string]spec.Schema{ + "type": { + SchemaProps: spec.SchemaProps{ + Description: "Type of daemon set update. Can be \"RollingUpdate\" or \"OnDelete\". Default is OnDelete.", + Type: []string{"string"}, + Format: "", + }, + }, + "rollingUpdate": { + SchemaProps: spec.SchemaProps{ + Description: "Rolling update config params. Present only if DaemonSetUpdateStrategy = RollingUpdate.", + Ref: ref("k8s.io/kubernetes/pkg/apis/extensions/v1beta1.RollingUpdateDaemonSet"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.RollingUpdateDaemonSet"}, + }, "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.Deployment": { Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -15031,6 +15095,23 @@ func GetOpenAPIDefinitions(ref openapi.ReferenceCallback) map[string]openapi.Ope }, Dependencies: []string{}, }, + "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.RollingUpdateDaemonSet": { + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Spec to control the desired behavior of daemon set rolling update.", + Properties: map[string]spec.Schema{ + "maxUnavailable": { + SchemaProps: spec.SchemaProps{ + Description: "The maximum number of DaemonSet pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of total number of DaemonSet pods at the start of the update (ex: 10%). Absolute number is calculated from percentage by rounding up. This cannot be 0. Default value is 1. Example: when this is set to 30%, 30% of the currently running DaemonSet pods can be stopped for an update at any given time. The update starts by stopping at most 30% of the currently running DaemonSet pods and then brings up new DaemonSet pods in their place. Once the new pods are ready, it then proceeds onto other DaemonSet pods, thus ensuring that at least 70% of original number of DaemonSet pods are available at all times during the update.", + Ref: ref("k8s.io/apimachinery/pkg/util/intstr.IntOrString"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/util/intstr.IntOrString"}, + }, "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.RollingUpdateDeployment": { Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ diff --git a/pkg/kubectl/rollout_status.go b/pkg/kubectl/rollout_status.go index aca79fb4f8a..af29e9ce266 100644 --- a/pkg/kubectl/rollout_status.go +++ b/pkg/kubectl/rollout_status.go @@ -36,6 +36,8 @@ func StatusViewerFor(kind schema.GroupKind, c internalclientset.Interface) (Stat switch kind { case extensions.Kind("Deployment"): return &DeploymentStatusViewer{c.Extensions()}, nil + case extensions.Kind("DaemonSet"): + return &DaemonSetStatusViewer{c.Extensions()}, nil } return nil, fmt.Errorf("no status viewer has been implemented for %v", kind) } @@ -44,6 +46,10 @@ type DeploymentStatusViewer struct { c extensionsclient.DeploymentsGetter } +type DaemonSetStatusViewer struct { + c extensionsclient.DaemonSetsGetter +} + // Status returns a message describing deployment status, and a bool value indicating if the status is considered done func (s *DeploymentStatusViewer) Status(namespace, name string, revision int64) (string, bool, error) { deployment, err := s.c.Deployments(namespace).Get(name, metav1.GetOptions{}) @@ -77,3 +83,23 @@ func (s *DeploymentStatusViewer) Status(namespace, name string, revision int64) } return fmt.Sprintf("Waiting for deployment spec update to be observed...\n"), false, nil } + +// Status returns a message describing daemon set status, and a bool value indicating if the status is considered done +func (s *DaemonSetStatusViewer) Status(namespace, name string, revision int64) (string, bool, error) { + //ignoring revision as DaemonSets does not have history yet + + daemon, err := s.c.DaemonSets(namespace).Get(name, metav1.GetOptions{}) + if err != nil { + return "", false, err + } + if daemon.Generation <= daemon.Status.ObservedGeneration { + if daemon.Status.UpdatedNumberScheduled < daemon.Status.DesiredNumberScheduled { + return fmt.Sprintf("Waiting for rollout to finish: %d out of %d new pod have been updated...\n", daemon.Status.UpdatedNumberScheduled, daemon.Status.DesiredNumberScheduled), false, nil + } + if daemon.Status.NumberAvailable < daemon.Status.DesiredNumberScheduled { + return fmt.Sprintf("Waiting for rollout to finish: %d of %d updated pods are available...\n", daemon.Status.NumberAvailable, daemon.Status.DesiredNumberScheduled), false, nil + } + return fmt.Sprintf("daemon set %q successfully rolled out\n", name), true, nil + } + return fmt.Sprintf("Waiting for daemon set spec update to be observed...\n"), false, nil +} diff --git a/pkg/registry/extensions/daemonset/storage/storage_test.go b/pkg/registry/extensions/daemonset/storage/storage_test.go index f21eff559d5..4f200901027 100644 --- a/pkg/registry/extensions/daemonset/storage/storage_test.go +++ b/pkg/registry/extensions/daemonset/storage/storage_test.go @@ -49,6 +49,9 @@ func newValidDaemonSet() *extensions.DaemonSet { Namespace: metav1.NamespaceDefault, }, Spec: extensions.DaemonSetSpec{ + UpdateStrategy: extensions.DaemonSetUpdateStrategy{ + Type: extensions.OnDeleteDaemonSetStrategyType, + }, Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"a": "b"}}, Template: api.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ diff --git a/pkg/registry/extensions/daemonset/strategy.go b/pkg/registry/extensions/daemonset/strategy.go index db5797e4cc3..6d02f60e725 100644 --- a/pkg/registry/extensions/daemonset/strategy.go +++ b/pkg/registry/extensions/daemonset/strategy.go @@ -53,6 +53,9 @@ func (daemonSetStrategy) PrepareForCreate(ctx genericapirequest.Context, obj run daemonSet.Status = extensions.DaemonSetStatus{} daemonSet.Generation = 1 + if daemonSet.Spec.TemplateGeneration < 1 { + daemonSet.Spec.TemplateGeneration = 1 + } } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. @@ -63,6 +66,9 @@ func (daemonSetStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, ol // update is not allowed to set status newDaemonSet.Status = oldDaemonSet.Status + // update is not allowed to set TemplateGeneration + newDaemonSet.Spec.TemplateGeneration = oldDaemonSet.Spec.TemplateGeneration + // Any changes to the spec increment the generation number, any changes to the // status should reflect the generation number of the corresponding object. We push // the burden of managing the status onto the clients because we can't (in general) @@ -74,6 +80,11 @@ func (daemonSetStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, ol // // TODO: Any changes to a part of the object that represents desired state (labels, // annotations etc) should also increment the generation. + if !reflect.DeepEqual(oldDaemonSet.Spec.Template, newDaemonSet.Spec.Template) { + newDaemonSet.Spec.TemplateGeneration = oldDaemonSet.Spec.TemplateGeneration + 1 + newDaemonSet.Generation = oldDaemonSet.Generation + 1 + return + } if !reflect.DeepEqual(oldDaemonSet.Spec, newDaemonSet.Spec) { newDaemonSet.Generation = oldDaemonSet.Generation + 1 } diff --git a/test/e2e/daemon_set.go b/test/e2e/daemon_set.go index 4103e95b341..40e0f8fd486 100644 --- a/test/e2e/daemon_set.go +++ b/test/e2e/daemon_set.go @@ -91,6 +91,7 @@ var _ = framework.KubeDescribe("Daemon set [Serial]", func() { f = framework.NewDefaultFramework("daemonsets") image := "gcr.io/google_containers/serve_hostname:v1.4" + redisImage := "gcr.io/google_containers/redis:e2e" dsName := "daemon-set" var ns string @@ -231,6 +232,64 @@ var _ = framework.KubeDescribe("Daemon set [Serial]", func() { err = wait.Poll(dsRetryPeriod, dsRetryTimeout, checkRunningOnAllNodes(f, label)) Expect(err).NotTo(HaveOccurred(), "error waiting for daemon pod to revive") }) + + It("Should not update pod when spec was updated and update strategy is on delete", func() { + label := map[string]string{daemonsetNameLabel: dsName} + + framework.Logf("Creating simple daemon set %s", dsName) + _, err := c.Extensions().DaemonSets(ns).Create(newDaemonSet(dsName, image, label)) + Expect(err).NotTo(HaveOccurred()) + + By("Check that daemon pods launch on every node of the cluster.") + Expect(err).NotTo(HaveOccurred()) + err = wait.Poll(dsRetryPeriod, dsRetryTimeout, checkRunningOnAllNodes(f, label)) + Expect(err).NotTo(HaveOccurred(), "error waiting for daemon pod to start") + + By("Update daemon pods image.") + ds, err := c.Extensions().DaemonSets(ns).Get(dsName, metav1.GetOptions{}) + ds.Spec.Template.Spec.Containers[0].Image = redisImage + _, err = c.Extensions().DaemonSets(ns).Update(ds) + Expect(err).NotTo(HaveOccurred()) + + By("Check that demon pods have not set updated image.") + err = wait.Poll(dsRetryPeriod, dsRetryTimeout, checkDaemonPodsImage(c, ns, label, image)) + Expect(err).NotTo(HaveOccurred()) + + By("Check that daemon pods are still running on every node of the cluster.") + Expect(err).NotTo(HaveOccurred()) + err = wait.Poll(dsRetryPeriod, dsRetryTimeout, checkRunningOnAllNodes(f, label)) + Expect(err).NotTo(HaveOccurred(), "error waiting for daemon pod to start") + }) + + It("Should update pod when spec was updated and update strategy is RollingUpdate", func() { + label := map[string]string{daemonsetNameLabel: dsName} + + framework.Logf("Creating simple daemon set %s", dsName) + _, err := c.Extensions().DaemonSets(ns).Create(newDaemonSet(dsName, image, label)) + Expect(err).NotTo(HaveOccurred()) + + By("Check that daemon pods launch on every node of the cluster.") + Expect(err).NotTo(HaveOccurred()) + err = wait.Poll(dsRetryPeriod, dsRetryTimeout, checkRunningOnAllNodes(f, label)) + Expect(err).NotTo(HaveOccurred(), "error waiting for daemon pod to start") + + By("Update daemon pods image.") + ds, err := c.Extensions().DaemonSets(ns).Get(dsName, metav1.GetOptions{}) + ds.Spec.Template.Spec.Containers[0].Image = redisImage + ds.Spec.UpdateStrategy = extensions.DaemonSetUpdateStrategy{Type: extensions.RollingUpdateDaemonSetStrategyType} + _, err = c.Extensions().DaemonSets(ns).Update(ds) + Expect(err).NotTo(HaveOccurred()) + + By("Check that demon pods have not set updated image.") + err = wait.Poll(dsRetryPeriod, dsRetryTimeout, checkDaemonPodsImage(c, ns, label, redisImage)) + Expect(err).NotTo(HaveOccurred()) + + By("Check that daemon pods are still running on every node of the cluster.") + Expect(err).NotTo(HaveOccurred()) + err = wait.Poll(dsRetryPeriod, dsRetryTimeout, checkRunningOnAllNodes(f, label)) + Expect(err).NotTo(HaveOccurred(), "error waiting for daemon pod to start") + }) + }) func newDaemonSet(dsName, image string, label map[string]string) *extensions.DaemonSet { @@ -389,3 +448,24 @@ func checkDaemonStatus(f *framework.Framework, dsName string) error { } return nil } + +func checkDaemonPodsImage(c clientset.Interface, ns string, selector map[string]string, image string) func() (bool, error) { + return func() (bool, error) { + selector := labels.Set(selector).AsSelector() + options := metav1.ListOptions{LabelSelector: selector.String()} + podList, err := c.Core().Pods(ns).List(options) + if err != nil { + return false, err + } + pods := podList.Items + + for _, pod := range pods { + podImage := pod.Spec.Containers[0].Image + if podImage != image || !v1.IsPodReady(&pod) { + framework.Logf("Wrong image for pod: %s. Expected: %s, got: %s. Pod Ready: %t", pod.Name, image, podImage, v1.IsPodReady(&pod)) + return false, nil + } + } + return true, nil + } +}