diff --git a/docs/features/canary.md b/docs/features/canary.md index 187620de81..d9ed004569 100644 --- a/docs/features/canary.md +++ b/docs/features/canary.md @@ -66,7 +66,7 @@ If no `duration` is specified for a pause step, the rollout will be paused indef kubectl argo rollouts promote ``` -## Controlling Canary Scale +## Dynamic Canary Scale (with Traffic Routing) By default, the rollout controller will scale the canary to match the current trafficWeight of the current step. For example, if the current weight is 25%, and there are four replicas, then the @@ -116,6 +116,38 @@ If no `duration` is specified for a pause step, the rollout will be paused indef kubectl argo rollouts promote ``` +## Dynamic Stable Scale (with Traffic Routing) + +!!! important + Available since v1.1 + +When using traffic routing, the stable ReplicaSet is left scaled to 100% during the update by default. +This has the advantage that if an abort occurs, traffic can be immediately shifted back to the +stable ReplicaSet without delay. + +It is possible to reduce the scale of the stable ReplicaSet during update such that it scales down as +the traffic weight increases to canary. This would be desirable in scenarios where many pods +are run. + +```yaml +spec: + strategy: + canary: + dynamicStableScale: true +``` + +NOTE: that if `dynamicStableScale` is set, and the rollout is aborted, the canary ReplicaSet will +scale down as traffic shifts back to stable. If you wish to leave the canary ReplicaSet scaled +up while aborting, then an explicit value for `abortScaleDownDelay` should be set + +```yaml +spec: + strategy: + canary: + dynamicStableScale: true + abortScaleDownDelay: 30 +``` + ## Mimicking Rolling Update If the `steps` field is omitted, the canary strategy will mimic the rolling update behavior. Similar to the deployment, the canary strategy has the `maxSurge` and `maxUnavailable` fields to configure how the Rollout should progress to the new version. diff --git a/manifests/crds/rollout-crd.yaml b/manifests/crds/rollout-crd.yaml index eb3719983e..72e351afa0 100644 --- a/manifests/crds/rollout-crd.yaml +++ b/manifests/crds/rollout-crd.yaml @@ -305,6 +305,8 @@ spec: type: object canaryService: type: string + dynamicStableScale: + type: boolean maxSurge: anyOf: - type: integer @@ -2776,6 +2778,50 @@ spec: - name - status type: object + weights: + properties: + additional: + items: + properties: + podTemplateHash: + type: string + serviceName: + type: string + weight: + format: int32 + type: integer + required: + - weight + type: object + type: array + canary: + properties: + podTemplateHash: + type: string + serviceName: + type: string + weight: + format: int32 + type: integer + required: + - weight + type: object + stable: + properties: + podTemplateHash: + type: string + serviceName: + type: string + weight: + format: int32 + type: integer + required: + - weight + type: object + required: + - canary + - stable + type: object type: object collisionCount: format: int32 diff --git a/manifests/install.yaml b/manifests/install.yaml index 450bc75af7..dabd177a77 100644 --- a/manifests/install.yaml +++ b/manifests/install.yaml @@ -10003,6 +10003,8 @@ spec: type: object canaryService: type: string + dynamicStableScale: + type: boolean maxSurge: anyOf: - type: integer @@ -12474,6 +12476,50 @@ spec: - name - status type: object + weights: + properties: + additional: + items: + properties: + podTemplateHash: + type: string + serviceName: + type: string + weight: + format: int32 + type: integer + required: + - weight + type: object + type: array + canary: + properties: + podTemplateHash: + type: string + serviceName: + type: string + weight: + format: int32 + type: integer + required: + - weight + type: object + stable: + properties: + podTemplateHash: + type: string + serviceName: + type: string + weight: + format: int32 + type: integer + required: + - weight + type: object + required: + - canary + - stable + type: object type: object collisionCount: format: int32 diff --git a/manifests/namespace-install.yaml b/manifests/namespace-install.yaml index a0d92de442..e9ab004f9d 100644 --- a/manifests/namespace-install.yaml +++ b/manifests/namespace-install.yaml @@ -10003,6 +10003,8 @@ spec: type: object canaryService: type: string + dynamicStableScale: + type: boolean maxSurge: anyOf: - type: integer @@ -12474,6 +12476,50 @@ spec: - name - status type: object + weights: + properties: + additional: + items: + properties: + podTemplateHash: + type: string + serviceName: + type: string + weight: + format: int32 + type: integer + required: + - weight + type: object + type: array + canary: + properties: + podTemplateHash: + type: string + serviceName: + type: string + weight: + format: int32 + type: integer + required: + - weight + type: object + stable: + properties: + podTemplateHash: + type: string + serviceName: + type: string + weight: + format: int32 + type: integer + required: + - weight + type: object + required: + - canary + - stable + type: object type: object collisionCount: format: int32 diff --git a/pkg/apiclient/rollout/rollout.swagger.json b/pkg/apiclient/rollout/rollout.swagger.json index a66384cec5..c7cd42ec0c 100644 --- a/pkg/apiclient/rollout/rollout.swagger.json +++ b/pkg/apiclient/rollout/rollout.swagger.json @@ -701,6 +701,10 @@ "currentExperiment": { "type": "string", "title": "CurrentExperiment indicates the running experiment" + }, + "weights": { + "$ref": "#/definitions/github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.TrafficWeights", + "title": "Weights records the weights which have been set on traffic provider. Only valid when using traffic routing" } }, "title": "CanaryStatus status fields that only pertain to the canary rollout" @@ -792,6 +796,10 @@ "type": "integer", "format": "int32", "title": "AbortScaleDownDelaySeconds adds a delay in second before scaling down the canary pods when update\nis aborted for canary strategy with traffic routing (not applicable for basic canary).\n0 means canary pods are not scaled down.\nDefault is 30 seconds.\n+optional" + }, + "dynamicStableScale": { + "type": "boolean", + "description": "DynamicStableScale is a traffic routing feature which dynamically scales the stable\nReplicaSet to minimize total pods which are running during an update. This is calculated by\nscaling down the stable as traffic is increased to canary. When disabled (the default behavior)\nthe stable ReplicaSet remains fully scaled to support instantaneous aborts." } }, "title": "CanaryStrategy defines parameters for a Replica Based Canary" @@ -1412,6 +1420,39 @@ }, "description": "TLSRoute holds the information on the virtual service's TLS/HTTPS routes that are desired to be matched for changing weights." }, + "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.TrafficWeights": { + "type": "object", + "properties": { + "canary": { + "$ref": "#/definitions/github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.WeightDestination" + }, + "stable": { + "$ref": "#/definitions/github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.WeightDestination" + }, + "additional": { + "type": "array", + "items": { + "$ref": "#/definitions/github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.WeightDestination" + } + } + }, + "title": "TrafficWeights describes the current status of how traffic has been split" + }, + "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.WeightDestination": { + "type": "object", + "properties": { + "weight": { + "type": "integer", + "format": "int32" + }, + "serviceName": { + "type": "string" + }, + "podTemplateHash": { + "type": "string" + } + } + }, "google.protobuf.Any": { "type": "object", "properties": { diff --git a/pkg/apis/api-rules/violation_exceptions.list b/pkg/apis/api-rules/violation_exceptions.list index 5ca2d709d9..8969806866 100644 --- a/pkg/apis/api-rules/violation_exceptions.list +++ b/pkg/apis/api-rules/violation_exceptions.list @@ -23,5 +23,6 @@ API rule violation: list_type_missing,github.com/argoproj/argo-rollouts/pkg/apis API rule violation: list_type_missing,github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1,RolloutStatus,Conditions API rule violation: list_type_missing,github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1,RolloutStatus,PauseConditions API rule violation: list_type_missing,github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1,TLSRoute,SNIHosts +API rule violation: list_type_missing,github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1,TrafficWeights,Additional API rule violation: list_type_missing,github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1,WebMetric,Headers API rule violation: names_match,github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1,RolloutStatus,HPAReplicas diff --git a/pkg/apis/rollouts/v1alpha1/generated.pb.go b/pkg/apis/rollouts/v1alpha1/generated.pb.go index e2feb8ff37..d3382b8301 100644 --- a/pkg/apis/rollouts/v1alpha1/generated.pb.go +++ b/pkg/apis/rollouts/v1alpha1/generated.pb.go @@ -1958,10 +1958,38 @@ func (m *SetCanaryScale) XXX_DiscardUnknown() { var xxx_messageInfo_SetCanaryScale proto.InternalMessageInfo +func (m *TLSRoute) Reset() { *m = TLSRoute{} } +func (*TLSRoute) ProtoMessage() {} +func (*TLSRoute) Descriptor() ([]byte, []int) { + return fileDescriptor_e0e705f843545fab, []int{68} +} +func (m *TLSRoute) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TLSRoute) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *TLSRoute) XXX_Merge(src proto.Message) { + xxx_messageInfo_TLSRoute.Merge(m, src) +} +func (m *TLSRoute) XXX_Size() int { + return m.Size() +} +func (m *TLSRoute) XXX_DiscardUnknown() { + xxx_messageInfo_TLSRoute.DiscardUnknown(m) +} + +var xxx_messageInfo_TLSRoute proto.InternalMessageInfo + func (m *TemplateService) Reset() { *m = TemplateService{} } func (*TemplateService) ProtoMessage() {} func (*TemplateService) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{68} + return fileDescriptor_e0e705f843545fab, []int{69} } func (m *TemplateService) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1989,7 +2017,7 @@ var xxx_messageInfo_TemplateService proto.InternalMessageInfo func (m *TemplateSpec) Reset() { *m = TemplateSpec{} } func (*TemplateSpec) ProtoMessage() {} func (*TemplateSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{69} + return fileDescriptor_e0e705f843545fab, []int{70} } func (m *TemplateSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2017,7 +2045,7 @@ var xxx_messageInfo_TemplateSpec proto.InternalMessageInfo func (m *TemplateStatus) Reset() { *m = TemplateStatus{} } func (*TemplateStatus) ProtoMessage() {} func (*TemplateStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{70} + return fileDescriptor_e0e705f843545fab, []int{71} } func (m *TemplateStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2042,10 +2070,38 @@ func (m *TemplateStatus) XXX_DiscardUnknown() { var xxx_messageInfo_TemplateStatus proto.InternalMessageInfo +func (m *TrafficWeights) Reset() { *m = TrafficWeights{} } +func (*TrafficWeights) ProtoMessage() {} +func (*TrafficWeights) Descriptor() ([]byte, []int) { + return fileDescriptor_e0e705f843545fab, []int{72} +} +func (m *TrafficWeights) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TrafficWeights) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *TrafficWeights) XXX_Merge(src proto.Message) { + xxx_messageInfo_TrafficWeights.Merge(m, src) +} +func (m *TrafficWeights) XXX_Size() int { + return m.Size() +} +func (m *TrafficWeights) XXX_DiscardUnknown() { + xxx_messageInfo_TrafficWeights.DiscardUnknown(m) +} + +var xxx_messageInfo_TrafficWeights proto.InternalMessageInfo + func (m *ValueFrom) Reset() { *m = ValueFrom{} } func (*ValueFrom) ProtoMessage() {} func (*ValueFrom) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{71} + return fileDescriptor_e0e705f843545fab, []int{73} } func (m *ValueFrom) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2073,7 +2129,7 @@ var xxx_messageInfo_ValueFrom proto.InternalMessageInfo func (m *WavefrontMetric) Reset() { *m = WavefrontMetric{} } func (*WavefrontMetric) ProtoMessage() {} func (*WavefrontMetric) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{72} + return fileDescriptor_e0e705f843545fab, []int{74} } func (m *WavefrontMetric) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2101,7 +2157,7 @@ var xxx_messageInfo_WavefrontMetric proto.InternalMessageInfo func (m *WebMetric) Reset() { *m = WebMetric{} } func (*WebMetric) ProtoMessage() {} func (*WebMetric) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{73} + return fileDescriptor_e0e705f843545fab, []int{75} } func (m *WebMetric) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2129,7 +2185,7 @@ var xxx_messageInfo_WebMetric proto.InternalMessageInfo func (m *WebMetricHeader) Reset() { *m = WebMetricHeader{} } func (*WebMetricHeader) ProtoMessage() {} func (*WebMetricHeader) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{74} + return fileDescriptor_e0e705f843545fab, []int{76} } func (m *WebMetricHeader) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2154,6 +2210,34 @@ func (m *WebMetricHeader) XXX_DiscardUnknown() { var xxx_messageInfo_WebMetricHeader proto.InternalMessageInfo +func (m *WeightDestination) Reset() { *m = WeightDestination{} } +func (*WeightDestination) ProtoMessage() {} +func (*WeightDestination) Descriptor() ([]byte, []int) { + return fileDescriptor_e0e705f843545fab, []int{77} +} +func (m *WeightDestination) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *WeightDestination) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *WeightDestination) XXX_Merge(src proto.Message) { + xxx_messageInfo_WeightDestination.Merge(m, src) +} +func (m *WeightDestination) XXX_Size() int { + return m.Size() +} +func (m *WeightDestination) XXX_DiscardUnknown() { + xxx_messageInfo_WeightDestination.DiscardUnknown(m) +} + +var xxx_messageInfo_WeightDestination proto.InternalMessageInfo + func init() { proto.RegisterType((*ALBTrafficRouting)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.ALBTrafficRouting") proto.RegisterType((*AmbassadorTrafficRouting)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.AmbassadorTrafficRouting") @@ -2227,13 +2311,16 @@ func init() { proto.RegisterType((*ScopeDetail)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.ScopeDetail") proto.RegisterType((*SecretKeyRef)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.SecretKeyRef") proto.RegisterType((*SetCanaryScale)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.SetCanaryScale") + proto.RegisterType((*TLSRoute)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.TLSRoute") proto.RegisterType((*TemplateService)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.TemplateService") proto.RegisterType((*TemplateSpec)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.TemplateSpec") proto.RegisterType((*TemplateStatus)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.TemplateStatus") + proto.RegisterType((*TrafficWeights)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.TrafficWeights") proto.RegisterType((*ValueFrom)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.ValueFrom") proto.RegisterType((*WavefrontMetric)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.WavefrontMetric") proto.RegisterType((*WebMetric)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.WebMetric") proto.RegisterType((*WebMetricHeader)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.WebMetricHeader") + proto.RegisterType((*WeightDestination)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.WeightDestination") } func init() { @@ -2241,371 +2328,384 @@ func init() { } var fileDescriptor_e0e705f843545fab = []byte{ - // 5823 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x5d, 0x6c, 0x24, 0xd9, - 0x55, 0xf0, 0x56, 0xff, 0xd8, 0xed, 0xd3, 0xfe, 0xbd, 0xe3, 0xc9, 0xf4, 0xce, 0xee, 0xb8, 0x27, - 0xb5, 0xd1, 0x7e, 0x93, 0x8f, 0xc4, 0x4e, 0x66, 0x77, 0x61, 0xc9, 0x46, 0x2b, 0xba, 0xed, 0x99, - 0x1d, 0x7b, 0xed, 0x19, 0xcf, 0x6d, 0xcf, 0x8e, 0xb2, 0x9b, 0x0d, 0x29, 0x77, 0x5f, 0xb7, 0x6b, - 0xa6, 0xba, 0xaa, 0x53, 0x55, 0xed, 0x19, 0x6f, 0xa2, 0xfc, 0x10, 0x25, 0x04, 0x94, 0x28, 0xcb, - 0xcf, 0x0b, 0x42, 0x20, 0x84, 0x78, 0x40, 0xe4, 0x05, 0xa1, 0x3c, 0x26, 0x22, 0x02, 0x22, 0x2d, - 0x0f, 0xa0, 0xf0, 0x00, 0x1b, 0x90, 0xd2, 0x24, 0x1d, 0x24, 0x04, 0x2f, 0x28, 0x28, 0x12, 0xca, - 0x4a, 0x48, 0xe8, 0xfe, 0xd4, 0xad, 0xba, 0xd5, 0xd5, 0xed, 0x6e, 0x77, 0x79, 0x88, 0x80, 0x37, - 0xf7, 0x3d, 0xe7, 0x9e, 0x73, 0x6f, 0xdd, 0x73, 0xcf, 0xcf, 0x3d, 0xe7, 0x5e, 0xc3, 0x76, 0xd3, - 0xf4, 0x0f, 0x3b, 0xfb, 0xab, 0x75, 0xa7, 0xb5, 0x66, 0xb8, 0x4d, 0xa7, 0xed, 0x3a, 0xf7, 0xd8, - 0x1f, 0xef, 0x77, 0x1d, 0xcb, 0x72, 0x3a, 0xbe, 0xb7, 0xd6, 0xbe, 0xdf, 0x5c, 0x33, 0xda, 0xa6, - 0xb7, 0x26, 0x5b, 0x8e, 0x3e, 0x68, 0x58, 0xed, 0x43, 0xe3, 0x83, 0x6b, 0x4d, 0x62, 0x13, 0xd7, - 0xf0, 0x49, 0x63, 0xb5, 0xed, 0x3a, 0xbe, 0x83, 0x3e, 0x1c, 0x52, 0x5b, 0x0d, 0xa8, 0xb1, 0x3f, - 0x7e, 0x31, 0xe8, 0xbb, 0xda, 0xbe, 0xdf, 0x5c, 0xa5, 0xd4, 0x56, 0x65, 0x4b, 0x40, 0xed, 0xe2, - 0xfb, 0x23, 0x63, 0x69, 0x3a, 0x4d, 0x67, 0x8d, 0x11, 0xdd, 0xef, 0x1c, 0xb0, 0x5f, 0xec, 0x07, - 0xfb, 0x8b, 0x33, 0xbb, 0xf8, 0xd4, 0xfd, 0xe7, 0xbd, 0x55, 0xd3, 0xa1, 0x63, 0x5b, 0xdb, 0x37, - 0xfc, 0xfa, 0xe1, 0xda, 0x51, 0xdf, 0x88, 0x2e, 0xea, 0x11, 0xa4, 0xba, 0xe3, 0x92, 0x24, 0x9c, - 0x67, 0x43, 0x9c, 0x96, 0x51, 0x3f, 0x34, 0x6d, 0xe2, 0x1e, 0x87, 0xb3, 0x6e, 0x11, 0xdf, 0x48, - 0xea, 0xb5, 0x36, 0xa8, 0x97, 0xdb, 0xb1, 0x7d, 0xb3, 0x45, 0xfa, 0x3a, 0xfc, 0xec, 0x49, 0x1d, - 0xbc, 0xfa, 0x21, 0x69, 0x19, 0x7d, 0xfd, 0x9e, 0x19, 0xd4, 0xaf, 0xe3, 0x9b, 0xd6, 0x9a, 0x69, - 0xfb, 0x9e, 0xef, 0xc6, 0x3b, 0xe9, 0xff, 0xae, 0xc1, 0x52, 0x65, 0xbb, 0xba, 0xe7, 0x1a, 0x07, - 0x07, 0x66, 0x1d, 0x3b, 0x1d, 0xdf, 0xb4, 0x9b, 0xe8, 0xbd, 0x30, 0x6d, 0xda, 0x4d, 0x97, 0x78, - 0x5e, 0x49, 0xbb, 0xac, 0x5d, 0x99, 0xa9, 0x2e, 0xbc, 0xd5, 0x2d, 0x3f, 0xd6, 0xeb, 0x96, 0xa7, - 0x37, 0x79, 0x33, 0x0e, 0xe0, 0xe8, 0x39, 0x28, 0x7a, 0xc4, 0x3d, 0x32, 0xeb, 0x64, 0xd7, 0x71, - 0xfd, 0x52, 0xe6, 0xb2, 0x76, 0x25, 0x5f, 0x3d, 0x27, 0xd0, 0x8b, 0xb5, 0x10, 0x84, 0xa3, 0x78, - 0xb4, 0x9b, 0xeb, 0x38, 0xbe, 0x80, 0x97, 0xb2, 0x8c, 0x8b, 0xec, 0x86, 0x43, 0x10, 0x8e, 0xe2, - 0xa1, 0x0d, 0x58, 0x34, 0x6c, 0xdb, 0xf1, 0x0d, 0xdf, 0x74, 0xec, 0x5d, 0x97, 0x1c, 0x98, 0x0f, - 0x4b, 0x39, 0xd6, 0xb7, 0x24, 0xfa, 0x2e, 0x56, 0x62, 0x70, 0xdc, 0xd7, 0x43, 0xdf, 0x80, 0x52, - 0xa5, 0xb5, 0x6f, 0x78, 0x9e, 0xd1, 0x70, 0xdc, 0xd8, 0xd4, 0xaf, 0x40, 0xa1, 0x65, 0xb4, 0xdb, - 0xa6, 0xdd, 0xa4, 0x73, 0xcf, 0x5e, 0x99, 0xa9, 0xce, 0xf6, 0xba, 0xe5, 0xc2, 0x8e, 0x68, 0xc3, - 0x12, 0xaa, 0xff, 0x7d, 0x06, 0x8a, 0x15, 0xdb, 0xb0, 0x8e, 0x3d, 0xd3, 0xc3, 0x1d, 0x1b, 0x7d, - 0x1c, 0x0a, 0x54, 0x06, 0x1a, 0x86, 0x6f, 0xb0, 0xaf, 0x56, 0xbc, 0xfa, 0x81, 0x55, 0xbe, 0x24, - 0xab, 0xd1, 0x25, 0x09, 0x25, 0x9b, 0x62, 0xaf, 0x1e, 0x7d, 0x70, 0xf5, 0xd6, 0xfe, 0x3d, 0x52, - 0xf7, 0x77, 0x88, 0x6f, 0x54, 0x91, 0x98, 0x05, 0x84, 0x6d, 0x58, 0x52, 0x45, 0x0e, 0xe4, 0xbc, - 0x36, 0xa9, 0xb3, 0x8f, 0x5c, 0xbc, 0xba, 0xb3, 0x3a, 0xc9, 0x2e, 0x5a, 0x8d, 0x0c, 0xbd, 0xd6, - 0x26, 0xf5, 0xea, 0xac, 0x60, 0x9d, 0xa3, 0xbf, 0x30, 0x63, 0x84, 0x1e, 0xc0, 0x94, 0xe7, 0x1b, - 0x7e, 0xc7, 0x63, 0x0b, 0x54, 0xbc, 0x7a, 0x2b, 0x3d, 0x96, 0x8c, 0x6c, 0x75, 0x5e, 0x30, 0x9d, - 0xe2, 0xbf, 0xb1, 0x60, 0xa7, 0xff, 0x83, 0x06, 0xe7, 0x22, 0xd8, 0x15, 0xb7, 0xd9, 0x69, 0x11, - 0xdb, 0x47, 0x97, 0x21, 0x67, 0x1b, 0x2d, 0x22, 0xa4, 0x52, 0x0e, 0xf9, 0xa6, 0xd1, 0x22, 0x98, - 0x41, 0xd0, 0x53, 0x90, 0x3f, 0x32, 0xac, 0x0e, 0x61, 0x1f, 0x69, 0xa6, 0x3a, 0x27, 0x50, 0xf2, - 0xaf, 0xd0, 0x46, 0xcc, 0x61, 0xe8, 0x53, 0x30, 0xc3, 0xfe, 0xb8, 0xee, 0x3a, 0xad, 0x94, 0xa6, - 0x26, 0x46, 0xf8, 0x4a, 0x40, 0xb6, 0x3a, 0xd7, 0xeb, 0x96, 0x67, 0xe4, 0x4f, 0x1c, 0x32, 0xd4, - 0xff, 0x51, 0x83, 0x85, 0xc8, 0xe4, 0xb6, 0x4d, 0xcf, 0x47, 0x1f, 0xed, 0x13, 0x9e, 0xd5, 0xd1, - 0x84, 0x87, 0xf6, 0x66, 0xa2, 0xb3, 0x28, 0x66, 0x5a, 0x08, 0x5a, 0x22, 0x82, 0x63, 0x43, 0xde, - 0xf4, 0x49, 0xcb, 0x2b, 0x65, 0x2e, 0x67, 0xaf, 0x14, 0xaf, 0x6e, 0xa6, 0xb6, 0x8c, 0xe1, 0xf7, - 0xdd, 0xa4, 0xf4, 0x31, 0x67, 0xa3, 0xff, 0x4e, 0x46, 0x99, 0x21, 0x95, 0x28, 0xe4, 0xc0, 0x74, - 0x8b, 0xf8, 0xae, 0x59, 0xe7, 0xfb, 0xaa, 0x78, 0x75, 0x63, 0xb2, 0x51, 0xec, 0x30, 0x62, 0xa1, - 0x66, 0xe2, 0xbf, 0x3d, 0x1c, 0x70, 0x41, 0x87, 0x90, 0x33, 0xdc, 0x66, 0x30, 0xe7, 0xeb, 0xe9, - 0xac, 0x6f, 0x28, 0x73, 0x15, 0xb7, 0xe9, 0x61, 0xc6, 0x01, 0xad, 0xc1, 0x8c, 0x4f, 0xdc, 0x96, - 0x69, 0x1b, 0x3e, 0x57, 0x65, 0x85, 0xea, 0x92, 0x40, 0x9b, 0xd9, 0x0b, 0x00, 0x38, 0xc4, 0xd1, - 0xdf, 0xce, 0xc0, 0x52, 0xdf, 0x66, 0x40, 0xcf, 0x42, 0xbe, 0x7d, 0x68, 0x78, 0x81, 0x74, 0xaf, - 0x04, 0x9f, 0x76, 0x97, 0x36, 0xbe, 0xd3, 0x2d, 0xcf, 0x05, 0x5d, 0x58, 0x03, 0xe6, 0xc8, 0x54, - 0x57, 0xb7, 0x88, 0xe7, 0x19, 0xcd, 0x40, 0xe4, 0x23, 0x5f, 0x84, 0x35, 0xe3, 0x00, 0x8e, 0x7e, - 0x59, 0x83, 0x39, 0xfe, 0x75, 0x30, 0xf1, 0x3a, 0x96, 0x4f, 0xb7, 0x35, 0xfd, 0x36, 0x5b, 0x69, - 0xac, 0x04, 0x27, 0x59, 0x3d, 0x2f, 0xb8, 0xcf, 0x45, 0x5b, 0x3d, 0xac, 0xf2, 0x45, 0x77, 0x61, - 0xc6, 0xf3, 0x0d, 0xd7, 0x27, 0x8d, 0x8a, 0xcf, 0x14, 0x78, 0xf1, 0xea, 0xff, 0x1f, 0x4d, 0xde, - 0xf7, 0xcc, 0x16, 0xe1, 0x7b, 0xab, 0x16, 0x10, 0xc0, 0x21, 0x2d, 0xfd, 0x6f, 0x55, 0xc5, 0x51, - 0xf3, 0xa9, 0xb1, 0x6b, 0x1e, 0xa3, 0xd7, 0xe0, 0x71, 0xaf, 0x53, 0xaf, 0x13, 0xcf, 0x3b, 0xe8, - 0x58, 0xb8, 0x63, 0xdf, 0x30, 0x3d, 0xdf, 0x71, 0x8f, 0xb7, 0xcd, 0x96, 0xe9, 0xb3, 0xef, 0x9d, - 0xaf, 0x5e, 0xea, 0x75, 0xcb, 0x8f, 0xd7, 0x06, 0x21, 0xe1, 0xc1, 0xfd, 0x91, 0x01, 0x4f, 0x74, - 0xec, 0xc1, 0xe4, 0xb9, 0x4d, 0x2c, 0xf7, 0xba, 0xe5, 0x27, 0xee, 0x0c, 0x46, 0xc3, 0xc3, 0x68, - 0xe8, 0xff, 0xaa, 0xc1, 0x62, 0x30, 0xaf, 0x3d, 0xd2, 0x6a, 0x5b, 0x86, 0x4f, 0x1e, 0x81, 0xc5, - 0xf1, 0x15, 0x8b, 0x83, 0xd3, 0xd1, 0x1b, 0xc1, 0xf8, 0x07, 0x99, 0x1d, 0xfd, 0x5f, 0x34, 0x58, - 0x8e, 0x23, 0x3f, 0x02, 0x2d, 0xe9, 0xa9, 0x5a, 0xf2, 0x66, 0xba, 0xb3, 0x1d, 0xa0, 0x2a, 0x7f, - 0x94, 0x30, 0xd7, 0xff, 0xe1, 0xfa, 0x52, 0xff, 0xc3, 0x1c, 0xcc, 0x56, 0x6c, 0xdf, 0xac, 0x1c, - 0x1c, 0x98, 0xb6, 0xe9, 0x1f, 0xa3, 0x2f, 0x67, 0x60, 0xad, 0xed, 0x92, 0x03, 0xe2, 0xba, 0xa4, - 0xb1, 0xd1, 0x71, 0x4d, 0xbb, 0x59, 0xab, 0x1f, 0x92, 0x46, 0xc7, 0x32, 0xed, 0xe6, 0x66, 0xd3, - 0x76, 0x64, 0xf3, 0xb5, 0x87, 0xa4, 0xde, 0xa1, 0xae, 0x9c, 0x58, 0xff, 0xd6, 0x64, 0xc3, 0xdc, - 0x1d, 0x8f, 0x69, 0xf5, 0x99, 0x5e, 0xb7, 0xbc, 0x36, 0x66, 0x27, 0x3c, 0xee, 0xd4, 0xd0, 0x97, - 0x32, 0xb0, 0xea, 0x92, 0x4f, 0x74, 0xcc, 0xd1, 0xbf, 0x06, 0xdf, 0xa0, 0xd6, 0x64, 0x5f, 0x03, - 0x8f, 0xc5, 0xb3, 0x7a, 0xb5, 0xd7, 0x2d, 0x8f, 0xd9, 0x07, 0x8f, 0x39, 0x2f, 0xfd, 0xcf, 0x35, - 0x28, 0x8c, 0xe1, 0xfd, 0x95, 0x55, 0xef, 0x6f, 0xa6, 0xcf, 0xf3, 0xf3, 0xfb, 0x3d, 0xbf, 0x97, - 0x26, 0xfb, 0x68, 0xa3, 0x78, 0x7c, 0xff, 0x46, 0xa3, 0xac, 0xb8, 0x87, 0x88, 0x0e, 0x61, 0xb9, - 0xed, 0x34, 0x82, 0x4d, 0x7f, 0xc3, 0xf0, 0x0e, 0x19, 0x4c, 0x4c, 0xef, 0xd9, 0x5e, 0xb7, 0xbc, - 0xbc, 0x9b, 0x00, 0x7f, 0xa7, 0x5b, 0x2e, 0x49, 0x22, 0x31, 0x04, 0x9c, 0x48, 0x11, 0xb5, 0xa1, - 0x70, 0x60, 0x12, 0xab, 0x81, 0xc9, 0x81, 0x90, 0x94, 0x09, 0xb7, 0xf7, 0x75, 0x41, 0x8d, 0x07, - 0x47, 0xc1, 0x2f, 0x2c, 0xb9, 0xe8, 0x3f, 0xc9, 0xc1, 0x42, 0xd5, 0xea, 0x90, 0x97, 0x5c, 0x42, - 0x02, 0xff, 0xa6, 0x02, 0x0b, 0x6d, 0x97, 0x1c, 0x99, 0xe4, 0x41, 0x8d, 0x58, 0xa4, 0xee, 0x3b, - 0xae, 0x98, 0xea, 0x05, 0xb1, 0x92, 0x0b, 0xbb, 0x2a, 0x18, 0xc7, 0xf1, 0xd1, 0x8b, 0x30, 0x6f, - 0xd4, 0x7d, 0xf3, 0x88, 0x48, 0x0a, 0x7c, 0xa1, 0xdf, 0x25, 0x28, 0xcc, 0x57, 0x14, 0x28, 0x8e, - 0x61, 0xa3, 0x8f, 0x42, 0xc9, 0xab, 0x1b, 0x16, 0xb9, 0xd3, 0x16, 0xac, 0xd6, 0x0f, 0x49, 0xfd, - 0xfe, 0xae, 0x63, 0xda, 0xbe, 0x70, 0xdc, 0x2e, 0x0b, 0x4a, 0xa5, 0xda, 0x00, 0x3c, 0x3c, 0x90, - 0x02, 0xfa, 0x53, 0x0d, 0x2e, 0xb5, 0x5d, 0xb2, 0xeb, 0x3a, 0x2d, 0x87, 0x4a, 0x6f, 0x9f, 0x8b, - 0x27, 0x5c, 0x9d, 0x57, 0x26, 0xdc, 0xa6, 0xbc, 0xa5, 0x3f, 0x9a, 0x7a, 0x77, 0xaf, 0x5b, 0xbe, - 0xb4, 0x3b, 0x6c, 0x00, 0x78, 0xf8, 0xf8, 0xd0, 0x9f, 0x69, 0xb0, 0xd2, 0x76, 0x3c, 0x7f, 0xc8, - 0x14, 0xf2, 0x67, 0x3a, 0x05, 0xbd, 0xd7, 0x2d, 0xaf, 0xec, 0x0e, 0x1d, 0x01, 0x3e, 0x61, 0x84, - 0x7a, 0xaf, 0x08, 0x4b, 0x11, 0xd9, 0x13, 0x1e, 0xe0, 0x0b, 0x30, 0x17, 0x08, 0x03, 0x3f, 0x73, - 0xe0, 0xb2, 0x27, 0xfd, 0xd5, 0x4a, 0x14, 0x88, 0x55, 0x5c, 0x2a, 0x77, 0x52, 0x14, 0x79, 0xef, - 0x98, 0xdc, 0xed, 0x2a, 0x50, 0x1c, 0xc3, 0x46, 0x9b, 0x70, 0x4e, 0xb4, 0x60, 0xd2, 0xb6, 0xcc, - 0xba, 0xb1, 0xee, 0x74, 0x84, 0xc8, 0xe5, 0xab, 0x17, 0x7a, 0xdd, 0xf2, 0xb9, 0xdd, 0x7e, 0x30, - 0x4e, 0xea, 0x83, 0xb6, 0x61, 0xd9, 0xe8, 0xf8, 0x8e, 0x9c, 0xff, 0x35, 0xdb, 0xd8, 0xb7, 0x48, - 0x83, 0x89, 0x56, 0xa1, 0x5a, 0xa2, 0x5a, 0xa3, 0x92, 0x00, 0xc7, 0x89, 0xbd, 0xd0, 0x6e, 0x8c, - 0x5a, 0x8d, 0xd4, 0x1d, 0xbb, 0xc1, 0x57, 0x39, 0x5f, 0x7d, 0x52, 0x4c, 0x4f, 0xa5, 0x28, 0x70, - 0x70, 0x62, 0x4f, 0x64, 0xc1, 0x7c, 0xcb, 0x78, 0x78, 0xc7, 0x36, 0x8e, 0x0c, 0xd3, 0xa2, 0x4c, - 0x4a, 0x53, 0x27, 0xb8, 0xa6, 0x1d, 0xdf, 0xb4, 0x56, 0xf9, 0xf9, 0xd4, 0xea, 0xa6, 0xed, 0xdf, - 0x72, 0x6b, 0x3e, 0x35, 0x02, 0x55, 0x44, 0x3f, 0xec, 0x8e, 0x42, 0x0b, 0xc7, 0x68, 0xa3, 0x5b, - 0x70, 0x9e, 0x6d, 0xc7, 0x0d, 0xe7, 0x81, 0xbd, 0x41, 0x2c, 0xe3, 0x38, 0x98, 0xc0, 0x34, 0x9b, - 0xc0, 0xe3, 0xbd, 0x6e, 0xf9, 0x7c, 0x2d, 0x09, 0x01, 0x27, 0xf7, 0xa3, 0xbe, 0xbc, 0x0a, 0xc0, - 0xe4, 0xc8, 0xf4, 0x4c, 0xc7, 0xe6, 0xbe, 0x7c, 0x21, 0xf4, 0xe5, 0x6b, 0x83, 0xd1, 0xf0, 0x30, - 0x1a, 0xe8, 0xb7, 0x35, 0x58, 0x4e, 0xda, 0x86, 0xa5, 0x99, 0x34, 0xce, 0x75, 0x62, 0x5b, 0x8b, - 0x4b, 0x44, 0xa2, 0x52, 0x48, 0x1c, 0x04, 0xfa, 0xac, 0x06, 0xb3, 0x46, 0xc4, 0x39, 0x2b, 0x01, - 0x1b, 0xd5, 0xd6, 0xa4, 0xde, 0x70, 0x48, 0xb1, 0xba, 0xd8, 0xeb, 0x96, 0x15, 0x07, 0x10, 0x2b, - 0x1c, 0xd1, 0xef, 0x6a, 0x70, 0x3e, 0x71, 0x8f, 0x97, 0x8a, 0x67, 0xf1, 0x85, 0x98, 0x90, 0x24, - 0xeb, 0x9c, 0xe4, 0x61, 0xa0, 0x37, 0x35, 0x69, 0xca, 0x76, 0x82, 0x78, 0x64, 0x96, 0x0d, 0xed, - 0xf6, 0x84, 0xfe, 0x68, 0x68, 0xbd, 0x03, 0xc2, 0xd5, 0x73, 0x11, 0xcb, 0x18, 0x34, 0xe2, 0x38, - 0x7b, 0xf4, 0x15, 0x2d, 0x30, 0x8d, 0x72, 0x44, 0x73, 0x67, 0x35, 0x22, 0x14, 0x5a, 0x5a, 0x39, - 0xa0, 0x18, 0x73, 0xf4, 0x31, 0xb8, 0x68, 0xec, 0x3b, 0xae, 0x9f, 0xb8, 0xf9, 0x4a, 0xf3, 0x6c, - 0x1b, 0xad, 0xf4, 0xba, 0xe5, 0x8b, 0x95, 0x81, 0x58, 0x78, 0x08, 0x05, 0xfd, 0x9f, 0xb3, 0x30, - 0xbb, 0x6e, 0xd8, 0x86, 0x7b, 0x2c, 0x4c, 0xd7, 0x37, 0x34, 0x78, 0xb2, 0xde, 0x71, 0x5d, 0x62, - 0xfb, 0x35, 0x9f, 0xb4, 0xfb, 0x0d, 0x97, 0x76, 0xa6, 0x86, 0xeb, 0x72, 0xaf, 0x5b, 0x7e, 0x72, - 0x7d, 0x08, 0x7f, 0x3c, 0x74, 0x74, 0xe8, 0xaf, 0x35, 0xd0, 0x05, 0x42, 0xd5, 0xa8, 0xdf, 0x6f, - 0xba, 0x4e, 0xc7, 0x6e, 0xf4, 0x4f, 0x22, 0x73, 0xa6, 0x93, 0x78, 0xba, 0xd7, 0x2d, 0xeb, 0xeb, - 0x27, 0x8e, 0x02, 0x8f, 0x30, 0x52, 0xf4, 0x12, 0x2c, 0x09, 0xac, 0x6b, 0x0f, 0xdb, 0xc4, 0x35, - 0xa9, 0xef, 0x2b, 0xce, 0xf9, 0x1f, 0x17, 0x66, 0x65, 0x69, 0x3d, 0x8e, 0x80, 0xfb, 0xfb, 0xe8, - 0x7f, 0x9c, 0x03, 0x08, 0x56, 0x9a, 0xb4, 0xd1, 0xcf, 0xc0, 0x8c, 0x47, 0xfc, 0xbb, 0xc4, 0x6c, - 0x1e, 0x06, 0x27, 0x37, 0xfc, 0x38, 0x28, 0x68, 0xc4, 0x21, 0x1c, 0xdd, 0x87, 0x7c, 0xdb, 0xe8, - 0x78, 0x44, 0x7c, 0xb7, 0xad, 0x54, 0xbe, 0xdb, 0x2e, 0xa5, 0xc8, 0x63, 0x0b, 0xf6, 0x27, 0xe6, - 0x3c, 0xd0, 0xe7, 0x35, 0x00, 0xa2, 0xce, 0xb5, 0x78, 0xb5, 0x96, 0x0a, 0xcb, 0xf0, 0x73, 0xd0, - 0x6f, 0x50, 0x9d, 0xef, 0x75, 0xcb, 0x10, 0xf9, 0x6a, 0x11, 0xb6, 0xe8, 0x01, 0x14, 0x8c, 0x40, - 0x5d, 0xe6, 0xce, 0x42, 0x5d, 0x32, 0x97, 0x5f, 0xae, 0xb7, 0x64, 0x86, 0xbe, 0xa4, 0xc1, 0xbc, - 0x47, 0x7c, 0xb1, 0x54, 0x74, 0xd3, 0x0a, 0x5f, 0x71, 0x7b, 0x32, 0xfe, 0x35, 0x85, 0x26, 0x57, - 0x3e, 0x6a, 0x1b, 0x8e, 0xf1, 0xd5, 0xdf, 0x2c, 0xc2, 0x7c, 0x20, 0x32, 0xa1, 0xfb, 0x57, 0xe7, - 0x2d, 0xc9, 0xee, 0xdf, 0x7a, 0x14, 0x88, 0x55, 0x5c, 0xda, 0xd9, 0xf3, 0xa9, 0xbf, 0xa1, 0x7a, - 0x7f, 0xb2, 0x73, 0x2d, 0x0a, 0xc4, 0x2a, 0x2e, 0x6a, 0x41, 0xde, 0xf3, 0x49, 0x3b, 0x38, 0x6c, - 0xbd, 0x31, 0xd9, 0xd7, 0x08, 0x77, 0x42, 0x78, 0xa0, 0x44, 0x7f, 0x79, 0x98, 0x73, 0x41, 0x5f, - 0xd5, 0x60, 0xde, 0x57, 0x72, 0x5a, 0x42, 0x0c, 0xd2, 0x91, 0x44, 0x35, 0x5d, 0xc6, 0x57, 0x43, - 0x6d, 0xc3, 0x31, 0xf6, 0x09, 0x1e, 0x61, 0xfe, 0x0c, 0x3d, 0xc2, 0x57, 0xa1, 0xd0, 0x32, 0x1e, - 0xd6, 0x3a, 0x6e, 0xf3, 0xf4, 0x9e, 0xa7, 0x48, 0xf9, 0x71, 0x2a, 0x58, 0xd2, 0x43, 0x9f, 0xd3, - 0x22, 0x9b, 0x6b, 0x9a, 0x11, 0xbf, 0x9b, 0xee, 0xe6, 0x92, 0x0a, 0x75, 0xe0, 0x36, 0xeb, 0xf3, - 0xcf, 0x0a, 0x8f, 0xdc, 0x3f, 0xa3, 0xbe, 0x06, 0xdf, 0x20, 0xd2, 0xd7, 0x98, 0x39, 0x53, 0x5f, - 0x63, 0x5d, 0x61, 0x86, 0x63, 0xcc, 0xd9, 0x78, 0xf8, 0x9e, 0x93, 0xe3, 0x81, 0x33, 0x1d, 0x4f, - 0x4d, 0x61, 0x86, 0x63, 0xcc, 0x07, 0x07, 0x25, 0xc5, 0xb3, 0x09, 0x4a, 0x66, 0x53, 0x08, 0x4a, - 0x86, 0xfb, 0x6b, 0x73, 0x13, 0xfb, 0x6b, 0x3f, 0xd2, 0xe0, 0xc2, 0xba, 0xd5, 0xf1, 0x7c, 0xe2, - 0xfe, 0xaf, 0xc9, 0x63, 0xfc, 0x87, 0x06, 0x4f, 0x0c, 0x98, 0xf3, 0x23, 0x48, 0x67, 0xbc, 0xa1, - 0xa6, 0x33, 0xee, 0x4c, 0x68, 0x77, 0x92, 0xe7, 0x31, 0x20, 0xab, 0xe1, 0xc3, 0xdc, 0x86, 0xe1, - 0x1b, 0x0d, 0xa7, 0xc9, 0xd3, 0x0c, 0xe8, 0x45, 0x28, 0x98, 0xb6, 0x4f, 0xdc, 0x23, 0xc3, 0x12, - 0x96, 0x57, 0x0f, 0x86, 0xbe, 0x29, 0xda, 0xdf, 0xe9, 0x96, 0xe7, 0x37, 0x3a, 0x2e, 0x2b, 0xd4, - 0xe0, 0x7a, 0x18, 0xcb, 0x3e, 0xe8, 0x29, 0xc8, 0x7f, 0xa2, 0x43, 0xdc, 0xe3, 0x78, 0x5a, 0xff, - 0x36, 0x6d, 0xc4, 0x1c, 0xa6, 0xff, 0x5d, 0x06, 0x22, 0x5e, 0xd1, 0x23, 0x10, 0x2b, 0x5b, 0x11, - 0xab, 0x09, 0xfd, 0x9c, 0x88, 0x8f, 0x37, 0xa8, 0x1e, 0xe3, 0x28, 0x56, 0x8f, 0x71, 0x33, 0x35, - 0x8e, 0xc3, 0xcb, 0x31, 0xde, 0xd6, 0xe0, 0x89, 0x10, 0xb9, 0xdf, 0xd7, 0x3f, 0xf9, 0x60, 0xfe, - 0x39, 0x28, 0x1a, 0x61, 0x37, 0xb1, 0x8a, 0xb2, 0xde, 0x27, 0x42, 0x11, 0x47, 0xf1, 0xc2, 0x94, - 0x78, 0xf6, 0x94, 0x29, 0xf1, 0xdc, 0xf0, 0x94, 0xb8, 0xfe, 0xe3, 0x0c, 0x5c, 0xea, 0x9f, 0x59, - 0x20, 0xdd, 0x98, 0x1c, 0x8c, 0x30, 0xb7, 0xe7, 0x61, 0xd6, 0x17, 0x1d, 0x68, 0xab, 0x98, 0xdc, - 0xb2, 0xc0, 0x9c, 0xdd, 0x8b, 0xc0, 0xb0, 0x82, 0x49, 0x7b, 0xd6, 0xf9, 0xbe, 0xaa, 0xd5, 0x9d, - 0x76, 0x50, 0x3b, 0x20, 0x7b, 0xae, 0x47, 0x60, 0x58, 0xc1, 0x94, 0xc9, 0xba, 0xdc, 0x99, 0x17, - 0x37, 0xd4, 0xe0, 0x7c, 0x90, 0xb3, 0xb9, 0xee, 0xb8, 0xeb, 0x4e, 0xab, 0x6d, 0x11, 0x96, 0x72, - 0xca, 0xb3, 0xc1, 0x5e, 0x12, 0x5d, 0xce, 0xe3, 0x24, 0x24, 0x9c, 0xdc, 0x57, 0x7f, 0x3b, 0x0b, - 0xe7, 0xc2, 0xcf, 0xbe, 0xee, 0xd8, 0x0d, 0x93, 0x65, 0xbe, 0x5e, 0x80, 0x9c, 0x7f, 0xdc, 0x0e, - 0x3e, 0xf6, 0xff, 0x0b, 0x86, 0xb3, 0x77, 0xdc, 0xa6, 0xab, 0x7d, 0x21, 0xa1, 0x0b, 0x05, 0x61, - 0xd6, 0x09, 0x6d, 0xcb, 0xdd, 0xc1, 0x57, 0xe0, 0x59, 0x55, 0x9a, 0xdf, 0xe9, 0x96, 0x13, 0xaa, - 0xfc, 0x56, 0x25, 0x25, 0x55, 0xe6, 0xd1, 0x3d, 0x98, 0xb7, 0x0c, 0xcf, 0xbf, 0xd3, 0x6e, 0x18, - 0x3e, 0xd9, 0x33, 0x5b, 0x44, 0xec, 0xb9, 0x71, 0xea, 0x14, 0xe4, 0xf1, 0xf0, 0xb6, 0x42, 0x09, - 0xc7, 0x28, 0xa3, 0x23, 0x40, 0xb4, 0x65, 0xcf, 0x35, 0x6c, 0x8f, 0xcf, 0x8a, 0xf2, 0x1b, 0xbf, - 0x2e, 0xe2, 0xa2, 0xe0, 0x87, 0xb6, 0xfb, 0xa8, 0xe1, 0x04, 0x0e, 0xe8, 0x69, 0x98, 0x72, 0x89, - 0xe1, 0x89, 0xc5, 0x9c, 0x09, 0xf7, 0x3f, 0x66, 0xad, 0x58, 0x40, 0xa3, 0x1b, 0x6a, 0xea, 0x84, - 0x0d, 0xf5, 0x3d, 0x0d, 0xe6, 0xc3, 0x65, 0x7a, 0x04, 0x66, 0xae, 0xa5, 0x9a, 0xb9, 0x1b, 0x69, - 0xa9, 0xc4, 0x01, 0x96, 0xed, 0x4f, 0x72, 0xd1, 0xf9, 0xb1, 0x4c, 0xfd, 0x27, 0x61, 0x26, 0xd8, - 0xd5, 0x41, 0xae, 0x7e, 0x42, 0x6f, 0x5c, 0xf1, 0x2c, 0x22, 0xa5, 0x44, 0x82, 0x09, 0x0e, 0xf9, - 0x51, 0xc3, 0xda, 0x10, 0x46, 0x53, 0x88, 0xbd, 0x34, 0xac, 0x81, 0x31, 0x4d, 0x32, 0xac, 0x41, - 0x1f, 0x74, 0x07, 0x2e, 0xb4, 0x5d, 0x87, 0xd5, 0x72, 0x6e, 0x10, 0xa3, 0x61, 0x99, 0x36, 0x09, - 0x9c, 0x3e, 0x9e, 0x9d, 0x78, 0xa2, 0xd7, 0x2d, 0x5f, 0xd8, 0x4d, 0x46, 0xc1, 0x83, 0xfa, 0xaa, - 0x25, 0x51, 0xb9, 0x93, 0x4b, 0xa2, 0xd0, 0xaf, 0xc8, 0xd0, 0x8a, 0x78, 0xa5, 0x3c, 0xfb, 0x88, - 0xaf, 0xa5, 0xb5, 0x94, 0x09, 0x6a, 0x3d, 0x14, 0xa9, 0x8a, 0x60, 0x8a, 0x25, 0xfb, 0xc1, 0xfe, - 0xfb, 0xd4, 0xe9, 0xfc, 0x77, 0xfd, 0x0b, 0x79, 0x58, 0x8c, 0x1b, 0xdb, 0xb3, 0x2f, 0xf7, 0xfa, - 0x75, 0x0d, 0x16, 0x03, 0x41, 0xe1, 0x3c, 0x49, 0x70, 0x08, 0xb1, 0x9d, 0x92, 0x7c, 0x72, 0xb7, - 0x41, 0xd6, 0xde, 0xee, 0xc5, 0xb8, 0xe1, 0x3e, 0xfe, 0xe8, 0x75, 0x28, 0xca, 0x58, 0xfd, 0x54, - 0xb5, 0x5f, 0x0b, 0xcc, 0x61, 0x08, 0x49, 0xe0, 0x28, 0x3d, 0xf4, 0x05, 0x0d, 0xa0, 0x1e, 0x68, - 0xf4, 0x40, 0x90, 0x6e, 0xa7, 0x25, 0x48, 0xd2, 0x56, 0x84, 0x7e, 0xa1, 0x6c, 0xf2, 0x70, 0x84, - 0x31, 0xfa, 0x0d, 0x16, 0xa5, 0x4b, 0x47, 0x86, 0x8a, 0x0e, 0x1d, 0xc9, 0x47, 0xd2, 0x16, 0xe9, - 0xf0, 0xec, 0x56, 0x7a, 0x0d, 0x11, 0x90, 0x87, 0x95, 0x41, 0xe8, 0x2f, 0x80, 0xcc, 0xd5, 0xd3, - 0x1d, 0xca, 0xb2, 0xf5, 0xbb, 0x86, 0x7f, 0x28, 0x44, 0x50, 0xee, 0xd0, 0xeb, 0x01, 0x00, 0x87, - 0x38, 0xfa, 0x5f, 0x68, 0xb0, 0xbc, 0xe9, 0xf9, 0xa6, 0xb3, 0x41, 0x3c, 0x9f, 0x6e, 0x5a, 0x6a, - 0xdf, 0x3b, 0x16, 0x19, 0xc1, 0x43, 0xda, 0x80, 0x45, 0x71, 0xa0, 0xd6, 0xd9, 0xf7, 0x88, 0x1f, - 0xf1, 0x92, 0xa4, 0xe8, 0xac, 0xc7, 0xe0, 0xb8, 0xaf, 0x07, 0xa5, 0x22, 0x4e, 0xd6, 0x42, 0x2a, - 0x59, 0x95, 0x4a, 0x2d, 0x06, 0xc7, 0x7d, 0x3d, 0xf4, 0x6f, 0x66, 0xe0, 0x1c, 0x9b, 0x46, 0xac, - 0xf0, 0xfb, 0xd7, 0x34, 0x98, 0x3f, 0x32, 0x5d, 0xbf, 0x63, 0x58, 0xd1, 0x23, 0xc2, 0x89, 0xa5, - 0x87, 0xf1, 0x7a, 0x45, 0x21, 0x1c, 0xfa, 0x05, 0x6a, 0x3b, 0x8e, 0x0d, 0x80, 0x8e, 0x69, 0xa1, - 0xa1, 0x7e, 0xed, 0x74, 0x42, 0xd8, 0xa4, 0x75, 0xe4, 0x89, 0xa6, 0x58, 0x23, 0x8e, 0xf3, 0xd7, - 0x5f, 0x13, 0x9f, 0x4f, 0x1d, 0xfa, 0x08, 0x42, 0xa0, 0xc3, 0x94, 0xeb, 0x74, 0xa8, 0x8d, 0xcc, - 0xb0, 0xba, 0x7a, 0x60, 0x8e, 0x06, 0x6b, 0xc1, 0x02, 0xa2, 0x7f, 0x4d, 0x83, 0x99, 0x2d, 0x67, - 0x5f, 0x04, 0x8d, 0x1f, 0x4b, 0x21, 0x80, 0x93, 0x7a, 0x5e, 0x9e, 0xd6, 0x84, 0xae, 0xc3, 0x8b, - 0x4a, 0xf8, 0xf6, 0x64, 0x84, 0xf6, 0x2a, 0xbb, 0x28, 0x42, 0x49, 0x6d, 0x39, 0xfb, 0x03, 0xe3, - 0xfb, 0xdf, 0xcf, 0xc3, 0xdc, 0xcb, 0xc6, 0x31, 0xb1, 0x7d, 0x43, 0x8c, 0xf8, 0xbd, 0x30, 0x6d, - 0x34, 0x1a, 0x49, 0x17, 0x27, 0x2a, 0xbc, 0x19, 0x07, 0x70, 0x16, 0x11, 0xb5, 0x59, 0x5e, 0x3f, - 0x62, 0xbb, 0xc3, 0x88, 0x28, 0x04, 0xe1, 0x28, 0x5e, 0xb8, 0x95, 0xd6, 0x1d, 0xfb, 0xc0, 0x6c, - 0x26, 0x6d, 0x82, 0xf5, 0x18, 0x1c, 0xf7, 0xf5, 0x40, 0x5b, 0x80, 0x44, 0xd9, 0x5f, 0xa5, 0x5e, - 0x77, 0x3a, 0x36, 0xdf, 0x4c, 0x3c, 0x58, 0x92, 0x4e, 0xe4, 0x4e, 0x1f, 0x06, 0x4e, 0xe8, 0x85, - 0x3e, 0x0a, 0xa5, 0x3a, 0xa3, 0x2c, 0x5c, 0x8a, 0x28, 0x45, 0xee, 0x56, 0xca, 0x9a, 0x9a, 0xf5, - 0x01, 0x78, 0x78, 0x20, 0x05, 0x3a, 0x52, 0xcf, 0x77, 0x5c, 0xa3, 0x49, 0xa2, 0x74, 0xa7, 0xd4, - 0x91, 0xd6, 0xfa, 0x30, 0x70, 0x42, 0x2f, 0xf4, 0x19, 0x98, 0xf1, 0x0f, 0x5d, 0xe2, 0x1d, 0x3a, - 0x56, 0x43, 0x1c, 0xdf, 0x4e, 0x18, 0x41, 0x8b, 0xd5, 0xdf, 0x0b, 0xa8, 0x46, 0x9c, 0x9c, 0xa0, - 0x09, 0x87, 0x3c, 0x91, 0x0b, 0x53, 0x1e, 0x0d, 0xdf, 0xbc, 0x52, 0x21, 0x0d, 0x37, 0x51, 0x70, - 0x67, 0x11, 0x61, 0x24, 0x76, 0x67, 0x1c, 0xb0, 0xe0, 0xa4, 0x7f, 0x3b, 0x03, 0xb3, 0x51, 0xc4, - 0x11, 0x76, 0xea, 0xe7, 0x35, 0x98, 0xad, 0x3b, 0xb6, 0xef, 0x3a, 0x16, 0x8f, 0x4b, 0xf9, 0x06, - 0x99, 0xf0, 0xda, 0x00, 0x23, 0xb5, 0x41, 0x7c, 0xc3, 0xb4, 0x22, 0x21, 0x6e, 0x84, 0x0d, 0x56, - 0x98, 0xa2, 0x2f, 0x6b, 0xb0, 0x10, 0xe6, 0xb5, 0xc2, 0x00, 0x39, 0xd5, 0x81, 0xc8, 0xd2, 0xb3, - 0x6b, 0x2a, 0x27, 0x1c, 0x67, 0xad, 0xef, 0xc3, 0x62, 0x7c, 0xb5, 0xe9, 0xa7, 0x6c, 0x1b, 0x62, - 0xaf, 0x67, 0xc3, 0x4f, 0xb9, 0x6b, 0x78, 0x1e, 0x66, 0x10, 0xf4, 0x3e, 0x28, 0xb4, 0x0c, 0xb7, - 0x69, 0xda, 0x86, 0xc5, 0xbe, 0x62, 0x36, 0xa2, 0x90, 0x44, 0x3b, 0x96, 0x18, 0xfa, 0x0f, 0x73, - 0x50, 0xdc, 0x21, 0x86, 0xd7, 0x71, 0x09, 0x3b, 0xc1, 0x3a, 0x73, 0x17, 0x51, 0xa9, 0xc3, 0xcf, - 0xa6, 0x57, 0x87, 0x8f, 0x5e, 0x05, 0x38, 0x30, 0x6d, 0xd3, 0x3b, 0x3c, 0x65, 0x85, 0x3f, 0xcb, - 0x70, 0x5e, 0x97, 0x14, 0x70, 0x84, 0x5a, 0x78, 0xc5, 0x27, 0x3f, 0xe4, 0x8a, 0xcf, 0x17, 0xb4, - 0x88, 0xf1, 0xe0, 0xce, 0xd7, 0xdd, 0x49, 0x0b, 0xa8, 0xe5, 0xc2, 0xac, 0x06, 0xc6, 0xe4, 0x9a, - 0xed, 0xbb, 0xc7, 0x43, 0x6d, 0xcc, 0x1e, 0x14, 0x5c, 0xe2, 0x75, 0x5a, 0xd4, 0xd9, 0x9d, 0x1e, - 0xfb, 0x33, 0xb0, 0x24, 0x10, 0x16, 0xfd, 0xb1, 0xa4, 0x74, 0xf1, 0x05, 0x98, 0x53, 0x86, 0x80, - 0x16, 0x21, 0x7b, 0x9f, 0x1c, 0x73, 0x39, 0xc1, 0xf4, 0x4f, 0xb4, 0xac, 0x94, 0xc2, 0x8a, 0xcf, - 0xf2, 0xa1, 0xcc, 0xf3, 0x9a, 0xfe, 0xe3, 0x29, 0x98, 0x12, 0xf6, 0xea, 0x64, 0x5d, 0x10, 0x3d, - 0xb8, 0xcd, 0x9c, 0xe2, 0xe0, 0x76, 0x0b, 0x66, 0x4d, 0xdb, 0xf4, 0x4d, 0xc3, 0x62, 0x11, 0x91, - 0xb0, 0x55, 0x4f, 0x07, 0xfb, 0x7f, 0x33, 0x02, 0x4b, 0xa0, 0xa3, 0xf4, 0x45, 0xb7, 0x21, 0xcf, - 0x94, 0xb9, 0x90, 0xa7, 0xf1, 0xf3, 0x7a, 0x2c, 0x67, 0xcf, 0x6b, 0xeb, 0x38, 0x25, 0xe6, 0x53, - 0xf2, 0x4b, 0x17, 0xd2, 0x91, 0x17, 0x62, 0x15, 0xfa, 0x94, 0x31, 0x38, 0xee, 0xeb, 0x41, 0xa9, - 0x1c, 0x18, 0xa6, 0xd5, 0x71, 0x49, 0x48, 0x65, 0x4a, 0xa5, 0x72, 0x3d, 0x06, 0xc7, 0x7d, 0x3d, - 0xd0, 0x01, 0xcc, 0x8a, 0x36, 0x9e, 0xd6, 0x99, 0x3e, 0xe5, 0x2c, 0x59, 0xfa, 0xee, 0x7a, 0x84, - 0x12, 0x56, 0xe8, 0xa2, 0x0e, 0x2c, 0x99, 0x76, 0xdd, 0xb1, 0xeb, 0x56, 0xc7, 0x33, 0x8f, 0x48, - 0x58, 0xd8, 0x76, 0x1a, 0x66, 0xe7, 0x7b, 0xdd, 0xf2, 0xd2, 0x66, 0x9c, 0x1c, 0xee, 0xe7, 0x80, - 0x3e, 0xa7, 0xc1, 0xf9, 0xba, 0x63, 0x7b, 0xac, 0xb4, 0xfb, 0x88, 0x5c, 0x73, 0x5d, 0xc7, 0xe5, - 0xbc, 0x67, 0x4e, 0xc9, 0x9b, 0x05, 0xe2, 0xeb, 0x49, 0x24, 0x71, 0x32, 0x27, 0xf4, 0x06, 0x14, - 0xda, 0xae, 0x73, 0x64, 0x36, 0x88, 0x2b, 0x52, 0x84, 0xdb, 0x69, 0xdc, 0xaa, 0xd8, 0x15, 0x34, - 0x43, 0x4d, 0x10, 0xb4, 0x60, 0xc9, 0x4f, 0xff, 0xfa, 0x14, 0xcc, 0xab, 0xe8, 0xe8, 0xd3, 0x00, - 0x6d, 0xd7, 0x69, 0x11, 0xff, 0x90, 0xc8, 0x02, 0xa5, 0x9b, 0x93, 0xde, 0x68, 0x08, 0xe8, 0x89, - 0x0b, 0x1f, 0x4c, 0x93, 0x86, 0xad, 0x38, 0xc2, 0x11, 0xb9, 0x30, 0x7d, 0x9f, 0xdb, 0x34, 0x61, - 0xe2, 0x5f, 0x4e, 0xc5, 0x21, 0x11, 0x9c, 0x8b, 0xd4, 0xe4, 0x88, 0x26, 0x1c, 0x30, 0x42, 0xfb, - 0x90, 0x7d, 0x40, 0xf6, 0xd3, 0xa9, 0xbd, 0xbf, 0x4b, 0x44, 0xa8, 0x50, 0x9d, 0xee, 0x75, 0xcb, - 0xd9, 0xbb, 0x64, 0x1f, 0x53, 0xe2, 0x74, 0x5e, 0x0d, 0x9e, 0x7e, 0x12, 0xaa, 0x62, 0xc2, 0x79, - 0x29, 0xb9, 0x2c, 0x3e, 0x2f, 0xd1, 0x84, 0x03, 0x46, 0xe8, 0x0d, 0x98, 0x79, 0x60, 0x1c, 0x91, - 0x03, 0xd7, 0xb1, 0x7d, 0x51, 0xe0, 0x30, 0x61, 0xe1, 0xcd, 0xdd, 0x80, 0x9c, 0xe0, 0xcb, 0xac, - 0xad, 0x6c, 0xc4, 0x21, 0x3b, 0x74, 0x04, 0x05, 0x9b, 0x3c, 0xc0, 0xc4, 0x32, 0xeb, 0xa2, 0xe6, - 0x61, 0x42, 0xb1, 0xbe, 0x29, 0xa8, 0x09, 0xce, 0xcc, 0x0c, 0x05, 0x6d, 0x58, 0xf2, 0xa2, 0x6b, - 0x79, 0xcf, 0xd9, 0x17, 0x8a, 0x6a, 0xc2, 0xb5, 0x94, 0x61, 0x1f, 0x5f, 0xcb, 0x2d, 0x67, 0x1f, - 0x53, 0xe2, 0xfa, 0x37, 0x73, 0x30, 0x1b, 0xbd, 0x4b, 0x38, 0x82, 0xcd, 0x92, 0x6e, 0x53, 0x66, - 0x1c, 0xb7, 0x89, 0x7a, 0xbd, 0xad, 0xd0, 0xc6, 0x07, 0x47, 0x65, 0x9b, 0xa9, 0x79, 0x0d, 0xa1, - 0xd7, 0x1b, 0x69, 0xf4, 0xb0, 0xc2, 0x74, 0x8c, 0xdc, 0x15, 0xf5, 0x83, 0xb8, 0x39, 0xe4, 0xc5, - 0xda, 0xd2, 0x0f, 0x52, 0x0c, 0xdc, 0x55, 0x80, 0xf0, 0x56, 0xa1, 0x38, 0xc0, 0x94, 0x87, 0x57, - 0x91, 0xdb, 0x8e, 0x11, 0x2c, 0xf4, 0x34, 0x4c, 0x51, 0x83, 0x41, 0x1a, 0xa2, 0x8a, 0x5a, 0x86, - 0x16, 0xd7, 0x59, 0x2b, 0x16, 0x50, 0xf4, 0x3c, 0xb5, 0xed, 0xa1, 0x9a, 0x17, 0xc5, 0xd1, 0xcb, - 0xa1, 0x6d, 0x0f, 0x61, 0x58, 0xc1, 0xa4, 0x43, 0x27, 0x54, 0x2b, 0x33, 0xd5, 0x1f, 0x19, 0x3a, - 0x53, 0xd5, 0x98, 0xc3, 0x58, 0xa8, 0x1b, 0xd3, 0xe2, 0x4c, 0x69, 0xe7, 0x23, 0xa1, 0x6e, 0x0c, - 0x8e, 0xfb, 0x7a, 0xe8, 0x1f, 0x87, 0x79, 0x55, 0x9a, 0xe9, 0x27, 0x6e, 0xbb, 0xce, 0x81, 0x69, - 0x91, 0x78, 0x90, 0xbe, 0xcb, 0x9b, 0x71, 0x00, 0x1f, 0x2d, 0xed, 0xfc, 0x97, 0x59, 0x38, 0x77, - 0xb3, 0x69, 0xda, 0x0f, 0x63, 0x27, 0x4a, 0x49, 0x8f, 0x15, 0x68, 0xe3, 0x3e, 0x56, 0x10, 0xd6, - 0x9e, 0x89, 0xa7, 0x17, 0x92, 0x6b, 0xcf, 0x82, 0x77, 0x19, 0x54, 0x5c, 0xf4, 0x3d, 0x0d, 0x9e, - 0x34, 0x1a, 0xdc, 0xbf, 0x30, 0x2c, 0xd1, 0x1a, 0x32, 0x0d, 0x64, 0xdc, 0x9b, 0x50, 0x5b, 0xf4, - 0x4f, 0x7e, 0xb5, 0x32, 0x84, 0x2b, 0xf7, 0x9a, 0xdf, 0x23, 0x66, 0xf0, 0xe4, 0x30, 0x54, 0x3c, - 0x74, 0xf8, 0x17, 0x6f, 0xc1, 0xbb, 0x4f, 0x64, 0x34, 0x96, 0x6f, 0xfc, 0x79, 0x0d, 0x66, 0xf8, - 0xe9, 0x11, 0x26, 0x07, 0x74, 0xf3, 0x18, 0x6d, 0xf3, 0x15, 0xe2, 0x7a, 0xc1, 0x8d, 0xc3, 0x99, - 0x70, 0xf3, 0x54, 0x76, 0x37, 0x05, 0x04, 0x47, 0xb0, 0xa8, 0x7a, 0xba, 0x6f, 0xda, 0x0d, 0xb1, - 0x4c, 0x52, 0x3d, 0xbd, 0x6c, 0xda, 0x0d, 0xcc, 0x20, 0x52, 0x81, 0x65, 0x07, 0x29, 0x30, 0xfd, - 0x0f, 0x34, 0x98, 0x67, 0xa5, 0xa5, 0xa1, 0x73, 0xf8, 0x9c, 0x4c, 0xd5, 0xf1, 0x61, 0x5c, 0x52, - 0x53, 0x75, 0xef, 0x74, 0xcb, 0x45, 0x5e, 0x8c, 0xaa, 0x66, 0xee, 0x5e, 0x13, 0x01, 0x1e, 0x4b, - 0x28, 0x66, 0xc6, 0x8e, 0x3f, 0xe4, 0x71, 0x46, 0x2d, 0x20, 0x82, 0x43, 0x7a, 0xfa, 0xd7, 0xb3, - 0x70, 0x2e, 0xa1, 0x46, 0x8a, 0xc6, 0x5e, 0x53, 0x96, 0xb1, 0x4f, 0xac, 0x20, 0x1d, 0xf6, 0x7a, - 0xea, 0x75, 0x58, 0xab, 0xdb, 0x8c, 0x3e, 0x97, 0x24, 0xa9, 0x9f, 0x78, 0x23, 0x16, 0xcc, 0xd1, - 0x6f, 0x69, 0x50, 0x34, 0x22, 0xc2, 0xce, 0x33, 0x84, 0xfb, 0xe9, 0x0f, 0xa6, 0x4f, 0xb6, 0x23, - 0x95, 0x0d, 0xa1, 0x28, 0x47, 0xc7, 0x72, 0xf1, 0xe7, 0xa1, 0x18, 0x99, 0xc2, 0x38, 0x32, 0x7a, - 0xf1, 0x45, 0x58, 0x9c, 0x48, 0xc6, 0x3f, 0x02, 0xe3, 0x5e, 0x61, 0xa5, 0x16, 0xe1, 0x41, 0xb4, - 0xe2, 0x5a, 0x7e, 0x71, 0x51, 0x72, 0x2d, 0xa0, 0xfa, 0x3e, 0x2c, 0xc6, 0x1d, 0xd0, 0x71, 0xce, - 0x44, 0x47, 0x52, 0xb7, 0x1f, 0x80, 0x31, 0x2f, 0x9d, 0xea, 0x7f, 0x95, 0x81, 0x69, 0x51, 0x68, - 0xf9, 0x08, 0x8a, 0x82, 0xee, 0x2b, 0xa7, 0xca, 0x9b, 0xa9, 0xd4, 0x87, 0x0e, 0xac, 0x08, 0xf2, - 0x62, 0x15, 0x41, 0x2f, 0xa7, 0xc3, 0x6e, 0x78, 0x39, 0xd0, 0x57, 0x33, 0xb0, 0x10, 0x2b, 0x5c, - 0x45, 0x5f, 0xd4, 0xfa, 0xb3, 0xe0, 0x77, 0x52, 0xad, 0x8d, 0x95, 0x25, 0x67, 0xc3, 0x13, 0xe2, - 0x9e, 0x72, 0x8d, 0xfd, 0x76, 0x6a, 0x4f, 0x9d, 0x0c, 0xbd, 0xd1, 0xfe, 0x4f, 0x1a, 0x3c, 0x3e, - 0xb0, 0x94, 0x97, 0x5d, 0x17, 0x72, 0x55, 0xa8, 0x90, 0xbd, 0x94, 0x4b, 0xf3, 0xe5, 0x69, 0x66, - 0xfc, 0x86, 0x47, 0x9c, 0x3d, 0x7a, 0x16, 0x66, 0x99, 0x1e, 0xa7, 0xdb, 0xc7, 0x27, 0x6d, 0xf1, - 0x46, 0x05, 0x3b, 0x39, 0xa8, 0x45, 0xda, 0xb1, 0x82, 0xa5, 0xff, 0x9e, 0x06, 0xa5, 0x41, 0x97, - 0x47, 0x46, 0xf0, 0xcb, 0x7f, 0x2e, 0x56, 0xa0, 0x53, 0xee, 0x2b, 0xd0, 0x89, 0x79, 0xe6, 0x41, - 0x2d, 0x4e, 0xc4, 0x29, 0xce, 0x9e, 0x50, 0x7f, 0xf2, 0x15, 0x0d, 0x2e, 0x0c, 0x10, 0x9c, 0xbe, - 0x42, 0x2d, 0xed, 0xd4, 0x85, 0x5a, 0x99, 0x51, 0x0b, 0xb5, 0xf4, 0xbf, 0xc9, 0xc2, 0xa2, 0x18, - 0x4f, 0x68, 0xcc, 0x9f, 0x57, 0xca, 0x9c, 0xde, 0x13, 0x2b, 0x73, 0x5a, 0x8e, 0xe3, 0xff, 0x5f, - 0x8d, 0xd3, 0x4f, 0x57, 0x8d, 0xd3, 0x4f, 0x32, 0x70, 0x3e, 0xf1, 0x62, 0x0e, 0xfa, 0x52, 0x82, - 0x16, 0xbc, 0x9b, 0xf2, 0x0d, 0xa0, 0x11, 0xf5, 0xe0, 0xa4, 0x85, 0x41, 0xbf, 0x19, 0x2d, 0xc8, - 0xe1, 0x61, 0xc2, 0xc1, 0x19, 0xdc, 0x65, 0x1a, 0xb3, 0x36, 0x47, 0xff, 0xd5, 0x2c, 0x5c, 0x19, - 0x95, 0xd0, 0x4f, 0x69, 0xed, 0xa6, 0xa7, 0xd4, 0x6e, 0x3e, 0x1a, 0x0b, 0x75, 0x36, 0x65, 0x9c, - 0x5f, 0xcb, 0x4a, 0xb3, 0xd7, 0x2f, 0x9f, 0x23, 0x25, 0x17, 0xa6, 0xa9, 0x17, 0x13, 0x3c, 0x4b, - 0x11, 0xaa, 0xc2, 0xe9, 0x1a, 0x6f, 0x7e, 0xa7, 0x5b, 0x5e, 0x12, 0xb7, 0xdf, 0x6b, 0xc4, 0x17, - 0x8d, 0x38, 0xe8, 0x84, 0xae, 0x40, 0xc1, 0xe5, 0xd0, 0xa0, 0x5a, 0x4d, 0x24, 0x4c, 0x78, 0x1b, - 0x96, 0x50, 0xf4, 0x99, 0x88, 0xdb, 0x97, 0x3b, 0xab, 0xbb, 0x21, 0xc3, 0xf2, 0x40, 0xaf, 0x43, - 0xc1, 0x0b, 0xde, 0xac, 0xe0, 0xa7, 0x83, 0xcf, 0x8c, 0x58, 0x04, 0x49, 0xa3, 0x84, 0xe0, 0x01, - 0x0b, 0x3e, 0x3f, 0xf9, 0xbc, 0x85, 0x24, 0x89, 0x74, 0xe9, 0xa0, 0xf3, 0x23, 0x1e, 0x48, 0x70, - 0xce, 0xdf, 0xd6, 0xa0, 0x28, 0x56, 0xeb, 0x11, 0xd4, 0x65, 0xde, 0x53, 0xeb, 0x32, 0xaf, 0xa5, - 0xa2, 0x3b, 0x06, 0x14, 0x65, 0xde, 0x83, 0xd9, 0xe8, 0xdd, 0x4c, 0xf4, 0x6a, 0x44, 0xf7, 0x69, - 0x93, 0xdc, 0x01, 0x0b, 0xb4, 0x63, 0xa8, 0x17, 0xf5, 0xb7, 0xa6, 0xe5, 0x57, 0x64, 0xd5, 0x9f, - 0x51, 0x19, 0xd4, 0x86, 0xca, 0x60, 0x54, 0x04, 0x32, 0xe9, 0x8b, 0xc0, 0x6d, 0x28, 0x04, 0x0a, - 0x4a, 0x98, 0xf1, 0xa7, 0xa2, 0x15, 0x2d, 0xd4, 0x17, 0xa0, 0xc4, 0x22, 0x82, 0xcb, 0xa2, 0x0a, - 0xb9, 0x86, 0x52, 0x71, 0x4a, 0x32, 0xe8, 0x0d, 0x28, 0x3e, 0x70, 0xdc, 0xfb, 0x96, 0x63, 0xb0, - 0xa7, 0x63, 0x20, 0x8d, 0x73, 0x5e, 0x79, 0xba, 0xc2, 0x2b, 0xf9, 0xee, 0x86, 0xf4, 0x71, 0x94, - 0x19, 0xaa, 0xc0, 0x42, 0xcb, 0xb4, 0x31, 0x31, 0x1a, 0xb2, 0xfc, 0x32, 0xc7, 0x9f, 0xcb, 0x08, - 0x9c, 0xdc, 0x1d, 0x15, 0x8c, 0xe3, 0xf8, 0xe8, 0x93, 0x50, 0xf0, 0xc4, 0xfd, 0xcf, 0x74, 0x4e, - 0xe4, 0x65, 0x78, 0xc4, 0x89, 0x86, 0xdf, 0x2e, 0x68, 0xc1, 0x92, 0x21, 0xda, 0x86, 0x65, 0x57, - 0xdc, 0xb0, 0x52, 0x5e, 0x83, 0xe3, 0xfb, 0x93, 0xbd, 0xca, 0x80, 0x13, 0xe0, 0x38, 0xb1, 0x17, - 0xf5, 0x62, 0xd8, 0x25, 0x63, 0x7e, 0x24, 0x5b, 0x08, 0xbd, 0x18, 0x26, 0xf0, 0x0d, 0x2c, 0xa0, - 0xc3, 0xca, 0x79, 0x0b, 0x13, 0x94, 0xf3, 0xde, 0x85, 0x19, 0x97, 0xb0, 0x50, 0xa0, 0x12, 0xa4, - 0xeb, 0xc6, 0xae, 0x13, 0xc0, 0x01, 0x01, 0x1c, 0xd2, 0xa2, 0x4b, 0x64, 0xa8, 0x8f, 0x3b, 0xdc, - 0x4e, 0xf1, 0x8d, 0x51, 0xb1, 0x4c, 0x03, 0xae, 0x52, 0xea, 0xff, 0x39, 0x07, 0x73, 0x4a, 0xc4, - 0x8b, 0x9e, 0x82, 0x3c, 0xbb, 0xc3, 0xc6, 0x76, 0x72, 0x21, 0xd4, 0x36, 0xec, 0xd2, 0x1b, 0xe6, - 0x30, 0xf4, 0x55, 0x0d, 0x16, 0xda, 0xca, 0xe9, 0x5c, 0xa0, 0xe4, 0x26, 0xcc, 0xba, 0xa8, 0x47, - 0x7e, 0x91, 0x67, 0x91, 0x54, 0x66, 0x38, 0xce, 0x9d, 0xee, 0x15, 0x51, 0x3a, 0x63, 0x11, 0x97, - 0x61, 0x0b, 0x77, 0x44, 0x92, 0x58, 0x57, 0xc1, 0x38, 0x8e, 0x4f, 0x57, 0x98, 0xcd, 0x6e, 0x92, - 0x17, 0x19, 0x2b, 0x01, 0x01, 0x1c, 0xd2, 0x42, 0x2f, 0xc2, 0xbc, 0xb8, 0xd3, 0xbf, 0xeb, 0x34, - 0x6e, 0x18, 0xde, 0xa1, 0xf0, 0xc3, 0x65, 0xdc, 0xb0, 0xae, 0x40, 0x71, 0x0c, 0x9b, 0xcd, 0x2d, - 0x7c, 0x38, 0x81, 0x11, 0x98, 0x52, 0x5f, 0x8d, 0x5a, 0x57, 0xc1, 0x38, 0x8e, 0x8f, 0xde, 0x17, - 0x51, 0xd1, 0x3c, 0xa3, 0x21, 0x37, 0x6e, 0x82, 0x9a, 0xae, 0xc0, 0x42, 0x87, 0x85, 0x2d, 0x8d, - 0x00, 0x28, 0xb6, 0x8e, 0x64, 0x78, 0x47, 0x05, 0xe3, 0x38, 0x3e, 0x7a, 0x01, 0xe6, 0x5c, 0xaa, - 0x88, 0x24, 0x01, 0x9e, 0xe6, 0x90, 0x67, 0xf6, 0x38, 0x0a, 0xc4, 0x2a, 0x2e, 0x7a, 0x09, 0x96, - 0xc2, 0xdb, 0xcd, 0x01, 0x01, 0x9e, 0xf7, 0x90, 0x0f, 0x27, 0x54, 0xe2, 0x08, 0xb8, 0xbf, 0x0f, - 0xfa, 0x05, 0x58, 0x8c, 0x7c, 0x89, 0x4d, 0xbb, 0x41, 0x1e, 0x8a, 0x1b, 0xa8, 0xcb, 0x2c, 0x77, - 0x12, 0x83, 0xe1, 0x3e, 0x6c, 0xf4, 0x21, 0x98, 0xaf, 0x3b, 0x96, 0xc5, 0xd4, 0x11, 0x7f, 0xb1, - 0x88, 0x5f, 0x35, 0xe5, 0x97, 0x72, 0x15, 0x08, 0x8e, 0x61, 0xa2, 0x2d, 0x40, 0xce, 0xbe, 0x47, - 0xdc, 0x23, 0xd2, 0x78, 0x89, 0x3f, 0x3a, 0x4d, 0xad, 0xf1, 0x9c, 0x5a, 0xb8, 0x77, 0xab, 0x0f, - 0x03, 0x27, 0xf4, 0x42, 0xfb, 0x70, 0x31, 0x30, 0x0d, 0xfd, 0x3d, 0x4a, 0x25, 0x25, 0xba, 0xb9, - 0x78, 0x77, 0x20, 0x26, 0x1e, 0x42, 0x05, 0xfd, 0x92, 0x5a, 0x39, 0x3e, 0x9f, 0xc6, 0x1b, 0x90, - 0xf1, 0x40, 0xfe, 0xc4, 0xb2, 0x71, 0x17, 0xa6, 0x78, 0xad, 0x66, 0x69, 0x21, 0x8d, 0x5b, 0xdd, - 0xd1, 0x07, 0x52, 0x42, 0x93, 0xc1, 0x5b, 0xb1, 0xe0, 0x84, 0x3e, 0x0d, 0x33, 0xfb, 0xc1, 0x6b, - 0x59, 0xa5, 0xc5, 0x34, 0xcc, 0x64, 0xec, 0xe1, 0xb7, 0x30, 0x50, 0x95, 0x00, 0x1c, 0xb2, 0x44, - 0x4f, 0x43, 0xf1, 0xc6, 0x6e, 0x45, 0x4a, 0xfa, 0x12, 0x93, 0xb0, 0x1c, 0xed, 0x82, 0xa3, 0x00, - 0xba, 0x8b, 0xa5, 0xfb, 0x84, 0xd8, 0x92, 0x87, 0xe6, 0xb7, 0xdf, 0x1b, 0xa2, 0xd8, 0x2c, 0x15, - 0x86, 0x6b, 0xa5, 0x73, 0x31, 0x6c, 0xd1, 0x8e, 0x25, 0x06, 0x7a, 0x1d, 0x8a, 0xc2, 0x26, 0x31, - 0xfd, 0xb7, 0x7c, 0xba, 0x5b, 0x09, 0x38, 0x24, 0x81, 0xa3, 0xf4, 0xd0, 0x73, 0x50, 0x6c, 0xb3, - 0x47, 0x84, 0xc8, 0xf5, 0x8e, 0x65, 0x95, 0xce, 0x33, 0xdd, 0x2c, 0x73, 0x04, 0xbb, 0x21, 0x08, - 0x47, 0xf1, 0xd0, 0x33, 0x41, 0x1e, 0xfb, 0x5d, 0x4a, 0xca, 0x47, 0xe6, 0xb1, 0xa5, 0xd3, 0x3b, - 0xa0, 0xfa, 0xef, 0xc2, 0x09, 0xe7, 0x18, 0x9f, 0x0b, 0xcf, 0x71, 0xe5, 0x3b, 0x19, 0x9f, 0x8a, - 0x4a, 0x83, 0x96, 0xc6, 0xd3, 0xd8, 0x7d, 0x4f, 0xb1, 0x71, 0x63, 0x91, 0x28, 0x0b, 0x6d, 0x29, - 0xff, 0xa9, 0x5c, 0xa9, 0x55, 0xdf, 0x00, 0xe1, 0x41, 0x91, 0x2a, 0xfd, 0xfa, 0xf7, 0x73, 0xf2, - 0x2c, 0x27, 0x96, 0xbe, 0x75, 0x21, 0x6f, 0x7a, 0xbe, 0xe9, 0xa4, 0x78, 0x0d, 0x20, 0xf6, 0x78, - 0x06, 0x2b, 0x47, 0x63, 0x00, 0xcc, 0x59, 0x51, 0x9e, 0x76, 0xd3, 0xb4, 0x1f, 0x8a, 0xe9, 0xdf, - 0x4e, 0x3d, 0x2f, 0xcb, 0x79, 0x32, 0x00, 0xe6, 0xac, 0xd0, 0x3d, 0xc8, 0x1a, 0xd6, 0x7e, 0x4a, - 0xcf, 0xa0, 0xc7, 0xff, 0x95, 0x00, 0x2f, 0xe6, 0xa8, 0x6c, 0x57, 0x31, 0x65, 0x42, 0x79, 0x79, - 0x2d, 0x53, 0xf8, 0x17, 0x13, 0xf2, 0xaa, 0xed, 0x6c, 0x26, 0xf1, 0xaa, 0xed, 0x6c, 0x62, 0xca, - 0x04, 0x7d, 0x51, 0x03, 0x30, 0xe4, 0x33, 0xff, 0xe9, 0xbc, 0x5b, 0x38, 0xe8, 0xdf, 0x06, 0xf0, - 0x2a, 0xab, 0x10, 0x8a, 0x23, 0x9c, 0xf5, 0x37, 0x35, 0x58, 0xea, 0x1b, 0x6c, 0xfc, 0x3f, 0x20, - 0x68, 0xa3, 0xff, 0x07, 0x04, 0xf1, 0xbc, 0x4a, 0xad, 0x6d, 0x99, 0x89, 0x57, 0x69, 0xf6, 0x62, - 0x70, 0xdc, 0xd7, 0x43, 0xff, 0x96, 0x06, 0xc5, 0x48, 0x19, 0x34, 0xf5, 0x7b, 0x59, 0xb9, 0xb8, - 0x18, 0x46, 0xf8, 0xb2, 0x0c, 0x3b, 0xbe, 0xe2, 0x30, 0x7e, 0x92, 0xda, 0x0c, 0xcf, 0x13, 0x23, - 0x27, 0xa9, 0xb4, 0x15, 0x0b, 0x28, 0xba, 0x0c, 0x39, 0xcf, 0x27, 0x6d, 0x26, 0x51, 0x91, 0xaa, - 0x68, 0x96, 0x4f, 0x60, 0x10, 0xc6, 0x8e, 0x2a, 0x47, 0x51, 0xe2, 0x12, 0x79, 0xc8, 0xc6, 0xa0, - 0x6e, 0x36, 0x83, 0xa1, 0x4b, 0x90, 0x25, 0x76, 0x43, 0x78, 0x8b, 0x45, 0x81, 0x92, 0xbd, 0x66, - 0x37, 0x30, 0x6d, 0xd7, 0x6f, 0xc1, 0x6c, 0x8d, 0xd4, 0x5d, 0xe2, 0xbf, 0x4c, 0x8e, 0x47, 0x3b, - 0xeb, 0xbb, 0xc4, 0x73, 0xa4, 0x19, 0x95, 0x20, 0xed, 0x4e, 0xdb, 0xf5, 0x3f, 0xd2, 0x20, 0xf6, - 0xae, 0x50, 0xe4, 0x54, 0x45, 0x1b, 0x74, 0xaa, 0xa2, 0xc4, 0xff, 0x99, 0xa1, 0xf1, 0xff, 0x16, - 0xa0, 0x96, 0xe1, 0xd7, 0x0f, 0xc5, 0xfa, 0x88, 0x27, 0xac, 0xb8, 0xa3, 0x1e, 0x5e, 0xba, 0xe8, - 0xc3, 0xc0, 0x09, 0xbd, 0xf4, 0x25, 0x58, 0x90, 0x51, 0x3c, 0x97, 0x0c, 0xfd, 0xdb, 0x59, 0x98, - 0x55, 0x5e, 0x90, 0x3e, 0xf9, 0x8b, 0x8c, 0x3e, 0xf6, 0x84, 0x68, 0x3c, 0x3b, 0x66, 0x34, 0x1e, - 0x3d, 0xfe, 0xc8, 0x9d, 0xed, 0xf1, 0x47, 0x3e, 0x9d, 0xe3, 0x0f, 0x1f, 0xa6, 0xc5, 0xff, 0x2c, - 0x11, 0x55, 0x75, 0x3b, 0x29, 0x5d, 0x9b, 0x14, 0xd7, 0xc0, 0x58, 0x21, 0x61, 0xb0, 0xcb, 0x03, - 0x56, 0xfa, 0x37, 0xf2, 0x30, 0xaf, 0x5e, 0xa4, 0x1c, 0x61, 0x25, 0xdf, 0xd7, 0xb7, 0x92, 0x63, - 0x86, 0x38, 0xd9, 0x49, 0x43, 0x9c, 0xdc, 0xa4, 0x21, 0x4e, 0xfe, 0x14, 0x21, 0x4e, 0x7f, 0x80, - 0x32, 0x35, 0x72, 0x80, 0xf2, 0x61, 0x99, 0x4a, 0x9b, 0x56, 0xce, 0x9e, 0xc3, 0x54, 0x1a, 0x52, - 0x97, 0x61, 0xdd, 0x69, 0x24, 0xa6, 0x24, 0x0b, 0x27, 0xd4, 0xe9, 0xb9, 0x89, 0x99, 0xaf, 0xf1, - 0x4f, 0x51, 0xde, 0x35, 0x46, 0xd6, 0x2b, 0xfc, 0xb7, 0x3c, 0xcc, 0x42, 0x80, 0x6a, 0x5d, 0x6a, - 0x21, 0x08, 0x47, 0xf1, 0xd8, 0x13, 0xcd, 0xea, 0x03, 0xd2, 0x2c, 0x62, 0x8c, 0x3e, 0xd1, 0x1c, - 0x7b, 0x70, 0x3a, 0x8e, 0xaf, 0x7f, 0x36, 0x03, 0xe1, 0x23, 0xd8, 0xec, 0xb5, 0x2a, 0x2f, 0xa2, - 0xa6, 0x85, 0x33, 0xb5, 0x35, 0xe9, 0x93, 0x70, 0x21, 0x45, 0x91, 0xb4, 0x8e, 0xb4, 0x60, 0x85, - 0xe3, 0x7f, 0xc3, 0xe3, 0xd7, 0x06, 0x2c, 0xc4, 0x6a, 0x77, 0x53, 0x2f, 0x82, 0xf9, 0x56, 0x06, - 0x66, 0x64, 0xf5, 0x33, 0xb5, 0x6c, 0x1d, 0x37, 0x78, 0x58, 0x47, 0x5a, 0xb6, 0x3b, 0x78, 0x1b, - 0xd3, 0x76, 0xf4, 0x10, 0xa6, 0x0f, 0x89, 0xd1, 0x20, 0x6e, 0x70, 0x4e, 0xb5, 0x93, 0x52, 0xd9, - 0xf5, 0x0d, 0x46, 0x35, 0x9c, 0x0b, 0xff, 0xed, 0xe1, 0x80, 0x1d, 0x7a, 0x11, 0xe6, 0x7d, 0xb3, - 0x45, 0x68, 0x80, 0x11, 0xb1, 0x1a, 0xd9, 0xf0, 0xf0, 0x67, 0x4f, 0x81, 0xe2, 0x18, 0x36, 0x55, - 0x6b, 0xf7, 0x3c, 0xc7, 0x66, 0x77, 0x94, 0x73, 0x6a, 0x14, 0xb7, 0x55, 0xbb, 0x75, 0x93, 0x5d, - 0x51, 0x96, 0x18, 0x14, 0xdb, 0x64, 0xd5, 0x9f, 0x2e, 0x11, 0x69, 0xad, 0xc5, 0xf0, 0xae, 0x0a, - 0x6f, 0xc7, 0x12, 0x43, 0xbf, 0x03, 0x0b, 0xb1, 0x89, 0x04, 0x1e, 0x82, 0x96, 0xec, 0x21, 0x8c, - 0xf4, 0xbf, 0x85, 0xaa, 0xab, 0x6f, 0xfd, 0x60, 0xe5, 0xb1, 0xef, 0xfc, 0x60, 0xe5, 0xb1, 0xef, - 0xfe, 0x60, 0xe5, 0xb1, 0xcf, 0xf6, 0x56, 0xb4, 0xb7, 0x7a, 0x2b, 0xda, 0x77, 0x7a, 0x2b, 0xda, - 0x77, 0x7b, 0x2b, 0xda, 0xf7, 0x7b, 0x2b, 0xda, 0x9b, 0x3f, 0x5c, 0x79, 0xec, 0xd5, 0x42, 0xf0, - 0x31, 0xff, 0x2b, 0x00, 0x00, 0xff, 0xff, 0x3e, 0x5d, 0xf5, 0x43, 0x5a, 0x6d, 0x00, 0x00, + // 6030 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x5d, 0x6c, 0x64, 0xc9, + 0x55, 0xf0, 0xde, 0x6e, 0xff, 0xb4, 0x4f, 0xfb, 0xb7, 0xc6, 0x93, 0xe9, 0x9d, 0xdd, 0x71, 0x4f, + 0xee, 0x46, 0xfb, 0x4d, 0x3e, 0x12, 0x3b, 0x99, 0xdd, 0x85, 0x25, 0x1b, 0xad, 0xe8, 0xb6, 0x67, + 0x76, 0xec, 0xb5, 0x67, 0x3c, 0xd5, 0x9e, 0x1d, 0x65, 0x93, 0x0d, 0xb9, 0xee, 0x2e, 0xb7, 0xef, + 0x4c, 0xf7, 0xbd, 0x9d, 0x7b, 0x6f, 0x7b, 0xc6, 0x9b, 0x28, 0x3f, 0x44, 0x09, 0x0b, 0x4a, 0x94, + 0xf0, 0xf3, 0x82, 0x50, 0x10, 0x42, 0x3c, 0x20, 0xf2, 0x82, 0x50, 0x78, 0x4b, 0x44, 0x04, 0x44, + 0x0a, 0x0f, 0xa0, 0x20, 0x01, 0x1b, 0x50, 0xd2, 0x24, 0x1d, 0x5e, 0xe0, 0x05, 0x05, 0x45, 0x42, + 0x59, 0x09, 0x09, 0xd5, 0xcf, 0xad, 0x5b, 0x75, 0xfb, 0x76, 0xbb, 0xdb, 0x7d, 0x3d, 0x44, 0xc0, + 0x9b, 0xbb, 0xce, 0xa9, 0x73, 0xaa, 0x6e, 0x9d, 0x3a, 0x7f, 0x75, 0xaa, 0x0c, 0xdb, 0x75, 0x3b, + 0x38, 0x6c, 0xef, 0xaf, 0x56, 0xdd, 0xe6, 0x9a, 0xe5, 0xd5, 0xdd, 0x96, 0xe7, 0xde, 0x63, 0x7f, + 0xbc, 0xdb, 0x73, 0x1b, 0x0d, 0xb7, 0x1d, 0xf8, 0x6b, 0xad, 0xfb, 0xf5, 0x35, 0xab, 0x65, 0xfb, + 0x6b, 0xb2, 0xe5, 0xe8, 0xbd, 0x56, 0xa3, 0x75, 0x68, 0xbd, 0x77, 0xad, 0x4e, 0x1c, 0xe2, 0x59, + 0x01, 0xa9, 0xad, 0xb6, 0x3c, 0x37, 0x70, 0xd1, 0xfb, 0x23, 0x6a, 0xab, 0x21, 0x35, 0xf6, 0xc7, + 0x2f, 0x86, 0x7d, 0x57, 0x5b, 0xf7, 0xeb, 0xab, 0x94, 0xda, 0xaa, 0x6c, 0x09, 0xa9, 0x5d, 0x7c, + 0xb7, 0x32, 0x96, 0xba, 0x5b, 0x77, 0xd7, 0x18, 0xd1, 0xfd, 0xf6, 0x01, 0xfb, 0xc5, 0x7e, 0xb0, + 0xbf, 0x38, 0xb3, 0x8b, 0x4f, 0xdd, 0x7f, 0xde, 0x5f, 0xb5, 0x5d, 0x3a, 0xb6, 0xb5, 0x7d, 0x2b, + 0xa8, 0x1e, 0xae, 0x1d, 0xf5, 0x8c, 0xe8, 0xa2, 0xa9, 0x20, 0x55, 0x5d, 0x8f, 0x24, 0xe1, 0x3c, + 0x1b, 0xe1, 0x34, 0xad, 0xea, 0xa1, 0xed, 0x10, 0xef, 0x38, 0x9a, 0x75, 0x93, 0x04, 0x56, 0x52, + 0xaf, 0xb5, 0x7e, 0xbd, 0xbc, 0xb6, 0x13, 0xd8, 0x4d, 0xd2, 0xd3, 0xe1, 0x67, 0x4f, 0xea, 0xe0, + 0x57, 0x0f, 0x49, 0xd3, 0xea, 0xe9, 0xf7, 0x4c, 0xbf, 0x7e, 0xed, 0xc0, 0x6e, 0xac, 0xd9, 0x4e, + 0xe0, 0x07, 0x5e, 0xbc, 0x93, 0xf9, 0xef, 0x06, 0x2c, 0x95, 0xb6, 0xcb, 0x7b, 0x9e, 0x75, 0x70, + 0x60, 0x57, 0xb1, 0xdb, 0x0e, 0x6c, 0xa7, 0x8e, 0xde, 0x09, 0xd3, 0xb6, 0x53, 0xf7, 0x88, 0xef, + 0x17, 0x8c, 0xcb, 0xc6, 0x95, 0x99, 0xf2, 0xc2, 0xb7, 0x3a, 0xc5, 0xc7, 0xba, 0x9d, 0xe2, 0xf4, + 0x26, 0x6f, 0xc6, 0x21, 0x1c, 0x3d, 0x07, 0x79, 0x9f, 0x78, 0x47, 0x76, 0x95, 0xec, 0xba, 0x5e, + 0x50, 0xc8, 0x5c, 0x36, 0xae, 0x4c, 0x96, 0xcf, 0x09, 0xf4, 0x7c, 0x25, 0x02, 0x61, 0x15, 0x8f, + 0x76, 0xf3, 0x5c, 0x37, 0x10, 0xf0, 0x42, 0x96, 0x71, 0x91, 0xdd, 0x70, 0x04, 0xc2, 0x2a, 0x1e, + 0xda, 0x80, 0x45, 0xcb, 0x71, 0xdc, 0xc0, 0x0a, 0x6c, 0xd7, 0xd9, 0xf5, 0xc8, 0x81, 0xfd, 0xb0, + 0x30, 0xc1, 0xfa, 0x16, 0x44, 0xdf, 0xc5, 0x52, 0x0c, 0x8e, 0x7b, 0x7a, 0x98, 0x1b, 0x50, 0x28, + 0x35, 0xf7, 0x2d, 0xdf, 0xb7, 0x6a, 0xae, 0x17, 0x9b, 0xfa, 0x15, 0xc8, 0x35, 0xad, 0x56, 0xcb, + 0x76, 0xea, 0x74, 0xee, 0xd9, 0x2b, 0x33, 0xe5, 0xd9, 0x6e, 0xa7, 0x98, 0xdb, 0x11, 0x6d, 0x58, + 0x42, 0xcd, 0x7f, 0xc8, 0x40, 0xbe, 0xe4, 0x58, 0x8d, 0x63, 0xdf, 0xf6, 0x71, 0xdb, 0x41, 0x1f, + 0x81, 0x1c, 0x95, 0x81, 0x9a, 0x15, 0x58, 0xec, 0xab, 0xe5, 0xaf, 0xbe, 0x67, 0x95, 0x2f, 0xc9, + 0xaa, 0xba, 0x24, 0x91, 0x64, 0x53, 0xec, 0xd5, 0xa3, 0xf7, 0xae, 0xde, 0xda, 0xbf, 0x47, 0xaa, + 0xc1, 0x0e, 0x09, 0xac, 0x32, 0x12, 0xb3, 0x80, 0xa8, 0x0d, 0x4b, 0xaa, 0xc8, 0x85, 0x09, 0xbf, + 0x45, 0xaa, 0xec, 0x23, 0xe7, 0xaf, 0xee, 0xac, 0x8e, 0xb3, 0x8b, 0x56, 0x95, 0xa1, 0x57, 0x5a, + 0xa4, 0x5a, 0x9e, 0x15, 0xac, 0x27, 0xe8, 0x2f, 0xcc, 0x18, 0xa1, 0x07, 0x30, 0xe5, 0x07, 0x56, + 0xd0, 0xf6, 0xd9, 0x02, 0xe5, 0xaf, 0xde, 0x4a, 0x8f, 0x25, 0x23, 0x5b, 0x9e, 0x17, 0x4c, 0xa7, + 0xf8, 0x6f, 0x2c, 0xd8, 0x99, 0xff, 0x68, 0xc0, 0x39, 0x05, 0xbb, 0xe4, 0xd5, 0xdb, 0x4d, 0xe2, + 0x04, 0xe8, 0x32, 0x4c, 0x38, 0x56, 0x93, 0x08, 0xa9, 0x94, 0x43, 0xbe, 0x69, 0x35, 0x09, 0x66, + 0x10, 0xf4, 0x14, 0x4c, 0x1e, 0x59, 0x8d, 0x36, 0x61, 0x1f, 0x69, 0xa6, 0x3c, 0x27, 0x50, 0x26, + 0x5f, 0xa1, 0x8d, 0x98, 0xc3, 0xd0, 0xc7, 0x61, 0x86, 0xfd, 0x71, 0xdd, 0x73, 0x9b, 0x29, 0x4d, + 0x4d, 0x8c, 0xf0, 0x95, 0x90, 0x6c, 0x79, 0xae, 0xdb, 0x29, 0xce, 0xc8, 0x9f, 0x38, 0x62, 0x68, + 0xfe, 0x93, 0x01, 0x0b, 0xca, 0xe4, 0xb6, 0x6d, 0x3f, 0x40, 0x1f, 0xea, 0x11, 0x9e, 0xd5, 0xe1, + 0x84, 0x87, 0xf6, 0x66, 0xa2, 0xb3, 0x28, 0x66, 0x9a, 0x0b, 0x5b, 0x14, 0xc1, 0x71, 0x60, 0xd2, + 0x0e, 0x48, 0xd3, 0x2f, 0x64, 0x2e, 0x67, 0xaf, 0xe4, 0xaf, 0x6e, 0xa6, 0xb6, 0x8c, 0xd1, 0xf7, + 0xdd, 0xa4, 0xf4, 0x31, 0x67, 0x63, 0x7e, 0x39, 0xa3, 0xcd, 0x90, 0x4a, 0x14, 0x72, 0x61, 0xba, + 0x49, 0x02, 0xcf, 0xae, 0xf2, 0x7d, 0x95, 0xbf, 0xba, 0x31, 0xde, 0x28, 0x76, 0x18, 0xb1, 0x48, + 0x33, 0xf1, 0xdf, 0x3e, 0x0e, 0xb9, 0xa0, 0x43, 0x98, 0xb0, 0xbc, 0x7a, 0x38, 0xe7, 0xeb, 0xe9, + 0xac, 0x6f, 0x24, 0x73, 0x25, 0xaf, 0xee, 0x63, 0xc6, 0x01, 0xad, 0xc1, 0x4c, 0x40, 0xbc, 0xa6, + 0xed, 0x58, 0x01, 0x57, 0x65, 0xb9, 0xf2, 0x92, 0x40, 0x9b, 0xd9, 0x0b, 0x01, 0x38, 0xc2, 0x31, + 0xdf, 0xcc, 0xc0, 0x52, 0xcf, 0x66, 0x40, 0xcf, 0xc2, 0x64, 0xeb, 0xd0, 0xf2, 0x43, 0xe9, 0x5e, + 0x09, 0x3f, 0xed, 0x2e, 0x6d, 0x7c, 0xab, 0x53, 0x9c, 0x0b, 0xbb, 0xb0, 0x06, 0xcc, 0x91, 0xa9, + 0xae, 0x6e, 0x12, 0xdf, 0xb7, 0xea, 0xa1, 0xc8, 0x2b, 0x5f, 0x84, 0x35, 0xe3, 0x10, 0x8e, 0x7e, + 0xd9, 0x80, 0x39, 0xfe, 0x75, 0x30, 0xf1, 0xdb, 0x8d, 0x80, 0x6e, 0x6b, 0xfa, 0x6d, 0xb6, 0xd2, + 0x58, 0x09, 0x4e, 0xb2, 0x7c, 0x5e, 0x70, 0x9f, 0x53, 0x5b, 0x7d, 0xac, 0xf3, 0x45, 0x77, 0x61, + 0xc6, 0x0f, 0x2c, 0x2f, 0x20, 0xb5, 0x52, 0xc0, 0x14, 0x78, 0xfe, 0xea, 0xff, 0x1f, 0x4e, 0xde, + 0xf7, 0xec, 0x26, 0xe1, 0x7b, 0xab, 0x12, 0x12, 0xc0, 0x11, 0x2d, 0xf3, 0xef, 0x74, 0xc5, 0x51, + 0x09, 0xa8, 0xb1, 0xab, 0x1f, 0xa3, 0x0f, 0xc2, 0xe3, 0x7e, 0xbb, 0x5a, 0x25, 0xbe, 0x7f, 0xd0, + 0x6e, 0xe0, 0xb6, 0x73, 0xc3, 0xf6, 0x03, 0xd7, 0x3b, 0xde, 0xb6, 0x9b, 0x76, 0xc0, 0xbe, 0xf7, + 0x64, 0xf9, 0x52, 0xb7, 0x53, 0x7c, 0xbc, 0xd2, 0x0f, 0x09, 0xf7, 0xef, 0x8f, 0x2c, 0x78, 0xa2, + 0xed, 0xf4, 0x27, 0xcf, 0x6d, 0x62, 0xb1, 0xdb, 0x29, 0x3e, 0x71, 0xa7, 0x3f, 0x1a, 0x1e, 0x44, + 0xc3, 0xfc, 0x57, 0x03, 0x16, 0xc3, 0x79, 0xed, 0x91, 0x66, 0xab, 0x61, 0x05, 0xe4, 0x11, 0x58, + 0x9c, 0x40, 0xb3, 0x38, 0x38, 0x1d, 0xbd, 0x11, 0x8e, 0xbf, 0x9f, 0xd9, 0x31, 0xff, 0xc5, 0x80, + 0xe5, 0x38, 0xf2, 0x23, 0xd0, 0x92, 0xbe, 0xae, 0x25, 0x6f, 0xa6, 0x3b, 0xdb, 0x3e, 0xaa, 0xf2, + 0x47, 0x09, 0x73, 0xfd, 0x1f, 0xae, 0x2f, 0xcd, 0x3f, 0x98, 0x80, 0xd9, 0x92, 0x13, 0xd8, 0xa5, + 0x83, 0x03, 0xdb, 0xb1, 0x83, 0x63, 0xf4, 0xf9, 0x0c, 0xac, 0xb5, 0x3c, 0x72, 0x40, 0x3c, 0x8f, + 0xd4, 0x36, 0xda, 0x9e, 0xed, 0xd4, 0x2b, 0xd5, 0x43, 0x52, 0x6b, 0x37, 0x6c, 0xa7, 0xbe, 0x59, + 0x77, 0x5c, 0xd9, 0x7c, 0xed, 0x21, 0xa9, 0xb6, 0xa9, 0x2b, 0x27, 0xd6, 0xbf, 0x39, 0xde, 0x30, + 0x77, 0x47, 0x63, 0x5a, 0x7e, 0xa6, 0xdb, 0x29, 0xae, 0x8d, 0xd8, 0x09, 0x8f, 0x3a, 0x35, 0xf4, + 0x46, 0x06, 0x56, 0x3d, 0xf2, 0xd1, 0xb6, 0x3d, 0xfc, 0xd7, 0xe0, 0x1b, 0xb4, 0x31, 0xde, 0xd7, + 0xc0, 0x23, 0xf1, 0x2c, 0x5f, 0xed, 0x76, 0x8a, 0x23, 0xf6, 0xc1, 0x23, 0xce, 0xcb, 0xfc, 0x73, + 0x03, 0x72, 0x23, 0x78, 0x7f, 0x45, 0xdd, 0xfb, 0x9b, 0xe9, 0xf1, 0xfc, 0x82, 0x5e, 0xcf, 0xef, + 0xa5, 0xf1, 0x3e, 0xda, 0x30, 0x1e, 0xdf, 0xbf, 0xd1, 0x28, 0x2b, 0xee, 0x21, 0xa2, 0x43, 0x58, + 0x6e, 0xb9, 0xb5, 0x70, 0xd3, 0xdf, 0xb0, 0xfc, 0x43, 0x06, 0x13, 0xd3, 0x7b, 0xb6, 0xdb, 0x29, + 0x2e, 0xef, 0x26, 0xc0, 0xdf, 0xea, 0x14, 0x0b, 0x92, 0x48, 0x0c, 0x01, 0x27, 0x52, 0x44, 0x2d, + 0xc8, 0x1d, 0xd8, 0xa4, 0x51, 0xc3, 0xe4, 0x40, 0x48, 0xca, 0x98, 0xdb, 0xfb, 0xba, 0xa0, 0xc6, + 0x83, 0xa3, 0xf0, 0x17, 0x96, 0x5c, 0xcc, 0x9f, 0x4c, 0xc0, 0x42, 0xb9, 0xd1, 0x26, 0x2f, 0x79, + 0x84, 0x84, 0xfe, 0x4d, 0x09, 0x16, 0x5a, 0x1e, 0x39, 0xb2, 0xc9, 0x83, 0x0a, 0x69, 0x90, 0x6a, + 0xe0, 0x7a, 0x62, 0xaa, 0x17, 0xc4, 0x4a, 0x2e, 0xec, 0xea, 0x60, 0x1c, 0xc7, 0x47, 0x2f, 0xc2, + 0xbc, 0x55, 0x0d, 0xec, 0x23, 0x22, 0x29, 0xf0, 0x85, 0x7e, 0x9b, 0xa0, 0x30, 0x5f, 0xd2, 0xa0, + 0x38, 0x86, 0x8d, 0x3e, 0x04, 0x05, 0xbf, 0x6a, 0x35, 0xc8, 0x9d, 0x96, 0x60, 0xb5, 0x7e, 0x48, + 0xaa, 0xf7, 0x77, 0x5d, 0xdb, 0x09, 0x84, 0xe3, 0x76, 0x59, 0x50, 0x2a, 0x54, 0xfa, 0xe0, 0xe1, + 0xbe, 0x14, 0xd0, 0x9f, 0x1a, 0x70, 0xa9, 0xe5, 0x91, 0x5d, 0xcf, 0x6d, 0xba, 0x54, 0x7a, 0x7b, + 0x5c, 0x3c, 0xe1, 0xea, 0xbc, 0x32, 0xe6, 0x36, 0xe5, 0x2d, 0xbd, 0xd1, 0xd4, 0xdb, 0xbb, 0x9d, + 0xe2, 0xa5, 0xdd, 0x41, 0x03, 0xc0, 0x83, 0xc7, 0x87, 0xfe, 0xcc, 0x80, 0x95, 0x96, 0xeb, 0x07, + 0x03, 0xa6, 0x30, 0x79, 0xa6, 0x53, 0x30, 0xbb, 0x9d, 0xe2, 0xca, 0xee, 0xc0, 0x11, 0xe0, 0x13, + 0x46, 0x68, 0x76, 0xf3, 0xb0, 0xa4, 0xc8, 0x9e, 0xf0, 0x00, 0x5f, 0x80, 0xb9, 0x50, 0x18, 0x78, + 0xce, 0x81, 0xcb, 0x9e, 0xf4, 0x57, 0x4b, 0x2a, 0x10, 0xeb, 0xb8, 0x54, 0xee, 0xa4, 0x28, 0xf2, + 0xde, 0x31, 0xb9, 0xdb, 0xd5, 0xa0, 0x38, 0x86, 0x8d, 0x36, 0xe1, 0x9c, 0x68, 0xc1, 0xa4, 0xd5, + 0xb0, 0xab, 0xd6, 0xba, 0xdb, 0x16, 0x22, 0x37, 0x59, 0xbe, 0xd0, 0xed, 0x14, 0xcf, 0xed, 0xf6, + 0x82, 0x71, 0x52, 0x1f, 0xb4, 0x0d, 0xcb, 0x56, 0x3b, 0x70, 0xe5, 0xfc, 0xaf, 0x39, 0xd6, 0x7e, + 0x83, 0xd4, 0x98, 0x68, 0xe5, 0xca, 0x05, 0xaa, 0x35, 0x4a, 0x09, 0x70, 0x9c, 0xd8, 0x0b, 0xed, + 0xc6, 0xa8, 0x55, 0x48, 0xd5, 0x75, 0x6a, 0x7c, 0x95, 0x27, 0xcb, 0x4f, 0x8a, 0xe9, 0xe9, 0x14, + 0x05, 0x0e, 0x4e, 0xec, 0x89, 0x1a, 0x30, 0xdf, 0xb4, 0x1e, 0xde, 0x71, 0xac, 0x23, 0xcb, 0x6e, + 0x50, 0x26, 0x85, 0xa9, 0x13, 0x5c, 0xd3, 0x76, 0x60, 0x37, 0x56, 0x79, 0x7e, 0x6a, 0x75, 0xd3, + 0x09, 0x6e, 0x79, 0x95, 0x80, 0x1a, 0x81, 0x32, 0xa2, 0x1f, 0x76, 0x47, 0xa3, 0x85, 0x63, 0xb4, + 0xd1, 0x2d, 0x38, 0xcf, 0xb6, 0xe3, 0x86, 0xfb, 0xc0, 0xd9, 0x20, 0x0d, 0xeb, 0x38, 0x9c, 0xc0, + 0x34, 0x9b, 0xc0, 0xe3, 0xdd, 0x4e, 0xf1, 0x7c, 0x25, 0x09, 0x01, 0x27, 0xf7, 0xa3, 0xbe, 0xbc, + 0x0e, 0xc0, 0xe4, 0xc8, 0xf6, 0x6d, 0xd7, 0xe1, 0xbe, 0x7c, 0x2e, 0xf2, 0xe5, 0x2b, 0xfd, 0xd1, + 0xf0, 0x20, 0x1a, 0xe8, 0xb7, 0x0d, 0x58, 0x4e, 0xda, 0x86, 0x85, 0x99, 0x34, 0xf2, 0x3a, 0xb1, + 0xad, 0xc5, 0x25, 0x22, 0x51, 0x29, 0x24, 0x0e, 0x02, 0x7d, 0xca, 0x80, 0x59, 0x4b, 0x71, 0xce, + 0x0a, 0xc0, 0x46, 0xb5, 0x35, 0xae, 0x37, 0x1c, 0x51, 0x2c, 0x2f, 0x76, 0x3b, 0x45, 0xcd, 0x01, + 0xc4, 0x1a, 0x47, 0xf4, 0x3b, 0x06, 0x9c, 0x4f, 0xdc, 0xe3, 0x85, 0xfc, 0x59, 0x7c, 0x21, 0x26, + 0x24, 0xc9, 0x3a, 0x27, 0x79, 0x18, 0xe8, 0x4b, 0x86, 0x34, 0x65, 0x3b, 0x61, 0x3c, 0x32, 0xcb, + 0x86, 0x76, 0x7b, 0x4c, 0x7f, 0x34, 0xb2, 0xde, 0x21, 0xe1, 0xf2, 0x39, 0xc5, 0x32, 0x86, 0x8d, + 0x38, 0xce, 0x1e, 0x7d, 0xc1, 0x08, 0x4d, 0xa3, 0x1c, 0xd1, 0xdc, 0x59, 0x8d, 0x08, 0x45, 0x96, + 0x56, 0x0e, 0x28, 0xc6, 0x1c, 0x7d, 0x18, 0x2e, 0x5a, 0xfb, 0xae, 0x17, 0x24, 0x6e, 0xbe, 0xc2, + 0x3c, 0xdb, 0x46, 0x2b, 0xdd, 0x4e, 0xf1, 0x62, 0xa9, 0x2f, 0x16, 0x1e, 0x40, 0xc1, 0xfc, 0xee, + 0x04, 0xcc, 0xae, 0x5b, 0x8e, 0xe5, 0x1d, 0x0b, 0xd3, 0xf5, 0x35, 0x03, 0x9e, 0xac, 0xb6, 0x3d, + 0x8f, 0x38, 0x41, 0x25, 0x20, 0xad, 0x5e, 0xc3, 0x65, 0x9c, 0xa9, 0xe1, 0xba, 0xdc, 0xed, 0x14, + 0x9f, 0x5c, 0x1f, 0xc0, 0x1f, 0x0f, 0x1c, 0x1d, 0xfa, 0x6b, 0x03, 0x4c, 0x81, 0x50, 0xb6, 0xaa, + 0xf7, 0xeb, 0x9e, 0xdb, 0x76, 0x6a, 0xbd, 0x93, 0xc8, 0x9c, 0xe9, 0x24, 0x9e, 0xee, 0x76, 0x8a, + 0xe6, 0xfa, 0x89, 0xa3, 0xc0, 0x43, 0x8c, 0x14, 0xbd, 0x04, 0x4b, 0x02, 0xeb, 0xda, 0xc3, 0x16, + 0xf1, 0x6c, 0xea, 0xfb, 0x8a, 0x3c, 0xff, 0xe3, 0xc2, 0xac, 0x2c, 0xad, 0xc7, 0x11, 0x70, 0x6f, + 0x1f, 0xe4, 0xc3, 0xf4, 0x03, 0x62, 0xd7, 0x0f, 0x83, 0xd0, 0x7d, 0xda, 0x1e, 0x6f, 0xf6, 0x22, + 0xe1, 0x7f, 0x97, 0xd3, 0x2c, 0xe7, 0x69, 0x30, 0x2c, 0x7e, 0xe0, 0x90, 0x93, 0xf9, 0x47, 0x13, + 0x00, 0xa1, 0x78, 0x91, 0x16, 0xfa, 0x19, 0x98, 0xf1, 0x49, 0xc0, 0xb1, 0x44, 0xba, 0x88, 0xe7, + 0xa0, 0xc2, 0x46, 0x1c, 0xc1, 0xd1, 0x7d, 0x98, 0x6c, 0x59, 0x6d, 0x9f, 0x88, 0xc5, 0xda, 0x4a, + 0x65, 0xb1, 0x76, 0x29, 0x45, 0x1e, 0xd0, 0xb0, 0x3f, 0x31, 0xe7, 0x81, 0x3e, 0x63, 0x00, 0x10, + 0xfd, 0x03, 0xe7, 0xaf, 0x56, 0x52, 0x61, 0x19, 0xad, 0x01, 0xfd, 0x06, 0xe5, 0xf9, 0x6e, 0xa7, + 0x08, 0xca, 0x52, 0x29, 0x6c, 0xd1, 0x03, 0xc8, 0x59, 0xa1, 0x8e, 0x9e, 0x38, 0x0b, 0x1d, 0xcd, + 0xe2, 0x0c, 0x29, 0x64, 0x92, 0x19, 0x7a, 0xc3, 0x80, 0x79, 0x9f, 0x04, 0x62, 0xa9, 0xa8, 0xa6, + 0x10, 0x0e, 0xea, 0x98, 0x42, 0x52, 0xd1, 0x68, 0x72, 0x8d, 0xa7, 0xb7, 0xe1, 0x18, 0x5f, 0xf3, + 0xbb, 0x79, 0x98, 0x0f, 0x45, 0x26, 0xf2, 0x39, 0xab, 0xbc, 0x25, 0xd9, 0xe7, 0x5c, 0x57, 0x81, + 0x58, 0xc7, 0xa5, 0x9d, 0xfd, 0x80, 0x3a, 0x39, 0xba, 0xcb, 0x29, 0x3b, 0x57, 0x54, 0x20, 0xd6, + 0x71, 0x51, 0x13, 0x26, 0xfd, 0x80, 0xb4, 0xc2, 0x0c, 0xef, 0x8d, 0xf1, 0xbe, 0x46, 0xb4, 0x13, + 0xa2, 0x2c, 0x16, 0xfd, 0xe5, 0x63, 0xce, 0x05, 0x7d, 0xd1, 0x80, 0xf9, 0x40, 0x3b, 0x48, 0x13, + 0x62, 0x90, 0x8e, 0x24, 0xea, 0x67, 0x74, 0x7c, 0x35, 0xf4, 0x36, 0x1c, 0x63, 0x9f, 0xe0, 0x86, + 0x4e, 0x9e, 0xa1, 0x1b, 0xfa, 0x2a, 0xe4, 0x9a, 0xd6, 0xc3, 0x4a, 0xdb, 0xab, 0x9f, 0xde, 0xdd, + 0x15, 0xe7, 0x8c, 0x9c, 0x0a, 0x96, 0xf4, 0xd0, 0xa7, 0x0d, 0x65, 0x73, 0x4d, 0x33, 0xe2, 0x77, + 0xd3, 0xdd, 0x5c, 0x52, 0x8b, 0xf7, 0xdd, 0x66, 0x3d, 0x4e, 0x61, 0xee, 0x91, 0x3b, 0x85, 0xd4, + 0xc1, 0xe1, 0x1b, 0x44, 0x3a, 0x38, 0x33, 0x67, 0xea, 0xe0, 0xac, 0x6b, 0xcc, 0x70, 0x8c, 0x39, + 0x1b, 0x0f, 0xdf, 0x73, 0x72, 0x3c, 0x70, 0xa6, 0xe3, 0xa9, 0x68, 0xcc, 0x70, 0x8c, 0x79, 0xff, + 0x48, 0x28, 0x7f, 0x36, 0x91, 0xd0, 0x6c, 0x0a, 0x91, 0xd0, 0x60, 0x27, 0x71, 0x6e, 0x5c, 0x27, + 0x11, 0x6d, 0x01, 0xaa, 0x1d, 0x3b, 0x56, 0xd3, 0xae, 0x0a, 0x65, 0xc9, 0x0c, 0xc4, 0x3c, 0x8b, + 0x94, 0x2f, 0x0a, 0x45, 0x86, 0x36, 0x7a, 0x30, 0x70, 0x42, 0x2f, 0xf3, 0x47, 0x06, 0x5c, 0x58, + 0x6f, 0xb4, 0xfd, 0x80, 0x78, 0xff, 0x6b, 0x0e, 0x62, 0xfe, 0xc3, 0x80, 0x27, 0xfa, 0xcc, 0xf9, + 0x11, 0x9c, 0xc7, 0xbc, 0xae, 0x9f, 0xc7, 0xdc, 0x19, 0xd3, 0x86, 0x25, 0xcf, 0xa3, 0xcf, 0xb1, + 0x4c, 0x00, 0x73, 0x1b, 0x56, 0x60, 0xd5, 0xdc, 0x3a, 0x3f, 0x27, 0x41, 0x2f, 0x42, 0xce, 0x76, + 0x02, 0xe2, 0x1d, 0x59, 0x0d, 0x61, 0xc5, 0xcd, 0x70, 0xe8, 0x9b, 0xa2, 0xfd, 0xad, 0x4e, 0x71, + 0x7e, 0xa3, 0xed, 0xb1, 0x4a, 0x13, 0xae, 0xd3, 0xb1, 0xec, 0x83, 0x9e, 0x82, 0xc9, 0x8f, 0xb6, + 0x89, 0x77, 0x1c, 0xaf, 0x4b, 0xb8, 0x4d, 0x1b, 0x31, 0x87, 0x99, 0x7f, 0x9f, 0x01, 0xc5, 0xc3, + 0x7a, 0x04, 0x62, 0xe5, 0x68, 0x62, 0x35, 0xa6, 0xcf, 0xa4, 0xf8, 0x8b, 0xfd, 0x0a, 0x4a, 0x8e, + 0x62, 0x05, 0x25, 0x37, 0x53, 0xe3, 0x38, 0xb8, 0x9e, 0xe4, 0x4d, 0x03, 0x9e, 0x88, 0x90, 0x7b, + 0x83, 0x95, 0x93, 0x4f, 0x16, 0x9e, 0x83, 0xbc, 0x15, 0x75, 0x13, 0xab, 0x28, 0x0b, 0x96, 0x14, + 0x8a, 0x58, 0xc5, 0x8b, 0xce, 0xf4, 0xb3, 0xa7, 0x3c, 0xd3, 0x9f, 0x18, 0x7c, 0xa6, 0x6f, 0xfe, + 0x38, 0x03, 0x97, 0x7a, 0x67, 0x16, 0x4a, 0x37, 0x26, 0x07, 0x43, 0xcc, 0xed, 0x79, 0x98, 0x0d, + 0x44, 0x07, 0xda, 0x2a, 0x26, 0xb7, 0x2c, 0x30, 0x67, 0xf7, 0x14, 0x18, 0xd6, 0x30, 0x69, 0xcf, + 0x2a, 0xdf, 0x57, 0x95, 0xaa, 0xdb, 0x0a, 0x8b, 0x1f, 0x64, 0xcf, 0x75, 0x05, 0x86, 0x35, 0x4c, + 0x79, 0xda, 0x38, 0x71, 0xe6, 0xd5, 0x19, 0x15, 0x38, 0x1f, 0x1e, 0x3a, 0x5d, 0x77, 0xbd, 0x75, + 0xb7, 0xd9, 0x6a, 0x10, 0x76, 0x66, 0x36, 0xc9, 0x06, 0x7b, 0x49, 0x74, 0x39, 0x8f, 0x93, 0x90, + 0x70, 0x72, 0x5f, 0xf3, 0xcd, 0x2c, 0x9c, 0x8b, 0x3e, 0xfb, 0xba, 0xeb, 0xd4, 0x6c, 0x76, 0x74, + 0xf7, 0x02, 0x4c, 0x04, 0xc7, 0xad, 0xf0, 0x63, 0xff, 0xbf, 0x70, 0x38, 0x7b, 0xc7, 0x2d, 0xba, + 0xda, 0x17, 0x12, 0xba, 0x50, 0x10, 0x66, 0x9d, 0xd0, 0xb6, 0xdc, 0x1d, 0x7c, 0x05, 0x9e, 0xd5, + 0xa5, 0xf9, 0xad, 0x4e, 0x31, 0xa1, 0x4c, 0x71, 0x55, 0x52, 0xd2, 0x65, 0x1e, 0xdd, 0x83, 0xf9, + 0x86, 0xe5, 0x07, 0x77, 0x5a, 0x35, 0x2b, 0x20, 0x7b, 0x76, 0x93, 0x88, 0x3d, 0x37, 0x4a, 0xa1, + 0x85, 0xcc, 0x6f, 0x6f, 0x6b, 0x94, 0x70, 0x8c, 0x32, 0x3a, 0x02, 0x44, 0x5b, 0xf6, 0x3c, 0xcb, + 0xf1, 0xf9, 0xac, 0x28, 0xbf, 0xd1, 0x0b, 0x3b, 0xa4, 0x51, 0xde, 0xee, 0xa1, 0x86, 0x13, 0x38, + 0xa0, 0xa7, 0x61, 0xca, 0x23, 0x96, 0x2f, 0x16, 0x73, 0x26, 0xda, 0xff, 0x98, 0xb5, 0x62, 0x01, + 0x55, 0x37, 0xd4, 0xd4, 0x09, 0x1b, 0xea, 0x7b, 0x06, 0xcc, 0x47, 0xcb, 0xf4, 0x08, 0xcc, 0x5c, + 0x53, 0x37, 0x73, 0x37, 0xd2, 0x52, 0x89, 0x7d, 0x2c, 0xdb, 0x1f, 0x4f, 0xa8, 0xf3, 0x63, 0xa5, + 0x06, 0x1f, 0x83, 0x99, 0x70, 0x57, 0x87, 0xc5, 0x06, 0x63, 0x7a, 0xf6, 0x9a, 0x67, 0xa1, 0xd4, + 0x42, 0x09, 0x26, 0x38, 0xe2, 0x47, 0x0d, 0x6b, 0x4d, 0x18, 0x4d, 0x21, 0xf6, 0xd2, 0xb0, 0x86, + 0xc6, 0x34, 0xc9, 0xb0, 0x86, 0x7d, 0xd0, 0x1d, 0xb8, 0xd0, 0xf2, 0x5c, 0x56, 0x8c, 0xba, 0x41, + 0xac, 0x5a, 0xc3, 0x76, 0x48, 0xe8, 0x40, 0xf2, 0xe3, 0x95, 0x27, 0xba, 0x9d, 0xe2, 0x85, 0xdd, + 0x64, 0x14, 0xdc, 0xaf, 0xaf, 0x5e, 0xd3, 0x35, 0x71, 0x72, 0x4d, 0x17, 0xfa, 0x15, 0x19, 0xa6, + 0x11, 0xbf, 0x30, 0xc9, 0x3e, 0xe2, 0x07, 0xd3, 0x5a, 0xca, 0x04, 0xb5, 0x1e, 0x89, 0x54, 0x49, + 0x30, 0xc5, 0x92, 0x7d, 0xff, 0x58, 0x60, 0xea, 0x74, 0xb1, 0x80, 0xf9, 0xd9, 0x49, 0x58, 0x8c, + 0x1b, 0xdb, 0xb3, 0xaf, 0x57, 0xfb, 0x75, 0x03, 0x16, 0x43, 0x41, 0xe1, 0x3c, 0x49, 0x98, 0xd0, + 0xd8, 0x4e, 0x49, 0x3e, 0xb9, 0xdb, 0x20, 0x8b, 0x87, 0xf7, 0x62, 0xdc, 0x70, 0x0f, 0x7f, 0xf4, + 0x1a, 0xe4, 0x65, 0xdc, 0x7f, 0xaa, 0xe2, 0xb5, 0x05, 0xe6, 0x30, 0x44, 0x24, 0xb0, 0x4a, 0x0f, + 0x7d, 0xd6, 0x00, 0xa8, 0x86, 0x1a, 0x3d, 0x14, 0xa4, 0xdb, 0x69, 0x09, 0x92, 0xb4, 0x15, 0x91, + 0x5f, 0x28, 0x9b, 0x7c, 0xac, 0x30, 0x46, 0xbf, 0xc1, 0x22, 0x7e, 0xe9, 0xc8, 0x50, 0xd1, 0xa1, + 0x23, 0xf9, 0x40, 0xda, 0x22, 0x1d, 0x25, 0x9f, 0xa5, 0xd7, 0xa0, 0x80, 0x7c, 0xac, 0x0d, 0xc2, + 0x7c, 0x01, 0x64, 0xb1, 0x01, 0xdd, 0xa1, 0xac, 0xdc, 0x60, 0xd7, 0x0a, 0x0e, 0x85, 0x08, 0xca, + 0x1d, 0x7a, 0x3d, 0x04, 0xe0, 0x08, 0xc7, 0xfc, 0x0b, 0x03, 0x96, 0x37, 0xfd, 0xc0, 0x76, 0x37, + 0x88, 0x1f, 0xd0, 0x4d, 0x4b, 0xed, 0x7b, 0xbb, 0x41, 0x86, 0xf0, 0x90, 0x36, 0x60, 0x51, 0x24, + 0xe7, 0xda, 0xfb, 0x3e, 0x09, 0x14, 0x2f, 0x49, 0x8a, 0xce, 0x7a, 0x0c, 0x8e, 0x7b, 0x7a, 0x50, + 0x2a, 0x22, 0x4b, 0x17, 0x51, 0xc9, 0xea, 0x54, 0x2a, 0x31, 0x38, 0xee, 0xe9, 0x61, 0x7e, 0x3d, + 0x03, 0xe7, 0xd8, 0x34, 0x62, 0x95, 0xeb, 0xbf, 0x66, 0xc0, 0xfc, 0x91, 0xed, 0x05, 0x6d, 0xab, + 0xa1, 0xa6, 0x1b, 0xc7, 0x96, 0x1e, 0xc6, 0xeb, 0x15, 0x8d, 0x70, 0xe4, 0x17, 0xe8, 0xed, 0x38, + 0x36, 0x00, 0x3a, 0xa6, 0x85, 0x9a, 0xfe, 0xb5, 0xd3, 0x09, 0x61, 0x93, 0xd6, 0x91, 0x9f, 0x94, + 0xc5, 0x1a, 0x71, 0x9c, 0xbf, 0xf9, 0xb7, 0x86, 0xf8, 0x7e, 0xfa, 0xd8, 0x87, 0x90, 0x02, 0x13, + 0xa6, 0x3c, 0xb7, 0x4d, 0x8d, 0x64, 0x86, 0xdd, 0x0c, 0x00, 0xe6, 0x69, 0xb0, 0x16, 0x2c, 0x20, + 0xe8, 0x01, 0xcc, 0x04, 0x0d, 0x9f, 0x37, 0x0a, 0x5d, 0x35, 0xa6, 0x73, 0xbb, 0xb7, 0x5d, 0x61, + 0xe4, 0x14, 0xfb, 0x23, 0x5a, 0xa8, 0x1d, 0x0d, 0x79, 0x99, 0x5f, 0x31, 0x60, 0x66, 0xcb, 0xdd, + 0x17, 0xe1, 0xea, 0x87, 0x53, 0x08, 0x1d, 0xa5, 0x85, 0x91, 0x39, 0xa7, 0xc8, 0x69, 0x79, 0x51, + 0x0b, 0x1c, 0x9f, 0x54, 0x68, 0xaf, 0xb2, 0x3b, 0x36, 0x94, 0xd4, 0x96, 0xbb, 0xdf, 0x37, 0xb3, + 0xf0, 0x7b, 0x93, 0x30, 0xf7, 0xb2, 0x75, 0x4c, 0x9c, 0xc0, 0x12, 0x23, 0x7e, 0x27, 0x4c, 0x5b, + 0xb5, 0x5a, 0xd2, 0x9d, 0x93, 0x12, 0x6f, 0xc6, 0x21, 0x9c, 0xc5, 0x62, 0x2d, 0x56, 0x12, 0xa1, + 0x78, 0x0d, 0x51, 0x2c, 0x16, 0x81, 0xb0, 0x8a, 0x17, 0x6d, 0xe2, 0x75, 0xd7, 0x39, 0xb0, 0xeb, + 0x49, 0xdb, 0x6f, 0x3d, 0x06, 0xc7, 0x3d, 0x3d, 0xd0, 0x16, 0x20, 0x51, 0x31, 0x59, 0xaa, 0x56, + 0xdd, 0xb6, 0xc3, 0xb7, 0x31, 0x0f, 0xd3, 0xa4, 0xfb, 0xba, 0xd3, 0x83, 0x81, 0x13, 0x7a, 0xa1, + 0x0f, 0x41, 0xa1, 0xca, 0x28, 0x0b, 0x67, 0x46, 0xa5, 0xc8, 0x1d, 0x5a, 0x59, 0x8e, 0xb4, 0xde, + 0x07, 0x0f, 0xf7, 0xa5, 0x40, 0x47, 0xea, 0x07, 0xae, 0x67, 0xd5, 0x89, 0x4a, 0x77, 0x4a, 0x1f, + 0x69, 0xa5, 0x07, 0x03, 0x27, 0xf4, 0x42, 0x9f, 0x84, 0x99, 0xe0, 0xd0, 0x23, 0xfe, 0xa1, 0xdb, + 0xa8, 0x89, 0x24, 0xf4, 0x98, 0xb1, 0xbb, 0x58, 0xfd, 0xbd, 0x90, 0xaa, 0x22, 0xde, 0x61, 0x13, + 0x8e, 0x78, 0x22, 0x0f, 0xa6, 0x7c, 0x1a, 0x38, 0xfa, 0x85, 0x5c, 0x1a, 0x0e, 0xaa, 0xe0, 0xce, + 0x62, 0x51, 0x25, 0x6b, 0xc0, 0x38, 0x60, 0xc1, 0xc9, 0xfc, 0x66, 0x06, 0x66, 0x55, 0xc4, 0x21, + 0x54, 0xc4, 0x67, 0x0c, 0x98, 0xad, 0xba, 0x4e, 0xe0, 0xb9, 0x0d, 0x1e, 0x11, 0xf3, 0x0d, 0x32, + 0xe6, 0x8d, 0x0b, 0x46, 0x6a, 0x83, 0x04, 0x96, 0xdd, 0x50, 0x82, 0x6b, 0x85, 0x0d, 0xd6, 0x98, + 0xa2, 0xcf, 0x1b, 0xb0, 0x10, 0x9d, 0xce, 0x45, 0xa1, 0x79, 0xaa, 0x03, 0x91, 0x55, 0x7b, 0xd7, + 0x74, 0x4e, 0x38, 0xce, 0xda, 0xdc, 0x87, 0xc5, 0xf8, 0x6a, 0xd3, 0x4f, 0xd9, 0xb2, 0xc4, 0x5e, + 0xcf, 0x46, 0x9f, 0x72, 0xd7, 0xf2, 0x7d, 0xcc, 0x20, 0xe8, 0x5d, 0x90, 0x6b, 0x5a, 0x5e, 0xdd, + 0x76, 0xac, 0x06, 0xfb, 0x8a, 0x59, 0x45, 0x21, 0x89, 0x76, 0x2c, 0x31, 0xcc, 0x1f, 0x4e, 0x40, + 0x7e, 0x87, 0x58, 0x7e, 0xdb, 0x23, 0x2c, 0x77, 0x76, 0xe6, 0xce, 0xa9, 0x76, 0x85, 0x21, 0x9b, + 0xde, 0x15, 0x06, 0xf4, 0x2a, 0xc0, 0x81, 0xed, 0xd8, 0xfe, 0xe1, 0x29, 0x2f, 0x47, 0xb0, 0x73, + 0xda, 0xeb, 0x92, 0x02, 0x56, 0xa8, 0x45, 0xb7, 0xa3, 0x26, 0x07, 0xdc, 0x8e, 0xfa, 0xac, 0xa1, + 0x18, 0x0f, 0xee, 0xf6, 0xdd, 0x1d, 0xb7, 0xf6, 0x5c, 0x2e, 0xcc, 0x6a, 0x68, 0x4c, 0xae, 0x39, + 0x81, 0x77, 0x3c, 0xd0, 0xc6, 0xec, 0x41, 0xce, 0x23, 0x7e, 0xbb, 0x49, 0xdd, 0xec, 0xe9, 0x91, + 0x3f, 0x03, 0x3b, 0xca, 0xc2, 0xa2, 0x3f, 0x96, 0x94, 0x2e, 0xbe, 0x00, 0x73, 0xda, 0x10, 0xd0, + 0x22, 0x64, 0xef, 0x93, 0x63, 0x2e, 0x27, 0x98, 0xfe, 0x89, 0x96, 0xb5, 0x2a, 0x62, 0xf1, 0x59, + 0xde, 0x97, 0x79, 0xde, 0x30, 0x7f, 0x3c, 0x05, 0x53, 0xc2, 0x5e, 0x9d, 0xac, 0x0b, 0xd4, 0x94, + 0x71, 0xe6, 0x14, 0x29, 0xe3, 0x2d, 0x98, 0xb5, 0x1d, 0x3b, 0xb0, 0xad, 0x06, 0x8b, 0xc5, 0x84, + 0xad, 0x7a, 0x3a, 0xdc, 0xff, 0x9b, 0x0a, 0x2c, 0x81, 0x8e, 0xd6, 0x17, 0xdd, 0x86, 0x49, 0xa6, + 0xcc, 0x85, 0x3c, 0x8d, 0x7e, 0x3a, 0xc9, 0x2a, 0x0f, 0x78, 0x59, 0x22, 0xa7, 0xc4, 0xbc, 0x59, + 0x7e, 0x5f, 0x45, 0x86, 0x10, 0x42, 0xac, 0x22, 0x6f, 0x36, 0x06, 0xc7, 0x3d, 0x3d, 0x28, 0x95, + 0x03, 0xcb, 0x6e, 0xb4, 0x3d, 0x12, 0x51, 0x99, 0xd2, 0xa9, 0x5c, 0x8f, 0xc1, 0x71, 0x4f, 0x0f, + 0x74, 0x00, 0xb3, 0xa2, 0x8d, 0x1f, 0x4e, 0x4d, 0x9f, 0x72, 0x96, 0xec, 0x10, 0xf2, 0xba, 0x42, + 0x09, 0x6b, 0x74, 0x51, 0x1b, 0x96, 0x6c, 0xa7, 0xea, 0x3a, 0xd5, 0x46, 0xdb, 0xb7, 0x8f, 0x48, + 0x54, 0x13, 0x78, 0x1a, 0x66, 0xe7, 0xbb, 0x9d, 0xe2, 0xd2, 0x66, 0x9c, 0x1c, 0xee, 0xe5, 0x80, + 0x3e, 0x6d, 0xc0, 0xf9, 0xaa, 0xeb, 0xf8, 0xac, 0x2a, 0xfe, 0x88, 0x5c, 0xf3, 0x3c, 0xd7, 0xe3, + 0xbc, 0x67, 0x4e, 0xc9, 0x9b, 0xa5, 0x00, 0xd6, 0x93, 0x48, 0xe2, 0x64, 0x4e, 0xe8, 0x75, 0xc8, + 0xb5, 0x3c, 0xf7, 0xc8, 0xae, 0x11, 0x4f, 0x1c, 0x74, 0x6e, 0xa7, 0x71, 0x21, 0x65, 0x57, 0xd0, + 0x8c, 0x34, 0x41, 0xd8, 0x82, 0x25, 0x3f, 0xf3, 0xab, 0x53, 0x30, 0xaf, 0xa3, 0xa3, 0x4f, 0x00, + 0xb4, 0x3c, 0xb7, 0x49, 0x82, 0x43, 0x22, 0x6b, 0xbb, 0x6e, 0x8e, 0x7b, 0x19, 0x24, 0xa4, 0x27, + 0xee, 0xca, 0x30, 0x4d, 0x1a, 0xb5, 0x62, 0x85, 0x23, 0xf2, 0x60, 0xfa, 0x3e, 0xb7, 0x69, 0xc2, + 0xc4, 0xbf, 0x9c, 0x8a, 0x43, 0x22, 0x38, 0xb3, 0xa2, 0x24, 0xd1, 0x84, 0x43, 0x46, 0x68, 0x1f, + 0xb2, 0x0f, 0xc8, 0x7e, 0x3a, 0xd7, 0x16, 0xee, 0x12, 0x11, 0x2a, 0x94, 0xa7, 0xbb, 0x9d, 0x62, + 0xf6, 0x2e, 0xd9, 0xc7, 0x94, 0x38, 0x9d, 0x57, 0x8d, 0x1f, 0x7c, 0x09, 0x55, 0x31, 0xe6, 0xbc, + 0xb4, 0x53, 0x34, 0x3e, 0x2f, 0xd1, 0x84, 0x43, 0x46, 0xe8, 0x75, 0x98, 0x79, 0x60, 0x1d, 0x91, + 0x03, 0xcf, 0x75, 0x02, 0x51, 0xa6, 0x31, 0x66, 0xf9, 0xd0, 0xdd, 0x90, 0x9c, 0xe0, 0xcb, 0xac, + 0xad, 0x6c, 0xc4, 0x11, 0x3b, 0x74, 0x04, 0x39, 0x87, 0x3c, 0xc0, 0xa4, 0x61, 0x57, 0x45, 0xe5, + 0xc6, 0x98, 0x62, 0x7d, 0x53, 0x50, 0x13, 0x9c, 0x99, 0x19, 0x0a, 0xdb, 0xb0, 0xe4, 0x45, 0xd7, + 0xf2, 0x9e, 0xbb, 0x2f, 0x14, 0xd5, 0x98, 0x6b, 0x29, 0xc3, 0x3e, 0xbe, 0x96, 0x5b, 0xee, 0x3e, + 0xa6, 0xc4, 0xcd, 0xaf, 0x4f, 0xc0, 0xac, 0x7a, 0x0d, 0x73, 0x08, 0x9b, 0x25, 0xdd, 0xa6, 0xcc, + 0x28, 0x6e, 0x13, 0xf5, 0x7a, 0x9b, 0x91, 0x8d, 0x0f, 0x03, 0xdf, 0xcd, 0xd4, 0xbc, 0x86, 0xc8, + 0xeb, 0x55, 0x1a, 0x7d, 0xac, 0x31, 0x1d, 0xe1, 0xd4, 0x8c, 0xfa, 0x41, 0xdc, 0x1c, 0xf2, 0x3a, + 0x77, 0xe9, 0x07, 0x69, 0x06, 0xee, 0x2a, 0x40, 0x74, 0x21, 0x53, 0xa4, 0x4e, 0x65, 0xda, 0x4c, + 0xb9, 0x28, 0xaa, 0x60, 0xa1, 0xa7, 0x61, 0x8a, 0x1a, 0x0c, 0x52, 0x13, 0x05, 0xe8, 0x32, 0xb4, + 0xb8, 0xce, 0x5a, 0xb1, 0x80, 0xa2, 0xe7, 0xa9, 0x6d, 0x8f, 0xd4, 0xbc, 0xa8, 0x2b, 0x5f, 0x8e, + 0x6c, 0x7b, 0x04, 0xc3, 0x1a, 0x26, 0x1d, 0x3a, 0xa1, 0x5a, 0x99, 0xa9, 0x7e, 0x65, 0xe8, 0x4c, + 0x55, 0x63, 0x0e, 0x63, 0xa1, 0x6e, 0x4c, 0x8b, 0x33, 0xa5, 0x3d, 0xa9, 0x84, 0xba, 0x31, 0x38, + 0xee, 0xe9, 0x61, 0x7e, 0x04, 0xe6, 0x75, 0x69, 0xa6, 0x9f, 0xb8, 0xe5, 0xb9, 0x07, 0x76, 0x83, + 0xc4, 0x83, 0xf4, 0x5d, 0xde, 0x8c, 0x43, 0xf8, 0x70, 0x07, 0xde, 0x7f, 0x99, 0x85, 0x73, 0x37, + 0xeb, 0xb6, 0xf3, 0x30, 0x96, 0xcb, 0x4a, 0x7a, 0xe7, 0xc1, 0x18, 0xf5, 0x9d, 0x87, 0xa8, 0x82, + 0x4e, 0xbc, 0x5a, 0x91, 0x5c, 0x41, 0x17, 0x3e, 0x69, 0xa1, 0xe3, 0xa2, 0xef, 0x19, 0xf0, 0xa4, + 0x55, 0xe3, 0xfe, 0x85, 0xd5, 0x10, 0xad, 0x11, 0xd3, 0x50, 0xc6, 0xfd, 0x31, 0xb5, 0x45, 0xef, + 0xe4, 0x57, 0x4b, 0x03, 0xb8, 0x72, 0xaf, 0xf9, 0x1d, 0x62, 0x06, 0x4f, 0x0e, 0x42, 0xc5, 0x03, + 0x87, 0x7f, 0xf1, 0x16, 0xbc, 0xfd, 0x44, 0x46, 0x23, 0xf9, 0xc6, 0x9f, 0x31, 0x60, 0x86, 0x67, + 0x8f, 0x30, 0x39, 0xa0, 0x9b, 0xc7, 0x6a, 0xd9, 0xaf, 0x10, 0xcf, 0x0f, 0x2f, 0x6b, 0xce, 0x44, + 0x9b, 0xa7, 0xb4, 0xbb, 0x29, 0x20, 0x58, 0xc1, 0xa2, 0xea, 0xe9, 0xbe, 0xed, 0xd4, 0xc4, 0x32, + 0x49, 0xf5, 0xf4, 0xb2, 0xed, 0xd4, 0x30, 0x83, 0x48, 0x05, 0x96, 0xed, 0xa7, 0xc0, 0xcc, 0xdf, + 0x37, 0x60, 0x9e, 0x15, 0xc8, 0x46, 0xce, 0xe1, 0x73, 0xf2, 0x90, 0x90, 0x0f, 0xe3, 0x92, 0x7e, + 0x48, 0xf8, 0x56, 0xa7, 0x98, 0xe7, 0x25, 0xb5, 0xfa, 0x99, 0xe1, 0x07, 0x45, 0x80, 0xc7, 0x8e, + 0x32, 0x33, 0x23, 0xc7, 0x1f, 0x32, 0x9d, 0x51, 0x09, 0x89, 0xe0, 0x88, 0x9e, 0xf9, 0xd5, 0x2c, + 0x9c, 0x4b, 0xa8, 0xf4, 0xa2, 0xb1, 0xd7, 0x54, 0xc3, 0xda, 0x27, 0x8d, 0xf0, 0x20, 0xee, 0xb5, + 0xd4, 0xab, 0xc9, 0x56, 0xb7, 0x19, 0x7d, 0x2e, 0x49, 0x52, 0x3f, 0xf1, 0x46, 0x2c, 0x98, 0xa3, + 0xdf, 0x32, 0x20, 0x6f, 0x29, 0xc2, 0xce, 0xcf, 0x26, 0xf7, 0xd3, 0x1f, 0x4c, 0x8f, 0x6c, 0x2b, + 0x35, 0x15, 0x91, 0x28, 0xab, 0x63, 0xb9, 0xf8, 0xf3, 0x90, 0x57, 0xa6, 0x30, 0x8a, 0x8c, 0x5e, + 0x7c, 0x11, 0x16, 0xc7, 0x92, 0xf1, 0x0f, 0xc0, 0xa8, 0xb7, 0x7f, 0xa9, 0x45, 0x78, 0xa0, 0xd6, + 0x8d, 0xcb, 0x2f, 0x2e, 0x0a, 0xc7, 0x05, 0xd4, 0xdc, 0x87, 0xc5, 0xb8, 0x03, 0x3a, 0x4a, 0x4e, + 0x74, 0x28, 0x75, 0xfb, 0x1e, 0x18, 0xf1, 0xbe, 0xae, 0xf9, 0x57, 0x19, 0x98, 0x16, 0xe5, 0xa2, + 0x8f, 0xa0, 0x1c, 0xe9, 0xbe, 0x96, 0x55, 0xde, 0x4c, 0xa5, 0xca, 0xb5, 0x6f, 0x2d, 0x92, 0x1f, + 0xab, 0x45, 0x7a, 0x39, 0x1d, 0x76, 0x83, 0x0b, 0x91, 0xbe, 0x98, 0x81, 0x85, 0x58, 0xf9, 0x2d, + 0xfa, 0x9c, 0xd1, 0x7b, 0xfe, 0x7e, 0x27, 0xd5, 0x0a, 0x5f, 0x59, 0xec, 0x36, 0xf8, 0x28, 0xde, + 0xd7, 0x5e, 0x00, 0xb8, 0x9d, 0xda, 0x2b, 0x31, 0x03, 0x1f, 0x03, 0xf8, 0x67, 0x03, 0x1e, 0xef, + 0x5b, 0x90, 0xcc, 0x6e, 0x5a, 0x79, 0x3a, 0x54, 0xc8, 0x5e, 0xca, 0x17, 0x0c, 0x64, 0x36, 0x33, + 0x7e, 0x39, 0x26, 0xce, 0x1e, 0x3d, 0x0b, 0xb3, 0x4c, 0x8f, 0xd3, 0xed, 0x13, 0x90, 0x96, 0x78, + 0xde, 0x83, 0x65, 0x0e, 0x2a, 0x4a, 0x3b, 0xd6, 0xb0, 0xcc, 0xdf, 0x35, 0xa0, 0xd0, 0xef, 0xde, + 0xcd, 0x10, 0x7e, 0xf9, 0xcf, 0xc5, 0x4a, 0x83, 0x8a, 0x3d, 0xa5, 0x41, 0x31, 0xcf, 0x3c, 0xac, + 0x02, 0x52, 0x9c, 0xe2, 0xec, 0x09, 0x95, 0x2f, 0x5f, 0x30, 0xe0, 0x42, 0x1f, 0xc1, 0xe9, 0x29, + 0x11, 0x33, 0x4e, 0x5d, 0x22, 0x96, 0x19, 0xb6, 0x44, 0xcc, 0xfc, 0x9b, 0x2c, 0x2c, 0x8a, 0xf1, + 0x44, 0xc6, 0xfc, 0x79, 0xad, 0xc0, 0xea, 0x1d, 0xb1, 0x02, 0xab, 0xe5, 0x38, 0xfe, 0xff, 0x55, + 0x57, 0xfd, 0x74, 0x55, 0x57, 0xfd, 0x24, 0x03, 0xe7, 0x13, 0xaf, 0x17, 0xa1, 0x37, 0x12, 0xb4, + 0xe0, 0xdd, 0x94, 0xef, 0x31, 0x0d, 0xa9, 0x07, 0xc7, 0x2d, 0x49, 0xfa, 0x4d, 0xb5, 0x14, 0x88, + 0x87, 0x09, 0x07, 0x67, 0x70, 0x23, 0x6b, 0xc4, 0xaa, 0x20, 0xf3, 0x57, 0xb3, 0x70, 0x65, 0x58, + 0x42, 0x3f, 0xa5, 0x55, 0xa3, 0xbe, 0x56, 0x35, 0xfa, 0x68, 0x2c, 0xd4, 0xd9, 0x14, 0x90, 0x7e, + 0x25, 0x2b, 0xcd, 0x5e, 0xaf, 0x7c, 0x0e, 0x75, 0xb8, 0x30, 0x4d, 0xbd, 0x98, 0xf0, 0x45, 0x8f, + 0x48, 0x15, 0x4e, 0x57, 0x78, 0xf3, 0x5b, 0x9d, 0xe2, 0x92, 0x78, 0x38, 0xa0, 0x42, 0x02, 0xd1, + 0x88, 0xc3, 0x4e, 0xe8, 0x0a, 0xe4, 0x3c, 0x0e, 0x0d, 0xeb, 0xe4, 0xc4, 0x81, 0x09, 0x6f, 0xc3, + 0x12, 0x8a, 0x3e, 0xa9, 0xb8, 0x7d, 0x13, 0x67, 0x75, 0xc3, 0x65, 0xd0, 0x39, 0xd0, 0x6b, 0x90, + 0xf3, 0xc3, 0xe7, 0x3e, 0x78, 0x76, 0xf0, 0x99, 0x21, 0xcb, 0x2f, 0x69, 0x94, 0x10, 0xbe, 0xfd, + 0xc1, 0xe7, 0x27, 0x5f, 0x06, 0x91, 0x24, 0x91, 0x29, 0x1d, 0x74, 0x9e, 0xe2, 0x81, 0x04, 0xe7, + 0xfc, 0x4d, 0x03, 0xf2, 0x62, 0xb5, 0x1e, 0x41, 0x45, 0xe8, 0x3d, 0xbd, 0x22, 0xf4, 0x5a, 0x2a, + 0xba, 0xa3, 0x4f, 0x39, 0xe8, 0x3d, 0x98, 0x55, 0x6f, 0x98, 0xa2, 0x57, 0x15, 0xdd, 0x67, 0x8c, + 0x73, 0x93, 0x2d, 0xd4, 0x8e, 0x91, 0x5e, 0x34, 0xbf, 0x9c, 0x93, 0x5f, 0x91, 0xd5, 0x9d, 0xaa, + 0x32, 0x68, 0x0c, 0x94, 0x41, 0x55, 0x04, 0x32, 0xe9, 0x8b, 0xc0, 0x6d, 0xc8, 0x85, 0x0a, 0x4a, + 0x98, 0xf1, 0xa7, 0xd4, 0x8a, 0x16, 0xea, 0x0b, 0x50, 0x62, 0x8a, 0xe0, 0xb2, 0xa8, 0x42, 0xae, + 0xa1, 0x54, 0x9c, 0x92, 0x0c, 0x7a, 0x1d, 0xf2, 0x0f, 0x5c, 0xef, 0x7e, 0xc3, 0xb5, 0xd8, 0xab, + 0x3b, 0x90, 0x46, 0x9e, 0x57, 0x66, 0x57, 0x78, 0x0d, 0xe1, 0xdd, 0x88, 0x3e, 0x56, 0x99, 0xa1, + 0x12, 0x2c, 0x34, 0x6d, 0x07, 0x13, 0xab, 0x26, 0x0b, 0x3f, 0x27, 0xf8, 0x4b, 0x23, 0xa1, 0x93, + 0xbb, 0xa3, 0x83, 0x71, 0x1c, 0x1f, 0x7d, 0x0c, 0x72, 0xbe, 0xb8, 0xc5, 0x9a, 0x4e, 0x46, 0x5e, + 0x86, 0x47, 0x9c, 0x68, 0xf4, 0xed, 0xc2, 0x16, 0x2c, 0x19, 0xa2, 0x6d, 0x58, 0xf6, 0xc4, 0x3d, + 0x31, 0xed, 0x21, 0x3d, 0xbe, 0x3f, 0xd9, 0x83, 0x16, 0x38, 0x01, 0x8e, 0x13, 0x7b, 0x51, 0x2f, + 0x86, 0x5d, 0x95, 0xe6, 0x29, 0xd9, 0x5c, 0xe4, 0xc5, 0x30, 0x81, 0xaf, 0x61, 0x01, 0x1d, 0x54, + 0x48, 0x9c, 0x1b, 0xa3, 0x90, 0xb8, 0x02, 0xe7, 0xe3, 0x20, 0x76, 0x9b, 0x8d, 0x5d, 0xa0, 0x53, + 0xac, 0xc7, 0x6e, 0x12, 0x12, 0x4e, 0xee, 0x8b, 0xee, 0xc2, 0x8c, 0x47, 0x58, 0x7c, 0x51, 0x0a, + 0xcf, 0x00, 0x47, 0x2e, 0x3e, 0xc0, 0x21, 0x01, 0x1c, 0xd1, 0xa2, 0xeb, 0x6e, 0xe9, 0x8f, 0x6d, + 0xdc, 0x4e, 0xf1, 0xcd, 0x57, 0xb1, 0xf6, 0x7d, 0x6e, 0x99, 0x9a, 0xff, 0x39, 0x07, 0x73, 0x5a, + 0x18, 0x8d, 0x9e, 0x82, 0x49, 0x76, 0xbd, 0x8f, 0xa9, 0x87, 0x5c, 0xa4, 0xc2, 0xf8, 0xc7, 0xe1, + 0x30, 0xf4, 0x45, 0x03, 0x16, 0x5a, 0x5a, 0xca, 0x2f, 0xd4, 0x9c, 0x63, 0x1e, 0xe5, 0xe8, 0x79, + 0x44, 0xe5, 0x99, 0x2a, 0x9d, 0x19, 0x8e, 0x73, 0xa7, 0x1b, 0x50, 0xd4, 0xe3, 0x34, 0x88, 0xc7, + 0xb0, 0x85, 0x8f, 0x23, 0x49, 0xac, 0xeb, 0x60, 0x1c, 0xc7, 0xa7, 0x2b, 0xcc, 0x66, 0x37, 0xce, + 0x0b, 0x99, 0xa5, 0x90, 0x00, 0x8e, 0x68, 0xa1, 0x17, 0x61, 0x5e, 0xbc, 0xb1, 0xb0, 0xeb, 0xd6, + 0x6e, 0x58, 0xfe, 0xa1, 0x70, 0xee, 0x65, 0x30, 0xb2, 0xae, 0x41, 0x71, 0x0c, 0x9b, 0xcd, 0x2d, + 0x7a, 0xc8, 0x82, 0x11, 0x98, 0xd2, 0x5f, 0xf1, 0x5a, 0xd7, 0xc1, 0x38, 0x8e, 0x8f, 0xde, 0xa5, + 0xe8, 0x7d, 0x7e, 0x4c, 0x22, 0xb5, 0x41, 0x82, 0xee, 0x2f, 0xc1, 0x42, 0x9b, 0xc5, 0x42, 0xb5, + 0x10, 0x28, 0xf6, 0xa3, 0x64, 0x78, 0x47, 0x07, 0xe3, 0x38, 0x3e, 0x7a, 0x01, 0xe6, 0x3c, 0xaa, + 0xdd, 0x24, 0x01, 0x7e, 0x76, 0x22, 0x0f, 0x02, 0xb0, 0x0a, 0xc4, 0x3a, 0x2e, 0x7a, 0x09, 0x96, + 0xa2, 0x8b, 0xdf, 0x21, 0x01, 0x7e, 0x98, 0x22, 0x1f, 0xb2, 0x28, 0xc5, 0x11, 0x70, 0x6f, 0x1f, + 0xf4, 0x0b, 0xb0, 0xa8, 0x7c, 0x89, 0x4d, 0xa7, 0x46, 0x1e, 0x8a, 0xcb, 0xb9, 0xcb, 0xec, 0x40, + 0x26, 0x06, 0xc3, 0x3d, 0xd8, 0xe8, 0x7d, 0x30, 0x5f, 0x75, 0x1b, 0x0d, 0xa6, 0xe3, 0xf8, 0x0b, + 0x52, 0xfc, 0x16, 0x2e, 0xbf, 0xaf, 0xac, 0x41, 0x70, 0x0c, 0x13, 0x6d, 0x01, 0x72, 0xf7, 0x7d, + 0xe2, 0x1d, 0x91, 0xda, 0x4b, 0xfc, 0x11, 0x70, 0x6a, 0xe2, 0xe7, 0xf4, 0x6a, 0xc0, 0x5b, 0x3d, + 0x18, 0x38, 0xa1, 0x17, 0xda, 0x87, 0x8b, 0xa1, 0xbd, 0xe9, 0xed, 0x51, 0x28, 0x68, 0x21, 0xd3, + 0xc5, 0xbb, 0x7d, 0x31, 0xf1, 0x00, 0x2a, 0xe8, 0x97, 0xf4, 0x42, 0xf8, 0xf9, 0x34, 0xde, 0xe4, + 0x8c, 0x67, 0x07, 0x4e, 0xac, 0x82, 0xf7, 0x60, 0x8a, 0x17, 0x80, 0x16, 0x16, 0xd2, 0xb8, 0xf0, + 0xae, 0x3e, 0x58, 0x13, 0xd9, 0x21, 0xde, 0x8a, 0x05, 0x27, 0xf4, 0x09, 0x98, 0xd9, 0x0f, 0x5f, + 0x2f, 0x2b, 0x2c, 0xa6, 0x61, 0x7b, 0x63, 0x0f, 0xf1, 0x45, 0xd1, 0xaf, 0x04, 0xe0, 0x88, 0x25, + 0x7a, 0x1a, 0xf2, 0x37, 0x76, 0x4b, 0x52, 0xd2, 0x97, 0x98, 0x84, 0x4d, 0xd0, 0x2e, 0x58, 0x05, + 0xd0, 0x5d, 0x2c, 0x7d, 0x32, 0xc4, 0x96, 0x3c, 0xb2, 0xe9, 0xbd, 0x2e, 0x16, 0xc5, 0x66, 0xe7, + 0x6b, 0xb8, 0x52, 0x38, 0x17, 0xc3, 0x16, 0xed, 0x58, 0x62, 0xa0, 0xd7, 0x20, 0x2f, 0x6c, 0x12, + 0xd3, 0x7f, 0xcb, 0xa7, 0xbb, 0x64, 0x81, 0x23, 0x12, 0x58, 0xa5, 0x87, 0x9e, 0x83, 0x7c, 0x8b, + 0x3d, 0xea, 0x44, 0xae, 0xb7, 0x1b, 0x8d, 0xc2, 0x79, 0xa6, 0x9b, 0xe5, 0xc1, 0xc3, 0x6e, 0x04, + 0xc2, 0x2a, 0x1e, 0x7a, 0x26, 0x3c, 0x1c, 0x7f, 0x9b, 0x76, 0x8e, 0x24, 0x0f, 0xc7, 0xa5, 0x27, + 0xdd, 0xa7, 0xa4, 0xf0, 0xc2, 0x09, 0xc9, 0x91, 0x4f, 0x47, 0xc9, 0x61, 0xf9, 0x84, 0xc8, 0xc7, + 0x55, 0x69, 0x30, 0xd2, 0x78, 0xaa, 0xbc, 0xe7, 0x69, 0x3c, 0x6e, 0x2c, 0x12, 0x65, 0xa1, 0x25, + 0xe5, 0x3f, 0x95, 0x1b, 0xc2, 0xfa, 0xf3, 0x28, 0x3c, 0xd2, 0xd2, 0xa5, 0xdf, 0xfc, 0xfe, 0x84, + 0x4c, 0x10, 0xc5, 0xce, 0x84, 0x3d, 0x98, 0xb4, 0xfd, 0xc0, 0x76, 0x53, 0xbc, 0xd5, 0x10, 0x7b, + 0x57, 0x84, 0xd5, 0xb8, 0x31, 0x00, 0xe6, 0xac, 0x28, 0x4f, 0xa7, 0x6e, 0x3b, 0x0f, 0xc5, 0xf4, + 0x6f, 0xa7, 0x7e, 0xd8, 0xcb, 0x79, 0x32, 0x00, 0xe6, 0xac, 0xd0, 0x3d, 0xc8, 0x5a, 0x8d, 0xfd, + 0x94, 0x9e, 0xa5, 0x8f, 0xff, 0x6b, 0x07, 0x5e, 0x21, 0x52, 0xda, 0x2e, 0x63, 0xca, 0x84, 0xf2, + 0xf2, 0x9b, 0xb6, 0xf0, 0x2f, 0xc6, 0xe4, 0x55, 0xd9, 0xd9, 0x4c, 0xe2, 0x55, 0xd9, 0xd9, 0xc4, + 0x94, 0x09, 0xfa, 0x9c, 0x01, 0x60, 0xc9, 0x7f, 0xbb, 0x90, 0xce, 0x3b, 0x92, 0xfd, 0xfe, 0x8d, + 0x03, 0x2f, 0xdd, 0x8a, 0xa0, 0x58, 0xe1, 0x6c, 0x7e, 0xc9, 0x80, 0xa5, 0x9e, 0xc1, 0xc6, 0xff, + 0x23, 0x85, 0x31, 0xfc, 0x7f, 0xa4, 0x10, 0x2f, 0xcf, 0x54, 0x5a, 0x0d, 0x3b, 0xf1, 0x66, 0xd0, + 0x5e, 0x0c, 0x8e, 0x7b, 0x7a, 0x98, 0xdf, 0x30, 0x20, 0xaf, 0xd4, 0x56, 0x53, 0xbf, 0x97, 0xd5, + 0xa0, 0x8b, 0x61, 0x44, 0x8f, 0xee, 0xb0, 0x9c, 0x18, 0x87, 0xf1, 0xf4, 0x6c, 0x3d, 0x4a, 0x52, + 0x2a, 0xe9, 0x59, 0xda, 0x8a, 0x05, 0x14, 0x5d, 0x86, 0x09, 0x3f, 0x20, 0x2d, 0x26, 0x51, 0x4a, + 0xa9, 0x35, 0x3b, 0xa4, 0x60, 0x10, 0xc6, 0x8e, 0x2a, 0x47, 0x51, 0x37, 0xa3, 0xbc, 0xf1, 0x63, + 0x51, 0x37, 0x9b, 0xc1, 0xd0, 0x25, 0xc8, 0x12, 0xa7, 0x26, 0xbc, 0xc5, 0xbc, 0x40, 0xc9, 0x5e, + 0x73, 0x6a, 0x98, 0xb6, 0x9b, 0xb7, 0x60, 0xb6, 0x42, 0xaa, 0x1e, 0x09, 0x5e, 0x26, 0xc7, 0xc3, + 0x25, 0x10, 0x2f, 0xf1, 0x83, 0xd7, 0x8c, 0x4e, 0x90, 0x76, 0xa7, 0xed, 0xe6, 0x1f, 0x1a, 0x10, + 0x7b, 0x72, 0x49, 0x49, 0xd5, 0x18, 0xfd, 0x52, 0x35, 0x5a, 0x52, 0x21, 0x33, 0x30, 0xa9, 0xb0, + 0x05, 0xa8, 0x69, 0x05, 0xd5, 0x43, 0xed, 0x41, 0x30, 0xe1, 0xa8, 0x47, 0x37, 0x39, 0x7a, 0x30, + 0x70, 0x42, 0x2f, 0xf3, 0x15, 0xc8, 0x85, 0xb7, 0x72, 0x58, 0x69, 0x7b, 0x18, 0xb3, 0xa8, 0xa5, + 0xed, 0x34, 0x64, 0x61, 0x10, 0x3a, 0x46, 0xdf, 0xb1, 0x6f, 0xb8, 0x7e, 0x10, 0x5e, 0x25, 0xe2, + 0x99, 0x89, 0x9b, 0x9b, 0xac, 0x0d, 0x4b, 0xa8, 0xb9, 0x04, 0x0b, 0x32, 0xe5, 0xc0, 0x25, 0xce, + 0xfc, 0x66, 0x16, 0x66, 0xb5, 0x97, 0xc2, 0x4f, 0xfe, 0xd2, 0xc3, 0x7f, 0x93, 0x84, 0xd4, 0x41, + 0x76, 0xc4, 0xd4, 0x81, 0x9a, 0xab, 0x99, 0x38, 0xdb, 0x5c, 0xcd, 0x64, 0x3a, 0xb9, 0x9a, 0x00, + 0xa6, 0xc5, 0xff, 0xa6, 0x11, 0x25, 0x80, 0x3b, 0x29, 0xdd, 0x2e, 0x15, 0xb7, 0xe5, 0x58, 0xd5, + 0x63, 0xa8, 0x3d, 0x42, 0x56, 0xe6, 0xd7, 0x26, 0x61, 0x5e, 0xbf, 0x6f, 0x3a, 0xc4, 0x4a, 0xbe, + 0xab, 0x67, 0x25, 0x47, 0x0c, 0x9d, 0xb2, 0xe3, 0x86, 0x4e, 0x13, 0xe3, 0x86, 0x4e, 0x93, 0xa7, + 0x08, 0x9d, 0x7a, 0x03, 0x9f, 0xa9, 0xa1, 0x03, 0x9f, 0xf7, 0xcb, 0x73, 0xbf, 0x69, 0x2d, 0x51, + 0x1e, 0x9d, 0xfb, 0x21, 0x7d, 0x19, 0xd6, 0xdd, 0x5a, 0xe2, 0xf9, 0x69, 0xee, 0x84, 0xa2, 0x42, + 0x2f, 0xf1, 0x98, 0x6e, 0xf4, 0xec, 0xcc, 0xdb, 0x46, 0x38, 0xa2, 0x8b, 0xfe, 0xfd, 0x12, 0xb3, + 0x3c, 0xa0, 0x5b, 0xad, 0x4a, 0x04, 0xc2, 0x2a, 0x1e, 0x7b, 0x8a, 0x5b, 0x7f, 0x28, 0x9c, 0x45, + 0xa2, 0xea, 0x53, 0xdc, 0xb1, 0x87, 0xc5, 0xe3, 0xf8, 0xe6, 0x1b, 0x59, 0x98, 0xd7, 0x9f, 0x52, + 0x44, 0x0f, 0xa4, 0xb7, 0x98, 0x8a, 0xa3, 0xca, 0xc9, 0x2a, 0xf7, 0x39, 0xfb, 0x86, 0x4c, 0xfc, + 0xff, 0x14, 0xed, 0xcb, 0xcb, 0xa5, 0x67, 0xc7, 0x58, 0xc4, 0x2a, 0x82, 0x1d, 0x7b, 0x7d, 0x31, + 0xaa, 0xb2, 0x13, 0x67, 0x7d, 0xa9, 0x73, 0x8f, 0xea, 0xe6, 0x24, 0x2b, 0xac, 0xb0, 0x35, 0x3f, + 0x95, 0x81, 0xe8, 0xdd, 0x79, 0xf6, 0x56, 0x9b, 0xaf, 0x58, 0x62, 0xb1, 0x18, 0x5b, 0xe3, 0x3e, + 0x88, 0x18, 0x51, 0x14, 0xc5, 0x0e, 0x4a, 0x0b, 0xd6, 0x38, 0xfe, 0x37, 0xbc, 0x37, 0x6f, 0xc1, + 0x42, 0xac, 0xe6, 0x3b, 0xf5, 0xe2, 0xa9, 0x6f, 0x64, 0x60, 0x46, 0x56, 0xcd, 0x53, 0xe7, 0xa5, + 0xed, 0x85, 0x4f, 0x41, 0x49, 0xe7, 0xe5, 0x0e, 0xde, 0xc6, 0xb4, 0x1d, 0x3d, 0x84, 0xe9, 0x43, + 0x62, 0xd5, 0x88, 0x17, 0xa6, 0x22, 0x77, 0x52, 0x2a, 0xd7, 0xbf, 0xc1, 0xa8, 0x46, 0x73, 0xe1, + 0xbf, 0x7d, 0x1c, 0xb2, 0x43, 0x2f, 0xc2, 0x7c, 0x60, 0x37, 0x09, 0x8d, 0x21, 0x15, 0x03, 0x9e, + 0x8d, 0xf2, 0x7b, 0x7b, 0x1a, 0x14, 0xc7, 0xb0, 0xa9, 0x85, 0xb9, 0xe7, 0xbb, 0x0e, 0xbb, 0x55, + 0x3f, 0xa1, 0x07, 0xea, 0x5b, 0x95, 0x5b, 0x37, 0xd9, 0xa5, 0x7a, 0x89, 0x41, 0xb1, 0x6d, 0x56, + 0x35, 0xec, 0x11, 0x71, 0x1c, 0xba, 0x18, 0xdd, 0x71, 0xe2, 0xed, 0x58, 0x62, 0x98, 0x77, 0x60, + 0x21, 0x36, 0x91, 0xd0, 0x09, 0x34, 0x92, 0x9d, 0xc0, 0xa1, 0xfe, 0x9d, 0x97, 0xf9, 0x27, 0x06, + 0x2c, 0xf5, 0xec, 0x9a, 0x61, 0x0b, 0xef, 0xe2, 0x2a, 0x34, 0x73, 0x7a, 0x15, 0x9a, 0x1d, 0x4d, + 0x85, 0x96, 0x57, 0xbf, 0xf5, 0x83, 0x95, 0xc7, 0xbe, 0xfd, 0x83, 0x95, 0xc7, 0xbe, 0xf3, 0x83, + 0x95, 0xc7, 0x3e, 0xd5, 0x5d, 0x31, 0xbe, 0xd5, 0x5d, 0x31, 0xbe, 0xdd, 0x5d, 0x31, 0xbe, 0xd3, + 0x5d, 0x31, 0xbe, 0xdf, 0x5d, 0x31, 0xbe, 0xf4, 0xc3, 0x95, 0xc7, 0x5e, 0xcd, 0x85, 0x42, 0xf0, + 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x21, 0x27, 0xf1, 0x08, 0x85, 0x71, 0x00, 0x00, } func (m *ALBTrafficRouting) Marshal() (dAtA []byte, err error) { @@ -3477,6 +3577,18 @@ func (m *CanaryStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Weights != nil { + { + size, err := m.Weights.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } i -= len(m.CurrentExperiment) copy(dAtA[i:], m.CurrentExperiment) i = encodeVarintGenerated(dAtA, i, uint64(len(m.CurrentExperiment))) @@ -3605,6 +3717,14 @@ func (m *CanaryStrategy) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + i-- + if m.DynamicStableScale { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x70 if m.AbortScaleDownDelaySeconds != nil { i = encodeVarintGenerated(dAtA, i, uint64(*m.AbortScaleDownDelaySeconds)) i-- @@ -4415,6 +4535,20 @@ func (m *IstioVirtualService) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.TLSRoutes) > 0 { + for iNdEx := len(m.TLSRoutes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.TLSRoutes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } if len(m.Routes) > 0 { for iNdEx := len(m.Routes) - 1; iNdEx >= 0; iNdEx-- { i -= len(m.Routes[iNdEx]) @@ -5894,6 +6028,14 @@ func (m *RolloutSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + i-- + if m.ProgressDeadlineAbort { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x60 if m.Analysis != nil { { size, err := m.Analysis.MarshalToSizedBuffer(dAtA[:i]) @@ -6476,6 +6618,41 @@ func (m *SetCanaryScale) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *TLSRoute) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TLSRoute) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TLSRoute) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.SNIHosts) > 0 { + for iNdEx := len(m.SNIHosts) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.SNIHosts[iNdEx]) + copy(dAtA[i:], m.SNIHosts[iNdEx]) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.SNIHosts[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + i = encodeVarintGenerated(dAtA, i, uint64(m.Port)) + i-- + dAtA[i] = 0x8 + return len(dAtA) - i, nil +} + func (m *TemplateService) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -6646,6 +6823,63 @@ func (m *TemplateStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *TrafficWeights) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TrafficWeights) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TrafficWeights) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Additional) > 0 { + for iNdEx := len(m.Additional) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Additional[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + { + size, err := m.Stable.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + { + size, err := m.Canary.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + func (m *ValueFrom) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -6817,6 +7051,42 @@ func (m *WebMetricHeader) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *WeightDestination) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *WeightDestination) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *WeightDestination) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + i -= len(m.PodTemplateHash) + copy(dAtA[i:], m.PodTemplateHash) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.PodTemplateHash))) + i-- + dAtA[i] = 0x1a + i -= len(m.ServiceName) + copy(dAtA[i:], m.ServiceName) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.ServiceName))) + i-- + dAtA[i] = 0x12 + i = encodeVarintGenerated(dAtA, i, uint64(m.Weight)) + i-- + dAtA[i] = 0x8 + return len(dAtA) - i, nil +} + func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int { offset -= sovGenerated(v) base := offset @@ -7163,6 +7433,10 @@ func (m *CanaryStatus) Size() (n int) { } l = len(m.CurrentExperiment) n += 1 + l + sovGenerated(uint64(l)) + if m.Weights != nil { + l = m.Weights.Size() + n += 1 + l + sovGenerated(uint64(l)) + } return n } @@ -7247,6 +7521,7 @@ func (m *CanaryStrategy) Size() (n int) { if m.AbortScaleDownDelaySeconds != nil { n += 1 + sovGenerated(uint64(*m.AbortScaleDownDelaySeconds)) } + n += 2 return n } @@ -7504,6 +7779,12 @@ func (m *IstioVirtualService) Size() (n int) { n += 1 + l + sovGenerated(uint64(l)) } } + if len(m.TLSRoutes) > 0 { + for _, e := range m.TLSRoutes { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } return n } @@ -8064,6 +8345,7 @@ func (m *RolloutSpec) Size() (n int) { l = m.Analysis.Size() n += 1 + l + sovGenerated(uint64(l)) } + n += 2 return n } @@ -8236,6 +8518,22 @@ func (m *SetCanaryScale) Size() (n int) { return n } +func (m *TLSRoute) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + n += 1 + sovGenerated(uint64(m.Port)) + if len(m.SNIHosts) > 0 { + for _, s := range m.SNIHosts { + l = len(s) + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + func (m *TemplateService) Size() (n int) { if m == nil { return 0 @@ -8300,6 +8598,25 @@ func (m *TemplateStatus) Size() (n int) { return n } +func (m *TrafficWeights) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Canary.Size() + n += 1 + l + sovGenerated(uint64(l)) + l = m.Stable.Size() + n += 1 + l + sovGenerated(uint64(l)) + if len(m.Additional) > 0 { + for _, e := range m.Additional { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + func (m *ValueFrom) Size() (n int) { if m == nil { return 0 @@ -8364,6 +8681,20 @@ func (m *WebMetricHeader) Size() (n int) { return n } +func (m *WeightDestination) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + n += 1 + sovGenerated(uint64(m.Weight)) + l = len(m.ServiceName) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.PodTemplateHash) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + func sovGenerated(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -8611,6 +8942,7 @@ func (this *CanaryStatus) String() string { `CurrentStepAnalysisRunStatus:` + strings.Replace(this.CurrentStepAnalysisRunStatus.String(), "RolloutAnalysisRunStatus", "RolloutAnalysisRunStatus", 1) + `,`, `CurrentBackgroundAnalysisRunStatus:` + strings.Replace(this.CurrentBackgroundAnalysisRunStatus.String(), "RolloutAnalysisRunStatus", "RolloutAnalysisRunStatus", 1) + `,`, `CurrentExperiment:` + fmt.Sprintf("%v", this.CurrentExperiment) + `,`, + `Weights:` + strings.Replace(this.Weights.String(), "TrafficWeights", "TrafficWeights", 1) + `,`, `}`, }, "") return s @@ -8652,6 +8984,7 @@ func (this *CanaryStrategy) String() string { `ScaleDownDelaySeconds:` + valueToStringGenerated(this.ScaleDownDelaySeconds) + `,`, `ScaleDownDelayRevisionLimit:` + valueToStringGenerated(this.ScaleDownDelayRevisionLimit) + `,`, `AbortScaleDownDelaySeconds:` + valueToStringGenerated(this.AbortScaleDownDelaySeconds) + `,`, + `DynamicStableScale:` + fmt.Sprintf("%v", this.DynamicStableScale) + `,`, `}`, }, "") return s @@ -8861,9 +9194,15 @@ func (this *IstioVirtualService) String() string { if this == nil { return "nil" } + repeatedStringForTLSRoutes := "[]TLSRoute{" + for _, f := range this.TLSRoutes { + repeatedStringForTLSRoutes += strings.Replace(strings.Replace(f.String(), "TLSRoute", "TLSRoute", 1), `&`, ``, 1) + "," + } + repeatedStringForTLSRoutes += "}" s := strings.Join([]string{`&IstioVirtualService{`, `Name:` + fmt.Sprintf("%v", this.Name) + `,`, `Routes:` + fmt.Sprintf("%v", this.Routes) + `,`, + `TLSRoutes:` + repeatedStringForTLSRoutes + `,`, `}`, }, "") return s @@ -9306,6 +9645,7 @@ func (this *RolloutSpec) String() string { `RestartAt:` + strings.Replace(fmt.Sprintf("%v", this.RestartAt), "Time", "v1.Time", 1) + `,`, `WorkloadRef:` + strings.Replace(this.WorkloadRef.String(), "ObjectRef", "ObjectRef", 1) + `,`, `Analysis:` + strings.Replace(this.Analysis.String(), "AnalysisRunStrategy", "AnalysisRunStrategy", 1) + `,`, + `ProgressDeadlineAbort:` + fmt.Sprintf("%v", this.ProgressDeadlineAbort) + `,`, `}`, }, "") return s @@ -9426,16 +9766,27 @@ func (this *SetCanaryScale) String() string { }, "") return s } -func (this *TemplateService) String() string { +func (this *TLSRoute) String() string { if this == nil { return "nil" } - s := strings.Join([]string{`&TemplateService{`, + s := strings.Join([]string{`&TLSRoute{`, + `Port:` + fmt.Sprintf("%v", this.Port) + `,`, + `SNIHosts:` + fmt.Sprintf("%v", this.SNIHosts) + `,`, `}`, }, "") return s } -func (this *TemplateSpec) String() string { +func (this *TemplateService) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&TemplateService{`, + `}`, + }, "") + return s +} +func (this *TemplateSpec) String() string { if this == nil { return "nil" } @@ -9470,6 +9821,23 @@ func (this *TemplateStatus) String() string { }, "") return s } +func (this *TrafficWeights) String() string { + if this == nil { + return "nil" + } + repeatedStringForAdditional := "[]WeightDestination{" + for _, f := range this.Additional { + repeatedStringForAdditional += strings.Replace(strings.Replace(f.String(), "WeightDestination", "WeightDestination", 1), `&`, ``, 1) + "," + } + repeatedStringForAdditional += "}" + s := strings.Join([]string{`&TrafficWeights{`, + `Canary:` + strings.Replace(strings.Replace(this.Canary.String(), "WeightDestination", "WeightDestination", 1), `&`, ``, 1) + `,`, + `Stable:` + strings.Replace(strings.Replace(this.Stable.String(), "WeightDestination", "WeightDestination", 1), `&`, ``, 1) + `,`, + `Additional:` + repeatedStringForAdditional + `,`, + `}`, + }, "") + return s +} func (this *ValueFrom) String() string { if this == nil { return "nil" @@ -9522,6 +9890,18 @@ func (this *WebMetricHeader) String() string { }, "") return s } +func (this *WeightDestination) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&WeightDestination{`, + `Weight:` + fmt.Sprintf("%v", this.Weight) + `,`, + `ServiceName:` + fmt.Sprintf("%v", this.ServiceName) + `,`, + `PodTemplateHash:` + fmt.Sprintf("%v", this.PodTemplateHash) + `,`, + `}`, + }, "") + return s +} func valueToStringGenerated(v interface{}) string { rv := reflect.ValueOf(v) if rv.IsNil() { @@ -12137,6 +12517,42 @@ func (m *CanaryStatus) Unmarshal(dAtA []byte) error { } m.CurrentExperiment = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Weights", 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 < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Weights == nil { + m.Weights = &TrafficWeights{} + } + if err := m.Weights.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -12811,6 +13227,26 @@ func (m *CanaryStrategy) Unmarshal(dAtA []byte) error { } } m.AbortScaleDownDelaySeconds = &v + case 14: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field DynamicStableScale", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.DynamicStableScale = bool(v != 0) default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -14957,6 +15393,40 @@ func (m *IstioVirtualService) Unmarshal(dAtA []byte) error { } m.Routes = append(m.Routes, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TLSRoutes", 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 < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TLSRoutes = append(m.TLSRoutes, TLSRoute{}) + if err := m.TLSRoutes[len(m.TLSRoutes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -20120,6 +20590,26 @@ func (m *RolloutSpec) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 12: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProgressDeadlineAbort", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.ProgressDeadlineAbort = bool(v != 0) default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -21735,6 +22225,107 @@ func (m *SetCanaryScale) Unmarshal(dAtA []byte) error { } return nil } +func (m *TLSRoute) 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: TLSRoute: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TLSRoute: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Port", wireType) + } + m.Port = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Port |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SNIHosts", 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 < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SNIHosts = append(m.SNIHosts, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *TemplateService) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -22353,6 +22944,156 @@ func (m *TemplateStatus) Unmarshal(dAtA []byte) error { } return nil } +func (m *TrafficWeights) 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: TrafficWeights: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TrafficWeights: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Canary", 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 < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Canary.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Stable", 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 < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Stable.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Additional", 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 < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Additional = append(m.Additional, WeightDestination{}) + if err := m.Additional[len(m.Additional)-1].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) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *ValueFrom) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -22890,6 +23631,139 @@ func (m *WebMetricHeader) Unmarshal(dAtA []byte) error { } return nil } +func (m *WeightDestination) 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: WeightDestination: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: WeightDestination: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Weight", wireType) + } + m.Weight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Weight |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ServiceName", 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 < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ServiceName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PodTemplateHash", 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 < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.PodTemplateHash = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipGenerated(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/pkg/apis/rollouts/v1alpha1/generated.proto b/pkg/apis/rollouts/v1alpha1/generated.proto index 6cf6fd21e0..c926b717e2 100644 --- a/pkg/apis/rollouts/v1alpha1/generated.proto +++ b/pkg/apis/rollouts/v1alpha1/generated.proto @@ -292,6 +292,9 @@ message CanaryStatus { // CurrentExperiment indicates the running experiment optional string currentExperiment = 3; + + // Weights records the weights which have been set on traffic provider. Only valid when using traffic routing + optional TrafficWeights weights = 4; } // CanaryStep defines a step of a canary deployment. @@ -391,6 +394,12 @@ message CanaryStrategy { // Default is 30 seconds. // +optional optional int32 abortScaleDownDelaySeconds = 13; + + // DynamicStableScale is a traffic routing feature which dynamically scales the stable + // ReplicaSet to minimize total pods which are running during an update. This is calculated by + // scaling down the stable as traffic is increased to canary. When disabled (the default behavior) + // the stable ReplicaSet remains fully scaled to support instantaneous aborts. + optional bool dynamicStableScale = 14; } // ClusterAnalysisTemplate holds the template for performing canary analysis @@ -590,8 +599,11 @@ message IstioVirtualService { // Name holds the name of the VirtualService optional string name = 1; - // Routes are list of routes within VirtualService to edit. If omitted, VirtualService must have a single route + // A list of HTTP routes within VirtualService to edit. If omitted, VirtualService must have a single route of this type. repeated string routes = 2; + + // A list of TLS/HTTPS routes within VirtualService to edit. If omitted, VirtualService must have a single route of this type. + repeated TLSRoute tlsRoutes = 3; } // JobMetric defines a job to run which acts as a metric @@ -1025,6 +1037,11 @@ message RolloutSpec { // Defaults to 600s. optional int32 progressDeadlineSeconds = 8; + // ProgressDeadlineAbort is whether to abort the update when ProgressDeadlineSeconds + // is exceeded if analysis is not used. Default is false. + // +optional + optional bool progressDeadlineAbort = 12; + // RestartAt indicates when all the pods of a Rollout should be restarted optional k8s.io.apimachinery.pkg.apis.meta.v1.Time restartAt = 9; @@ -1207,6 +1224,15 @@ message SetCanaryScale { optional bool matchTrafficWeight = 3; } +// TLSRoute holds the information on the virtual service's TLS/HTTPS routes that are desired to be matched for changing weights. +message TLSRoute { + // Port number of the TLS Route desired to be matched in the given Istio VirtualService. + optional int64 port = 1; + + // A list of all the SNI Hosts of the TLS Route desired to be matched in the given Istio VirtualService. + repeated string sniHosts = 2; +} + message TemplateService { } @@ -1277,6 +1303,15 @@ message TemplateStatus { optional string podTemplateHash = 11; } +// TrafficWeights describes the current status of how traffic has been split +message TrafficWeights { + optional WeightDestination canary = 1; + + optional WeightDestination stable = 2; + + repeated WeightDestination additional = 3; +} + message ValueFrom { // Secret is a reference to where a secret is stored. This field is one of the fields with valueFrom // +optional @@ -1322,3 +1357,11 @@ message WebMetricHeader { optional string value = 2; } +message WeightDestination { + optional int32 weight = 1; + + optional string serviceName = 2; + + optional string podTemplateHash = 3; +} + diff --git a/pkg/apis/rollouts/v1alpha1/openapi_generated.go b/pkg/apis/rollouts/v1alpha1/openapi_generated.go index 5962af0c1c..ea7871325c 100644 --- a/pkg/apis/rollouts/v1alpha1/openapi_generated.go +++ b/pkg/apis/rollouts/v1alpha1/openapi_generated.go @@ -97,13 +97,16 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.ScopeDetail": schema_pkg_apis_rollouts_v1alpha1_ScopeDetail(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.SecretKeyRef": schema_pkg_apis_rollouts_v1alpha1_SecretKeyRef(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.SetCanaryScale": schema_pkg_apis_rollouts_v1alpha1_SetCanaryScale(ref), + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.TLSRoute": schema_pkg_apis_rollouts_v1alpha1_TLSRoute(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.TemplateService": schema_pkg_apis_rollouts_v1alpha1_TemplateService(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.TemplateSpec": schema_pkg_apis_rollouts_v1alpha1_TemplateSpec(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.TemplateStatus": schema_pkg_apis_rollouts_v1alpha1_TemplateStatus(ref), + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.TrafficWeights": schema_pkg_apis_rollouts_v1alpha1_TrafficWeights(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.ValueFrom": schema_pkg_apis_rollouts_v1alpha1_ValueFrom(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.WavefrontMetric": schema_pkg_apis_rollouts_v1alpha1_WavefrontMetric(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.WebMetric": schema_pkg_apis_rollouts_v1alpha1_WebMetric(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.WebMetricHeader": schema_pkg_apis_rollouts_v1alpha1_WebMetricHeader(ref), + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.WeightDestination": schema_pkg_apis_rollouts_v1alpha1_WeightDestination(ref), } } @@ -875,11 +878,17 @@ func schema_pkg_apis_rollouts_v1alpha1_CanaryStatus(ref common.ReferenceCallback Format: "", }, }, + "weights": { + SchemaProps: spec.SchemaProps{ + Description: "Weights records the weights which have been set on traffic provider. Only valid when using traffic routing", + Ref: ref("github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.TrafficWeights"), + }, + }, }, }, }, Dependencies: []string{ - "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RolloutAnalysisRunStatus"}, + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RolloutAnalysisRunStatus", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.TrafficWeights"}, } } @@ -1027,6 +1036,13 @@ func schema_pkg_apis_rollouts_v1alpha1_CanaryStrategy(ref common.ReferenceCallba Format: "int32", }, }, + "dynamicStableScale": { + SchemaProps: spec.SchemaProps{ + Description: "DynamicStableScale is a traffic routing feature which dynamically scales the stable ReplicaSet to minimize total pods which are running during an update. This is calculated by scaling down the stable as traffic is increased to canary. When disabled (the default behavior) the stable ReplicaSet remains fully scaled to support instantaneous aborts.", + Type: []string{"boolean"}, + Format: "", + }, + }, }, }, }, @@ -1686,7 +1702,7 @@ func schema_pkg_apis_rollouts_v1alpha1_IstioVirtualService(ref common.ReferenceC }, "routes": { SchemaProps: spec.SchemaProps{ - Description: "Routes are list of routes within VirtualService to edit. If omitted, VirtualService must have a single route", + Description: "A list of HTTP routes within VirtualService to edit. If omitted, VirtualService must have a single route of this type.", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ @@ -1699,10 +1715,26 @@ func schema_pkg_apis_rollouts_v1alpha1_IstioVirtualService(ref common.ReferenceC }, }, }, + "tlsRoutes": { + SchemaProps: spec.SchemaProps{ + Description: "A list of TLS/HTTPS routes within VirtualService to edit. If omitted, VirtualService must have a single route of this type.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.TLSRoute"), + }, + }, + }, + }, + }, }, Required: []string{"name"}, }, }, + Dependencies: []string{ + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.TLSRoute"}, } } @@ -3019,6 +3051,13 @@ func schema_pkg_apis_rollouts_v1alpha1_RolloutSpec(ref common.ReferenceCallback) Format: "int32", }, }, + "progressDeadlineAbort": { + SchemaProps: spec.SchemaProps{ + Description: "ProgressDeadlineAbort is whether to abort the update when ProgressDeadlineSeconds is exceeded if analysis is not used. Default is false.", + Type: []string{"boolean"}, + Format: "", + }, + }, "restartAt": { SchemaProps: spec.SchemaProps{ Description: "RestartAt indicates when all the pods of a Rollout should be restarted", @@ -3442,6 +3481,41 @@ func schema_pkg_apis_rollouts_v1alpha1_SetCanaryScale(ref common.ReferenceCallba } } +func schema_pkg_apis_rollouts_v1alpha1_TLSRoute(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "TLSRoute holds the information on the virtual service's TLS/HTTPS routes that are desired to be matched for changing weights.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "port": { + SchemaProps: spec.SchemaProps{ + Description: "Port number of the TLS Route desired to be matched in the given Istio VirtualService.", + Type: []string{"integer"}, + Format: "int64", + }, + }, + "sniHosts": { + SchemaProps: spec.SchemaProps{ + Description: "A list of all the SNI Hosts of the TLS Route desired to be matched in the given Istio VirtualService.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + func schema_pkg_apis_rollouts_v1alpha1_TemplateService(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -3605,6 +3679,47 @@ func schema_pkg_apis_rollouts_v1alpha1_TemplateStatus(ref common.ReferenceCallba } } +func schema_pkg_apis_rollouts_v1alpha1_TrafficWeights(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "TrafficWeights describes the current status of how traffic has been split", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "canary": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.WeightDestination"), + }, + }, + "stable": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.WeightDestination"), + }, + }, + "additional": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.WeightDestination"), + }, + }, + }, + }, + }, + }, + Required: []string{"canary", "stable"}, + }, + }, + Dependencies: []string{ + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.WeightDestination"}, + } +} + func schema_pkg_apis_rollouts_v1alpha1_ValueFrom(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -3748,3 +3863,35 @@ func schema_pkg_apis_rollouts_v1alpha1_WebMetricHeader(ref common.ReferenceCallb }, } } + +func schema_pkg_apis_rollouts_v1alpha1_WeightDestination(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "weight": { + SchemaProps: spec.SchemaProps{ + Default: 0, + Type: []string{"integer"}, + Format: "int32", + }, + }, + "serviceName": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "podTemplateHash": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"weight"}, + }, + }, + } +} diff --git a/pkg/apis/rollouts/v1alpha1/types.go b/pkg/apis/rollouts/v1alpha1/types.go index 930dec7473..8f16935df0 100644 --- a/pkg/apis/rollouts/v1alpha1/types.go +++ b/pkg/apis/rollouts/v1alpha1/types.go @@ -299,6 +299,11 @@ type CanaryStrategy struct { // Default is 30 seconds. // +optional AbortScaleDownDelaySeconds *int32 `json:"abortScaleDownDelaySeconds,omitempty" protobuf:"varint,13,opt,name=abortScaleDownDelaySeconds"` + // DynamicStableScale is a traffic routing feature which dynamically scales the stable + // ReplicaSet to minimize total pods which are running during an update. This is calculated by + // scaling down the stable as traffic is increased to canary. When disabled (the default behavior) + // the stable ReplicaSet remains fully scaled to support instantaneous aborts. + DynamicStableScale bool `json:"dynamicStableScale,omitempty" protobuf:"varint,14,opt,name=dynamicStableScale"` } // AnalysisRunStrategy configuration for the analysis runs and experiments to retain @@ -758,6 +763,21 @@ type CanaryStatus struct { CurrentBackgroundAnalysisRunStatus *RolloutAnalysisRunStatus `json:"currentBackgroundAnalysisRunStatus,omitempty" protobuf:"bytes,2,opt,name=currentBackgroundAnalysisRunStatus"` // CurrentExperiment indicates the running experiment CurrentExperiment string `json:"currentExperiment,omitempty" protobuf:"bytes,3,opt,name=currentExperiment"` + // Weights records the weights which have been set on traffic provider. Only valid when using traffic routing + Weights *TrafficWeights `json:"weights,omitempty" protobuf:"bytes,4,opt,name=weights"` +} + +// TrafficWeights describes the current status of how traffic has been split +type TrafficWeights struct { + Canary WeightDestination `json:"canary" protobuf:"bytes,1,opt,name=canary"` + Stable WeightDestination `json:"stable" protobuf:"bytes,2,opt,name=stable"` + Additional []WeightDestination `json:"additional,omitempty" protobuf:"bytes,3,rep,name=additional"` +} + +type WeightDestination struct { + Weight int32 `json:"weight" protobuf:"varint,1,opt,name=weight"` + ServiceName string `json:"serviceName,omitempty" protobuf:"bytes,2,opt,name=serviceName"` + PodTemplateHash string `json:"podTemplateHash,omitempty" protobuf:"bytes,3,opt,name=podTemplateHash"` } type RolloutAnalysisRunStatus struct { diff --git a/pkg/apis/rollouts/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/rollouts/v1alpha1/zz_generated.deepcopy.go index 7d7c9ebbf6..3cbde89b8e 100644 --- a/pkg/apis/rollouts/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/rollouts/v1alpha1/zz_generated.deepcopy.go @@ -506,6 +506,11 @@ func (in *CanaryStatus) DeepCopyInto(out *CanaryStatus) { *out = new(RolloutAnalysisRunStatus) **out = **in } + if in.Weights != nil { + in, out := &in.Weights, &out.Weights + *out = new(TrafficWeights) + (*in).DeepCopyInto(*out) + } return } @@ -1962,6 +1967,29 @@ func (in *TemplateStatus) DeepCopy() *TemplateStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficWeights) DeepCopyInto(out *TrafficWeights) { + *out = *in + out.Canary = in.Canary + out.Stable = in.Stable + if in.Additional != nil { + in, out := &in.Additional, &out.Additional + *out = make([]WeightDestination, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficWeights. +func (in *TrafficWeights) DeepCopy() *TrafficWeights { + if in == nil { + return nil + } + out := new(TrafficWeights) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ValueFrom) DeepCopyInto(out *ValueFrom) { *out = *in @@ -2040,3 +2068,19 @@ func (in *WebMetricHeader) DeepCopy() *WebMetricHeader { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WeightDestination) DeepCopyInto(out *WeightDestination) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WeightDestination. +func (in *WeightDestination) DeepCopy() *WeightDestination { + if in == nil { + return nil + } + out := new(WeightDestination) + in.DeepCopyInto(out) + return out +} diff --git a/rollout/canary.go b/rollout/canary.go index 11813ed44b..21e9f9dfc6 100644 --- a/rollout/canary.go +++ b/rollout/canary.go @@ -91,8 +91,15 @@ func (c *rolloutContext) reconcileCanaryStableReplicaSet() (bool, error) { c.log.Info("No StableRS exists to reconcile or matches newRS") return false, nil } - _, stableRSReplicaCount := replicasetutil.CalculateReplicaCountsForCanary(c.rollout, c.newRS, c.stableRS, c.otherRSs) - scaled, _, err := c.scaleReplicaSetAndRecordEvent(c.stableRS, stableRSReplicaCount) + var desiredStableRSReplicaCount int32 + if c.rollout.Spec.Strategy.Canary.TrafficRouting == nil { + _, desiredStableRSReplicaCount = replicasetutil.CalculateReplicaCountsForBasicCanary(c.rollout, c.newRS, c.stableRS, c.otherRSs) + } else { + // note the use of c.newStatus instead of c.rollout.Status. We want to factor the weights + // that we previously just set into our scaling + _, desiredStableRSReplicaCount = replicasetutil.CalculateReplicaCountsForTrafficRoutedCanary(c.rollout, c.newStatus.Canary.Weights) + } + scaled, _, err := c.scaleReplicaSetAndRecordEvent(c.stableRS, desiredStableRSReplicaCount) return scaled, err } @@ -264,9 +271,9 @@ func (c *rolloutContext) completedCurrentCanaryStep() bool { case currentStep.Pause != nil: return c.pauseContext.CompletedCanaryPauseStep(*currentStep.Pause) case currentStep.SetCanaryScale != nil: - return replicasetutil.AtDesiredReplicaCountsForCanary(c.rollout, c.newRS, c.stableRS, c.otherRSs) + return replicasetutil.AtDesiredReplicaCountsForCanary(c.rollout, c.newRS, c.stableRS, c.otherRSs, c.newStatus.Canary.Weights) case currentStep.SetWeight != nil: - if !replicasetutil.AtDesiredReplicaCountsForCanary(c.rollout, c.newRS, c.stableRS, c.otherRSs) { + if !replicasetutil.AtDesiredReplicaCountsForCanary(c.rollout, c.newRS, c.stableRS, c.otherRSs, c.newStatus.Canary.Weights) { return false } if !c.areTargetsVerified() { diff --git a/rollout/replicaset.go b/rollout/replicaset.go index e2ff4ebaa3..ea0d4e806a 100644 --- a/rollout/replicaset.go +++ b/rollout/replicaset.go @@ -115,13 +115,13 @@ func (c *rolloutContext) reconcileNewReplicaSet() (bool, error) { if c.newRS == nil { return false, nil } - newReplicasCount, err := replicasetutil.NewRSNewReplicas(c.rollout, c.allRSs, c.newRS) + newReplicasCount, err := replicasetutil.NewRSNewReplicas(c.rollout, c.allRSs, c.newRS, c.newStatus.Canary.Weights) if err != nil { return false, err } if c.shouldDelayScaleDownOnAbort() { - abortScaleDownDelaySeconds := defaults.GetAbortScaleDownDelaySecondsOrDefault(c.rollout) + abortScaleDownDelaySeconds, _ := defaults.GetAbortScaleDownDelaySecondsOrDefault(c.rollout) c.log.Infof("Scale down new rs '%s' on abort (%v)", c.newRS.Name, abortScaleDownDelaySeconds) // if the newRS has scale down annotation, check if it should be scaled down now @@ -146,10 +146,15 @@ func (c *rolloutContext) reconcileNewReplicaSet() (bool, error) { } } } else if abortScaleDownDelaySeconds != nil { - err = c.addScaleDownDelay(c.newRS, *abortScaleDownDelaySeconds) - if err != nil { - return false, err + // Don't annotate until need to ensure the stable RS is fully scaled + if c.stableRS.Status.AvailableReplicas == *c.rollout.Spec.Replicas { + err = c.addScaleDownDelay(c.newRS, *abortScaleDownDelaySeconds) + if err != nil { + return false, err + } } + // leave newRS scaled up until we annotate + return false, nil } } @@ -157,9 +162,27 @@ func (c *rolloutContext) reconcileNewReplicaSet() (bool, error) { return scaled, err } -// shouldDelayScaleDownOnAbort returns if we are aborted and we should delay scaledown of canary/preview +// shouldDelayScaleDownOnAbort returns if we are aborted and we should delay scaledown of canary or preview func (c *rolloutContext) shouldDelayScaleDownOnAbort() bool { - return c.pauseContext.IsAborted() && defaults.GetAbortScaleDownDelaySecondsOrDefault(c.rollout) != nil + if !c.pauseContext.IsAborted() { + // only applicable to aborted rollouts + return false + } + if c.rollout.Spec.Strategy.Canary != nil && c.rollout.Spec.Strategy.Canary.TrafficRouting == nil { + // basic canary should not use this + return false + } + abortDelay, abortDelayWasSet := defaults.GetAbortScaleDownDelaySecondsOrDefault(c.rollout) + if abortDelay == nil { + // user explicitly set abortScaleDownDelaySeconds: 0, and wishes to leave canary/preview up indefinitely + return false + } + usesDynamicStableScaling := c.rollout.Spec.Strategy.Canary != nil && c.rollout.Spec.Strategy.Canary.DynamicStableScale + if usesDynamicStableScaling && !abortDelayWasSet { + // we are using dynamic stable/canary scaling and so abortScaleDownDelay does not matter + return false + } + return true } // reconcileOtherReplicaSets reconciles "other" ReplicaSets. diff --git a/rollout/trafficrouting.go b/rollout/trafficrouting.go index 945c81d1fe..24dd93cdd1 100644 --- a/rollout/trafficrouting.go +++ b/rollout/trafficrouting.go @@ -68,6 +68,8 @@ func (c *rolloutContext) reconcileTrafficRouting() error { return err } if reconciler == nil { + // Not using traffic routing + c.newStatus.Canary.Weights = nil return nil } c.log.Infof("Reconciling TrafficRouting with type '%s'", reconciler.Type()) @@ -90,11 +92,16 @@ func (c *rolloutContext) reconcileTrafficRouting() error { if rolloututil.IsFullyPromoted(c.rollout) { // when we are fully promoted. desired canary weight should be 0 } else if c.pauseContext.IsAborted() { - // when promote aborted. desired canary weight should be 0 + // when aborted, desired canary weight should be 0 (100% to stable), *unless* we + // are using dynamic stable scaling. In that case, we can only decrease canary weight + // according to available replica counts of the stable. + if c.rollout.Spec.Strategy.Canary.DynamicStableScale { + desiredWeight = 100 - ((100 * c.stableRS.Status.AvailableReplicas) / *c.rollout.Spec.Replicas) + } } else if c.newRS == nil || c.newRS.Status.AvailableReplicas == 0 { // when newRS is not available or replicas num is 0. never weight to canary } else if index != nil { - atDesiredReplicaCount := replicasetutil.AtDesiredReplicaCountsForCanary(c.rollout, c.newRS, c.stableRS, c.otherRSs) + atDesiredReplicaCount := replicasetutil.AtDesiredReplicaCountsForCanary(c.rollout, c.newRS, c.stableRS, c.otherRSs, nil) if !atDesiredReplicaCount { // Use the previous weight since the new RS is not ready for a new weight for i := *index - 1; i >= 0; i-- { @@ -142,6 +149,7 @@ func (c *rolloutContext) reconcileTrafficRouting() error { c.recorder.Warnf(c.rollout, record.EventOptions{EventReason: "TrafficRoutingError"}, err.Error()) return err } + c.newStatus.Canary.Weights = calculateWeightStatus(desiredWeight, weightDestinations...) // If we are in the middle of an update at a setWeight step, also perform weight verification. // Note that we don't do this every reconciliation because weight verification typically involves @@ -166,3 +174,17 @@ func (c *rolloutContext) reconcileTrafficRouting() error { return nil } + +func calculateWeightStatus(desiredWeight int32, weightDestinations ...trafficrouting.WeightDestination) *v1alpha1.TrafficWeights { + weights := v1alpha1.TrafficWeights{ + Canary: v1alpha1.WeightDestination{ + Weight: desiredWeight, + }, + } + stableWeight := 100 - desiredWeight + for _, weightDest := range weightDestinations { + stableWeight -= weightDest.Weight + } + weights.Stable.Weight = stableWeight + return &weights +} diff --git a/test/e2e/canary_test.go b/test/e2e/canary_test.go index 723fc9cddd..3cc399be4c 100644 --- a/test/e2e/canary_test.go +++ b/test/e2e/canary_test.go @@ -112,7 +112,6 @@ func (s *CanarySuite) TestRolloutScalingWhenPaused() { ExpectCanaryStablePodCount(1, 3) } - // TestRolloutWithMaxSurgeScalingDuringUpdate verifies behavior when scaling a rollout up/down in middle of update and with maxSurge 100% func (s *CanarySuite) TestRolloutWithMaxSurgeScalingDuringUpdate() { s.Given(). @@ -213,7 +212,7 @@ spec: ExpectCanaryStablePodCount(6, 4). When(). ScaleRollout(4). - WaitForRolloutReplicas(6). + WaitForRolloutReplicas(6). Then(). ExpectCanaryStablePodCount(2, 4) } @@ -556,3 +555,27 @@ func (s *CanarySuite) TestCanaryUnScaleDownOnAbort() { ExpectRevisionPodCount("2", 1). ExpectRevisionScaleDown("2", false) } + +func (s *CanarySuite) TestCanaryDynamicStableScale() { + s.Given(). + HealthyRollout(`@functional/canary-dynamic-stable-scale.yaml`). + When(). + UpdateSpec(). // update to revision 2 + WaitForRolloutStatus("Paused"). + Sleep(2*time.Second). + Then(). + ExpectRevisionPodCount("1", 3). + ExpectRevisionPodCount("2", 1). + When(). + PromoteRollout(). + WaitForRolloutCanaryStepIndex(3). + Sleep(2*time.Second). + Then(). + ExpectRevisionPodCount("1", 1). + ExpectRevisionPodCount("2", 3). + // TODO: test abort + When(). + AbortRollout() + // Then(). + // ExpectRevisionPodCount("1", 4) +} diff --git a/test/e2e/functional/canary-dynamic-stable-scale.yaml b/test/e2e/functional/canary-dynamic-stable-scale.yaml new file mode 100644 index 0000000000..fb8023500c --- /dev/null +++ b/test/e2e/functional/canary-dynamic-stable-scale.yaml @@ -0,0 +1,96 @@ +apiVersion: v1 +kind: Service +metadata: + name: dynamic-stable-scale-root +spec: + ports: + - port: 80 + targetPort: http + protocol: TCP + name: http + selector: + app: dynamic-stable-scale +--- +apiVersion: v1 +kind: Service +metadata: + name: dynamic-stable-scale-canary +spec: + ports: + - port: 80 + targetPort: http + protocol: TCP + name: http + selector: + app: dynamic-stable-scale +--- +apiVersion: v1 +kind: Service +metadata: + name: dynamic-stable-scale-stable +spec: + type: NodePort + ports: + - port: 80 + targetPort: http + protocol: TCP + name: http + selector: + app: dynamic-stable-scale +--- +apiVersion: networking.k8s.io/v1beta1 +kind: Ingress +metadata: + name: dynamic-stable-scale-ingress + annotations: + kubernetes.io/ingress.class: alb +spec: + rules: + - http: + paths: + - path: /* + backend: + serviceName: dynamic-stable-scale-root + servicePort: use-annotation +--- +apiVersion: argoproj.io/v1alpha1 +kind: Rollout +metadata: + name: dynamic-stable-scale +spec: + replicas: 4 + selector: + matchLabels: + app: dynamic-stable-scale + template: + metadata: + labels: + app: dynamic-stable-scale + spec: + containers: + - name: dynamic-stable-scale + image: nginx:1.19-alpine + ports: + - name: http + containerPort: 80 + protocol: TCP + resources: + requests: + memory: 16Mi + cpu: 5m + strategy: + canary: + dynamicStableScale: true + abortScaleDownDelaySeconds: 30 + canaryService: dynamic-stable-scale-canary + stableService: dynamic-stable-scale-stable + steps: + - setWeight: 25 + - pause: {} + - setWeight: 75 + - pause: {} + trafficRouting: + alb: + ingress: dynamic-stable-scale-ingress + rootService: dynamic-stable-scale-root + servicePort: 80 \ No newline at end of file diff --git a/utils/defaults/defaults.go b/utils/defaults/defaults.go index 1d51a1493c..d34c540c55 100644 --- a/utils/defaults/defaults.go +++ b/utils/defaults/defaults.go @@ -151,17 +151,19 @@ func GetScaleDownDelaySecondsOrDefault(rollout *v1alpha1.Rollout) time.Duration return time.Duration(delaySeconds) * time.Second } -// GetAbortScaleDownDelaySecondsOrDefault returns the duration seconds to delay the scale down of -// the canary/preview ReplicaSet in a abort situation. A nil value indicates it should not +// GetAbortScaleDownDelaySecondsOrDefault returns the duration to delay the scale down of +// the canary/preview ReplicaSet in an abort situation. A nil value indicates it should not // scale down at all (abortScaleDownDelaySeconds: 0). A value of 0 indicates it should scale down -// immediately. -func GetAbortScaleDownDelaySecondsOrDefault(rollout *v1alpha1.Rollout) *time.Duration { +// immediately. Also returns a boolean to indicate if the value was explicitly set. +func GetAbortScaleDownDelaySecondsOrDefault(rollout *v1alpha1.Rollout) (*time.Duration, bool) { var delaySeconds int32 + wasSet := false if rollout.Spec.Strategy.BlueGreen != nil { delaySeconds = DefaultAbortScaleDownDelaySeconds if rollout.Spec.Strategy.BlueGreen.AbortScaleDownDelaySeconds != nil { + wasSet = true if *rollout.Spec.Strategy.BlueGreen.AbortScaleDownDelaySeconds == 0 { - return nil + return nil, wasSet } delaySeconds = *rollout.Spec.Strategy.BlueGreen.AbortScaleDownDelaySeconds } @@ -169,15 +171,16 @@ func GetAbortScaleDownDelaySecondsOrDefault(rollout *v1alpha1.Rollout) *time.Dur if rollout.Spec.Strategy.Canary.TrafficRouting != nil { delaySeconds = DefaultAbortScaleDownDelaySeconds if rollout.Spec.Strategy.Canary.AbortScaleDownDelaySeconds != nil { + wasSet = true if *rollout.Spec.Strategy.Canary.AbortScaleDownDelaySeconds == 0 { - return nil + return nil, wasSet } delaySeconds = *rollout.Spec.Strategy.Canary.AbortScaleDownDelaySeconds } } } dur := time.Duration(delaySeconds) * time.Second - return &dur + return &dur, wasSet } func GetAutoPromotionEnabledOrDefault(rollout *v1alpha1.Rollout) bool { diff --git a/utils/defaults/defaults_test.go b/utils/defaults/defaults_test.go index 129fd1c959..d3df2554bc 100644 --- a/utils/defaults/defaults_test.go +++ b/utils/defaults/defaults_test.go @@ -222,7 +222,9 @@ func TestGetAbortScaleDownDelaySecondsOrDefault(t *testing.T) { }, }, } - assert.Equal(t, time.Duration(abortScaleDownDelaySeconds)*time.Second, *GetAbortScaleDownDelaySecondsOrDefault(blueGreenNonDefaultValue)) + abortDelay, wasSet := GetAbortScaleDownDelaySecondsOrDefault(blueGreenNonDefaultValue) + assert.Equal(t, time.Duration(abortScaleDownDelaySeconds)*time.Second, *abortDelay) + assert.True(t, wasSet) } { // dont scale down preview @@ -236,7 +238,9 @@ func TestGetAbortScaleDownDelaySecondsOrDefault(t *testing.T) { }, }, } - assert.Nil(t, GetAbortScaleDownDelaySecondsOrDefault(blueGreenZeroValue)) + abortDelay, wasSet := GetAbortScaleDownDelaySecondsOrDefault(blueGreenZeroValue) + assert.Nil(t, abortDelay) + assert.True(t, wasSet) } { blueGreenDefaultValue := &v1alpha1.Rollout{ @@ -246,7 +250,9 @@ func TestGetAbortScaleDownDelaySecondsOrDefault(t *testing.T) { }, }, } - assert.Equal(t, time.Duration(DefaultAbortScaleDownDelaySeconds)*time.Second, *GetAbortScaleDownDelaySecondsOrDefault(blueGreenDefaultValue)) + abortDelay, wasSet := GetAbortScaleDownDelaySecondsOrDefault(blueGreenDefaultValue) + assert.Equal(t, time.Duration(DefaultAbortScaleDownDelaySeconds)*time.Second, *abortDelay) + assert.False(t, wasSet) } { abortScaleDownDelaySeconds := int32(60) @@ -260,7 +266,9 @@ func TestGetAbortScaleDownDelaySecondsOrDefault(t *testing.T) { }, }, } - assert.Equal(t, time.Duration(abortScaleDownDelaySeconds)*time.Second, *GetAbortScaleDownDelaySecondsOrDefault(canaryNonDefaultValue)) + abortDelay, wasSet := GetAbortScaleDownDelaySecondsOrDefault(canaryNonDefaultValue) + assert.Equal(t, time.Duration(abortScaleDownDelaySeconds)*time.Second, *abortDelay) + assert.True(t, wasSet) } { // dont scale down canary @@ -275,11 +283,15 @@ func TestGetAbortScaleDownDelaySecondsOrDefault(t *testing.T) { }, }, } - assert.Nil(t, GetAbortScaleDownDelaySecondsOrDefault(canaryZeroValue)) + abortDelay, wasSet := GetAbortScaleDownDelaySecondsOrDefault(canaryZeroValue) + assert.Nil(t, abortDelay) + assert.True(t, wasSet) } { rolloutNoStrategyDefaultValue := &v1alpha1.Rollout{} - assert.Equal(t, time.Duration(0), *GetAbortScaleDownDelaySecondsOrDefault(rolloutNoStrategyDefaultValue)) + abortDelay, wasSet := GetAbortScaleDownDelaySecondsOrDefault(rolloutNoStrategyDefaultValue) + assert.Equal(t, time.Duration(0), *abortDelay) + assert.False(t, wasSet) } { canaryDefaultValue := &v1alpha1.Rollout{ @@ -291,7 +303,9 @@ func TestGetAbortScaleDownDelaySecondsOrDefault(t *testing.T) { }, }, } - assert.Equal(t, time.Duration(DefaultAbortScaleDownDelaySeconds)*time.Second, *GetAbortScaleDownDelaySecondsOrDefault(canaryDefaultValue)) + abortDelay, wasSet := GetAbortScaleDownDelaySecondsOrDefault(canaryDefaultValue) + assert.Equal(t, time.Duration(DefaultAbortScaleDownDelaySeconds)*time.Second, *abortDelay) + assert.False(t, wasSet) } { // basic canary should not have scaledown delay seconds @@ -302,7 +316,9 @@ func TestGetAbortScaleDownDelaySecondsOrDefault(t *testing.T) { }, }, } - assert.Equal(t, time.Duration(0), *GetAbortScaleDownDelaySecondsOrDefault(canaryDefaultValue)) + abortDelay, wasSet := GetAbortScaleDownDelaySecondsOrDefault(canaryDefaultValue) + assert.Equal(t, time.Duration(0), *abortDelay) + assert.False(t, wasSet) } } diff --git a/utils/replicaset/bluegreen.go b/utils/replicaset/bluegreen.go index be311b9145..2854be006d 100644 --- a/utils/replicaset/bluegreen.go +++ b/utils/replicaset/bluegreen.go @@ -31,7 +31,7 @@ func GetReplicaSetByTemplateHash(allRS []*appsv1.ReplicaSet, podTemplateHash str } func ReadyForPause(rollout *v1alpha1.Rollout, newRS *appsv1.ReplicaSet, allRSs []*appsv1.ReplicaSet) bool { - newRSReplicaCount, err := NewRSNewReplicas(rollout, allRSs, newRS) + newRSReplicaCount, err := NewRSNewReplicas(rollout, allRSs, newRS, nil) if err != nil { return false } diff --git a/utils/replicaset/canary.go b/utils/replicaset/canary.go index 6f89d184c6..71fffc811c 100644 --- a/utils/replicaset/canary.go +++ b/utils/replicaset/canary.go @@ -17,6 +17,33 @@ const ( EphemeralMetadataAnnotation = "rollout.argoproj.io/ephemeral-metadata" ) +func allDesiredAreAvailable(rs *appsv1.ReplicaSet, desired int32) bool { + return rs != nil && desired == *rs.Spec.Replicas && desired == rs.Status.AvailableReplicas +} + +func AtDesiredReplicaCountsForCanary(ro *v1alpha1.Rollout, newRS, stableRS *appsv1.ReplicaSet, olderRSs []*appsv1.ReplicaSet, weights *v1alpha1.TrafficWeights) bool { + var desiredNewRSReplicaCount, desiredStableRSReplicaCount int32 + if ro.Spec.Strategy.Canary.TrafficRouting == nil { + desiredNewRSReplicaCount, desiredStableRSReplicaCount = CalculateReplicaCountsForBasicCanary(ro, newRS, stableRS, olderRSs) + } else { + desiredNewRSReplicaCount, desiredStableRSReplicaCount = CalculateReplicaCountsForTrafficRoutedCanary(ro, weights) + } + if !allDesiredAreAvailable(newRS, desiredNewRSReplicaCount) { + return false + } + if ro.Spec.Strategy.Canary.TrafficRouting == nil || !ro.Spec.Strategy.Canary.DynamicStableScale { + if !allDesiredAreAvailable(stableRS, desiredStableRSReplicaCount) { + // only check stable RS if we are not using dynamic stable scaling + return false + } + } + if GetAvailableReplicaCountForReplicaSets(olderRSs) != int32(0) { + return false + } + return true +} + +/* // AtDesiredReplicaCountsForCanary indicates if the rollout is at the desired state for the current step func AtDesiredReplicaCountsForCanary(rollout *v1alpha1.Rollout, newRS, stableRS *appsv1.ReplicaSet, olderRSs []*appsv1.ReplicaSet) bool { desiredNewRSReplicaCount, desiredStableRSReplicaCount := DesiredReplicaCountsForCanary(rollout, newRS, stableRS) @@ -31,7 +58,9 @@ func AtDesiredReplicaCountsForCanary(rollout *v1alpha1.Rollout, newRS, stableRS } return true } +*/ +/* //DesiredReplicaCountsForCanary calculates the desired endstate replica count for the new and stable replicasets func DesiredReplicaCountsForCanary(rollout *v1alpha1.Rollout, newRS, stableRS *appsv1.ReplicaSet) (int32, int32) { rolloutSpecReplica := defaults.GetReplicasOrDefault(rollout.Spec.Replicas) @@ -62,9 +91,11 @@ func DesiredReplicaCountsForCanary(rollout *v1alpha1.Rollout, newRS, stableRS *a return desiredNewRSReplicaCount, desiredStableRSReplicaCount } +*/ -// CalculateReplicaCountsForCanary calculates the number of replicas for the newRS and the stableRS. The function -// calculates the desired number of replicas for the new and stable RS using the following equations: +// CalculateReplicaCountsForBasicCanary calculates the number of replicas for the newRS and the stableRS +// when using the basic canary strategy. The function calculates the desired number of replicas for +// the new and stable RS using the following equations: // // newRS Replica count = spec.Replica * (setweight / 100) // stableRS Replica count = spec.Replica * (1 - setweight / 100) @@ -96,20 +127,13 @@ func DesiredReplicaCountsForCanary(rollout *v1alpha1.Rollout, newRS, stableRS *a // replicas 10 currentWeight 5 NewRS 0 stableRS 10 max unavailable 1, surge 1 - should return newRS 1 stableRS 9 // replicas 1 currentWeight 5 NewRS 0 stableRS 1 max unavailable 0, surge 1 - should return newRS 1 stableRS 1 // replicas 1 currentWeight 95 NewRS 0 stableRS 1 max unavailable 0, surge 1 - should return newRS 1 stableRS 1 -// For more examples, check the TestCalculateReplicaCountsForCanary test in canary/canary_test.go -func CalculateReplicaCountsForCanary(rollout *v1alpha1.Rollout, newRS *appsv1.ReplicaSet, stableRS *appsv1.ReplicaSet, oldRSs []*appsv1.ReplicaSet) (int32, int32) { +// For more examples, check the CalculateReplicaCountsForBasicCanary test in canary/canary_test.go +func CalculateReplicaCountsForBasicCanary(rollout *v1alpha1.Rollout, newRS *appsv1.ReplicaSet, stableRS *appsv1.ReplicaSet, oldRSs []*appsv1.ReplicaSet) (int32, int32) { rolloutSpecReplica := defaults.GetReplicasOrDefault(rollout.Spec.Replicas) - replicas, weight := GetCanaryReplicasOrWeight(rollout) - if replicas != nil { - return *replicas, rolloutSpecReplica - } + _, desiredWeight := GetCanaryReplicasOrWeight(rollout) - desiredStableRSReplicaCount := int32(math.Ceil(float64(rolloutSpecReplica) * (1 - (float64(weight) / 100)))) - desiredNewRSReplicaCount := int32(math.Ceil(float64(rolloutSpecReplica) * (float64(weight) / 100))) - - if rollout.Spec.Strategy.Canary.TrafficRouting != nil { - return desiredNewRSReplicaCount, rolloutSpecReplica - } + desiredStableRSReplicaCount := int32(math.Ceil(float64(rolloutSpecReplica) * (1 - (float64(desiredWeight) / 100)))) + desiredNewRSReplicaCount := int32(math.Ceil(float64(rolloutSpecReplica) * (float64(desiredWeight) / 100))) stableRSReplicaCount := int32(0) newRSReplicaCount := int32(0) @@ -129,7 +153,7 @@ func CalculateReplicaCountsForCanary(rollout *v1alpha1.Rollout, newRS *appsv1.Re maxSurge := MaxSurge(rollout) - if extraReplicaAdded(rolloutSpecReplica, weight) { + if extraReplicaAdded(rolloutSpecReplica, desiredWeight) { // In the case where the weight of the stable and canary replica counts cannot be divided evenly, // the controller needs to surges by one to account for both replica counts being rounded up. maxSurge = maxSurge + 1 @@ -263,6 +287,64 @@ func maxValue(countA int32, countB int32) int32 { return countA } +// CalculateReplicaCountsForTrafficRoutedCanary calculates the canary and stable replica counts +// when using canary with traffic routing. If current traffic weights are supplied, we factor the +// those weights into the and return the higher of current traffic scale vs. desired traffic scale +func CalculateReplicaCountsForTrafficRoutedCanary(rollout *v1alpha1.Rollout, weights *v1alpha1.TrafficWeights) (int32, int32) { + var canaryCount, stableCount int32 + rolloutSpecReplica := defaults.GetReplicasOrDefault(rollout.Spec.Replicas) + setCanaryScaleReplicas, desiredWeight := GetCanaryReplicasOrWeight(rollout) + if setCanaryScaleReplicas != nil { + // a canary count was explicitly set + canaryCount = *setCanaryScaleReplicas + } else { + canaryCount = trafficWeightToReplicas(rolloutSpecReplica, desiredWeight) + } + + if !rollout.Spec.Strategy.Canary.DynamicStableScale { + // Not using dynamic stable scaling. Stable should be left fully scaled (100%), and canary + // will be calculated from setWeight + return canaryCount, rolloutSpecReplica + } + + // When using dynamic stable scaling, the stable replica count is calculated from the higher of: + // 1. actual stable traffic weight + // 2. desired stable traffic weight + // Case 1 occurs when we are going from low to high canary weight. The stable scale must remain + // high, until we reduce traffic to it. + // Case 2 occurs when we are going from high to low canary weight. In this scenario, + // we need to increase the stable scale in preparation for increasing the traffic to stable. + stableCount = trafficWeightToReplicas(rolloutSpecReplica, 100-desiredWeight) + if weights != nil { + actualStableWeightReplicaCount := trafficWeightToReplicas(rolloutSpecReplica, weights.Stable.Weight) + stableCount = max(stableCount, actualStableWeightReplicaCount) + } + + if rollout.Status.Abort && weights != nil { + // When aborting and using dynamic stable scaling, we cannot reduce canary count until + // traffic has shifted back to stable. Canary count is calculated from the higher of: + // 1. actual canary traffic weight + // 2. desired canary traffic weight + // This if block makes sure we don't scale down the canary prematurely + trafficWeightReplicaCount := trafficWeightToReplicas(rolloutSpecReplica, weights.Canary.Weight) + canaryCount = max(trafficWeightReplicaCount, canaryCount) + } + return canaryCount, stableCount +} + +// trafficWeightToReplicas returns the appropriate replicas given the full spec.replicas and a weight +// Rounds up if not evenly divisible. +func trafficWeightToReplicas(replicas, weight int32) int32 { + return int32(math.Ceil(float64(weight*replicas) / 100)) +} + +func max(left, right int32) int32 { + if left > right { + return left + } + return right +} + // BeforeStartingStep checks if canary rollout is at the starting step func BeforeStartingStep(rollout *v1alpha1.Rollout) bool { if rollout.Spec.Strategy.Canary == nil || rollout.Spec.Strategy.Canary.Analysis == nil || rollout.Spec.Strategy.Canary.Analysis.StartingStep == nil { @@ -383,10 +465,12 @@ func UseSetCanaryScale(rollout *v1alpha1.Rollout) *v1alpha1.SetCanaryScale { // SetCanaryScale only works with TrafficRouting return nil } - if rollout.Status.Abort && defaults.GetAbortScaleDownDelaySecondsOrDefault(rollout) != nil { - // If rollout is aborted do not use the set canary scale, *unless* the user explicitly - // indicated to leave the canary scaled up (abortScaleDownDelaySeconds: 0). - return nil + if rollout.Status.Abort { + if abortDelay, _ := defaults.GetAbortScaleDownDelaySecondsOrDefault(rollout); abortDelay != nil { + // If rollout is aborted do not use the set canary scale, *unless* the user explicitly + // indicated to leave the canary scaled up (abortScaleDownDelaySeconds: 0). + return nil + } } currentStep, currentStepIndex := GetCurrentCanaryStep(rollout) if currentStep == nil { diff --git a/utils/replicaset/canary_test.go b/utils/replicaset/canary_test.go index 21b93a9d26..cc2cdddc88 100644 --- a/utils/replicaset/canary_test.go +++ b/utils/replicaset/canary_test.go @@ -636,7 +636,12 @@ func TestCalculateReplicaCountsForCanary(t *testing.T) { stableRS := newRS("stable", test.stableSpecReplica, test.stableAvailableReplica) canaryRS := newRS("canary", test.canarySpecReplica, test.canaryAvailableReplica) rollout.Spec.Strategy.Canary.AbortScaleDownDelaySeconds = test.abortScaleDownDelaySeconds - newRSReplicaCount, stableRSReplicaCount := CalculateReplicaCountsForCanary(rollout, canaryRS, stableRS, []*appsv1.ReplicaSet{test.olderRS}) + var newRSReplicaCount, stableRSReplicaCount int32 + if test.trafficRouting != nil { + newRSReplicaCount, stableRSReplicaCount = CalculateReplicaCountsForTrafficRoutedCanary(rollout, nil) + } else { + newRSReplicaCount, stableRSReplicaCount = CalculateReplicaCountsForBasicCanary(rollout, canaryRS, stableRS, []*appsv1.ReplicaSet{test.olderRS}) + } assert.Equal(t, test.expectedCanaryReplicaCount, newRSReplicaCount, "check canary replica count") assert.Equal(t, test.expectedStableReplicaCount, stableRSReplicaCount, "check stable replica count") }) @@ -647,7 +652,7 @@ func TestCalculateReplicaCountsForNewDeployment(t *testing.T) { rollout := newRollout(10, 10, intstr.FromInt(0), intstr.FromInt(1), "canary", "stable", nil, nil) stableRS := newRS("stable", 10, 0) newRS := newRS("stable", 10, 0) - newRSReplicaCount, stableRSReplicaCount := CalculateReplicaCountsForCanary(rollout, newRS, stableRS, nil) + newRSReplicaCount, stableRSReplicaCount := CalculateReplicaCountsForBasicCanary(rollout, newRS, stableRS, nil) assert.Equal(t, int32(10), newRSReplicaCount) assert.Equal(t, int32(0), stableRSReplicaCount) } @@ -655,25 +660,41 @@ func TestCalculateReplicaCountsForNewDeployment(t *testing.T) { func TestCalculateReplicaCountsForCanaryTrafficRouting(t *testing.T) { rollout := newRollout(10, 10, intstr.FromInt(0), intstr.FromInt(1), "canary", "stable", nil, nil) rollout.Spec.Strategy.Canary.TrafficRouting = &v1alpha1.RolloutTrafficRouting{} - stableRS := newRS("stable", 10, 10) - newRS := newRS("canary", 0, 0) - newRSReplicaCount, stableRSReplicaCount := CalculateReplicaCountsForCanary(rollout, newRS, stableRS, nil) + newRSReplicaCount, stableRSReplicaCount := CalculateReplicaCountsForTrafficRoutedCanary(rollout, rollout.Status.Canary.Weights) assert.Equal(t, int32(1), newRSReplicaCount) assert.Equal(t, int32(10), stableRSReplicaCount) } +func TestCalculateReplicaCountsForCanaryTrafficRoutingDynamicScale(t *testing.T) { + rollout := newRollout(10, 10, intstr.FromInt(0), intstr.FromInt(1), "canary", "stable", nil, nil) + rollout.Spec.Strategy.Canary.TrafficRouting = &v1alpha1.RolloutTrafficRouting{} + rollout.Spec.Strategy.Canary.DynamicStableScale = true + newRSReplicaCount, stableRSReplicaCount := CalculateReplicaCountsForTrafficRoutedCanary(rollout, rollout.Status.Canary.Weights) + assert.Equal(t, int32(1), newRSReplicaCount) + assert.Equal(t, int32(9), stableRSReplicaCount) +} + func TestCalculateReplicaCountsForCanaryStableRSdEdgeCases(t *testing.T) { rollout := newRollout(10, 10, intstr.FromInt(0), intstr.FromInt(1), "", "", nil, nil) newRS := newRS("stable", 9, 9) - newRSReplicaCount, stableRSReplicaCount := CalculateReplicaCountsForCanary(rollout, newRS, nil, []*appsv1.ReplicaSet{}) + newRSReplicaCount, stableRSReplicaCount := CalculateReplicaCountsForBasicCanary(rollout, newRS, nil, []*appsv1.ReplicaSet{}) assert.Equal(t, int32(10), newRSReplicaCount) assert.Equal(t, int32(0), stableRSReplicaCount) - newRSReplicaCount, stableRSReplicaCount = CalculateReplicaCountsForCanary(rollout, newRS, newRS, []*appsv1.ReplicaSet{}) + newRSReplicaCount, stableRSReplicaCount = CalculateReplicaCountsForBasicCanary(rollout, newRS, newRS, []*appsv1.ReplicaSet{}) assert.Equal(t, int32(10), newRSReplicaCount) assert.Equal(t, int32(0), stableRSReplicaCount) } +func TestTrafficWeightToReplicas(t *testing.T) { + assert.Equal(t, int32(0), trafficWeightToReplicas(10, 0)) + assert.Equal(t, int32(2), trafficWeightToReplicas(10, 20)) + assert.Equal(t, int32(3), trafficWeightToReplicas(10, 25)) + assert.Equal(t, int32(4), trafficWeightToReplicas(10, 33)) + assert.Equal(t, int32(10), trafficWeightToReplicas(10, 99)) + assert.Equal(t, int32(10), trafficWeightToReplicas(10, 100)) +} + func TestGetOtherRSs(t *testing.T) { rs := func(podHash string) appsv1.ReplicaSet { return appsv1.ReplicaSet{ diff --git a/utils/replicaset/replicaset.go b/utils/replicaset/replicaset.go index 598b301ad1..95813fbf7f 100644 --- a/utils/replicaset/replicaset.go +++ b/utils/replicaset/replicaset.go @@ -232,7 +232,7 @@ func FindOldReplicaSets(rollout *v1alpha1.Rollout, rsList []*appsv1.ReplicaSet) // When one of the followings is true, we're rolling out the deployment; otherwise, we're scaling it. // 1) The new RS is saturated: newRS's replicas == deployment's replicas // 2) Max number of pods allowed is reached: deployment's replicas + maxSurge == all RSs' replicas -func NewRSNewReplicas(rollout *v1alpha1.Rollout, allRSs []*appsv1.ReplicaSet, newRS *appsv1.ReplicaSet) (int32, error) { +func NewRSNewReplicas(rollout *v1alpha1.Rollout, allRSs []*appsv1.ReplicaSet, newRS *appsv1.ReplicaSet, weights *v1alpha1.TrafficWeights) (int32, error) { if rollout.Spec.Strategy.BlueGreen != nil { desiredReplicas := defaults.GetReplicasOrDefault(rollout.Spec.Replicas) if rollout.Spec.Strategy.BlueGreen.PreviewReplicaCount != nil { @@ -263,8 +263,13 @@ func NewRSNewReplicas(rollout *v1alpha1.Rollout, allRSs []*appsv1.ReplicaSet, ne } if rollout.Spec.Strategy.Canary != nil { stableRS := GetStableRS(rollout, newRS, allRSs) - otherRSs := GetOtherRSs(rollout, newRS, stableRS, allRSs) - newRSReplicaCount, _ := CalculateReplicaCountsForCanary(rollout, newRS, stableRS, otherRSs) + var newRSReplicaCount int32 + if rollout.Spec.Strategy.Canary.TrafficRouting == nil { + otherRSs := GetOtherRSs(rollout, newRS, stableRS, allRSs) + newRSReplicaCount, _ = CalculateReplicaCountsForBasicCanary(rollout, newRS, stableRS, otherRSs) + } else { + newRSReplicaCount, _ = CalculateReplicaCountsForTrafficRoutedCanary(rollout, weights) + } return newRSReplicaCount, nil } return 0, fmt.Errorf("no rollout strategy provided") diff --git a/utils/replicaset/replicaset_test.go b/utils/replicaset/replicaset_test.go index 09165dd113..39fb7a628b 100644 --- a/utils/replicaset/replicaset_test.go +++ b/utils/replicaset/replicaset_test.go @@ -193,12 +193,12 @@ func TestGetReplicaCountForReplicaSets(t *testing.T) { func TestNewRSNewReplicas(t *testing.T) { ro := generateRollout("test") ro.Spec.Strategy.BlueGreen = &v1alpha1.BlueGreenStrategy{} - blueGreenNewRSCount, err := NewRSNewReplicas(&ro, nil, nil) + blueGreenNewRSCount, err := NewRSNewReplicas(&ro, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, blueGreenNewRSCount, *ro.Spec.Replicas) ro.Spec.Strategy.BlueGreen = nil - _, err = NewRSNewReplicas(&ro, nil, nil) + _, err = NewRSNewReplicas(&ro, nil, nil, nil) assert.Error(t, err, "no rollout strategy provided") } @@ -285,7 +285,7 @@ func TestNewRSNewReplicasWitPreviewReplicaCount(t *testing.T) { if test.overrideCurrentPodHash != "" { r.Status.CurrentPodHash = test.overrideCurrentPodHash } - count, err := NewRSNewReplicas(r, []*appsv1.ReplicaSet{rs, rs2}, rs) + count, err := NewRSNewReplicas(r, []*appsv1.ReplicaSet{rs, rs2}, rs, nil) assert.Nil(t, err) assert.Equal(t, test.expectReplicaCount, count) })