From 4193f15553b8620113b89b74545b86997d077bf4 Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Mon, 29 Jul 2024 14:52:55 +0200 Subject: [PATCH 1/4] feat(api): add Conditions to ProjectStatus Signed-off-by: Hidde Beydals --- api/v1alpha1/project_types.go | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/api/v1alpha1/project_types.go b/api/v1alpha1/project_types.go index a9f4d5ac8..bfe95cba2 100644 --- a/api/v1alpha1/project_types.go +++ b/api/v1alpha1/project_types.go @@ -30,7 +30,8 @@ func (p *ProjectPhase) IsTerminal() bool { // +kubebuilder:object:root=true // +kubebuilder:resource:scope=Cluster // +kubebuilder:subresource:status -// +kubebuilder:printcolumn:name=Phase,type=string,JSONPath=`.status.phase` +// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status" +// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message" // +kubebuilder:printcolumn:name=Age,type=date,JSONPath=`.metadata.creationTimestamp` // Project is a resource type that reconciles to a specially labeled namespace @@ -73,14 +74,33 @@ type PromotionPolicy struct { // ProjectStatus describes a Project's current status. type ProjectStatus struct { + // Conditions contains the last observations of the Project's current + // state. + // +patchMergeKey=type + // +patchStrategy=merge + // +listType=map + // +listMapKey=type + Conditions []metav1.Condition `json:"conditions,omitempty" patchMergeKey:"type" patchStrategy:"merge" protobuf:"bytes,3,rep,name=conditions"` // Phase describes the Project's current phase. + // + // Deprecated: Use the Conditions field instead. Phase ProjectPhase `json:"phase,omitempty" protobuf:"bytes,1,opt,name=phase"` // Message is a display message about the Project, including any errors // preventing the Project from being reconciled. i.e. If the Phase field has a // value of CreationFailed, this field can be expected to explain why. + // + // Deprecated: Use the Conditions field instead. Message string `json:"message,omitempty" protobuf:"bytes,2,opt,name=message"` } +func (w *ProjectStatus) GetConditions() []metav1.Condition { + return w.Conditions +} + +func (w *ProjectStatus) SetConditions(conditions []metav1.Condition) { + w.Conditions = conditions +} + // +kubebuilder:object:root=true // ProjectList is a list of Project resources. From 7a04320395d44c7f8724b618a696cc1573624e8f Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Wed, 7 Aug 2024 12:24:48 +0200 Subject: [PATCH 2/4] chore: run codegen Signed-off-by: Hidde Beydals --- api/v1alpha1/generated.pb.go | 579 ++++++++++-------- api/v1alpha1/generated.proto | 12 + api/v1alpha1/zz_generated.deepcopy.go | 9 +- .../crds/kargo.akuity.io_projects.yaml | 91 ++- .../projects.kargo.akuity.io_v1alpha1.json | 64 +- ui/src/gen/v1alpha1/generated_pb.ts | 17 + 6 files changed, 507 insertions(+), 265 deletions(-) diff --git a/api/v1alpha1/generated.pb.go b/api/v1alpha1/generated.pb.go index 6ba657993..037a84848 100644 --- a/api/v1alpha1/generated.pb.go +++ b/api/v1alpha1/generated.pb.go @@ -2044,265 +2044,266 @@ func init() { } var fileDescriptor_e26b7f7bbc391025 = []byte{ - // 4126 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x3c, 0x5d, 0x6c, 0x24, 0x47, - 0x5a, 0xdb, 0x33, 0xe3, 0xb1, 0xe7, 0x1b, 0xff, 0x96, 0xbd, 0x1b, 0xc7, 0x61, 0xed, 0xa5, 0x2f, - 0x44, 0x09, 0xc9, 0x8d, 0xd9, 0xdd, 0x6c, 0x6e, 0xb3, 0x09, 0x7b, 0xcc, 0xd8, 0xd9, 0x5d, 0x27, - 0x4e, 0x62, 0x6a, 0xbc, 0xbb, 0x47, 0x2e, 0xd1, 0x51, 0x9e, 0x29, 0xcf, 0x34, 0x9e, 0xe9, 0x9e, - 0x74, 0xf7, 0x38, 0xe7, 0x3b, 0x04, 0xe1, 0x00, 0xe9, 0x5e, 0x40, 0x3c, 0x20, 0xdd, 0x21, 0x81, - 0x84, 0xe0, 0x05, 0x09, 0xc1, 0x3b, 0xe2, 0xe1, 0x1e, 0x4e, 0x82, 0xe8, 0x40, 0x51, 0x04, 0x3c, - 0x04, 0x74, 0xb2, 0x2e, 0x3e, 0xe9, 0x78, 0x3b, 0x89, 0x07, 0x1e, 0x58, 0x84, 0x84, 0xea, 0xaf, - 0xbb, 0xba, 0xa7, 0xc7, 0xee, 0x9e, 0xb5, 0xf7, 0x36, 0x6f, 0x33, 0xf5, 0x7d, 0xf5, 0x7d, 0x55, - 0x5f, 0x7d, 0xf5, 0xfd, 0xd6, 0x0c, 0xbc, 0xd8, 0xb2, 0xfc, 0x76, 0x7f, 0xa7, 0xd2, 0x70, 0xba, - 0xab, 0x64, 0xaf, 0x6f, 0xf9, 0x07, 0xab, 0x7b, 0xc4, 0x6d, 0x39, 0xab, 0xa4, 0x67, 0xad, 0xee, - 0x5f, 0x26, 0x9d, 0x5e, 0x9b, 0x5c, 0x5e, 0x6d, 0x51, 0x9b, 0xba, 0xc4, 0xa7, 0xcd, 0x4a, 0xcf, - 0x75, 0x7c, 0x07, 0x3d, 0x1d, 0xce, 0xaa, 0x88, 0x59, 0x15, 0x3e, 0xab, 0x42, 0x7a, 0x56, 0x45, - 0xcd, 0x5a, 0xfa, 0xa2, 0x46, 0xbb, 0xe5, 0xb4, 0x9c, 0x55, 0x3e, 0x79, 0xa7, 0xbf, 0xcb, 0xbf, - 0xf1, 0x2f, 0xfc, 0x93, 0x20, 0xba, 0xf4, 0xe2, 0xde, 0x75, 0xaf, 0x62, 0x71, 0xce, 0x5d, 0xd2, - 0x68, 0x5b, 0x36, 0x75, 0x0f, 0x56, 0x7b, 0x7b, 0x2d, 0x36, 0xe0, 0xad, 0x76, 0xa9, 0x4f, 0x56, - 0xf7, 0x07, 0x96, 0xb2, 0xb4, 0x3a, 0x6c, 0x96, 0xdb, 0xb7, 0x7d, 0xab, 0x4b, 0x07, 0x26, 0xbc, - 0x74, 0xd2, 0x04, 0xaf, 0xd1, 0xa6, 0x5d, 0x12, 0x9f, 0x67, 0xbe, 0x0b, 0xf3, 0x55, 0x9b, 0x74, - 0x0e, 0x3c, 0xcb, 0xc3, 0x7d, 0xbb, 0xea, 0xb6, 0xfa, 0x5d, 0x6a, 0xfb, 0xe8, 0x12, 0x14, 0x6c, - 0xd2, 0xa5, 0x8b, 0xc6, 0x25, 0xe3, 0xd9, 0x52, 0x6d, 0xf2, 0xa3, 0xc3, 0x95, 0x73, 0x47, 0x87, - 0x2b, 0x85, 0xb7, 0x48, 0x97, 0x62, 0x0e, 0x41, 0x5f, 0x80, 0xb1, 0x7d, 0xd2, 0xe9, 0xd3, 0xc5, - 0x1c, 0x47, 0x99, 0x92, 0x28, 0x63, 0xf7, 0xd8, 0x20, 0x16, 0x30, 0xf3, 0x77, 0xf3, 0x11, 0xf2, - 0x6f, 0x52, 0x9f, 0x34, 0x89, 0x4f, 0x50, 0x17, 0x8a, 0x1d, 0xb2, 0x43, 0x3b, 0xde, 0xa2, 0x71, - 0x29, 0xff, 0x6c, 0xf9, 0xca, 0x6b, 0x95, 0x34, 0xa2, 0xaf, 0x24, 0x90, 0xaa, 0x6c, 0x72, 0x3a, - 0xaf, 0xd9, 0xbe, 0x7b, 0x50, 0x9b, 0x96, 0x8b, 0x28, 0x8a, 0x41, 0x2c, 0x99, 0xa0, 0xdf, 0x31, - 0xa0, 0x4c, 0x6c, 0xdb, 0xf1, 0x89, 0x6f, 0x39, 0xb6, 0xb7, 0x98, 0xe3, 0x4c, 0x5f, 0x1f, 0x9d, - 0x69, 0x35, 0x24, 0x26, 0x38, 0xcf, 0x4b, 0xce, 0x65, 0x0d, 0x82, 0x75, 0x9e, 0x4b, 0x2f, 0x43, - 0x59, 0x5b, 0x2a, 0x9a, 0x85, 0xfc, 0x1e, 0x3d, 0x10, 0xf2, 0xc5, 0xec, 0x23, 0x5a, 0x88, 0x08, - 0x54, 0x4a, 0xf0, 0x46, 0xee, 0xba, 0xb1, 0x74, 0x13, 0x66, 0xe3, 0x0c, 0xb3, 0xcc, 0x37, 0xff, - 0xd0, 0x80, 0x05, 0x6d, 0x17, 0x98, 0xee, 0x52, 0x97, 0xda, 0x0d, 0x8a, 0x56, 0xa1, 0xc4, 0xce, - 0xd2, 0xeb, 0x91, 0x86, 0x3a, 0xea, 0x39, 0xb9, 0x91, 0xd2, 0x5b, 0x0a, 0x80, 0x43, 0x9c, 0x40, - 0x2d, 0x72, 0xc7, 0xa9, 0x45, 0xaf, 0x4d, 0x3c, 0xba, 0x98, 0x8f, 0xaa, 0xc5, 0x16, 0x1b, 0xc4, - 0x02, 0x66, 0xfe, 0x32, 0x3c, 0xa9, 0xd6, 0xb3, 0x4d, 0xbb, 0xbd, 0x0e, 0xf1, 0x69, 0xb8, 0xa8, - 0x13, 0x55, 0xcf, 0x9c, 0x81, 0xa9, 0x6a, 0xaf, 0xe7, 0x3a, 0xfb, 0xb4, 0x59, 0xf7, 0x49, 0x8b, - 0x9a, 0xdf, 0x32, 0xe0, 0x7c, 0xd5, 0x6d, 0x39, 0x6b, 0xeb, 0xd5, 0x5e, 0xef, 0x0e, 0x25, 0x1d, - 0xbf, 0x5d, 0xf7, 0x89, 0xdf, 0xf7, 0xd0, 0x4d, 0x28, 0x7a, 0xfc, 0x93, 0x24, 0xf7, 0x8c, 0xd2, - 0x10, 0x01, 0x7f, 0x70, 0xb8, 0xb2, 0x90, 0x30, 0x91, 0x62, 0x39, 0x0b, 0x3d, 0x07, 0xe3, 0x5d, - 0xea, 0x79, 0xa4, 0xa5, 0xf6, 0x3c, 0x23, 0x09, 0x8c, 0xbf, 0x29, 0x86, 0xb1, 0x82, 0x9b, 0x3f, - 0xc8, 0xc1, 0x4c, 0x40, 0x4b, 0xb2, 0x3f, 0x03, 0x01, 0xf7, 0x61, 0xb2, 0xad, 0xed, 0x90, 0xcb, - 0xb9, 0x7c, 0xe5, 0x95, 0x94, 0xba, 0x9c, 0x24, 0xa4, 0xda, 0x82, 0x64, 0x33, 0xa9, 0x8f, 0xe2, - 0x08, 0x1b, 0xd4, 0x05, 0xf0, 0x0e, 0xec, 0x86, 0x64, 0x5a, 0xe0, 0x4c, 0x5f, 0xce, 0xc8, 0xb4, - 0x1e, 0x10, 0xa8, 0x21, 0xc9, 0x12, 0xc2, 0x31, 0xac, 0x31, 0x30, 0xff, 0xd6, 0x80, 0xf9, 0x84, - 0x79, 0xe8, 0xd5, 0xd8, 0x79, 0x3e, 0x3d, 0x70, 0x9e, 0x68, 0x60, 0x5a, 0x78, 0x9a, 0x2f, 0xc0, - 0x84, 0x4b, 0xf7, 0x2d, 0xcf, 0x72, 0x6c, 0x29, 0xe1, 0x59, 0x39, 0x7f, 0x02, 0xcb, 0x71, 0x1c, - 0x60, 0xa0, 0xe7, 0xa1, 0xa4, 0x3e, 0x33, 0x31, 0xe7, 0x99, 0x3a, 0xb3, 0x83, 0x53, 0xa8, 0x1e, - 0x0e, 0xe1, 0xe6, 0x3f, 0xe8, 0xa7, 0x7f, 0xb7, 0xd7, 0x24, 0x3e, 0x65, 0xca, 0x43, 0x7a, 0xbd, - 0xb7, 0x42, 0x65, 0x0e, 0x94, 0xa7, 0x2a, 0x86, 0xb1, 0x82, 0xa3, 0xeb, 0x30, 0x29, 0x3f, 0x0a, - 0x5d, 0x11, 0xab, 0x0b, 0x0e, 0xa6, 0xaa, 0xc1, 0x70, 0x04, 0x13, 0xdd, 0x87, 0xa2, 0xe3, 0x5a, - 0x2d, 0xcb, 0x96, 0x87, 0x72, 0x35, 0xdd, 0xa1, 0xdc, 0x72, 0xa9, 0xd5, 0x6a, 0xfb, 0x6f, 0xf3, - 0xa9, 0x35, 0x60, 0x22, 0x14, 0x9f, 0xb1, 0x24, 0x87, 0xfa, 0x30, 0xe5, 0x39, 0x7d, 0xb7, 0x41, - 0xc5, 0x6e, 0x84, 0x08, 0xca, 0x57, 0xae, 0x67, 0x39, 0xf4, 0xba, 0x46, 0xa0, 0x76, 0x5e, 0xee, - 0x66, 0x4a, 0x1f, 0xf5, 0x70, 0x94, 0x8b, 0xf9, 0x03, 0x03, 0x40, 0x4c, 0xbe, 0x43, 0x3b, 0x5d, - 0xd4, 0x80, 0xa2, 0xd5, 0x25, 0x2d, 0xaa, 0x3c, 0x45, 0x26, 0x45, 0x67, 0x14, 0x36, 0xd8, 0x6c, - 0xb9, 0x82, 0xc0, 0x3f, 0xf0, 0x41, 0x0f, 0x4b, 0xd2, 0x9a, 0x0c, 0x73, 0xa7, 0x2a, 0x43, 0xf3, - 0xbf, 0x02, 0xc3, 0x14, 0x5b, 0x0a, 0xb3, 0x93, 0x9c, 0xb9, 0xd4, 0x8c, 0xc0, 0x4e, 0x72, 0x1c, - 0x2c, 0x60, 0x67, 0x77, 0xb6, 0x17, 0x85, 0xf7, 0x10, 0x5a, 0x56, 0x96, 0xbc, 0xf3, 0x6f, 0xd0, - 0x03, 0xe1, 0x4a, 0x5e, 0x51, 0xae, 0x44, 0x18, 0xf1, 0x5f, 0x88, 0xf8, 0x76, 0x66, 0x33, 0xb5, - 0x9d, 0xf0, 0xb1, 0xed, 0x83, 0x5e, 0xe0, 0xf3, 0xff, 0xcd, 0x50, 0x37, 0xe1, 0x8d, 0xbe, 0xe7, - 0x3b, 0x5d, 0xeb, 0x1b, 0x14, 0xb5, 0x63, 0xa7, 0xf8, 0x2b, 0x59, 0x4e, 0x31, 0x20, 0xf3, 0x33, - 0x3d, 0xca, 0x7f, 0x32, 0x60, 0x69, 0xf8, 0x7a, 0xb2, 0x9e, 0x67, 0xfe, 0x74, 0xcf, 0x73, 0x15, - 0x4a, 0x7d, 0x8f, 0xae, 0x5b, 0x2d, 0xea, 0xf9, 0x7c, 0xe3, 0x13, 0xa1, 0x9f, 0xb9, 0xab, 0x00, - 0x38, 0xc4, 0x31, 0xbf, 0x9f, 0x07, 0x34, 0x78, 0x45, 0x99, 0xc5, 0x72, 0x69, 0xcf, 0xb9, 0x8b, - 0x37, 0xe3, 0x16, 0x0b, 0x8b, 0x61, 0xac, 0xe0, 0x6c, 0xc3, 0x8d, 0x36, 0x71, 0xfd, 0x78, 0xfc, - 0xb7, 0xc6, 0x06, 0xb1, 0x80, 0x69, 0x1b, 0x2e, 0x9e, 0xee, 0x86, 0xb7, 0x60, 0xa1, 0xcf, 0x97, - 0xbc, 0x4d, 0xdc, 0x16, 0xf5, 0x95, 0x49, 0xe6, 0x72, 0x9d, 0xa8, 0xfd, 0x9c, 0x5c, 0xcc, 0xc2, - 0xdd, 0x04, 0x1c, 0x9c, 0x38, 0x13, 0xed, 0x40, 0x69, 0x4f, 0x1d, 0xac, 0xbc, 0x6e, 0xd7, 0x46, - 0xd2, 0x52, 0xe1, 0x24, 0x82, 0xaf, 0x38, 0x24, 0x8b, 0xde, 0x82, 0x42, 0x9b, 0x76, 0xba, 0x8b, - 0x63, 0x9c, 0xfc, 0x2f, 0x65, 0x35, 0x65, 0xb5, 0x09, 0x16, 0x0b, 0xb0, 0x4f, 0x98, 0xd3, 0x31, - 0x7f, 0x1b, 0x84, 0xb8, 0xb3, 0x9c, 0xdb, 0xc9, 0x11, 0xc6, 0x73, 0x30, 0xbe, 0x4f, 0xdd, 0x40, - 0x9c, 0x1a, 0xb1, 0x7b, 0x62, 0x18, 0x2b, 0xb8, 0xf9, 0xaf, 0x06, 0x2c, 0xf0, 0x15, 0xac, 0x5b, - 0x5e, 0xc3, 0xd9, 0xa7, 0xee, 0x01, 0xa6, 0x5e, 0xbf, 0x73, 0xca, 0x0b, 0x5a, 0x87, 0x59, 0x8f, - 0x76, 0xf7, 0xa9, 0xbb, 0xe6, 0xd8, 0x9e, 0xef, 0x12, 0xcb, 0xf6, 0xe5, 0xca, 0x16, 0x25, 0xf6, - 0x6c, 0x3d, 0x06, 0xc7, 0x03, 0x33, 0xd0, 0xb3, 0x30, 0x21, 0x97, 0xcd, 0xe2, 0x17, 0xe6, 0xcd, - 0x27, 0x99, 0xe3, 0x97, 0x7b, 0xf2, 0x70, 0x00, 0x35, 0x7f, 0x62, 0xc0, 0x1c, 0xdf, 0x55, 0xbd, - 0xbf, 0xe3, 0x35, 0x5c, 0xab, 0xc7, 0xe2, 0xee, 0xc7, 0x71, 0x4b, 0x37, 0x61, 0xba, 0xa9, 0x04, - 0xbf, 0x69, 0x75, 0x2d, 0x9f, 0x2b, 0xee, 0x58, 0xed, 0x82, 0xa4, 0x31, 0xbd, 0x1e, 0x81, 0xe2, - 0x18, 0xb6, 0xf9, 0xa7, 0x79, 0x98, 0x57, 0x28, 0xb4, 0x59, 0x75, 0x7d, 0x6b, 0x97, 0x34, 0x7c, - 0x0f, 0x35, 0x61, 0xb2, 0x19, 0x0e, 0xfb, 0xf2, 0x3a, 0xfc, 0x62, 0x45, 0xe4, 0x98, 0x15, 0x3d, - 0xc7, 0xac, 0xf4, 0xf6, 0x5a, 0x6c, 0xc0, 0xab, 0xb0, 0x54, 0xb6, 0xb2, 0x7f, 0xb9, 0xb2, 0x6d, - 0x75, 0x69, 0x18, 0xb9, 0x68, 0xe4, 0x7d, 0x1c, 0xa1, 0x8a, 0xee, 0x43, 0xbe, 0x65, 0xf9, 0xd2, - 0x23, 0xa4, 0x0c, 0x2b, 0x6e, 0x5b, 0x71, 0x55, 0x0b, 0xdd, 0xd7, 0x6d, 0xcb, 0xc7, 0x8c, 0x22, - 0xda, 0x09, 0xbc, 0x8d, 0x48, 0xf4, 0x6e, 0xa4, 0xa3, 0xcd, 0x4d, 0x75, 0x9c, 0xfa, 0x30, 0x3f, - 0xb3, 0x03, 0x45, 0x6e, 0xe2, 0x54, 0x58, 0x94, 0x92, 0x47, 0xd2, 0x65, 0x09, 0x79, 0x70, 0xa8, - 0x87, 0x25, 0x65, 0xf3, 0xd3, 0x1c, 0xcc, 0x86, 0xf2, 0x5b, 0x73, 0xba, 0x5d, 0xcb, 0x47, 0x4b, - 0x90, 0xb3, 0x9a, 0x52, 0x03, 0x41, 0x4e, 0xcc, 0x6d, 0xac, 0xe3, 0x9c, 0xd5, 0x44, 0xcf, 0x40, - 0x71, 0xc7, 0x25, 0x76, 0xa3, 0x2d, 0x35, 0x2f, 0x20, 0x5c, 0xe3, 0xa3, 0x58, 0x42, 0x99, 0xfb, - 0xf7, 0x49, 0x4b, 0x2a, 0x5c, 0x20, 0xbf, 0x6d, 0xd2, 0xc2, 0x6c, 0x9c, 0x69, 0xba, 0xd7, 0xdf, - 0xf9, 0x0d, 0xda, 0x10, 0x27, 0xaf, 0x69, 0x7a, 0x5d, 0x0c, 0x63, 0x05, 0x67, 0x1c, 0x49, 0xdf, - 0x6f, 0x3b, 0x2e, 0xb7, 0x69, 0x1a, 0xc7, 0x2a, 0x1f, 0xc5, 0x12, 0xca, 0x1c, 0x54, 0x83, 0xaf, - 0xdf, 0xa7, 0x2e, 0xf7, 0x05, 0x5a, 0x22, 0xb4, 0xa6, 0x00, 0x38, 0xc4, 0x41, 0xef, 0x41, 0xb9, - 0xe1, 0x52, 0xe2, 0x3b, 0xee, 0x3a, 0xf1, 0xe9, 0xe2, 0x78, 0x66, 0x0d, 0x9c, 0x61, 0xd9, 0xf8, - 0x5a, 0x48, 0x02, 0xeb, 0xf4, 0xcc, 0x9f, 0x1a, 0xb0, 0x18, 0x8a, 0x56, 0x38, 0xe9, 0x20, 0x03, - 0x95, 0xe2, 0x31, 0x86, 0x88, 0xe7, 0x19, 0x28, 0x36, 0x43, 0x4f, 0xab, 0xed, 0x59, 0xba, 0x59, - 0x09, 0x45, 0x57, 0x00, 0x5a, 0x96, 0x2f, 0x8d, 0x83, 0x14, 0x76, 0x90, 0xf7, 0xdc, 0x0e, 0x20, - 0x58, 0xc3, 0x42, 0xf7, 0xa1, 0xc4, 0x97, 0x39, 0xe2, 0xb5, 0xe3, 0xae, 0x67, 0x4d, 0x11, 0xc0, - 0x21, 0x2d, 0xf3, 0x93, 0x02, 0x8c, 0x4b, 0xb7, 0x8a, 0x7e, 0x1d, 0x26, 0xba, 0xb2, 0x92, 0xc1, - 0x37, 0xc9, 0x5c, 0x51, 0x2a, 0x1e, 0x6f, 0xf3, 0x43, 0x7f, 0x93, 0xfa, 0x24, 0xdc, 0x48, 0x38, - 0x86, 0x03, 0xaa, 0x2c, 0x38, 0x20, 0x1d, 0x8b, 0x78, 0xfc, 0xdc, 0xb4, 0xe0, 0xa0, 0xca, 0x06, - 0xb1, 0x80, 0xa1, 0xaf, 0x06, 0xc1, 0x41, 0x69, 0xf4, 0xe0, 0x20, 0x10, 0x7e, 0x2c, 0x40, 0x78, - 0x07, 0xc6, 0x85, 0x32, 0xa9, 0x0b, 0xba, 0x9a, 0xda, 0xc0, 0x08, 0x7d, 0x0c, 0x95, 0x5e, 0x7c, - 0xf7, 0xb0, 0x22, 0x88, 0xea, 0x81, 0x7d, 0x29, 0x70, 0xd2, 0xcf, 0x67, 0xb0, 0x2f, 0x43, 0x0d, - 0x4a, 0x3d, 0x30, 0x28, 0x63, 0x59, 0x88, 0x72, 0x93, 0x31, 0xcc, 0x82, 0x30, 0x11, 0xcb, 0x74, - 0x79, 0x94, 0xf8, 0x4b, 0xe6, 0xea, 0xd3, 0xd1, 0x1c, 0x5b, 0x65, 0xd3, 0xe6, 0x1f, 0xe7, 0x61, - 0x4e, 0x62, 0xae, 0x39, 0x9d, 0x0e, 0x6d, 0x70, 0x37, 0x29, 0xec, 0x53, 0x3e, 0xd1, 0x3e, 0x59, - 0x30, 0x66, 0xf9, 0xb4, 0xab, 0xb2, 0x80, 0x5a, 0xa6, 0xd5, 0x84, 0x3c, 0x2a, 0x1b, 0x8c, 0x88, - 0x28, 0xbc, 0x05, 0xa7, 0x24, 0xb1, 0xb0, 0xe0, 0x80, 0x7e, 0xdf, 0x80, 0xf9, 0x7d, 0xea, 0x5a, - 0xbb, 0x56, 0x83, 0x97, 0xcd, 0xee, 0x58, 0x9e, 0xef, 0xb8, 0x07, 0xd2, 0x23, 0xbc, 0x94, 0x8e, - 0xf3, 0x3d, 0x8d, 0xc0, 0x86, 0xbd, 0xeb, 0xd4, 0x9e, 0x92, 0xdc, 0xe6, 0xef, 0x0d, 0x92, 0xc6, - 0x49, 0xfc, 0x96, 0x7a, 0x00, 0xe1, 0x6a, 0x13, 0xaa, 0x76, 0x9b, 0x7a, 0xd5, 0x2e, 0xf5, 0xc2, - 0xd4, 0x66, 0x95, 0xc9, 0xd2, 0xab, 0x7d, 0xdf, 0x33, 0xa0, 0x2c, 0xe1, 0x9b, 0x96, 0xe7, 0xa3, - 0x77, 0x07, 0x6e, 0x7b, 0x25, 0xdd, 0x6d, 0x67, 0xb3, 0xf9, 0x5d, 0x0f, 0x8a, 0x24, 0x6a, 0x44, - 0xbb, 0xe9, 0x58, 0x1d, 0xa9, 0x10, 0xec, 0x17, 0x33, 0xad, 0x5f, 0x4b, 0x93, 0x18, 0x0d, 0x79, - 0x76, 0xa6, 0x0b, 0x53, 0x91, 0x4b, 0x8e, 0xae, 0x41, 0x61, 0xcf, 0xb2, 0x95, 0xd7, 0xfb, 0x79, - 0x15, 0x4f, 0xbd, 0x61, 0xd9, 0xcd, 0x07, 0x87, 0x2b, 0x73, 0x11, 0x64, 0x36, 0x88, 0x39, 0xfa, - 0xc9, 0x61, 0xd8, 0x8d, 0x89, 0xef, 0xfe, 0xf9, 0xca, 0xb9, 0x0f, 0x7f, 0x78, 0xe9, 0x9c, 0xf9, - 0x9d, 0x3c, 0xcc, 0xc6, 0xa5, 0x9a, 0xa2, 0x0a, 0x1e, 0xda, 0xb0, 0x89, 0x33, 0xb5, 0x61, 0xb9, - 0xb3, 0xb3, 0x61, 0xf9, 0xb3, 0xb0, 0x61, 0x85, 0x53, 0xb3, 0x61, 0xe6, 0xc7, 0x06, 0x4c, 0x07, - 0x27, 0xf3, 0x7e, 0x9f, 0x79, 0xd6, 0x50, 0xea, 0xc6, 0xe9, 0x4b, 0xfd, 0x6b, 0x30, 0x2e, 0x2a, - 0x52, 0x9e, 0xbc, 0x93, 0x2f, 0x66, 0x33, 0x9a, 0x62, 0xae, 0x16, 0x33, 0x89, 0x01, 0xac, 0xa8, - 0x9a, 0xef, 0x06, 0xfb, 0x91, 0x20, 0x11, 0x51, 0xb8, 0x2c, 0xde, 0x32, 0x78, 0xfe, 0xaa, 0x45, - 0x14, 0x6c, 0x14, 0x4b, 0x28, 0x32, 0xb9, 0x39, 0x57, 0x81, 0x6d, 0x49, 0x64, 0xc6, 0xbc, 0x04, - 0x2e, 0xac, 0x72, 0x8b, 0x7a, 0xe6, 0x4f, 0xf3, 0xc1, 0xed, 0x91, 0x35, 0xd3, 0x0f, 0x00, 0x84, - 0x65, 0xa2, 0xcd, 0x0d, 0x5b, 0x9a, 0xde, 0xb5, 0x11, 0x1c, 0x81, 0x34, 0x87, 0x8c, 0x8a, 0xb0, - 0xbd, 0x41, 0x0c, 0x10, 0x02, 0xb0, 0xc6, 0x0a, 0x7d, 0x13, 0xca, 0x44, 0xd6, 0xe9, 0x6f, 0x39, - 0xae, 0xd4, 0xe1, 0xf5, 0x51, 0x38, 0x57, 0x43, 0x32, 0xf1, 0x7e, 0x4b, 0x08, 0xc1, 0x3a, 0xb7, - 0x25, 0x17, 0x66, 0x62, 0xeb, 0x4d, 0xb0, 0xbe, 0x1b, 0x51, 0xeb, 0x7b, 0x35, 0x8b, 0x5b, 0x90, - 0xcd, 0x07, 0xbd, 0x51, 0xe3, 0xc1, 0x6c, 0x7c, 0xa5, 0xa7, 0xc6, 0x34, 0xd2, 0xf1, 0xd0, 0xed, - 0xfd, 0x4f, 0x72, 0x50, 0x0a, 0x6e, 0x7c, 0x96, 0x2c, 0x55, 0x78, 0xea, 0xdc, 0x09, 0x99, 0x44, - 0x3e, 0x4d, 0x26, 0x51, 0x18, 0x12, 0x2a, 0xdf, 0x86, 0x39, 0xd1, 0x45, 0x58, 0x6b, 0xd3, 0xc6, - 0x9e, 0x58, 0xa2, 0xcc, 0x14, 0x9e, 0x94, 0xc8, 0x73, 0x77, 0xe2, 0x08, 0x78, 0x70, 0x8e, 0xde, - 0x87, 0x29, 0x1e, 0xdf, 0x87, 0xd1, 0x52, 0x92, 0xf1, 0xf4, 0x29, 0xc9, 0xc4, 0xc9, 0x29, 0x89, - 0xf9, 0x17, 0x06, 0xa0, 0xc1, 0xfc, 0x33, 0x8b, 0xc4, 0x49, 0xdc, 0xa0, 0xa7, 0x74, 0xf7, 0xf1, - 0x24, 0x70, 0xb8, 0x5d, 0x37, 0xe7, 0x61, 0xee, 0xb6, 0xe5, 0xdf, 0xe9, 0xef, 0x6c, 0xf5, 0x3b, - 0x1d, 0x69, 0x2f, 0xe5, 0xe0, 0x26, 0x89, 0x0c, 0x7e, 0x58, 0x84, 0x29, 0x95, 0x85, 0x64, 0xae, - 0xfe, 0xdd, 0x3f, 0x8d, 0xd8, 0x3d, 0xa9, 0xb0, 0x57, 0x87, 0xf3, 0x96, 0xed, 0xd1, 0x46, 0xdf, - 0xa5, 0xf5, 0x3d, 0xab, 0xb7, 0xbd, 0x59, 0xe7, 0xb7, 0xed, 0x40, 0x56, 0x35, 0x2f, 0xca, 0x15, - 0x9d, 0xdf, 0x48, 0x42, 0xc2, 0xc9, 0x73, 0x59, 0x26, 0xe6, 0x52, 0xd2, 0xac, 0xe9, 0x1a, 0x1d, - 0x18, 0x2f, 0x1c, 0x40, 0xb0, 0x86, 0x85, 0xae, 0x41, 0xf9, 0x03, 0xd7, 0xf2, 0xa9, 0x9c, 0x24, - 0x34, 0x3c, 0x30, 0x3b, 0xf7, 0x43, 0x10, 0xd6, 0xf1, 0xd0, 0x3e, 0x94, 0x7b, 0xa1, 0x90, 0x65, - 0xa5, 0x2f, 0xa5, 0xb5, 0xd5, 0x4e, 0x67, 0xcb, 0x75, 0xba, 0x0e, 0x8b, 0x23, 0xdf, 0xa4, 0x8d, - 0x36, 0xb1, 0x2d, 0xaf, 0x2b, 0x12, 0x5a, 0x0d, 0x05, 0xeb, 0x8c, 0x50, 0x0b, 0x8a, 0x2e, 0xb5, - 0x9b, 0x32, 0xbb, 0x4e, 0xcd, 0xf2, 0x0d, 0x36, 0x84, 0xf9, 0xc4, 0x04, 0x96, 0xfc, 0x80, 0x04, - 0x14, 0x4b, 0xf2, 0xc8, 0xd6, 0xeb, 0xa4, 0x22, 0x2d, 0xaf, 0xa6, 0xe4, 0xa5, 0xa6, 0x25, 0x70, - 0x1a, 0x5e, 0x33, 0x7d, 0x47, 0xd6, 0x4c, 0x45, 0x7c, 0xf5, 0x6a, 0x3a, 0x56, 0x77, 0x68, 0xa7, - 0x9b, 0xc0, 0x25, 0x5e, 0x3f, 0xfd, 0xd6, 0x18, 0xcc, 0xdc, 0xb6, 0x46, 0x2e, 0xf3, 0xf9, 0xf0, - 0x84, 0xb8, 0x76, 0x75, 0x2a, 0x33, 0x93, 0xba, 0xef, 0x12, 0x9f, 0xb6, 0x54, 0x67, 0xe5, 0x86, - 0x9c, 0xfa, 0xc4, 0x5a, 0x32, 0xda, 0x83, 0xe1, 0x20, 0x3c, 0x8c, 0x74, 0x6a, 0xd3, 0x9c, 0x54, - 0x62, 0x2c, 0x64, 0x2e, 0x31, 0xae, 0x42, 0x89, 0x74, 0x3a, 0xce, 0x07, 0xdb, 0xa4, 0xe5, 0x49, - 0xcb, 0x1d, 0x58, 0xc9, 0xaa, 0x02, 0xe0, 0x10, 0x07, 0x55, 0x00, 0xac, 0x96, 0xed, 0xb8, 0x94, - 0xcf, 0x28, 0xf2, 0x38, 0x65, 0x9a, 0xdd, 0xb3, 0x8d, 0x60, 0x14, 0x6b, 0x18, 0xc3, 0x2f, 0xfc, - 0xf8, 0x43, 0x5c, 0xf8, 0x17, 0x61, 0xd2, 0xb2, 0x1b, 0x9d, 0x7e, 0x93, 0x6e, 0x11, 0xbf, 0xed, - 0x2d, 0x4e, 0xf0, 0x65, 0xcc, 0x1e, 0x1d, 0xae, 0x4c, 0x6e, 0x68, 0xe3, 0x38, 0x82, 0xc5, 0x66, - 0xd1, 0xaf, 0x6b, 0xb3, 0x4a, 0xe1, 0xac, 0xd7, 0xbe, 0xae, 0xcf, 0xd2, 0xb1, 0x12, 0x8a, 0xb0, - 0x90, 0xa9, 0x08, 0xfb, 0xb1, 0x01, 0x45, 0xe1, 0x03, 0xd1, 0xb5, 0x58, 0x77, 0xfb, 0xe2, 0x40, - 0x77, 0xbb, 0x9c, 0xf4, 0x48, 0xc1, 0x84, 0xa2, 0xe5, 0x79, 0xfd, 0x68, 0x58, 0xb8, 0xc1, 0x47, - 0xb0, 0x84, 0x20, 0x0b, 0x80, 0xa8, 0xf6, 0xb4, 0x8a, 0xf9, 0xaf, 0x65, 0xed, 0xdf, 0xc7, 0x7a, - 0xf7, 0x01, 0xc0, 0xc3, 0x1a, 0x71, 0xf3, 0x7f, 0x0d, 0x78, 0x92, 0x5d, 0x32, 0x51, 0xeb, 0xa4, - 0x3d, 0x66, 0x37, 0xec, 0xc6, 0x81, 0x74, 0x32, 0xdc, 0x16, 0xf7, 0x1c, 0xcf, 0xe2, 0xe9, 0xb8, - 0x11, 0xb7, 0xc5, 0x0a, 0x82, 0x35, 0xac, 0x14, 0xf5, 0xf4, 0x33, 0xeb, 0x94, 0xb2, 0x28, 0x81, - 0xed, 0x83, 0x9d, 0xb5, 0xbc, 0x70, 0x61, 0x94, 0xa0, 0x00, 0x38, 0xc4, 0x31, 0xff, 0x3a, 0x07, - 0x33, 0x0f, 0xd9, 0xec, 0x1d, 0x3b, 0xdd, 0x2d, 0xdc, 0x84, 0x69, 0x1e, 0x2d, 0x7a, 0xb7, 0xac, - 0x0e, 0xd7, 0x59, 0x29, 0xc7, 0x40, 0x41, 0xef, 0x45, 0xa0, 0x38, 0x86, 0xad, 0x9a, 0xc5, 0xf9, - 0x93, 0x9a, 0xc5, 0x85, 0x11, 0x9a, 0xc5, 0x7f, 0x97, 0x83, 0x0b, 0xc9, 0xc6, 0x1a, 0xbd, 0x17, - 0xeb, 0x19, 0x5f, 0x4b, 0x6f, 0xfa, 0xd3, 0x34, 0x8a, 0x5b, 0x41, 0xae, 0x2a, 0x42, 0xb1, 0x2f, - 0xa7, 0x27, 0x9f, 0xa8, 0xd8, 0x43, 0x6b, 0x70, 0x67, 0xd5, 0xf4, 0x35, 0xff, 0xc6, 0x00, 0xa1, - 0x41, 0x59, 0x7c, 0x56, 0xb4, 0x28, 0x9d, 0x4b, 0x55, 0x94, 0x3e, 0xa1, 0x5d, 0x10, 0xd6, 0xc3, - 0x0b, 0xc7, 0xd5, 0xc3, 0xcd, 0x1f, 0x1b, 0xb0, 0x90, 0xd4, 0x63, 0xc9, 0xb2, 0xfc, 0x17, 0x60, - 0xa2, 0xd7, 0x21, 0xfe, 0xae, 0xe3, 0x76, 0xe3, 0x2f, 0x78, 0xb6, 0xe4, 0x38, 0x0e, 0x30, 0x90, - 0xcb, 0x6c, 0x8d, 0x2c, 0xe6, 0x28, 0xa3, 0x77, 0x33, 0x6b, 0xc8, 0x1d, 0x6d, 0x0e, 0xe8, 0xb6, - 0x4a, 0x51, 0xc6, 0x1a, 0x17, 0xf3, 0xe3, 0x02, 0xcc, 0xf1, 0x29, 0xa3, 0x46, 0x15, 0xa3, 0x9c, - 0x50, 0x0f, 0x2e, 0x70, 0xb5, 0x1e, 0x0c, 0x44, 0xc4, 0xa1, 0x5d, 0x97, 0xf3, 0x2f, 0x6c, 0x24, - 0x62, 0x3d, 0x18, 0x0a, 0xc1, 0x43, 0xe8, 0x7e, 0x5e, 0xa2, 0x0b, 0x5d, 0x5f, 0xc6, 0x4f, 0xd4, - 0x97, 0xa1, 0xb1, 0xc8, 0xc4, 0x43, 0xc4, 0x22, 0x83, 0xf1, 0x41, 0x29, 0x53, 0x7c, 0xf0, 0x8f, - 0x06, 0x5c, 0xd0, 0xc2, 0xf4, 0xcf, 0xf1, 0xa3, 0x93, 0x43, 0x03, 0x2e, 0x1e, 0x9b, 0x70, 0xa0, - 0x66, 0xcc, 0xe6, 0xbf, 0x9a, 0x39, 0x8b, 0xf9, 0x99, 0xbe, 0x11, 0xfa, 0x4f, 0x03, 0x16, 0x4e, - 0xe3, 0x75, 0xd0, 0x29, 0xc7, 0x30, 0x97, 0xa0, 0xd0, 0x0b, 0xdd, 0x7e, 0x10, 0x3e, 0x71, 0x67, - 0xcf, 0x21, 0xd1, 0xa3, 0xcc, 0xa7, 0x38, 0xca, 0xff, 0x30, 0xe0, 0xa9, 0x63, 0xf2, 0x39, 0xad, - 0x05, 0x6f, 0x64, 0x69, 0x8f, 0x3f, 0x1e, 0x4f, 0xbd, 0xfe, 0x24, 0x07, 0xe3, 0x5b, 0xae, 0xc3, - 0x1b, 0xdc, 0x67, 0xdf, 0x2b, 0x7d, 0x1b, 0x0a, 0x5e, 0x8f, 0x36, 0xe4, 0x26, 0x2e, 0xa7, 0x2c, - 0x15, 0x88, 0xe5, 0xd5, 0x7b, 0xb4, 0x21, 0xb2, 0x5a, 0xf6, 0x09, 0x73, 0x42, 0x5a, 0xd3, 0x2f, - 0xd3, 0x85, 0x57, 0x24, 0x8f, 0x6f, 0xfa, 0x7d, 0xcf, 0x80, 0xb2, 0xc4, 0x7c, 0x6c, 0xbb, 0x4b, - 0x72, 0x7d, 0x43, 0xba, 0x4b, 0x7f, 0x10, 0xee, 0x80, 0x09, 0x0d, 0xfd, 0x16, 0xcc, 0xf5, 0x94, - 0x02, 0x6f, 0x39, 0x1d, 0xab, 0x61, 0x65, 0x0d, 0x39, 0xb7, 0x22, 0xd3, 0x0f, 0xc2, 0xd2, 0xe6, - 0x56, 0x9c, 0x2e, 0x1e, 0x64, 0x65, 0x3a, 0x30, 0x15, 0x11, 0x3d, 0xba, 0xaa, 0x9e, 0xd0, 0x47, - 0x93, 0x40, 0xf1, 0x84, 0xfe, 0xc1, 0xe1, 0xca, 0xa4, 0x44, 0xd7, 0x9f, 0xd4, 0x67, 0x79, 0xa8, - 0xfe, 0x97, 0x39, 0x28, 0x05, 0x2b, 0x7b, 0x04, 0x0a, 0x7e, 0x37, 0xa2, 0xe0, 0x57, 0x33, 0xca, - 0x94, 0xab, 0x78, 0x60, 0xb3, 0x34, 0x35, 0x7f, 0x2f, 0xa6, 0xe6, 0x59, 0x0f, 0xeb, 0x04, 0x45, - 0xff, 0xbe, 0xc1, 0xcf, 0x45, 0xe0, 0x3e, 0x02, 0x55, 0xdf, 0x8e, 0xaa, 0xfa, 0x6a, 0xc6, 0xdd, - 0x0c, 0x51, 0xf6, 0x1f, 0xe5, 0x60, 0x7e, 0xd0, 0x3c, 0x9f, 0x5d, 0x52, 0x82, 0x3c, 0x98, 0x6e, - 0xe9, 0x45, 0x65, 0x75, 0x95, 0xae, 0xa6, 0x6e, 0x5d, 0x86, 0x73, 0xc3, 0x10, 0x29, 0x32, 0xec, - 0xe1, 0x18, 0x0b, 0xf4, 0x4d, 0x98, 0x25, 0xd1, 0xb7, 0xf7, 0x4a, 0x8c, 0x59, 0x4b, 0x1c, 0x92, - 0x71, 0x10, 0xc3, 0xc6, 0x00, 0x1e, 0x1e, 0x60, 0x64, 0x7e, 0xdb, 0x80, 0x99, 0x98, 0x05, 0x60, - 0xfe, 0x9e, 0xb7, 0xe3, 0xe2, 0xfe, 0x5e, 0x36, 0x6f, 0x38, 0x0c, 0x6d, 0xc1, 0x02, 0xe9, 0xfb, - 0x4e, 0x30, 0xf7, 0x35, 0x9b, 0xec, 0x74, 0x68, 0x53, 0x86, 0x52, 0xc1, 0x1b, 0xd6, 0x6a, 0x02, - 0x0e, 0x4e, 0x9c, 0x69, 0xfe, 0x73, 0x0e, 0x50, 0x30, 0x98, 0xa5, 0x8d, 0xfd, 0x1e, 0x8c, 0xef, - 0x8a, 0xa3, 0x7d, 0xb8, 0x77, 0x08, 0xb5, 0xb2, 0xfe, 0x14, 0x43, 0xd1, 0x44, 0xbf, 0x76, 0x3a, - 0x57, 0x15, 0x06, 0xaf, 0x29, 0x7a, 0x07, 0x60, 0xd7, 0xb2, 0x2d, 0xaf, 0x3d, 0xe2, 0x8b, 0x29, - 0x9e, 0x3c, 0xdc, 0x0a, 0x28, 0x60, 0x8d, 0x9a, 0xf9, 0x35, 0xcd, 0x02, 0x70, 0x57, 0x91, 0xea, - 0x58, 0x9f, 0x8b, 0xca, 0xb2, 0x34, 0xf8, 0x44, 0x45, 0xc1, 0xcd, 0xbf, 0x1a, 0xd3, 0x54, 0x47, - 0x5a, 0xff, 0xd7, 0x01, 0x75, 0x88, 0xe7, 0xdf, 0x21, 0x76, 0x93, 0x1d, 0x34, 0xdd, 0x75, 0xa9, - 0xa7, 0xda, 0x0f, 0x4b, 0x92, 0x12, 0xda, 0x1c, 0xc0, 0xc0, 0x09, 0xb3, 0xd0, 0xb5, 0xa8, 0x27, - 0x59, 0x89, 0x7b, 0x92, 0xe9, 0x50, 0x6f, 0x47, 0xf3, 0x25, 0xe8, 0x7d, 0xcd, 0x26, 0xe6, 0xb3, - 0x74, 0x96, 0x63, 0xdb, 0xae, 0xa8, 0x9f, 0xd6, 0x89, 0xf6, 0x6e, 0x60, 0x28, 0xd5, 0xb0, 0x66, - 0x28, 0x35, 0x5d, 0x1d, 0x3b, 0x03, 0x5d, 0xfd, 0x4d, 0x98, 0xdb, 0x8d, 0x3f, 0x38, 0x92, 0x7d, - 0x8e, 0x2f, 0x8d, 0xf8, 0x5e, 0xa9, 0x76, 0xfe, 0x28, 0x7c, 0xa5, 0x12, 0x0e, 0xe3, 0x41, 0x46, - 0x31, 0x75, 0x2e, 0x9e, 0xa6, 0x3a, 0x2f, 0xbd, 0x02, 0x53, 0x11, 0x29, 0x67, 0xfa, 0x0d, 0xe1, - 0xbf, 0x1b, 0x70, 0xf1, 0xd8, 0xfe, 0x14, 0x0b, 0x3b, 0x85, 0x78, 0xa4, 0x73, 0xfc, 0x52, 0x6a, - 0x8b, 0x1f, 0xed, 0x56, 0x8a, 0x6b, 0x2e, 0x86, 0xb1, 0x24, 0x29, 0x89, 0x77, 0xc8, 0x8e, 0xb4, - 0x4f, 0xe9, 0x89, 0x47, 0xbb, 0x9e, 0x01, 0xf1, 0x4d, 0x22, 0x88, 0x77, 0xc8, 0x8e, 0xf9, 0xdd, - 0x1c, 0xcc, 0x32, 0x77, 0x12, 0xa9, 0xd8, 0x6c, 0xa9, 0xd7, 0xc9, 0x19, 0x0c, 0x56, 0xac, 0x97, - 0x54, 0x1b, 0x8f, 0x3c, 0x4b, 0xfe, 0x8a, 0x4a, 0x02, 0x33, 0x6d, 0x61, 0xa0, 0x96, 0x54, 0x2b, - 0x0d, 0x64, 0x8e, 0x5f, 0x51, 0xbf, 0xc5, 0xc8, 0x67, 0xa1, 0x3c, 0xf0, 0xc4, 0x5d, 0x50, 0xd6, - 0x7f, 0xc0, 0x61, 0x7e, 0x27, 0x07, 0xc2, 0xba, 0x3d, 0x82, 0x38, 0xf1, 0x57, 0x23, 0x71, 0x62, - 0xca, 0x00, 0x88, 0x2f, 0x6e, 0x68, 0x8c, 0x18, 0x77, 0x3c, 0x97, 0xb3, 0x10, 0x3d, 0x3e, 0x3e, - 0xfc, 0x7b, 0x03, 0x4a, 0x1c, 0xef, 0x11, 0xc4, 0x86, 0x5b, 0xd1, 0xd8, 0xf0, 0xf9, 0x0c, 0xbb, - 0x18, 0x12, 0x17, 0xfe, 0x59, 0x5e, 0xae, 0x3e, 0xf0, 0x6b, 0x6d, 0xe2, 0x36, 0xa5, 0x9b, 0x09, - 0xfd, 0x1a, 0x1b, 0xc4, 0x02, 0x86, 0xbe, 0x01, 0xb3, 0xae, 0xb8, 0x44, 0xb4, 0x79, 0x2b, 0x30, - 0xc0, 0xf9, 0xcc, 0x0f, 0xa4, 0xd4, 0x4d, 0x0c, 0x62, 0x2c, 0x1c, 0xa3, 0x8a, 0x07, 0xf8, 0xa0, - 0xdf, 0x33, 0x60, 0xbe, 0x37, 0x18, 0xc6, 0x4a, 0x55, 0x79, 0x39, 0xa3, 0xcb, 0x09, 0x09, 0xd4, - 0x9e, 0x38, 0x3a, 0x5c, 0x49, 0x0a, 0x90, 0x71, 0x12, 0x3b, 0xd4, 0x86, 0x49, 0xfd, 0x8d, 0xa7, - 0x54, 0xaa, 0x2b, 0xd9, 0x1f, 0x93, 0x8a, 0xa6, 0xa2, 0x3e, 0x82, 0x23, 0x94, 0xcd, 0xff, 0x19, - 0x83, 0xb2, 0xa6, 0x85, 0x43, 0xa2, 0x82, 0xf2, 0x48, 0x51, 0xc1, 0xe5, 0x68, 0x54, 0xf0, 0x54, - 0x3c, 0x2a, 0x00, 0xce, 0x38, 0x12, 0x11, 0x78, 0x30, 0x2d, 0x7d, 0x95, 0x7a, 0x47, 0x2b, 0x1e, - 0xf8, 0x8d, 0xec, 0x11, 0x11, 0x8b, 0xea, 0x6f, 0x45, 0x48, 0xe2, 0x18, 0x0b, 0x74, 0x33, 0x60, - 0x5a, 0xef, 0x77, 0xbb, 0xc4, 0x3d, 0x58, 0x9c, 0x8c, 0xf6, 0xad, 0x6e, 0x45, 0xa0, 0x38, 0x86, - 0x8d, 0xb6, 0xa0, 0x28, 0x1e, 0x12, 0xc9, 0xb7, 0x03, 0x2f, 0xa4, 0xed, 0xf0, 0xb0, 0x39, 0xc2, - 0x51, 0x88, 0xcf, 0x58, 0xd2, 0xd1, 0x03, 0xa3, 0xd2, 0x09, 0x81, 0xd1, 0xeb, 0x80, 0x9c, 0x1d, - 0x8f, 0xba, 0xfb, 0xb4, 0x79, 0x5b, 0xfc, 0xe5, 0x02, 0x53, 0x18, 0xe6, 0xd0, 0xf3, 0xe1, 0x81, - 0xbd, 0x3d, 0x80, 0x81, 0x13, 0x66, 0xb1, 0x9b, 0xd7, 0xe8, 0xbb, 0x2e, 0xb5, 0x43, 0xb7, 0x2b, - 0x23, 0x92, 0xeb, 0x19, 0x35, 0x3f, 0x0c, 0x7e, 0x16, 0xd8, 0xcd, 0x5b, 0x8b, 0x51, 0xc5, 0x03, - 0x7c, 0xd0, 0xfb, 0x30, 0xc5, 0x54, 0x28, 0x64, 0x0c, 0x0f, 0xc9, 0x78, 0xee, 0xe8, 0x70, 0x65, - 0x6a, 0x53, 0x27, 0x89, 0xa3, 0x1c, 0xcc, 0xff, 0xcb, 0x41, 0xe4, 0x6a, 0xa0, 0x6f, 0x1b, 0x30, - 0x47, 0x62, 0xff, 0x17, 0xa0, 0xf2, 0xca, 0x2f, 0x67, 0xfb, 0x13, 0x87, 0x81, 0xbf, 0x1b, 0x08, - 0x8b, 0x35, 0x71, 0x14, 0x0f, 0x0f, 0x32, 0xe5, 0x86, 0x88, 0x0c, 0xfe, 0x21, 0x44, 0x36, 0x43, - 0x94, 0xf0, 0x8f, 0x12, 0xc2, 0x10, 0x25, 0x00, 0x70, 0x12, 0x3b, 0xf4, 0x55, 0x28, 0x10, 0xb7, - 0xa5, 0x5a, 0x5a, 0xd9, 0xd9, 0xaa, 0xff, 0xf9, 0x08, 0x9d, 0x66, 0xd5, 0x6d, 0x79, 0x98, 0x13, - 0x35, 0x7f, 0x98, 0x87, 0xd9, 0xf8, 0xcb, 0x77, 0xf9, 0x58, 0xb0, 0x90, 0xf8, 0x58, 0xf0, 0x0b, - 0x30, 0x46, 0x1a, 0x7e, 0xf0, 0xe0, 0x2e, 0xfc, 0xb5, 0x07, 0x1b, 0xc4, 0x02, 0x86, 0xee, 0x43, - 0xc9, 0xf3, 0x89, 0xeb, 0xb3, 0x30, 0x55, 0x06, 0xee, 0x99, 0x7f, 0xd9, 0x52, 0x57, 0x04, 0x70, - 0x48, 0x0b, 0x5d, 0x8f, 0x9a, 0x33, 0x33, 0x6e, 0xce, 0xe6, 0xf4, 0xbd, 0x8c, 0x9a, 0xe7, 0x74, - 0xa1, 0xac, 0x9d, 0x83, 0x34, 0xfc, 0x37, 0x32, 0xcb, 0x3d, 0x54, 0xbb, 0x19, 0xf1, 0x67, 0x21, - 0x21, 0x44, 0xa7, 0x1f, 0xa6, 0x01, 0x5c, 0x5a, 0x0f, 0x95, 0x06, 0x70, 0x71, 0x69, 0xd4, 0xcc, - 0x19, 0x98, 0x8a, 0x3c, 0x60, 0xe5, 0xf5, 0xc0, 0xfb, 0xc4, 0xa5, 0x6d, 0xa7, 0xef, 0xd1, 0xc7, - 0xb5, 0x1e, 0x18, 0x2c, 0xf0, 0xb4, 0xeb, 0x81, 0x21, 0xe1, 0x93, 0xeb, 0x81, 0x01, 0xee, 0x63, - 0x5b, 0x0f, 0x0c, 0x56, 0x38, 0x24, 0xee, 0xfb, 0xef, 0x9c, 0xb6, 0x8b, 0x68, 0xec, 0x97, 0x3b, - 0x26, 0xf6, 0x7b, 0x17, 0x26, 0x2c, 0xdb, 0xa7, 0xee, 0x3e, 0xe9, 0xc8, 0x1a, 0x4b, 0xca, 0xad, - 0xae, 0xf7, 0x5d, 0x19, 0xf0, 0xa8, 0xad, 0x6e, 0x48, 0x3a, 0x38, 0xa0, 0x88, 0x3a, 0x70, 0x5e, - 0x65, 0xc2, 0x2e, 0x25, 0x61, 0x19, 0x4d, 0x36, 0xaf, 0x5f, 0x52, 0x6d, 0xd7, 0x5b, 0x49, 0x48, - 0x0f, 0x86, 0x01, 0x70, 0x32, 0x51, 0xe4, 0xc1, 0x94, 0xa7, 0x25, 0x3d, 0xca, 0x91, 0xa4, 0xac, - 0x22, 0xc4, 0xf3, 0x44, 0xed, 0x5f, 0x2d, 0x74, 0xa2, 0x38, 0xca, 0xc3, 0xfc, 0x97, 0x3c, 0xcc, - 0xc4, 0x34, 0x0d, 0x35, 0x00, 0x1a, 0x8e, 0xdd, 0xb4, 0xc4, 0x2a, 0x4a, 0xf2, 0x98, 0x53, 0x89, - 0x75, 0x4d, 0xcd, 0x0b, 0xaf, 0x5a, 0x30, 0xe4, 0x61, 0x8d, 0xec, 0x90, 0xc0, 0xb1, 0x38, 0x52, - 0xe0, 0x98, 0x1c, 0xd3, 0x14, 0x46, 0x8a, 0x69, 0x5e, 0x11, 0x71, 0x85, 0x3c, 0xb9, 0x8d, 0x75, - 0xf9, 0x02, 0x3b, 0x90, 0xe6, 0xa6, 0x0e, 0xc4, 0x51, 0x5c, 0xee, 0x85, 0x9b, 0x83, 0xbf, 0x5b, - 0x96, 0x41, 0xd1, 0xcb, 0x59, 0x5f, 0x78, 0x04, 0x04, 0x84, 0x17, 0x4e, 0x00, 0xe0, 0x24, 0x76, - 0xb5, 0xd7, 0x3f, 0xfa, 0x6c, 0xf9, 0xdc, 0x27, 0x9f, 0x2d, 0x9f, 0xfb, 0xf4, 0xb3, 0xe5, 0x73, - 0x1f, 0x1e, 0x2d, 0x1b, 0x1f, 0x1d, 0x2d, 0x1b, 0x9f, 0x1c, 0x2d, 0x1b, 0x9f, 0x1e, 0x2d, 0x1b, - 0x3f, 0x3a, 0x5a, 0x36, 0xfe, 0xe8, 0xc7, 0xcb, 0xe7, 0xde, 0x79, 0x3a, 0xcd, 0x7f, 0x91, 0xfd, - 0x7f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xde, 0x5d, 0x87, 0xff, 0xb2, 0x4c, 0x00, 0x00, + // 4134 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x3c, 0x4d, 0x6c, 0x23, 0xd7, + 0x79, 0x3b, 0x24, 0x45, 0x89, 0x1f, 0xf5, 0xfb, 0xa4, 0x5d, 0xcb, 0x72, 0x57, 0xda, 0x4e, 0x5c, + 0xc3, 0xae, 0x1d, 0xaa, 0xbb, 0xeb, 0x75, 0xd6, 0x6b, 0x77, 0x53, 0x52, 0xf2, 0xee, 0xca, 0x96, + 0x6d, 0xf5, 0x51, 0xbb, 0x9b, 0x3a, 0x36, 0xd2, 0x27, 0xf2, 0x89, 0x9c, 0x8a, 0x9c, 0xa1, 0x67, + 0x86, 0x72, 0x94, 0x14, 0xad, 0x9b, 0xb6, 0x40, 0x2e, 0x2d, 0x7a, 0x28, 0x90, 0x14, 0x68, 0x81, + 0xa2, 0xbd, 0x14, 0x28, 0xda, 0x7b, 0xd1, 0x43, 0x0e, 0x01, 0x5a, 0x23, 0x2d, 0x0c, 0xa3, 0xcd, + 0xc1, 0x2d, 0x02, 0x21, 0x56, 0x80, 0xf4, 0x16, 0xa0, 0x87, 0x1e, 0xba, 0x45, 0x81, 0xe0, 0xfd, + 0xcd, 0xbc, 0x19, 0x0e, 0xa5, 0x19, 0xae, 0xb4, 0xd9, 0xdc, 0xc8, 0xf7, 0xfd, 0xbd, 0x9f, 0xef, + 0x7d, 0xbf, 0x8f, 0x84, 0x17, 0x5b, 0x96, 0xdf, 0xee, 0xef, 0x54, 0x1a, 0x4e, 0x77, 0x95, 0xec, + 0xf5, 0x2d, 0xff, 0x60, 0x75, 0x8f, 0xb8, 0x2d, 0x67, 0x95, 0xf4, 0xac, 0xd5, 0xfd, 0xcb, 0xa4, + 0xd3, 0x6b, 0x93, 0xcb, 0xab, 0x2d, 0x6a, 0x53, 0x97, 0xf8, 0xb4, 0x59, 0xe9, 0xb9, 0x8e, 0xef, + 0xa0, 0xa7, 0x43, 0xaa, 0x8a, 0xa0, 0xaa, 0x70, 0xaa, 0x0a, 0xe9, 0x59, 0x15, 0x45, 0xb5, 0xf4, + 0x79, 0x8d, 0x77, 0xcb, 0x69, 0x39, 0xab, 0x9c, 0x78, 0xa7, 0xbf, 0xcb, 0xbf, 0xf1, 0x2f, 0xfc, + 0x93, 0x60, 0xba, 0xf4, 0xe2, 0xde, 0x75, 0xaf, 0x62, 0x71, 0xc9, 0x5d, 0xd2, 0x68, 0x5b, 0x36, + 0x75, 0x0f, 0x56, 0x7b, 0x7b, 0x2d, 0x36, 0xe0, 0xad, 0x76, 0xa9, 0x4f, 0x56, 0xf7, 0x07, 0xa6, + 0xb2, 0xb4, 0x3a, 0x8c, 0xca, 0xed, 0xdb, 0xbe, 0xd5, 0xa5, 0x03, 0x04, 0x2f, 0x9d, 0x44, 0xe0, + 0x35, 0xda, 0xb4, 0x4b, 0xe2, 0x74, 0xe6, 0xbb, 0x30, 0x5f, 0xb5, 0x49, 0xe7, 0xc0, 0xb3, 0x3c, + 0xdc, 0xb7, 0xab, 0x6e, 0xab, 0xdf, 0xa5, 0xb6, 0x8f, 0x2e, 0x41, 0xc1, 0x26, 0x5d, 0xba, 0x68, + 0x5c, 0x32, 0x9e, 0x2d, 0xd5, 0x26, 0x3f, 0x3a, 0x5c, 0x39, 0x77, 0x74, 0xb8, 0x52, 0x78, 0x8b, + 0x74, 0x29, 0xe6, 0x10, 0xf4, 0x39, 0x18, 0xdb, 0x27, 0x9d, 0x3e, 0x5d, 0xcc, 0x71, 0x94, 0x29, + 0x89, 0x32, 0x76, 0x8f, 0x0d, 0x62, 0x01, 0x33, 0x7f, 0x3f, 0x1f, 0x61, 0xff, 0x26, 0xf5, 0x49, + 0x93, 0xf8, 0x04, 0x75, 0xa1, 0xd8, 0x21, 0x3b, 0xb4, 0xe3, 0x2d, 0x1a, 0x97, 0xf2, 0xcf, 0x96, + 0xaf, 0xbc, 0x56, 0x49, 0xb3, 0xf5, 0x95, 0x04, 0x56, 0x95, 0x4d, 0xce, 0xe7, 0x35, 0xdb, 0x77, + 0x0f, 0x6a, 0xd3, 0x72, 0x12, 0x45, 0x31, 0x88, 0xa5, 0x10, 0xf4, 0x7b, 0x06, 0x94, 0x89, 0x6d, + 0x3b, 0x3e, 0xf1, 0x2d, 0xc7, 0xf6, 0x16, 0x73, 0x5c, 0xe8, 0xeb, 0xa3, 0x0b, 0xad, 0x86, 0xcc, + 0x84, 0xe4, 0x79, 0x29, 0xb9, 0xac, 0x41, 0xb0, 0x2e, 0x73, 0xe9, 0x65, 0x28, 0x6b, 0x53, 0x45, + 0xb3, 0x90, 0xdf, 0xa3, 0x07, 0x62, 0x7f, 0x31, 0xfb, 0x88, 0x16, 0x22, 0x1b, 0x2a, 0x77, 0xf0, + 0x46, 0xee, 0xba, 0xb1, 0x74, 0x13, 0x66, 0xe3, 0x02, 0xb3, 0xd0, 0x9b, 0x7f, 0x6c, 0xc0, 0x82, + 0xb6, 0x0a, 0x4c, 0x77, 0xa9, 0x4b, 0xed, 0x06, 0x45, 0xab, 0x50, 0x62, 0x67, 0xe9, 0xf5, 0x48, + 0x43, 0x1d, 0xf5, 0x9c, 0x5c, 0x48, 0xe9, 0x2d, 0x05, 0xc0, 0x21, 0x4e, 0xa0, 0x16, 0xb9, 0xe3, + 0xd4, 0xa2, 0xd7, 0x26, 0x1e, 0x5d, 0xcc, 0x47, 0xd5, 0x62, 0x8b, 0x0d, 0x62, 0x01, 0x33, 0x7f, + 0x15, 0x9e, 0x54, 0xf3, 0xd9, 0xa6, 0xdd, 0x5e, 0x87, 0xf8, 0x34, 0x9c, 0xd4, 0x89, 0xaa, 0x67, + 0xce, 0xc0, 0x54, 0xb5, 0xd7, 0x73, 0x9d, 0x7d, 0xda, 0xac, 0xfb, 0xa4, 0x45, 0xcd, 0x6f, 0x18, + 0x70, 0xbe, 0xea, 0xb6, 0x9c, 0xb5, 0xf5, 0x6a, 0xaf, 0x77, 0x87, 0x92, 0x8e, 0xdf, 0xae, 0xfb, + 0xc4, 0xef, 0x7b, 0xe8, 0x26, 0x14, 0x3d, 0xfe, 0x49, 0xb2, 0x7b, 0x46, 0x69, 0x88, 0x80, 0x3f, + 0x38, 0x5c, 0x59, 0x48, 0x20, 0xa4, 0x58, 0x52, 0xa1, 0xe7, 0x60, 0xbc, 0x4b, 0x3d, 0x8f, 0xb4, + 0xd4, 0x9a, 0x67, 0x24, 0x83, 0xf1, 0x37, 0xc5, 0x30, 0x56, 0x70, 0xf3, 0x7b, 0x39, 0x98, 0x09, + 0x78, 0x49, 0xf1, 0x67, 0xb0, 0xc1, 0x7d, 0x98, 0x6c, 0x6b, 0x2b, 0xe4, 0xfb, 0x5c, 0xbe, 0xf2, + 0x4a, 0x4a, 0x5d, 0x4e, 0xda, 0xa4, 0xda, 0x82, 0x14, 0x33, 0xa9, 0x8f, 0xe2, 0x88, 0x18, 0xd4, + 0x05, 0xf0, 0x0e, 0xec, 0x86, 0x14, 0x5a, 0xe0, 0x42, 0x5f, 0xce, 0x28, 0xb4, 0x1e, 0x30, 0xa8, + 0x21, 0x29, 0x12, 0xc2, 0x31, 0xac, 0x09, 0x30, 0xff, 0xde, 0x80, 0xf9, 0x04, 0x3a, 0xf4, 0x6a, + 0xec, 0x3c, 0x9f, 0x1e, 0x38, 0x4f, 0x34, 0x40, 0x16, 0x9e, 0xe6, 0x0b, 0x30, 0xe1, 0xd2, 0x7d, + 0xcb, 0xb3, 0x1c, 0x5b, 0xee, 0xf0, 0xac, 0xa4, 0x9f, 0xc0, 0x72, 0x1c, 0x07, 0x18, 0xe8, 0x79, + 0x28, 0xa9, 0xcf, 0x6c, 0x9b, 0xf3, 0x4c, 0x9d, 0xd9, 0xc1, 0x29, 0x54, 0x0f, 0x87, 0x70, 0xf3, + 0x9f, 0xf4, 0xd3, 0xbf, 0xdb, 0x6b, 0x12, 0x9f, 0x32, 0xe5, 0x21, 0xbd, 0xde, 0x5b, 0xa1, 0x32, + 0x07, 0xca, 0x53, 0x15, 0xc3, 0x58, 0xc1, 0xd1, 0x75, 0x98, 0x94, 0x1f, 0x85, 0xae, 0x88, 0xd9, + 0x05, 0x07, 0x53, 0xd5, 0x60, 0x38, 0x82, 0x89, 0xee, 0x43, 0xd1, 0x71, 0xad, 0x96, 0x65, 0xcb, + 0x43, 0xb9, 0x9a, 0xee, 0x50, 0x6e, 0xb9, 0xd4, 0x6a, 0xb5, 0xfd, 0xb7, 0x39, 0x69, 0x0d, 0xd8, + 0x16, 0x8a, 0xcf, 0x58, 0xb2, 0x43, 0x7d, 0x98, 0xf2, 0x9c, 0xbe, 0xdb, 0xa0, 0x62, 0x35, 0x62, + 0x0b, 0xca, 0x57, 0xae, 0x67, 0x39, 0xf4, 0xba, 0xc6, 0xa0, 0x76, 0x5e, 0xae, 0x66, 0x4a, 0x1f, + 0xf5, 0x70, 0x54, 0x8a, 0xf9, 0x3d, 0x03, 0x40, 0x10, 0xdf, 0xa1, 0x9d, 0x2e, 0x6a, 0x40, 0xd1, + 0xea, 0x92, 0x16, 0x55, 0x9e, 0x22, 0x93, 0xa2, 0x33, 0x0e, 0x1b, 0x8c, 0x5a, 0xce, 0x20, 0xf0, + 0x0f, 0x7c, 0xd0, 0xc3, 0x92, 0xb5, 0xb6, 0x87, 0xb9, 0x53, 0xdd, 0x43, 0xf3, 0xbf, 0x03, 0xc3, + 0x14, 0x9b, 0x0a, 0xb3, 0x93, 0x5c, 0xb8, 0xd4, 0x8c, 0xc0, 0x4e, 0x72, 0x1c, 0x2c, 0x60, 0x67, + 0x77, 0xb6, 0x17, 0x85, 0xf7, 0x10, 0x5a, 0x56, 0x96, 0xb2, 0xf3, 0x6f, 0xd0, 0x03, 0xe1, 0x4a, + 0x5e, 0x51, 0xae, 0x44, 0x18, 0xf1, 0x5f, 0x8a, 0xf8, 0x76, 0x66, 0x33, 0xb5, 0x95, 0xf0, 0xb1, + 0xed, 0x83, 0x5e, 0xe0, 0xf3, 0xbf, 0x6f, 0xa8, 0x9b, 0xf0, 0x46, 0xdf, 0xf3, 0x9d, 0xae, 0xf5, + 0x35, 0x8a, 0xda, 0xb1, 0x53, 0xfc, 0xb5, 0x2c, 0xa7, 0x18, 0xb0, 0xf9, 0x99, 0x1e, 0xe5, 0xbf, + 0x18, 0xb0, 0x34, 0x7c, 0x3e, 0x59, 0xcf, 0x33, 0x7f, 0xba, 0xe7, 0xb9, 0x0a, 0xa5, 0xbe, 0x47, + 0xd7, 0xad, 0x16, 0xf5, 0x7c, 0xbe, 0xf0, 0x89, 0xd0, 0xcf, 0xdc, 0x55, 0x00, 0x1c, 0xe2, 0x98, + 0xdf, 0xcd, 0x03, 0x1a, 0xbc, 0xa2, 0xcc, 0x62, 0xb9, 0xb4, 0xe7, 0xdc, 0xc5, 0x9b, 0x71, 0x8b, + 0x85, 0xc5, 0x30, 0x56, 0x70, 0xb6, 0xe0, 0x46, 0x9b, 0xb8, 0x7e, 0x3c, 0xfe, 0x5b, 0x63, 0x83, + 0x58, 0xc0, 0xb4, 0x05, 0x17, 0x4f, 0x77, 0xc1, 0x5b, 0xb0, 0xd0, 0xe7, 0x53, 0xde, 0x26, 0x6e, + 0x8b, 0xfa, 0xca, 0x24, 0xf3, 0x7d, 0x9d, 0xa8, 0xfd, 0x82, 0x9c, 0xcc, 0xc2, 0xdd, 0x04, 0x1c, + 0x9c, 0x48, 0x89, 0x76, 0xa0, 0xb4, 0xa7, 0x0e, 0x56, 0x5e, 0xb7, 0x6b, 0x23, 0x69, 0xa9, 0x70, + 0x12, 0xc1, 0x57, 0x1c, 0xb2, 0x45, 0x6f, 0x41, 0xa1, 0x4d, 0x3b, 0xdd, 0xc5, 0x31, 0xce, 0xfe, + 0x57, 0xb2, 0x9a, 0xb2, 0xda, 0x04, 0x8b, 0x05, 0xd8, 0x27, 0xcc, 0xf9, 0x98, 0xbf, 0x0b, 0x62, + 0xbb, 0xb3, 0x9c, 0xdb, 0xc9, 0x11, 0xc6, 0x73, 0x30, 0xbe, 0x4f, 0xdd, 0x60, 0x3b, 0x35, 0x66, + 0xf7, 0xc4, 0x30, 0x56, 0x70, 0xf3, 0xdf, 0x0d, 0x58, 0xe0, 0x33, 0x58, 0xb7, 0xbc, 0x86, 0xb3, + 0x4f, 0xdd, 0x03, 0x4c, 0xbd, 0x7e, 0xe7, 0x94, 0x27, 0xb4, 0x0e, 0xb3, 0x1e, 0xed, 0xee, 0x53, + 0x77, 0xcd, 0xb1, 0x3d, 0xdf, 0x25, 0x96, 0xed, 0xcb, 0x99, 0x2d, 0x4a, 0xec, 0xd9, 0x7a, 0x0c, + 0x8e, 0x07, 0x28, 0xd0, 0xb3, 0x30, 0x21, 0xa7, 0xcd, 0xe2, 0x17, 0xe6, 0xcd, 0x27, 0x99, 0xe3, + 0x97, 0x6b, 0xf2, 0x70, 0x00, 0x35, 0x7f, 0x6c, 0xc0, 0x1c, 0x5f, 0x55, 0xbd, 0xbf, 0xe3, 0x35, + 0x5c, 0xab, 0xc7, 0xe2, 0xee, 0xc7, 0x71, 0x49, 0x37, 0x61, 0xba, 0xa9, 0x36, 0x7e, 0xd3, 0xea, + 0x5a, 0x3e, 0x57, 0xdc, 0xb1, 0xda, 0x05, 0xc9, 0x63, 0x7a, 0x3d, 0x02, 0xc5, 0x31, 0x6c, 0xf3, + 0xcf, 0xf3, 0x30, 0xaf, 0x50, 0x68, 0xb3, 0xea, 0xfa, 0xd6, 0x2e, 0x69, 0xf8, 0x1e, 0x6a, 0xc2, + 0x64, 0x33, 0x1c, 0xf6, 0xe5, 0x75, 0xf8, 0xe5, 0x8a, 0xc8, 0x31, 0x2b, 0x7a, 0x8e, 0x59, 0xe9, + 0xed, 0xb5, 0xd8, 0x80, 0x57, 0x61, 0xa9, 0x6c, 0x65, 0xff, 0x72, 0x65, 0xdb, 0xea, 0xd2, 0x30, + 0x72, 0xd1, 0xd8, 0xfb, 0x38, 0xc2, 0x15, 0xdd, 0x87, 0x7c, 0xcb, 0xf2, 0xa5, 0x47, 0x48, 0x19, + 0x56, 0xdc, 0xb6, 0xe2, 0xaa, 0x16, 0xba, 0xaf, 0xdb, 0x96, 0x8f, 0x19, 0x47, 0xb4, 0x13, 0x78, + 0x1b, 0x91, 0xe8, 0xdd, 0x48, 0xc7, 0x9b, 0x9b, 0xea, 0x38, 0xf7, 0x61, 0x7e, 0x66, 0x07, 0x8a, + 0xdc, 0xc4, 0xa9, 0xb0, 0x28, 0xa5, 0x8c, 0xa4, 0xcb, 0x12, 0xca, 0xe0, 0x50, 0x0f, 0x4b, 0xce, + 0xe6, 0xa7, 0x39, 0x98, 0x0d, 0xf7, 0x6f, 0xcd, 0xe9, 0x76, 0x2d, 0x1f, 0x2d, 0x41, 0xce, 0x6a, + 0x4a, 0x0d, 0x04, 0x49, 0x98, 0xdb, 0x58, 0xc7, 0x39, 0xab, 0x89, 0x9e, 0x81, 0xe2, 0x8e, 0x4b, + 0xec, 0x46, 0x5b, 0x6a, 0x5e, 0xc0, 0xb8, 0xc6, 0x47, 0xb1, 0x84, 0x32, 0xf7, 0xef, 0x93, 0x96, + 0x54, 0xb8, 0x60, 0xff, 0xb6, 0x49, 0x0b, 0xb3, 0x71, 0xa6, 0xe9, 0x5e, 0x7f, 0xe7, 0xb7, 0x68, + 0x43, 0x9c, 0xbc, 0xa6, 0xe9, 0x75, 0x31, 0x8c, 0x15, 0x9c, 0x49, 0x24, 0x7d, 0xbf, 0xed, 0xb8, + 0xdc, 0xa6, 0x69, 0x12, 0xab, 0x7c, 0x14, 0x4b, 0x28, 0x73, 0x50, 0x0d, 0x3e, 0x7f, 0x9f, 0xba, + 0xdc, 0x17, 0x68, 0x89, 0xd0, 0x9a, 0x02, 0xe0, 0x10, 0x07, 0xbd, 0x07, 0xe5, 0x86, 0x4b, 0x89, + 0xef, 0xb8, 0xeb, 0xc4, 0xa7, 0x8b, 0xe3, 0x99, 0x35, 0x70, 0x86, 0x65, 0xe3, 0x6b, 0x21, 0x0b, + 0xac, 0xf3, 0x33, 0x7f, 0x62, 0xc0, 0x62, 0xb8, 0xb5, 0xc2, 0x49, 0x07, 0x19, 0xa8, 0xdc, 0x1e, + 0x63, 0xc8, 0xf6, 0x3c, 0x03, 0xc5, 0x66, 0xe8, 0x69, 0xb5, 0x35, 0x4b, 0x37, 0x2b, 0xa1, 0xe8, + 0x0a, 0x40, 0xcb, 0xf2, 0xa5, 0x71, 0x90, 0x9b, 0x1d, 0xe4, 0x3d, 0xb7, 0x03, 0x08, 0xd6, 0xb0, + 0xd0, 0x7d, 0x28, 0xf1, 0x69, 0x8e, 0x78, 0xed, 0xb8, 0xeb, 0x59, 0x53, 0x0c, 0x70, 0xc8, 0xcb, + 0xfc, 0xa4, 0x00, 0xe3, 0xd2, 0xad, 0xa2, 0xdf, 0x84, 0x89, 0xae, 0xac, 0x64, 0xf0, 0x45, 0x32, + 0x57, 0x94, 0x4a, 0xc6, 0xdb, 0xfc, 0xd0, 0xdf, 0xa4, 0x3e, 0x09, 0x17, 0x12, 0x8e, 0xe1, 0x80, + 0x2b, 0x0b, 0x0e, 0x48, 0xc7, 0x22, 0x1e, 0x3f, 0x37, 0x2d, 0x38, 0xa8, 0xb2, 0x41, 0x2c, 0x60, + 0xe8, 0xcb, 0x41, 0x70, 0x50, 0x1a, 0x3d, 0x38, 0x08, 0x36, 0x3f, 0x16, 0x20, 0xbc, 0x03, 0xe3, + 0x42, 0x99, 0xd4, 0x05, 0x5d, 0x4d, 0x6d, 0x60, 0x84, 0x3e, 0x86, 0x4a, 0x2f, 0xbe, 0x7b, 0x58, + 0x31, 0x44, 0xf5, 0xc0, 0xbe, 0x14, 0x38, 0xeb, 0xe7, 0x33, 0xd8, 0x97, 0xa1, 0x06, 0xa5, 0x1e, + 0x18, 0x94, 0xb1, 0x2c, 0x4c, 0xb9, 0xc9, 0x18, 0x66, 0x41, 0xd8, 0x16, 0xcb, 0x74, 0x79, 0x94, + 0xf8, 0x4b, 0xe6, 0xea, 0xd3, 0xd1, 0x1c, 0x5b, 0x65, 0xd3, 0xe6, 0x9f, 0xe6, 0x61, 0x4e, 0x62, + 0xae, 0x39, 0x9d, 0x0e, 0x6d, 0x70, 0x37, 0x29, 0xec, 0x53, 0x3e, 0xd1, 0x3e, 0x59, 0x30, 0x66, + 0xf9, 0xb4, 0xab, 0xb2, 0x80, 0x5a, 0xa6, 0xd9, 0x84, 0x32, 0x2a, 0x1b, 0x8c, 0x89, 0x28, 0xbc, + 0x05, 0xa7, 0x24, 0xb1, 0xb0, 0x90, 0x80, 0xfe, 0xd0, 0x80, 0xf9, 0x7d, 0xea, 0x5a, 0xbb, 0x56, + 0x83, 0x97, 0xcd, 0xee, 0x58, 0x9e, 0xef, 0xb8, 0x07, 0xd2, 0x23, 0xbc, 0x94, 0x4e, 0xf2, 0x3d, + 0x8d, 0xc1, 0x86, 0xbd, 0xeb, 0xd4, 0x9e, 0x92, 0xd2, 0xe6, 0xef, 0x0d, 0xb2, 0xc6, 0x49, 0xf2, + 0x96, 0x7a, 0x00, 0xe1, 0x6c, 0x13, 0xaa, 0x76, 0x9b, 0x7a, 0xd5, 0x2e, 0xf5, 0xc4, 0xd4, 0x62, + 0x95, 0xc9, 0xd2, 0xab, 0x7d, 0xdf, 0x31, 0xa0, 0x2c, 0xe1, 0x9b, 0x96, 0xe7, 0xa3, 0x77, 0x07, + 0x6e, 0x7b, 0x25, 0xdd, 0x6d, 0x67, 0xd4, 0xfc, 0xae, 0x07, 0x45, 0x12, 0x35, 0xa2, 0xdd, 0x74, + 0xac, 0x8e, 0x54, 0x6c, 0xec, 0xe7, 0x33, 0xcd, 0x5f, 0x4b, 0x93, 0x18, 0x0f, 0x79, 0x76, 0xa6, + 0x0b, 0x53, 0x91, 0x4b, 0x8e, 0xae, 0x41, 0x61, 0xcf, 0xb2, 0x95, 0xd7, 0xfb, 0x45, 0x15, 0x4f, + 0xbd, 0x61, 0xd9, 0xcd, 0x07, 0x87, 0x2b, 0x73, 0x11, 0x64, 0x36, 0x88, 0x39, 0xfa, 0xc9, 0x61, + 0xd8, 0x8d, 0x89, 0x6f, 0xff, 0xe5, 0xca, 0xb9, 0x0f, 0x7f, 0x70, 0xe9, 0x9c, 0xf9, 0xad, 0x3c, + 0xcc, 0xc6, 0x77, 0x35, 0x45, 0x15, 0x3c, 0xb4, 0x61, 0x13, 0x67, 0x6a, 0xc3, 0x72, 0x67, 0x67, + 0xc3, 0xf2, 0x67, 0x61, 0xc3, 0x0a, 0xa7, 0x66, 0xc3, 0xcc, 0x8f, 0x0d, 0x98, 0x0e, 0x4e, 0xe6, + 0xfd, 0x3e, 0xf3, 0xac, 0xe1, 0xae, 0x1b, 0xa7, 0xbf, 0xeb, 0x5f, 0x81, 0x71, 0x51, 0x91, 0xf2, + 0xe4, 0x9d, 0x7c, 0x31, 0x9b, 0xd1, 0x14, 0xb4, 0x5a, 0xcc, 0x24, 0x06, 0xb0, 0xe2, 0x6a, 0xbe, + 0x1b, 0xac, 0x47, 0x82, 0x44, 0x44, 0xe1, 0xb2, 0x78, 0xcb, 0xe0, 0xf9, 0xab, 0x16, 0x51, 0xb0, + 0x51, 0x2c, 0xa1, 0xc8, 0xe4, 0xe6, 0x5c, 0x05, 0xb6, 0x25, 0x91, 0x19, 0xf3, 0x12, 0xb8, 0xb0, + 0xca, 0x2d, 0xea, 0x99, 0x3f, 0xc9, 0x07, 0xb7, 0x47, 0xd6, 0x4c, 0x3f, 0x00, 0x10, 0x96, 0x89, + 0x36, 0x37, 0x6c, 0x69, 0x7a, 0xd7, 0x46, 0x70, 0x04, 0xd2, 0x1c, 0x32, 0x2e, 0xc2, 0xf6, 0x06, + 0x31, 0x40, 0x08, 0xc0, 0x9a, 0x28, 0xf4, 0x75, 0x28, 0x13, 0x59, 0xa7, 0xbf, 0xe5, 0xb8, 0x52, + 0x87, 0xd7, 0x47, 0x91, 0x5c, 0x0d, 0xd9, 0xc4, 0xfb, 0x2d, 0x21, 0x04, 0xeb, 0xd2, 0x96, 0x5c, + 0x98, 0x89, 0xcd, 0x37, 0xc1, 0xfa, 0x6e, 0x44, 0xad, 0xef, 0xd5, 0x2c, 0x6e, 0x41, 0x36, 0x1f, + 0xf4, 0x46, 0x8d, 0x07, 0xb3, 0xf1, 0x99, 0x9e, 0x9a, 0xd0, 0x48, 0xc7, 0x43, 0xb7, 0xf7, 0x3f, + 0xce, 0x41, 0x29, 0xb8, 0xf1, 0x59, 0xb2, 0x54, 0xe1, 0xa9, 0x73, 0x27, 0x64, 0x12, 0xf9, 0x34, + 0x99, 0x44, 0x61, 0x48, 0xa8, 0x7c, 0x1b, 0xe6, 0x44, 0x17, 0x61, 0xad, 0x4d, 0x1b, 0x7b, 0x62, + 0x8a, 0x32, 0x53, 0x78, 0x52, 0x22, 0xcf, 0xdd, 0x89, 0x23, 0xe0, 0x41, 0x1a, 0xbd, 0x0f, 0x53, + 0x3c, 0xbe, 0x0f, 0xa3, 0xa5, 0x24, 0xe3, 0xe9, 0x53, 0x92, 0x89, 0x93, 0x53, 0x12, 0xf3, 0xaf, + 0x0c, 0x40, 0x83, 0xf9, 0x67, 0x96, 0x1d, 0x27, 0x71, 0x83, 0x9e, 0xd2, 0xdd, 0xc7, 0x93, 0xc0, + 0xe1, 0x76, 0xdd, 0x9c, 0x87, 0xb9, 0xdb, 0x96, 0x7f, 0xa7, 0xbf, 0xb3, 0xd5, 0xef, 0x74, 0xa4, + 0xbd, 0x94, 0x83, 0x9b, 0x24, 0x32, 0xf8, 0x61, 0x11, 0xa6, 0x54, 0x16, 0x92, 0xb9, 0xfa, 0x77, + 0xff, 0x34, 0x62, 0xf7, 0xa4, 0xc2, 0x5e, 0x1d, 0xce, 0x5b, 0xb6, 0x47, 0x1b, 0x7d, 0x97, 0xd6, + 0xf7, 0xac, 0xde, 0xf6, 0x66, 0x9d, 0xdf, 0xb6, 0x03, 0x59, 0xd5, 0xbc, 0x28, 0x67, 0x74, 0x7e, + 0x23, 0x09, 0x09, 0x27, 0xd3, 0xb2, 0x4c, 0xcc, 0xa5, 0xa4, 0x59, 0xd3, 0x35, 0x3a, 0x30, 0x5e, + 0x38, 0x80, 0x60, 0x0d, 0x0b, 0x5d, 0x83, 0xf2, 0x07, 0xae, 0xe5, 0x53, 0x49, 0x24, 0x34, 0x3c, + 0x30, 0x3b, 0xf7, 0x43, 0x10, 0xd6, 0xf1, 0xd0, 0x3e, 0x94, 0x7b, 0xe1, 0x26, 0xcb, 0x4a, 0x5f, + 0x4a, 0x6b, 0xab, 0x9d, 0xce, 0x96, 0xeb, 0x74, 0x1d, 0x16, 0x47, 0xbe, 0x49, 0x1b, 0x6d, 0x62, + 0x5b, 0x5e, 0x57, 0x24, 0xb4, 0x1a, 0x0a, 0xd6, 0x05, 0xa1, 0x16, 0x14, 0x5d, 0x6a, 0x37, 0x65, + 0x76, 0x9d, 0x5a, 0xe4, 0x1b, 0x6c, 0x08, 0x73, 0xc2, 0x04, 0x91, 0xfc, 0x80, 0x04, 0x14, 0x4b, + 0xf6, 0xc8, 0xd6, 0xeb, 0xa4, 0x22, 0x2d, 0xaf, 0xa6, 0x94, 0xa5, 0xc8, 0x12, 0x24, 0x0d, 0xaf, + 0x99, 0xbe, 0x23, 0x6b, 0xa6, 0x22, 0xbe, 0x7a, 0x35, 0x9d, 0xa8, 0x3b, 0xb4, 0xd3, 0x4d, 0x90, + 0x12, 0xaf, 0x9f, 0x7e, 0x63, 0x0c, 0x66, 0x6e, 0x5b, 0x23, 0x97, 0xf9, 0x7c, 0x78, 0x42, 0x5c, + 0xbb, 0x3a, 0x95, 0x99, 0x49, 0xdd, 0x77, 0x89, 0x4f, 0x5b, 0xaa, 0xb3, 0x72, 0x43, 0x92, 0x3e, + 0xb1, 0x96, 0x8c, 0xf6, 0x60, 0x38, 0x08, 0x0f, 0x63, 0x9d, 0xda, 0x34, 0x27, 0x95, 0x18, 0x0b, + 0x99, 0x4b, 0x8c, 0xab, 0x50, 0x22, 0x9d, 0x8e, 0xf3, 0xc1, 0x36, 0x69, 0x79, 0xd2, 0x72, 0x07, + 0x56, 0xb2, 0xaa, 0x00, 0x38, 0xc4, 0x41, 0x15, 0x00, 0xab, 0x65, 0x3b, 0x2e, 0xe5, 0x14, 0x45, + 0x1e, 0xa7, 0x4c, 0xb3, 0x7b, 0xb6, 0x11, 0x8c, 0x62, 0x0d, 0x63, 0xf8, 0x85, 0x1f, 0x7f, 0x88, + 0x0b, 0xff, 0x22, 0x4c, 0x5a, 0x76, 0xa3, 0xd3, 0x6f, 0xd2, 0x2d, 0xe2, 0xb7, 0xbd, 0xc5, 0x09, + 0x3e, 0x8d, 0xd9, 0xa3, 0xc3, 0x95, 0xc9, 0x0d, 0x6d, 0x1c, 0x47, 0xb0, 0x18, 0x15, 0xfd, 0xaa, + 0x46, 0x55, 0x0a, 0xa9, 0x5e, 0xfb, 0xaa, 0x4e, 0xa5, 0x63, 0x25, 0x14, 0x61, 0x21, 0x53, 0x11, + 0xf6, 0x63, 0x03, 0x8a, 0xc2, 0x07, 0xa2, 0x6b, 0xb1, 0xee, 0xf6, 0xc5, 0x81, 0xee, 0x76, 0x39, + 0xe9, 0x91, 0x82, 0x09, 0x45, 0xcb, 0xf3, 0xfa, 0xd1, 0xb0, 0x70, 0x83, 0x8f, 0x60, 0x09, 0x41, + 0x16, 0x00, 0x51, 0xed, 0x69, 0x15, 0xf3, 0x5f, 0xcb, 0xda, 0xbf, 0x8f, 0xf5, 0xee, 0x03, 0x80, + 0x87, 0x35, 0xe6, 0xe6, 0xff, 0x19, 0xf0, 0x24, 0xbb, 0x64, 0xa2, 0xd6, 0x49, 0x7b, 0xcc, 0x6e, + 0xd8, 0x8d, 0x03, 0xe9, 0x64, 0xb8, 0x2d, 0xee, 0x39, 0x9e, 0xc5, 0xd3, 0x71, 0x23, 0x6e, 0x8b, + 0x15, 0x04, 0x6b, 0x58, 0x29, 0xea, 0xe9, 0x67, 0xd6, 0x29, 0x65, 0x51, 0x02, 0x5b, 0x07, 0x3b, + 0x6b, 0x79, 0xe1, 0xc2, 0x28, 0x41, 0x01, 0x70, 0x88, 0x63, 0xfe, 0x6d, 0x0e, 0x66, 0x1e, 0xb2, + 0xd9, 0x3b, 0x76, 0xba, 0x4b, 0xb8, 0x09, 0xd3, 0x3c, 0x5a, 0xf4, 0x6e, 0x59, 0x1d, 0xae, 0xb3, + 0x72, 0x1f, 0x03, 0x05, 0xbd, 0x17, 0x81, 0xe2, 0x18, 0xb6, 0x6a, 0x16, 0xe7, 0x4f, 0x6a, 0x16, + 0x17, 0x46, 0x68, 0x16, 0xff, 0x43, 0x0e, 0x2e, 0x24, 0x1b, 0x6b, 0xf4, 0x5e, 0xac, 0x67, 0x7c, + 0x2d, 0xbd, 0xe9, 0x4f, 0xd3, 0x28, 0x6e, 0x05, 0xb9, 0xaa, 0x08, 0xc5, 0xbe, 0x98, 0x9e, 0x7d, + 0xa2, 0x62, 0x0f, 0xad, 0xc1, 0x9d, 0x55, 0xd3, 0xd7, 0xfc, 0x3b, 0x03, 0x84, 0x06, 0x65, 0xf1, + 0x59, 0xd1, 0xa2, 0x74, 0x2e, 0x55, 0x51, 0xfa, 0x84, 0x76, 0x41, 0x58, 0x0f, 0x2f, 0x1c, 0x57, + 0x0f, 0x37, 0x7f, 0x64, 0xc0, 0x42, 0x52, 0x8f, 0x25, 0xcb, 0xf4, 0x5f, 0x80, 0x89, 0x5e, 0x87, + 0xf8, 0xbb, 0x8e, 0xdb, 0x8d, 0xbf, 0xe0, 0xd9, 0x92, 0xe3, 0x38, 0xc0, 0x40, 0x2e, 0xb3, 0x35, + 0xb2, 0x98, 0xa3, 0x8c, 0xde, 0xcd, 0xac, 0x21, 0x77, 0xb4, 0x39, 0xa0, 0xdb, 0x2a, 0xc5, 0x19, + 0x6b, 0x52, 0xcc, 0x8f, 0x0b, 0x30, 0xc7, 0x49, 0x46, 0x8d, 0x2a, 0x46, 0x39, 0xa1, 0x1e, 0x5c, + 0xe0, 0x6a, 0x3d, 0x18, 0x88, 0x88, 0x43, 0xbb, 0x2e, 0xe9, 0x2f, 0x6c, 0x24, 0x62, 0x3d, 0x18, + 0x0a, 0xc1, 0x43, 0xf8, 0xfe, 0xbc, 0x44, 0x17, 0xba, 0xbe, 0x8c, 0x9f, 0xa8, 0x2f, 0x43, 0x63, + 0x91, 0x89, 0x87, 0x88, 0x45, 0x06, 0xe3, 0x83, 0x52, 0xa6, 0xf8, 0xe0, 0x9f, 0x0d, 0xb8, 0xa0, + 0x85, 0xe9, 0x3f, 0xc7, 0x8f, 0x4e, 0x0e, 0x0d, 0xb8, 0x78, 0x6c, 0xc2, 0x81, 0x9a, 0x31, 0x9b, + 0xff, 0x6a, 0xe6, 0x2c, 0xe6, 0x67, 0xfa, 0x46, 0xe8, 0xbf, 0x0c, 0x58, 0x38, 0x8d, 0xd7, 0x41, + 0xa7, 0x1c, 0xc3, 0x5c, 0x82, 0x42, 0x2f, 0x74, 0xfb, 0x41, 0xf8, 0xc4, 0x9d, 0x3d, 0x87, 0x44, + 0x8f, 0x32, 0x9f, 0xe2, 0x28, 0xff, 0xd3, 0x80, 0xa7, 0x8e, 0xc9, 0xe7, 0xb4, 0x16, 0xbc, 0x91, + 0xa5, 0x3d, 0xfe, 0x78, 0x3c, 0xf5, 0xfa, 0xb3, 0x1c, 0x8c, 0x6f, 0xb9, 0x0e, 0x6f, 0x70, 0x9f, + 0x7d, 0xaf, 0xf4, 0x6d, 0x28, 0x78, 0x3d, 0xda, 0x90, 0x8b, 0xb8, 0x9c, 0xb2, 0x54, 0x20, 0xa6, + 0x57, 0xef, 0xd1, 0x86, 0xc8, 0x6a, 0xd9, 0x27, 0xcc, 0x19, 0x69, 0x4d, 0xbf, 0x4c, 0x17, 0x5e, + 0xb1, 0x3c, 0xbe, 0xe9, 0xf7, 0x1d, 0x03, 0xca, 0x12, 0xf3, 0xb1, 0xed, 0x2e, 0xc9, 0xf9, 0x0d, + 0xe9, 0x2e, 0xfd, 0x51, 0xb8, 0x02, 0xb6, 0x69, 0xe8, 0x77, 0x60, 0xae, 0xa7, 0x14, 0x78, 0xcb, + 0xe9, 0x58, 0x0d, 0x2b, 0x6b, 0xc8, 0xb9, 0x15, 0x21, 0x3f, 0x08, 0x4b, 0x9b, 0x5b, 0x71, 0xbe, + 0x78, 0x50, 0x94, 0xf9, 0x7d, 0x03, 0xa6, 0x22, 0x7b, 0x8f, 0x1a, 0x00, 0x0d, 0xc7, 0x6e, 0x5a, + 0x7e, 0xf0, 0xf2, 0xb8, 0x7c, 0x65, 0x35, 0xdd, 0xae, 0xae, 0x29, 0xba, 0x50, 0xe9, 0x82, 0x21, + 0x0f, 0x6b, 0x6c, 0xd1, 0x55, 0xf5, 0x50, 0x3f, 0x9a, 0x6a, 0x8a, 0x87, 0xfa, 0x0f, 0x0e, 0x57, + 0x26, 0xe5, 0x9c, 0xf4, 0x87, 0xfb, 0x59, 0x9e, 0xc3, 0xff, 0x75, 0x0e, 0x4a, 0xc1, 0xfa, 0x1f, + 0xc1, 0x35, 0xba, 0x1b, 0xb9, 0x46, 0x57, 0x33, 0x9e, 0x1c, 0xbf, 0x48, 0x81, 0x65, 0xd4, 0x2e, + 0xd3, 0x7b, 0xb1, 0xcb, 0x94, 0x55, 0x25, 0x4e, 0xb8, 0x4e, 0xdf, 0x15, 0x87, 0x2f, 0x70, 0x1f, + 0xc1, 0x85, 0xda, 0x8e, 0x5e, 0xa8, 0xd5, 0x8c, 0xab, 0x19, 0x72, 0xa5, 0x7e, 0x98, 0x83, 0xf9, + 0x41, 0x27, 0x70, 0x76, 0xa9, 0x0f, 0xf2, 0x60, 0xba, 0xa5, 0x97, 0xae, 0xd5, 0x85, 0xbd, 0x9a, + 0xba, 0x41, 0x1a, 0xd2, 0x86, 0x81, 0x58, 0x64, 0xd8, 0xc3, 0x31, 0x11, 0xe8, 0xeb, 0x30, 0x4b, + 0xa2, 0x2f, 0xfc, 0xd5, 0x36, 0x66, 0x2d, 0xa4, 0x48, 0xc1, 0x41, 0xa4, 0x1c, 0x03, 0x78, 0x78, + 0x40, 0x90, 0xf9, 0x4d, 0x03, 0x66, 0x62, 0x76, 0x86, 0x45, 0x15, 0xbc, 0xe9, 0x17, 0x8f, 0x2a, + 0x64, 0x8b, 0x88, 0xc3, 0xd0, 0x16, 0x2c, 0x90, 0xbe, 0xef, 0x04, 0xb4, 0xaf, 0xd9, 0x64, 0xa7, + 0x43, 0x9b, 0x32, 0x60, 0x0b, 0x5e, 0xca, 0x56, 0x13, 0x70, 0x70, 0x22, 0xa5, 0xf9, 0xaf, 0x39, + 0x40, 0xc1, 0x60, 0x96, 0x66, 0xf9, 0x7b, 0x30, 0xbe, 0x2b, 0x8e, 0xf6, 0xe1, 0x5e, 0x3b, 0xd4, + 0xca, 0xfa, 0x83, 0x0f, 0xc5, 0x13, 0xfd, 0xc6, 0xe9, 0x5c, 0x55, 0x18, 0xbc, 0xa6, 0xe8, 0x1d, + 0x80, 0x5d, 0xcb, 0xb6, 0xbc, 0xf6, 0x88, 0xef, 0xb2, 0x78, 0x8a, 0x72, 0x2b, 0xe0, 0x80, 0x35, + 0x6e, 0xe6, 0x57, 0x34, 0x0b, 0xc0, 0x1d, 0x52, 0xaa, 0x63, 0x7d, 0x2e, 0xba, 0x97, 0xa5, 0xc1, + 0x87, 0x30, 0x0a, 0x6e, 0xfe, 0xcd, 0x98, 0xa6, 0x3a, 0xd2, 0xc5, 0xbc, 0x0e, 0xa8, 0x43, 0x3c, + 0xff, 0x0e, 0xb1, 0x9b, 0xec, 0xa0, 0xe9, 0xae, 0x4b, 0x3d, 0xd5, 0xe4, 0x58, 0x92, 0x9c, 0xd0, + 0xe6, 0x00, 0x06, 0x4e, 0xa0, 0x42, 0xd7, 0xa2, 0x9e, 0x64, 0x25, 0xee, 0x49, 0xa6, 0x43, 0xbd, + 0x1d, 0xcd, 0x97, 0xa0, 0xf7, 0x35, 0x9b, 0x98, 0xcf, 0xd2, 0xbf, 0x8e, 0x2d, 0xbb, 0xa2, 0x7e, + 0xc0, 0x27, 0x9a, 0xc8, 0x81, 0xa1, 0x54, 0xc3, 0x9a, 0xa1, 0xd4, 0x74, 0x75, 0xec, 0x0c, 0x74, + 0xf5, 0xb7, 0x61, 0x6e, 0x37, 0xfe, 0xac, 0x49, 0x76, 0x53, 0xbe, 0x30, 0xe2, 0xab, 0xa8, 0xda, + 0xf9, 0xa3, 0xf0, 0x2d, 0x4c, 0x38, 0x8c, 0x07, 0x05, 0xc5, 0xd4, 0xb9, 0x78, 0x9a, 0xea, 0xbc, + 0xf4, 0x0a, 0x4c, 0x45, 0x76, 0x39, 0xd3, 0x2f, 0x15, 0xff, 0xc3, 0x80, 0x8b, 0xc7, 0x76, 0xc1, + 0x58, 0x70, 0x2b, 0xb6, 0x47, 0x3a, 0xc7, 0x2f, 0xa4, 0xb6, 0xf8, 0xd1, 0x9e, 0xa8, 0xb8, 0xe6, + 0x62, 0x18, 0x4b, 0x96, 0x92, 0x79, 0x87, 0xec, 0x48, 0xfb, 0x94, 0x9e, 0x79, 0xb4, 0xb7, 0x1a, + 0x30, 0xdf, 0x24, 0x82, 0x79, 0x87, 0xec, 0x98, 0xdf, 0xce, 0xc1, 0x2c, 0x73, 0x27, 0x91, 0xba, + 0xd0, 0x96, 0x7a, 0x03, 0x9d, 0xc1, 0x60, 0xc5, 0x3a, 0x56, 0xb5, 0xf1, 0xc8, 0xe3, 0xe7, 0x2f, + 0xa9, 0x54, 0x33, 0xd3, 0x12, 0x06, 0x2a, 0x56, 0xb5, 0xd2, 0x40, 0x7e, 0xfa, 0x25, 0xf5, 0x8b, + 0x8f, 0x7c, 0x16, 0xce, 0x03, 0x0f, 0xe9, 0x05, 0x67, 0xfd, 0x67, 0x22, 0xe6, 0xb7, 0x72, 0x20, + 0xac, 0xdb, 0x23, 0x88, 0x13, 0x7f, 0x3d, 0x12, 0x27, 0xa6, 0x0c, 0x80, 0xf8, 0xe4, 0x86, 0xc6, + 0x88, 0x71, 0xc7, 0x73, 0x39, 0x0b, 0xd3, 0xe3, 0xe3, 0xc3, 0x7f, 0x34, 0xa0, 0xc4, 0xf1, 0x1e, + 0x41, 0x6c, 0xb8, 0x15, 0x8d, 0x0d, 0x9f, 0xcf, 0xb0, 0x8a, 0x21, 0x71, 0xe1, 0x5f, 0xe4, 0xe5, + 0xec, 0x03, 0xbf, 0xd6, 0x26, 0x6e, 0x53, 0xba, 0x99, 0xd0, 0xaf, 0xb1, 0x41, 0x2c, 0x60, 0xe8, + 0x6b, 0x30, 0xeb, 0x8a, 0x4b, 0x44, 0x9b, 0xb7, 0x02, 0x03, 0x9c, 0xcf, 0xfc, 0x0c, 0x4b, 0xdd, + 0xc4, 0x20, 0xc6, 0xc2, 0x31, 0xae, 0x78, 0x40, 0x0e, 0xfa, 0x03, 0x03, 0xe6, 0x7b, 0x83, 0x61, + 0xac, 0x54, 0x95, 0x97, 0x33, 0xba, 0x9c, 0x90, 0x41, 0xed, 0x89, 0xa3, 0xc3, 0x95, 0xa4, 0x00, + 0x19, 0x27, 0x89, 0x43, 0x6d, 0x98, 0xd4, 0x5f, 0x92, 0x4a, 0xa5, 0xba, 0x92, 0xfd, 0xc9, 0xaa, + 0x68, 0x5d, 0xea, 0x23, 0x38, 0xc2, 0xd9, 0xfc, 0xdf, 0x31, 0x28, 0x6b, 0x5a, 0x38, 0x24, 0x2a, + 0x28, 0x8f, 0x14, 0x15, 0x5c, 0x8e, 0x46, 0x05, 0x4f, 0xc5, 0xa3, 0x02, 0xe0, 0x82, 0x23, 0x11, + 0x81, 0x07, 0xd3, 0xd2, 0x57, 0xa9, 0xd7, 0xba, 0xe2, 0x19, 0xe1, 0xc8, 0x1e, 0x11, 0xb1, 0xa8, + 0xfe, 0x56, 0x84, 0x25, 0x8e, 0x89, 0x40, 0x37, 0x03, 0xa1, 0xf5, 0x7e, 0xb7, 0x4b, 0xdc, 0x83, + 0xc5, 0xc9, 0x68, 0x77, 0xec, 0x56, 0x04, 0x8a, 0x63, 0xd8, 0x68, 0x0b, 0x8a, 0xe2, 0xb9, 0x92, + 0x7c, 0xa1, 0xf0, 0x42, 0xda, 0x3e, 0x12, 0xa3, 0x11, 0x8e, 0x42, 0x7c, 0xc6, 0x92, 0x8f, 0x1e, + 0x18, 0x95, 0x4e, 0x08, 0x8c, 0x5e, 0x07, 0xe4, 0xec, 0x78, 0xd4, 0xdd, 0xa7, 0xcd, 0xdb, 0xe2, + 0x8f, 0x1d, 0x98, 0xc2, 0x30, 0x87, 0x9e, 0x0f, 0x0f, 0xec, 0xed, 0x01, 0x0c, 0x9c, 0x40, 0xc5, + 0x6e, 0x5e, 0xa3, 0xef, 0xba, 0xd4, 0x0e, 0xdd, 0xae, 0x8c, 0x48, 0xae, 0x67, 0xd4, 0xfc, 0x30, + 0xf8, 0x59, 0x60, 0x37, 0x6f, 0x2d, 0xc6, 0x15, 0x0f, 0xc8, 0x41, 0xef, 0xc3, 0x14, 0x53, 0xa1, + 0x50, 0x30, 0x3c, 0xa4, 0xe0, 0xb9, 0xa3, 0xc3, 0x95, 0xa9, 0x4d, 0x9d, 0x25, 0x8e, 0x4a, 0x30, + 0xff, 0x3f, 0x07, 0x91, 0xab, 0x81, 0xbe, 0x69, 0xc0, 0x1c, 0x89, 0xfd, 0x2b, 0x81, 0xca, 0x2b, + 0xbf, 0x98, 0xed, 0xaf, 0x22, 0x06, 0xfe, 0xd4, 0x20, 0x2c, 0x09, 0xc5, 0x51, 0x3c, 0x3c, 0x28, + 0x94, 0x1b, 0x22, 0x32, 0xf8, 0xb7, 0x13, 0xd9, 0x0c, 0x51, 0xc2, 0xff, 0x56, 0x08, 0x43, 0x94, + 0x00, 0xc0, 0x49, 0xe2, 0xd0, 0x97, 0xa1, 0x40, 0xdc, 0x96, 0xaa, 0x40, 0x65, 0x17, 0xab, 0xfe, + 0x4d, 0x24, 0x74, 0x9a, 0x55, 0xb7, 0xe5, 0x61, 0xce, 0xd4, 0xfc, 0x41, 0x1e, 0x66, 0xe3, 0xef, + 0xeb, 0xe5, 0x93, 0xc4, 0x42, 0xe2, 0x93, 0xc4, 0xcf, 0xc1, 0x18, 0x69, 0xf8, 0xc1, 0xb3, 0xbe, + 0xf0, 0x37, 0x25, 0x6c, 0x10, 0x0b, 0x18, 0xba, 0x0f, 0x25, 0xcf, 0x27, 0xae, 0xcf, 0xc2, 0x54, + 0x19, 0xb8, 0x67, 0xfe, 0xfd, 0x4c, 0x5d, 0x31, 0xc0, 0x21, 0x2f, 0x74, 0x3d, 0x6a, 0xce, 0xcc, + 0xb8, 0x39, 0x9b, 0xd3, 0xd7, 0x32, 0x6a, 0x9e, 0xd3, 0x85, 0xb2, 0x76, 0x0e, 0xd2, 0xf0, 0xdf, + 0xc8, 0xbc, 0xef, 0xa1, 0xda, 0xcd, 0x88, 0xbf, 0x24, 0x09, 0x21, 0x3a, 0xff, 0x30, 0x0d, 0xe0, + 0xbb, 0xf5, 0x50, 0x69, 0x00, 0xdf, 0x2e, 0x8d, 0x9b, 0x39, 0x03, 0x53, 0x91, 0x67, 0xb2, 0xbc, + 0x1e, 0x78, 0x9f, 0xb8, 0xb4, 0xed, 0xf4, 0x3d, 0xfa, 0xb8, 0xd6, 0x03, 0x83, 0x09, 0x9e, 0x76, + 0x3d, 0x30, 0x64, 0x7c, 0x72, 0x3d, 0x30, 0xc0, 0x7d, 0x6c, 0xeb, 0x81, 0xc1, 0x0c, 0x87, 0xc4, + 0x7d, 0xff, 0x93, 0xd3, 0x56, 0x11, 0x8d, 0xfd, 0x72, 0xc7, 0xc4, 0x7e, 0xef, 0xc2, 0x84, 0x65, + 0xfb, 0xd4, 0xdd, 0x27, 0x1d, 0x59, 0x63, 0x49, 0xb9, 0xd4, 0xf5, 0xbe, 0x2b, 0x03, 0x1e, 0xb5, + 0xd4, 0x0d, 0xc9, 0x07, 0x07, 0x1c, 0x51, 0x07, 0xce, 0xab, 0x4c, 0xd8, 0xa5, 0x24, 0x2c, 0xa3, + 0xc9, 0x16, 0xf9, 0x4b, 0xaa, 0xb9, 0x7b, 0x2b, 0x09, 0xe9, 0xc1, 0x30, 0x00, 0x4e, 0x66, 0x8a, + 0x3c, 0x98, 0xf2, 0xb4, 0xa4, 0x47, 0x39, 0x92, 0x94, 0x55, 0x84, 0x78, 0x9e, 0xa8, 0xfd, 0x77, + 0x86, 0xce, 0x14, 0x47, 0x65, 0x98, 0xff, 0x96, 0x87, 0x99, 0x98, 0xa6, 0xc5, 0x9a, 0x09, 0xa5, + 0xb3, 0x69, 0x26, 0x24, 0x07, 0x8e, 0xc5, 0x91, 0x02, 0xc7, 0xe4, 0x98, 0xa6, 0x30, 0x52, 0x4c, + 0xf3, 0x8a, 0x88, 0x2b, 0xe4, 0xc9, 0x6d, 0xac, 0xcb, 0x77, 0xde, 0xc1, 0x6e, 0x6e, 0xea, 0x40, + 0x1c, 0xc5, 0xe5, 0x5e, 0xb8, 0x39, 0xf8, 0xeb, 0x68, 0x19, 0x14, 0xbd, 0x9c, 0xf5, 0x1d, 0x49, + 0xc0, 0x40, 0x78, 0xe1, 0x04, 0x00, 0x4e, 0x12, 0x57, 0x7b, 0xfd, 0xa3, 0xcf, 0x96, 0xcf, 0x7d, + 0xf2, 0xd9, 0xf2, 0xb9, 0x4f, 0x3f, 0x5b, 0x3e, 0xf7, 0xe1, 0xd1, 0xb2, 0xf1, 0xd1, 0xd1, 0xb2, + 0xf1, 0xc9, 0xd1, 0xb2, 0xf1, 0xe9, 0xd1, 0xb2, 0xf1, 0xc3, 0xa3, 0x65, 0xe3, 0x4f, 0x7e, 0xb4, + 0x7c, 0xee, 0x9d, 0xa7, 0xd3, 0xfc, 0xe3, 0xd9, 0x4f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xc3, 0xf9, + 0xea, 0xc9, 0x18, 0x4d, 0x00, 0x00, } func (m *AnalysisRunArgument) Marshal() (dAtA []byte, err error) { @@ -4852,6 +4853,20 @@ func (m *ProjectStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.Conditions) > 0 { + for iNdEx := len(m.Conditions) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Conditions[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } i -= len(m.Message) copy(dAtA[i:], m.Message) i = encodeVarintGenerated(dAtA, i, uint64(len(m.Message))) @@ -6988,6 +7003,12 @@ func (m *ProjectStatus) Size() (n int) { n += 1 + l + sovGenerated(uint64(l)) l = len(m.Message) n += 1 + l + sovGenerated(uint64(l)) + if len(m.Conditions) > 0 { + for _, e := range m.Conditions { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } return n } @@ -8164,9 +8185,15 @@ func (this *ProjectStatus) String() string { if this == nil { return "nil" } + repeatedStringForConditions := "[]Condition{" + for _, f := range this.Conditions { + repeatedStringForConditions += fmt.Sprintf("%v", f) + "," + } + repeatedStringForConditions += "}" s := strings.Join([]string{`&ProjectStatus{`, `Phase:` + fmt.Sprintf("%v", this.Phase) + `,`, `Message:` + fmt.Sprintf("%v", this.Message) + `,`, + `Conditions:` + repeatedStringForConditions + `,`, `}`, }, "") return s @@ -16796,6 +16823,40 @@ func (m *ProjectStatus) Unmarshal(dAtA []byte) error { } m.Message = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Conditions", 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.Conditions = append(m.Conditions, v1.Condition{}) + if err := m.Conditions[len(m.Conditions)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) diff --git a/api/v1alpha1/generated.proto b/api/v1alpha1/generated.proto index 93518c969..f1c53954f 100644 --- a/api/v1alpha1/generated.proto +++ b/api/v1alpha1/generated.proto @@ -1194,12 +1194,24 @@ message ProjectSpec { // ProjectStatus describes a Project's current status. message ProjectStatus { + // Conditions contains the last observations of the Project's current + // state. + // +patchMergeKey=type + // +patchStrategy=merge + // +listType=map + // +listMapKey=type + repeated k8s.io.apimachinery.pkg.apis.meta.v1.Condition conditions = 3; + // Phase describes the Project's current phase. + // + // Deprecated: Use the Conditions field instead. optional string phase = 1; // Message is a display message about the Project, including any errors // preventing the Project from being reconciled. i.e. If the Phase field has a // value of CreationFailed, this field can be expected to explain why. + // + // Deprecated: Use the Conditions field instead. optional string message = 2; } diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 5cd363978..754e69718 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1065,7 +1065,7 @@ func (in *Project) DeepCopyInto(out *Project) { *out = new(ProjectSpec) (*in).DeepCopyInto(*out) } - out.Status = in.Status + in.Status.DeepCopyInto(&out.Status) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Project. @@ -1141,6 +1141,13 @@ func (in *ProjectSpec) DeepCopy() *ProjectSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProjectStatus) DeepCopyInto(out *ProjectStatus) { *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProjectStatus. diff --git a/charts/kargo/resources/crds/kargo.akuity.io_projects.yaml b/charts/kargo/resources/crds/kargo.akuity.io_projects.yaml index 67c1ee0e9..62a713626 100644 --- a/charts/kargo/resources/crds/kargo.akuity.io_projects.yaml +++ b/charts/kargo/resources/crds/kargo.akuity.io_projects.yaml @@ -15,8 +15,11 @@ spec: scope: Cluster versions: - additionalPrinterColumns: - - jsonPath: .status.phase - name: Phase + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status type: string - jsonPath: .metadata.creationTimestamp name: Age @@ -79,14 +82,96 @@ spec: status: description: Status describes the Project's current status. properties: + conditions: + description: |- + Conditions contains the last observations of the Project's current + state. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map message: description: |- Message is a display message about the Project, including any errors preventing the Project from being reconciled. i.e. If the Phase field has a value of CreationFailed, this field can be expected to explain why. + + + Deprecated: Use the Conditions field instead. type: string phase: - description: Phase describes the Project's current phase. + description: |- + Phase describes the Project's current phase. + + + Deprecated: Use the Conditions field instead. type: string type: object type: object diff --git a/ui/src/gen/schema/projects.kargo.akuity.io_v1alpha1.json b/ui/src/gen/schema/projects.kargo.akuity.io_v1alpha1.json index 1db157fe1..5ecbb78d2 100644 --- a/ui/src/gen/schema/projects.kargo.akuity.io_v1alpha1.json +++ b/ui/src/gen/schema/projects.kargo.akuity.io_v1alpha1.json @@ -44,12 +44,72 @@ "status": { "description": "Status describes the Project's current status.", "properties": { + "conditions": { + "description": "Conditions contains the last observations of the Project's current\nstate.", + "items": { + "description": "Condition contains details for one aspect of the current state of this API Resource.\n---\nThis struct is intended for direct use as an array at the field path .status.conditions. For example,\n\n\n\ttype FooStatus struct{\n\t // Represents the observations of a foo's current state.\n\t // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t // other fields\n\t}", + "properties": { + "lastTransitionTime": { + "description": "lastTransitionTime is the last time the condition transitioned from one status to another.\nThis should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.", + "format": "date-time", + "type": "string" + }, + "message": { + "description": "message is a human readable message indicating details about the transition.\nThis may be an empty string.", + "maxLength": 32768, + "type": "string" + }, + "observedGeneration": { + "description": "observedGeneration represents the .metadata.generation that the condition was set based upon.\nFor instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date\nwith respect to the current state of the instance.", + "format": "int64", + "maximum": 9223372036854776000, + "minimum": 0, + "type": "integer" + }, + "reason": { + "description": "reason contains a programmatic identifier indicating the reason for the condition's last transition.\nProducers of specific condition types may define expected values and meanings for this field,\nand whether the values are considered a guaranteed API.\nThe value should be a CamelCase string.\nThis field may not be empty.", + "maxLength": 1024, + "minLength": 1, + "pattern": "^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$", + "type": "string" + }, + "status": { + "description": "status of the condition, one of True, False, Unknown.", + "enum": [ + "True", + "False", + "Unknown" + ], + "type": "string" + }, + "type": { + "description": "type of condition in CamelCase or in foo.example.com/CamelCase.\n---\nMany .condition.type values are consistent across resources like Available, but because arbitrary conditions can be\nuseful (see .node.status.conditions), the ability to deconflict is important.\nThe regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)", + "maxLength": 316, + "pattern": "^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$", + "type": "string" + } + }, + "required": [ + "lastTransitionTime", + "message", + "reason", + "status", + "type" + ], + "type": "object" + }, + "type": "array", + "x-kubernetes-list-map-keys": [ + "type" + ], + "x-kubernetes-list-type": "map" + }, "message": { - "description": "Message is a display message about the Project, including any errors\npreventing the Project from being reconciled. i.e. If the Phase field has a\nvalue of CreationFailed, this field can be expected to explain why.", + "description": "Message is a display message about the Project, including any errors\npreventing the Project from being reconciled. i.e. If the Phase field has a\nvalue of CreationFailed, this field can be expected to explain why.\n\n\nDeprecated: Use the Conditions field instead.", "type": "string" }, "phase": { - "description": "Phase describes the Project's current phase.", + "description": "Phase describes the Project's current phase.\n\n\nDeprecated: Use the Conditions field instead.", "type": "string" } }, diff --git a/ui/src/gen/v1alpha1/generated_pb.ts b/ui/src/gen/v1alpha1/generated_pb.ts index 45d632e81..0e92adcfc 100644 --- a/ui/src/gen/v1alpha1/generated_pb.ts +++ b/ui/src/gen/v1alpha1/generated_pb.ts @@ -3448,9 +3448,23 @@ export class ProjectSpec extends Message { * @generated from message github.com.akuity.kargo.api.v1alpha1.ProjectStatus */ export class ProjectStatus extends Message { + /** + * Conditions contains the last observations of the Project's current + * state. + * +patchMergeKey=type + * +patchStrategy=merge + * +listType=map + * +listMapKey=type + * + * @generated from field: repeated k8s.io.apimachinery.pkg.apis.meta.v1.Condition conditions = 3; + */ + conditions: Condition[] = []; + /** * Phase describes the Project's current phase. * + * Deprecated: Use the Conditions field instead. + * * @generated from field: optional string phase = 1; */ phase?: string; @@ -3460,6 +3474,8 @@ export class ProjectStatus extends Message { * preventing the Project from being reconciled. i.e. If the Phase field has a * value of CreationFailed, this field can be expected to explain why. * + * Deprecated: Use the Conditions field instead. + * * @generated from field: optional string message = 2; */ message?: string; @@ -3472,6 +3488,7 @@ export class ProjectStatus extends Message { static readonly runtime: typeof proto2 = proto2; static readonly typeName = "github.com.akuity.kargo.api.v1alpha1.ProjectStatus"; static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 3, name: "conditions", kind: "message", T: Condition, repeated: true }, { no: 1, name: "phase", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, { no: 2, name: "message", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, ]); From fa9005de0099e82f73b547998ba212dd76ebaeda Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Mon, 29 Jul 2024 14:54:16 +0200 Subject: [PATCH 3/4] feat(controller): implement Project conditions Signed-off-by: Hidde Beydals --- api/v1alpha1/conditions.go | 16 + .../management/projects/projects.go | 162 ++++++- .../management/projects/projects_test.go | 454 ++++++++++++++---- 3 files changed, 534 insertions(+), 98 deletions(-) diff --git a/api/v1alpha1/conditions.go b/api/v1alpha1/conditions.go index 8108c293c..16df5d971 100644 --- a/api/v1alpha1/conditions.go +++ b/api/v1alpha1/conditions.go @@ -36,6 +36,22 @@ const ( // reconciled. ConditionTypeReconciling = "Reconciling" + // ConditionTypeStalled denotes that the reconciliation of the resource + // has stalled. + // + // This condition is used to indicate that the controller has stopped + // making progress on the resource, and further changes to the resource + // are not expected until the reason for the stall is resolved, which + // MAY require manual intervention. The condition is removed when the + // controller has resumed making progress on the resource. + // + // This is a "normal-false" or "negative polarity" condition, meaning + // that the presence of the condition with a status of "True" indicates + // that the resource has stalled, and the absence of the condition or + // a status of "False" indicates that the resource is operating as + // expected. + ConditionTypeStalled = "Stalled" + // ConditionTypeHealthy denotes that the resource is healthy. // // The meaning of "healthy" is specific to the resource type. For example, diff --git a/internal/controller/management/projects/projects.go b/internal/controller/management/projects/projects.go index 31c189d53..9fa892178 100644 --- a/internal/controller/management/projects/projects.go +++ b/internal/controller/management/projects/projects.go @@ -2,6 +2,7 @@ package projects import ( "context" + "errors" "fmt" "github.com/kelseyhightower/envconfig" @@ -20,6 +21,7 @@ import ( rbacapi "github.com/akuity/kargo/api/rbac/v1alpha1" kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/internal/conditions" "github.com/akuity/kargo/internal/controller" rolloutsapi "github.com/akuity/kargo/internal/controller/rollouts/api/v1alpha1" "github.com/akuity/kargo/internal/kubeclient" @@ -36,6 +38,8 @@ func ReconcilerConfigFromEnv() ReconcilerConfig { return cfg } +var errProjectNamespaceExists = errors.New("namespace already exists and is not labeled as a Project namespace") + // reconciler reconciles Project resources. type reconciler struct { cfg ReconcilerConfig @@ -182,22 +186,20 @@ func (r *reconciler) Reconcile( return ctrl.Result{}, nil } - if project.Status.Phase.IsTerminal() { - logger.Debug( - "nothing to do", - "projectStatus", project.Status.Phase, - ) + if newStatus, ok := migratePhaseToConditions(project); ok { + logger.Debug("migrated Project phase to conditions") + patchErr := r.patchProjectStatusFn(ctx, project, newStatus) + return ctrl.Result{Requeue: true}, patchErr + } + + if reason, ok := mustReconcileProject(project); !ok { + logger.Debug("nothing to do", "reason", reason) return ctrl.Result{}, nil } newStatus, err := r.syncProjectFn(ctx, project) if err != nil { - newStatus.Message = err.Error() logger.Error(err, "error syncing Project") - } else { - // Be sure to blank this out in case there's an error in this field from - // the previous reconciliation - newStatus.Message = "" } patchErr := r.patchProjectStatusFn(ctx, project, newStatus) @@ -222,20 +224,70 @@ func (r *reconciler) syncProject( ctx context.Context, project *kargoapi.Project, ) (kargoapi.ProjectStatus, error) { + conditions.Set(&project.Status, &metav1.Condition{ + Type: kargoapi.ConditionTypeReconciling, + Status: metav1.ConditionTrue, + Reason: "Initializing", + Message: "Creating project namespace and initializing permissions", + ObservedGeneration: project.GetGeneration(), + }) + status, err := r.ensureNamespaceFn(ctx, project) if err != nil { + if errors.Is(err, errProjectNamespaceExists) { + conditions.Delete(&status, kargoapi.ConditionTypeReconciling) + conditions.Set(&status, &metav1.Condition{ + Type: kargoapi.ConditionTypeStalled, + Status: metav1.ConditionTrue, + Reason: "ExistingNamespaceMissingLabel", + Message: fmt.Sprintf( + "Namespace %q already exists but is not labeled as a Project namespace using label %q", + project.Name, + kargoapi.ProjectLabelKey, + ), + ObservedGeneration: project.GetGeneration(), + }) + } + conditions.Set(&status, &metav1.Condition{ + Type: kargoapi.ConditionTypeReady, + Status: metav1.ConditionFalse, + Reason: "NamespaceInitializationFailed", + Message: "Failed to initialize project namespace: " + err.Error(), + ObservedGeneration: project.GetGeneration(), + }) return status, fmt.Errorf("error ensuring namespace: %w", err) } if err = r.ensureAPIAdminPermissionsFn(ctx, project); err != nil { + conditions.Set(&status, &metav1.Condition{ + Type: kargoapi.ConditionTypeReady, + Status: metav1.ConditionFalse, + Reason: "PermissionsInitializationFailed", + Message: "Failed to initialize project admin permissions: " + err.Error(), + ObservedGeneration: project.GetGeneration(), + }) return status, fmt.Errorf("error ensuring project admin permissions: %w", err) } if err = r.ensureDefaultProjectRolesFn(ctx, project); err != nil { + conditions.Set(&status, &metav1.Condition{ + Type: kargoapi.ConditionTypeReady, + Status: metav1.ConditionFalse, + Reason: "RolesInitializationFailed", + Message: "Failed to initialize default project roles: " + err.Error(), + ObservedGeneration: project.GetGeneration(), + }) return status, fmt.Errorf("error ensuring default project roles: %w", err) } - status.Phase = kargoapi.ProjectPhaseReady + conditions.Delete(&status, kargoapi.ConditionTypeReconciling) + conditions.Set(&status, &metav1.Condition{ + Type: kargoapi.ConditionTypeReady, + Status: metav1.ConditionTrue, + Reason: "Initialized", + Message: "Project is initialized and ready for use", + ObservedGeneration: project.GetGeneration(), + }) return status, nil } @@ -266,12 +318,9 @@ func (r *reconciler) ensureNamespace( // We found an existing namespace with the same name as the Project. It's // only a problem if it is not labeled as a Project namespace. if ns.Labels[kargoapi.ProjectLabelKey] != kargoapi.LabelTrueValue { - status.Phase = kargoapi.ProjectPhaseInitializationFailed return status, fmt.Errorf( - "failed to initialize Project %q because namespace %q already exists"+ - " and is not labeled as a Project namespace", - project.Name, - project.Name, + "failed to initialize Project %q with namespace %q: %w", + project.Name, project.Name, errProjectNamespaceExists, ) } for _, ownerRef := range ns.OwnerReferences { @@ -599,3 +648,84 @@ func (r *reconciler) patchProjectStatus( }, ) } + +// migratePhaseToConditions migrates the Project's Phase and Message fields to +// Conditions. It returns the updated ProjectStatus and a boolean indicating +// whether the Project status was updated. +func migratePhaseToConditions(project *kargoapi.Project) (kargoapi.ProjectStatus, bool) { + status := *project.Status.DeepCopy() + if project.Status.Phase == "" { // nolint:staticcheck + status.Message = "" // nolint:staticcheck + return status, project.Status.Message != "" // nolint:staticcheck + } + + switch project.Status.Phase { // nolint:staticcheck + case kargoapi.ProjectPhaseInitializing: + conditions.Set(&status, &metav1.Condition{ + Type: kargoapi.ConditionTypeReconciling, + Status: metav1.ConditionTrue, + Reason: "Initializing", + Message: "Creating project namespace and initializing permissions", + ObservedGeneration: project.GetGeneration(), + }) + conditions.Set(&status, &metav1.Condition{ + Type: kargoapi.ConditionTypeReady, + Status: metav1.ConditionFalse, + Reason: "Initializing", + Message: "Creating project namespace and initializing permissions", + ObservedGeneration: project.GetGeneration(), + }) + case kargoapi.ProjectPhaseInitializationFailed: + // If the Project is in the InitializationFailed phase, it means that the + // namespace already exists but is not labeled as a Project namespace. + conditions.Set(&status, &metav1.Condition{ + Type: kargoapi.ConditionTypeStalled, + Status: metav1.ConditionTrue, + Reason: "ExistingNamespaceMissingLabel", + Message: fmt.Sprintf( + "Namespace %q already exists but is not labeled as a Project namespace using label %q", + project.Name, + kargoapi.ProjectLabelKey, + ), + ObservedGeneration: project.GetGeneration(), + }) + conditions.Set(&status, &metav1.Condition{ + Type: kargoapi.ConditionTypeReady, + Status: metav1.ConditionFalse, + Reason: "NamespaceInitializationFailed", + Message: "Failed to initialize project namespace: " + errProjectNamespaceExists.Error(), + ObservedGeneration: project.GetGeneration(), + }) + case kargoapi.ProjectPhaseReady: + conditions.Set(&status, &metav1.Condition{ + Type: kargoapi.ConditionTypeReady, + Status: metav1.ConditionTrue, + Reason: "Initialized", + Message: "Project is initialized and ready for use", + ObservedGeneration: project.GetGeneration(), + }) + } + + // Clear the phase and message now that we've migrated them to conditions. + status.Phase = "" // nolint:staticcheck + status.Message = "" // nolint:staticcheck + + return status, true +} + +// mustReconcileProject returns if the Project should be reconciled, or if it +// should be left alone, and the reason why. +func mustReconcileProject(project *kargoapi.Project) (string, bool) { + if stalled := conditions.Get(&project.Status, kargoapi.ConditionTypeStalled); stalled != nil { + if stalled.Status == metav1.ConditionTrue { + return stalled.Reason, false + } + } + + if ready := conditions.Get(&project.Status, kargoapi.ConditionTypeReady); ready != nil { + if ready.Status == metav1.ConditionTrue { + return ready.Reason, false + } + } + return "", true +} diff --git a/internal/controller/management/projects/projects_test.go b/internal/controller/management/projects/projects_test.go index 787564a58..ae3d7d5a6 100644 --- a/internal/controller/management/projects/projects_test.go +++ b/internal/controller/management/projects/projects_test.go @@ -16,6 +16,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/internal/conditions" ) func TestNewReconciler(t *testing.T) { @@ -126,9 +127,8 @@ func TestReconcile(t *testing.T) { patchProjectStatusFn: func( _ context.Context, _ *kargoapi.Project, - status kargoapi.ProjectStatus, + _ kargoapi.ProjectStatus, ) error { - require.Equal(t, "something went wrong", status.Message) return nil }, }, @@ -155,9 +155,8 @@ func TestReconcile(t *testing.T) { patchProjectStatusFn: func( _ context.Context, _ *kargoapi.Project, - status kargoapi.ProjectStatus, + _ kargoapi.ProjectStatus, ) error { - require.Empty(t, status.Message) return nil }, }, @@ -192,8 +191,19 @@ func TestSyncProject(t *testing.T) { }, assertions: func(t *testing.T, status kargoapi.ProjectStatus, err error) { require.ErrorContains(t, err, "something went wrong") + // Still initializing because retry could succeed - require.Equal(t, kargoapi.ProjectPhaseInitializing, status.Phase) + require.Len(t, status.Conditions, 2) + + readyCondition := conditions.Get(&status, kargoapi.ConditionTypeReady) + require.NotNil(t, readyCondition) + require.Equal(t, metav1.ConditionFalse, readyCondition.Status) + require.Equal(t, "NamespaceInitializationFailed", readyCondition.Reason) + + reconcilingCondition := conditions.Get(&status, kargoapi.ConditionTypeReconciling) + require.NotNil(t, reconcilingCondition) + require.Equal(t, metav1.ConditionTrue, reconcilingCondition.Status) + require.Equal(t, "Initializing", reconcilingCondition.Reason) }, }, { @@ -204,18 +214,24 @@ func TestSyncProject(t *testing.T) { project *kargoapi.Project, ) (kargoapi.ProjectStatus, error) { status := *project.Status.DeepCopy() - status.Phase = kargoapi.ProjectPhaseInitializationFailed - return status, errors.New("something went very wrong") + return status, errProjectNamespaceExists }, }, assertions: func(t *testing.T, status kargoapi.ProjectStatus, err error) { - require.ErrorContains(t, err, "something went very wrong") + require.True(t, errors.Is(err, errProjectNamespaceExists)) + // Failed because retry cannot possibly succeed - require.Equal( - t, - kargoapi.ProjectPhaseInitializationFailed, - status.Phase, - ) + require.Len(t, status.Conditions, 2) + + readyCondition := conditions.Get(&status, kargoapi.ConditionTypeReady) + require.NotNil(t, readyCondition) + require.Equal(t, metav1.ConditionFalse, readyCondition.Status) + require.Equal(t, "NamespaceInitializationFailed", readyCondition.Reason) + + stalledCondition := conditions.Get(&status, kargoapi.ConditionTypeStalled) + require.NotNil(t, stalledCondition) + require.Equal(t, metav1.ConditionTrue, stalledCondition.Status) + require.Equal(t, "ExistingNamespaceMissingLabel", stalledCondition.Reason) }, }, { @@ -236,8 +252,19 @@ func TestSyncProject(t *testing.T) { }, assertions: func(t *testing.T, status kargoapi.ProjectStatus, err error) { require.ErrorContains(t, err, "something went wrong") + // Still initializing because retry could succeed - require.Equal(t, kargoapi.ProjectPhaseInitializing, status.Phase) + require.Len(t, status.Conditions, 2) + + readyCondition := conditions.Get(&status, kargoapi.ConditionTypeReady) + require.NotNil(t, readyCondition) + require.Equal(t, metav1.ConditionFalse, readyCondition.Status) + require.Equal(t, "PermissionsInitializationFailed", readyCondition.Reason) + + reconcilingCondition := conditions.Get(&status, kargoapi.ConditionTypeReconciling) + require.NotNil(t, reconcilingCondition) + require.Equal(t, metav1.ConditionTrue, reconcilingCondition.Status) + require.Equal(t, "Initializing", reconcilingCondition.Reason) }, }, { @@ -264,8 +291,19 @@ func TestSyncProject(t *testing.T) { }, assertions: func(t *testing.T, status kargoapi.ProjectStatus, err error) { require.ErrorContains(t, err, "something went wrong") + // Still initializing because retry could succeed - require.Equal(t, kargoapi.ProjectPhaseInitializing, status.Phase) + require.Len(t, status.Conditions, 2) + + readyCondition := conditions.Get(&status, kargoapi.ConditionTypeReady) + require.NotNil(t, readyCondition) + require.Equal(t, metav1.ConditionFalse, readyCondition.Status) + require.Equal(t, "RolesInitializationFailed", readyCondition.Reason) + + reconcilingCondition := conditions.Get(&status, kargoapi.ConditionTypeReconciling) + require.NotNil(t, reconcilingCondition) + require.Equal(t, metav1.ConditionTrue, reconcilingCondition.Status) + require.Equal(t, "Initializing", reconcilingCondition.Reason) }, }, { @@ -292,8 +330,13 @@ func TestSyncProject(t *testing.T) { }, assertions: func(t *testing.T, status kargoapi.ProjectStatus, err error) { require.NoError(t, err) - // Success == ready - require.Equal(t, kargoapi.ProjectPhaseReady, status.Phase) + + require.Len(t, status.Conditions, 1) + + readyCondition := conditions.Get(&status, kargoapi.ConditionTypeReady) + require.NotNil(t, readyCondition) + require.Equal(t, metav1.ConditionTrue, readyCondition.Status) + require.Equal(t, "Initialized", readyCondition.Reason) }, }, } @@ -302,9 +345,7 @@ func TestSyncProject(t *testing.T) { status, err := testCase.reconciler.syncProject( context.Background(), &kargoapi.Project{ - Status: kargoapi.ProjectStatus{ - Phase: kargoapi.ProjectPhaseInitializing, - }, + Status: kargoapi.ProjectStatus{}, }, ) testCase.assertions(t, status, err) @@ -320,12 +361,8 @@ func TestEnsureNamespace(t *testing.T) { assertions func(*testing.T, kargoapi.ProjectStatus, error) }{ { - name: "error getting namespace", - project: &kargoapi.Project{ - Status: kargoapi.ProjectStatus{ - Phase: kargoapi.ProjectPhaseInitializing, - }, - }, + name: "error getting namespace", + project: &kargoapi.Project{}, reconciler: &reconciler{ getNamespaceFn: func( context.Context, @@ -336,20 +373,14 @@ func TestEnsureNamespace(t *testing.T) { return errors.New("something went wrong") }, }, - assertions: func(t *testing.T, status kargoapi.ProjectStatus, err error) { + assertions: func(t *testing.T, _ kargoapi.ProjectStatus, err error) { require.ErrorContains(t, err, "something went wrong") require.ErrorContains(t, err, "error getting namespace") - // Phase wasn't changed - require.Equal(t, kargoapi.ProjectPhaseInitializing, status.Phase) }, }, { - name: "namespace exists and is not labeled as a project namespace", - project: &kargoapi.Project{ - Status: kargoapi.ProjectStatus{ - Phase: kargoapi.ProjectPhaseInitializing, - }, - }, + name: "namespace exists and is not labeled as a project namespace", + project: &kargoapi.Project{}, reconciler: &reconciler{ getNamespaceFn: func( context.Context, @@ -360,10 +391,8 @@ func TestEnsureNamespace(t *testing.T) { return nil }, }, - assertions: func(t *testing.T, status kargoapi.ProjectStatus, err error) { - require.ErrorContains(t, err, "failed to initialize Project") - require.ErrorContains(t, err, "not labeled as a Project namespace") - require.Equal(t, kargoapi.ProjectPhaseInitializationFailed, status.Phase) + assertions: func(t *testing.T, _ kargoapi.ProjectStatus, err error) { + require.True(t, errors.Is(err, errProjectNamespaceExists)) }, }, { @@ -373,9 +402,6 @@ func TestEnsureNamespace(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ UID: types.UID("fake-uid"), }, - Status: kargoapi.ProjectStatus{ - Phase: kargoapi.ProjectPhaseInitializing, - }, }, reconciler: &reconciler{ getNamespaceFn: func( @@ -390,25 +416,19 @@ func TestEnsureNamespace(t *testing.T) { kargoapi.ProjectLabelKey: kargoapi.LabelTrueValue, } ns.OwnerReferences = []metav1.OwnerReference{{ - UID: types.UID("fake-uid"), + UID: "fake-uid", }} return nil }, }, - assertions: func(t *testing.T, status kargoapi.ProjectStatus, err error) { + assertions: func(t *testing.T, _ kargoapi.ProjectStatus, err error) { require.NoError(t, err) - // Phase wasn't changed - require.Equal(t, kargoapi.ProjectPhaseInitializing, status.Phase) }, }, { name: "namespace exists, is labeled as a project namespace, and is " + "NOT already owned by the project; error ensuring finalizer", - project: &kargoapi.Project{ - Status: kargoapi.ProjectStatus{ - Phase: kargoapi.ProjectPhaseInitializing, - }, - }, + project: &kargoapi.Project{}, reconciler: &reconciler{ getNamespaceFn: func( _ context.Context, @@ -431,21 +451,15 @@ func TestEnsureNamespace(t *testing.T) { return false, errors.New("something went wrong") }, }, - assertions: func(t *testing.T, status kargoapi.ProjectStatus, err error) { + assertions: func(t *testing.T, _ kargoapi.ProjectStatus, err error) { require.ErrorContains(t, err, "error ensuring finalizer on namespace") require.ErrorContains(t, err, "something went wrong") - // Phase wasn't changed - require.Equal(t, kargoapi.ProjectPhaseInitializing, status.Phase) }, }, { name: "namespace exists, is labeled as a project namespace, and is " + "NOT already owned by the project; error patching it", - project: &kargoapi.Project{ - Status: kargoapi.ProjectStatus{ - Phase: kargoapi.ProjectPhaseInitializing, - }, - }, + project: &kargoapi.Project{}, reconciler: &reconciler{ getNamespaceFn: func( _ context.Context, @@ -475,21 +489,15 @@ func TestEnsureNamespace(t *testing.T) { return errors.New("something went wrong") }, }, - assertions: func(t *testing.T, status kargoapi.ProjectStatus, err error) { + assertions: func(t *testing.T, _ kargoapi.ProjectStatus, err error) { require.ErrorContains(t, err, "error patching namespace") require.ErrorContains(t, err, "something went wrong") - // Phase wasn't changed - require.Equal(t, kargoapi.ProjectPhaseInitializing, status.Phase) }, }, { name: "namespace exists, is labeled as a project namespace, and is " + "NOT already owned by the project; success", - project: &kargoapi.Project{ - Status: kargoapi.ProjectStatus{ - Phase: kargoapi.ProjectPhaseInitializing, - }, - }, + project: &kargoapi.Project{}, reconciler: &reconciler{ getNamespaceFn: func( _ context.Context, @@ -519,19 +527,13 @@ func TestEnsureNamespace(t *testing.T) { return nil }, }, - assertions: func(t *testing.T, status kargoapi.ProjectStatus, err error) { + assertions: func(t *testing.T, _ kargoapi.ProjectStatus, err error) { require.NoError(t, err) - // Phase wasn't changed - require.Equal(t, kargoapi.ProjectPhaseInitializing, status.Phase) }, }, { - name: "namespace does not exist; error creating it", - project: &kargoapi.Project{ - Status: kargoapi.ProjectStatus{ - Phase: kargoapi.ProjectPhaseInitializing, - }, - }, + name: "namespace does not exist; error creating it", + project: &kargoapi.Project{}, reconciler: &reconciler{ getNamespaceFn: func( context.Context, @@ -549,11 +551,9 @@ func TestEnsureNamespace(t *testing.T) { return errors.New("something went wrong") }, }, - assertions: func(t *testing.T, status kargoapi.ProjectStatus, err error) { + assertions: func(t *testing.T, _ kargoapi.ProjectStatus, err error) { require.ErrorContains(t, err, "something went wrong") require.ErrorContains(t, err, "error creating namespace") - // Phase wasn't changed - require.Equal(t, kargoapi.ProjectPhaseInitializing, status.Phase) }, }, { @@ -580,10 +580,8 @@ func TestEnsureNamespace(t *testing.T) { return nil }, }, - assertions: func(t *testing.T, status kargoapi.ProjectStatus, err error) { + assertions: func(t *testing.T, _ kargoapi.ProjectStatus, err error) { require.NoError(t, err) - // Phase wasn't changed - require.Equal(t, kargoapi.ProjectPhaseInitializing, status.Phase) }, }, } @@ -781,3 +779,295 @@ func TestEnsureDefaultProjectRoles(t *testing.T) { }) } } + +func TestMigratePhaseToConditions(t *testing.T) { + tests := []struct { + name string + project *kargoapi.Project + assertions func(t *testing.T, status kargoapi.ProjectStatus, ok bool) + }{ + { + name: "Empty Phase", + project: &kargoapi.Project{ + Status: kargoapi.ProjectStatus{ + Phase: "", + Message: "Some message", + }, + }, + assertions: func(t *testing.T, status kargoapi.ProjectStatus, ok bool) { + require.True(t, ok) + require.Empty(t, status.Phase) // nolint:staticcheck + require.Empty(t, status.Message) // nolint:staticcheck + require.Empty(t, status.Conditions) + }, + }, + { + name: "Initializing Phase", + project: &kargoapi.Project{ + ObjectMeta: metav1.ObjectMeta{ + Generation: 1, + }, + Status: kargoapi.ProjectStatus{ + Phase: kargoapi.ProjectPhaseInitializing, + }, + }, + assertions: func(t *testing.T, status kargoapi.ProjectStatus, ok bool) { + require.True(t, ok) + require.Empty(t, status.Phase) // nolint:staticcheck + require.Empty(t, status.Message) // nolint:staticcheck + require.Len(t, status.Conditions, 2) + + reconcilingCondition := conditions.Get(&status, kargoapi.ConditionTypeReconciling) + require.NotNil(t, reconcilingCondition) + require.Equal(t, metav1.ConditionTrue, reconcilingCondition.Status) + require.Equal(t, "Initializing", reconcilingCondition.Reason) + require.Equal( + t, + "Creating project namespace and initializing permissions", + reconcilingCondition.Message, + ) + require.Equal(t, int64(1), reconcilingCondition.ObservedGeneration) + + readyCondition := conditions.Get(&status, kargoapi.ConditionTypeReady) + require.NotNil(t, readyCondition) + require.Equal(t, metav1.ConditionFalse, readyCondition.Status) + require.Equal(t, "Initializing", readyCondition.Reason) + require.Equal( + t, + "Creating project namespace and initializing permissions", + readyCondition.Message, + ) + require.Equal(t, int64(1), readyCondition.ObservedGeneration) + }, + }, + { + name: "InitializationFailed Phase", + project: &kargoapi.Project{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-project", + Generation: 2, + }, + Status: kargoapi.ProjectStatus{ + Phase: kargoapi.ProjectPhaseInitializationFailed, + }, + }, + assertions: func(t *testing.T, status kargoapi.ProjectStatus, ok bool) { + require.True(t, ok) + require.Empty(t, status.Phase) // nolint:staticcheck + require.Empty(t, status.Message) // nolint:staticcheck + require.Len(t, status.Conditions, 2) + + stalledCondition := conditions.Get(&status, kargoapi.ConditionTypeStalled) + require.NotNil(t, stalledCondition) + require.Equal(t, metav1.ConditionTrue, stalledCondition.Status) + require.Equal(t, "ExistingNamespaceMissingLabel", stalledCondition.Reason) + require.Contains( + t, + stalledCondition.Message, + "already exists but is not labeled as a Project namespace using label", + ) + require.Equal(t, int64(2), stalledCondition.ObservedGeneration) + + readyCondition := conditions.Get(&status, kargoapi.ConditionTypeReady) + require.NotNil(t, readyCondition) + require.Equal(t, metav1.ConditionFalse, readyCondition.Status) + require.Equal(t, "NamespaceInitializationFailed", readyCondition.Reason) + require.Contains( + t, + readyCondition.Message, + "namespace already exists and is not labeled as a Project namespace", + ) + require.Equal(t, int64(2), readyCondition.ObservedGeneration) + }, + }, + { + name: "Ready Phase", + project: &kargoapi.Project{ + ObjectMeta: metav1.ObjectMeta{ + Generation: 3, + }, + Status: kargoapi.ProjectStatus{ + Phase: kargoapi.ProjectPhaseReady, + }, + }, + assertions: func(t *testing.T, status kargoapi.ProjectStatus, ok bool) { + require.True(t, ok) + require.Empty(t, status.Phase) // nolint:staticcheck + require.Empty(t, status.Message) // nolint:staticcheck + require.Len(t, status.Conditions, 1) + + readyCondition := conditions.Get(&status, kargoapi.ConditionTypeReady) + require.NotNil(t, readyCondition) + require.Equal(t, metav1.ConditionTrue, readyCondition.Status) + require.Equal(t, "Initialized", readyCondition.Reason) + require.Equal(t, "Project is initialized and ready for use", readyCondition.Message) + require.Equal(t, int64(3), readyCondition.ObservedGeneration) + }, + }, + { + name: "Unknown Phase", + project: &kargoapi.Project{ + ObjectMeta: metav1.ObjectMeta{ + Generation: 4, + }, + Status: kargoapi.ProjectStatus{ + Phase: "UnknownPhase", + }, + }, + assertions: func(t *testing.T, status kargoapi.ProjectStatus, ok bool) { + require.True(t, ok) + require.Empty(t, status.Phase) // nolint:staticcheck + require.Empty(t, status.Message) // nolint:staticcheck + require.Empty(t, status.Conditions) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + status, ok := migratePhaseToConditions(tt.project) + tt.assertions(t, status, ok) + }) + } +} + +func TestMustReconcileProject(t *testing.T) { + tests := []struct { + name string + project *kargoapi.Project + assertions func(t *testing.T, reason string, ok bool) + }{ + { + name: "Stalled condition is true", + project: &kargoapi.Project{ + Status: kargoapi.ProjectStatus{ + Conditions: []metav1.Condition{ + { + Type: kargoapi.ConditionTypeStalled, + Status: metav1.ConditionTrue, + Reason: "StalledReason", + }, + }, + }, + }, + assertions: func(t *testing.T, reason string, ok bool) { + require.Equal(t, "StalledReason", reason) + require.False(t, ok) + }, + }, + { + name: "Stalled condition is false", + project: &kargoapi.Project{ + Status: kargoapi.ProjectStatus{ + Conditions: []metav1.Condition{ + { + Type: kargoapi.ConditionTypeStalled, + Status: metav1.ConditionFalse, + Reason: "NotStalledReason", + }, + }, + }, + }, + assertions: func(t *testing.T, reason string, ok bool) { + require.Empty(t, reason) + require.True(t, ok) + }, + }, + { + name: "Ready condition is true", + project: &kargoapi.Project{ + Status: kargoapi.ProjectStatus{ + Conditions: []metav1.Condition{ + { + Type: kargoapi.ConditionTypeReady, + Status: metav1.ConditionTrue, + Reason: "ReadyReason", + }, + }, + }, + }, + assertions: func(t *testing.T, reason string, ok bool) { + require.Equal(t, "ReadyReason", reason) + require.False(t, ok) + }, + }, + { + name: "Ready condition is false", + project: &kargoapi.Project{ + Status: kargoapi.ProjectStatus{ + Conditions: []metav1.Condition{ + { + Type: kargoapi.ConditionTypeReady, + Status: metav1.ConditionFalse, + Reason: "NotReadyReason", + }, + }, + }, + }, + assertions: func(t *testing.T, reason string, ok bool) { + require.Empty(t, reason) + require.True(t, ok) + }, + }, + { + name: "Stalled true takes precedence over Ready true", + project: &kargoapi.Project{ + Status: kargoapi.ProjectStatus{ + Conditions: []metav1.Condition{ + { + Type: kargoapi.ConditionTypeStalled, + Status: metav1.ConditionTrue, + Reason: "StalledReason", + }, + { + Type: kargoapi.ConditionTypeReady, + Status: metav1.ConditionTrue, + Reason: "ReadyReason", + }, + }, + }, + }, + assertions: func(t *testing.T, reason string, ok bool) { + require.Equal(t, "StalledReason", reason) + require.False(t, ok) + }, + }, + { + name: "No relevant conditions", + project: &kargoapi.Project{ + Status: kargoapi.ProjectStatus{ + Conditions: []metav1.Condition{ + { + Type: "SomeOtherCondition", + Status: metav1.ConditionTrue, + Reason: "SomeOtherReason", + }, + }, + }, + }, + assertions: func(t *testing.T, reason string, ok bool) { + require.Empty(t, reason) + require.True(t, ok) + }, + }, + { + name: "Empty conditions", + project: &kargoapi.Project{ + Status: kargoapi.ProjectStatus{ + Conditions: []metav1.Condition{}, + }, + }, + assertions: func(t *testing.T, reason string, ok bool) { + require.Empty(t, reason) + require.True(t, ok) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + reason, ok := mustReconcileProject(tt.project) + tt.assertions(t, reason, ok) + }) + } +} From 152c4fea52edbc863ff7d0350310bdddf0bea1b4 Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Mon, 29 Jul 2024 14:54:35 +0200 Subject: [PATCH 4/4] feat(cli): use conditions for `kargo get projects` Signed-off-by: Hidde Beydals --- internal/cli/cmd/get/projects.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/internal/cli/cmd/get/projects.go b/internal/cli/cmd/get/projects.go index b92732e75..3a2503991 100644 --- a/internal/cli/cmd/get/projects.go +++ b/internal/cli/cmd/get/projects.go @@ -20,6 +20,7 @@ import ( "github.com/akuity/kargo/internal/cli/io" "github.com/akuity/kargo/internal/cli/kubernetes" "github.com/akuity/kargo/internal/cli/templates" + "github.com/akuity/kargo/internal/conditions" v1alpha1 "github.com/akuity/kargo/pkg/api/service/v1alpha1" ) @@ -134,10 +135,18 @@ func newProjectTable(list *metav1.List) *metav1.Table { rows := make([]metav1.TableRow, len(list.Items)) for i, item := range list.Items { project := item.Object.(*kargoapi.Project) // nolint: forcetypeassert + + var ready, status = string(metav1.ConditionUnknown), "" + if readyCond := conditions.Get(&project.Status, kargoapi.ConditionTypeReady); readyCond != nil { + ready = string(readyCond.Status) + status = readyCond.Message + } + rows[i] = metav1.TableRow{ Cells: []any{ project.Name, - project.Status.Phase, + ready, + status, duration.HumanDuration(time.Since(project.CreationTimestamp.Time)), }, Object: list.Items[i], @@ -146,7 +155,8 @@ func newProjectTable(list *metav1.List) *metav1.Table { return &metav1.Table{ ColumnDefinitions: []metav1.TableColumnDefinition{ {Name: "Name", Type: "string"}, - {Name: "Phase", Type: "string"}, + {Name: "Ready", Type: "string"}, + {Name: "Status", Type: "string"}, {Name: "Age", Type: "string"}, }, Rows: rows,