diff --git a/api/v1alpha1/generated.pb.go b/api/v1alpha1/generated.pb.go index d8d1e06647..127482dbc2 100644 --- a/api/v1alpha1/generated.pb.go +++ b/api/v1alpha1/generated.pb.go @@ -1038,10 +1038,94 @@ func (m *FreightStatus) XXX_DiscardUnknown() { var xxx_messageInfo_FreightStatus proto.InternalMessageInfo +func (m *GenericWebhookAction) Reset() { *m = GenericWebhookAction{} } +func (*GenericWebhookAction) ProtoMessage() {} +func (*GenericWebhookAction) Descriptor() ([]byte, []int) { + return fileDescriptor_e26b7f7bbc391025, []int{36} +} +func (m *GenericWebhookAction) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenericWebhookAction) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *GenericWebhookAction) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenericWebhookAction.Merge(m, src) +} +func (m *GenericWebhookAction) XXX_Size() int { + return m.Size() +} +func (m *GenericWebhookAction) XXX_DiscardUnknown() { + xxx_messageInfo_GenericWebhookAction.DiscardUnknown(m) +} + +var xxx_messageInfo_GenericWebhookAction proto.InternalMessageInfo + +func (m *GenericWebhookReceiverConfig) Reset() { *m = GenericWebhookReceiverConfig{} } +func (*GenericWebhookReceiverConfig) ProtoMessage() {} +func (*GenericWebhookReceiverConfig) Descriptor() ([]byte, []int) { + return fileDescriptor_e26b7f7bbc391025, []int{37} +} +func (m *GenericWebhookReceiverConfig) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenericWebhookReceiverConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *GenericWebhookReceiverConfig) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenericWebhookReceiverConfig.Merge(m, src) +} +func (m *GenericWebhookReceiverConfig) XXX_Size() int { + return m.Size() +} +func (m *GenericWebhookReceiverConfig) XXX_DiscardUnknown() { + xxx_messageInfo_GenericWebhookReceiverConfig.DiscardUnknown(m) +} + +var xxx_messageInfo_GenericWebhookReceiverConfig proto.InternalMessageInfo + +func (m *GenericWebhookTarget) Reset() { *m = GenericWebhookTarget{} } +func (*GenericWebhookTarget) ProtoMessage() {} +func (*GenericWebhookTarget) Descriptor() ([]byte, []int) { + return fileDescriptor_e26b7f7bbc391025, []int{38} +} +func (m *GenericWebhookTarget) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenericWebhookTarget) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *GenericWebhookTarget) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenericWebhookTarget.Merge(m, src) +} +func (m *GenericWebhookTarget) XXX_Size() int { + return m.Size() +} +func (m *GenericWebhookTarget) XXX_DiscardUnknown() { + xxx_messageInfo_GenericWebhookTarget.DiscardUnknown(m) +} + +var xxx_messageInfo_GenericWebhookTarget proto.InternalMessageInfo + func (m *GitCommit) Reset() { *m = GitCommit{} } func (*GitCommit) ProtoMessage() {} func (*GitCommit) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{36} + return fileDescriptor_e26b7f7bbc391025, []int{39} } func (m *GitCommit) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1069,7 +1153,7 @@ var xxx_messageInfo_GitCommit proto.InternalMessageInfo func (m *GitDiscoveryResult) Reset() { *m = GitDiscoveryResult{} } func (*GitDiscoveryResult) ProtoMessage() {} func (*GitDiscoveryResult) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{37} + return fileDescriptor_e26b7f7bbc391025, []int{40} } func (m *GitDiscoveryResult) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1097,7 +1181,7 @@ var xxx_messageInfo_GitDiscoveryResult proto.InternalMessageInfo func (m *GitHubWebhookReceiverConfig) Reset() { *m = GitHubWebhookReceiverConfig{} } func (*GitHubWebhookReceiverConfig) ProtoMessage() {} func (*GitHubWebhookReceiverConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{38} + return fileDescriptor_e26b7f7bbc391025, []int{41} } func (m *GitHubWebhookReceiverConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1125,7 +1209,7 @@ var xxx_messageInfo_GitHubWebhookReceiverConfig proto.InternalMessageInfo func (m *GitLabWebhookReceiverConfig) Reset() { *m = GitLabWebhookReceiverConfig{} } func (*GitLabWebhookReceiverConfig) ProtoMessage() {} func (*GitLabWebhookReceiverConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{39} + return fileDescriptor_e26b7f7bbc391025, []int{42} } func (m *GitLabWebhookReceiverConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1153,7 +1237,7 @@ var xxx_messageInfo_GitLabWebhookReceiverConfig proto.InternalMessageInfo func (m *GitSubscription) Reset() { *m = GitSubscription{} } func (*GitSubscription) ProtoMessage() {} func (*GitSubscription) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{40} + return fileDescriptor_e26b7f7bbc391025, []int{43} } func (m *GitSubscription) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1181,7 +1265,7 @@ var xxx_messageInfo_GitSubscription proto.InternalMessageInfo func (m *GiteaWebhookReceiverConfig) Reset() { *m = GiteaWebhookReceiverConfig{} } func (*GiteaWebhookReceiverConfig) ProtoMessage() {} func (*GiteaWebhookReceiverConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{41} + return fileDescriptor_e26b7f7bbc391025, []int{44} } func (m *GiteaWebhookReceiverConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1209,7 +1293,7 @@ var xxx_messageInfo_GiteaWebhookReceiverConfig proto.InternalMessageInfo func (m *HarborWebhookReceiverConfig) Reset() { *m = HarborWebhookReceiverConfig{} } func (*HarborWebhookReceiverConfig) ProtoMessage() {} func (*HarborWebhookReceiverConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{42} + return fileDescriptor_e26b7f7bbc391025, []int{45} } func (m *HarborWebhookReceiverConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1237,7 +1321,7 @@ var xxx_messageInfo_HarborWebhookReceiverConfig proto.InternalMessageInfo func (m *Health) Reset() { *m = Health{} } func (*Health) ProtoMessage() {} func (*Health) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{43} + return fileDescriptor_e26b7f7bbc391025, []int{46} } func (m *Health) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1265,7 +1349,7 @@ var xxx_messageInfo_Health proto.InternalMessageInfo func (m *HealthCheckStep) Reset() { *m = HealthCheckStep{} } func (*HealthCheckStep) ProtoMessage() {} func (*HealthCheckStep) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{44} + return fileDescriptor_e26b7f7bbc391025, []int{47} } func (m *HealthCheckStep) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1293,7 +1377,7 @@ var xxx_messageInfo_HealthCheckStep proto.InternalMessageInfo func (m *HealthStats) Reset() { *m = HealthStats{} } func (*HealthStats) ProtoMessage() {} func (*HealthStats) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{45} + return fileDescriptor_e26b7f7bbc391025, []int{48} } func (m *HealthStats) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1321,7 +1405,7 @@ var xxx_messageInfo_HealthStats proto.InternalMessageInfo func (m *Image) Reset() { *m = Image{} } func (*Image) ProtoMessage() {} func (*Image) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{46} + return fileDescriptor_e26b7f7bbc391025, []int{49} } func (m *Image) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1349,7 +1433,7 @@ var xxx_messageInfo_Image proto.InternalMessageInfo func (m *ImageDiscoveryResult) Reset() { *m = ImageDiscoveryResult{} } func (*ImageDiscoveryResult) ProtoMessage() {} func (*ImageDiscoveryResult) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{47} + return fileDescriptor_e26b7f7bbc391025, []int{50} } func (m *ImageDiscoveryResult) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1377,7 +1461,7 @@ var xxx_messageInfo_ImageDiscoveryResult proto.InternalMessageInfo func (m *ImageSubscription) Reset() { *m = ImageSubscription{} } func (*ImageSubscription) ProtoMessage() {} func (*ImageSubscription) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{48} + return fileDescriptor_e26b7f7bbc391025, []int{51} } func (m *ImageSubscription) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1402,10 +1486,66 @@ func (m *ImageSubscription) XXX_DiscardUnknown() { var xxx_messageInfo_ImageSubscription proto.InternalMessageInfo +func (m *IndexSelector) Reset() { *m = IndexSelector{} } +func (*IndexSelector) ProtoMessage() {} +func (*IndexSelector) Descriptor() ([]byte, []int) { + return fileDescriptor_e26b7f7bbc391025, []int{52} +} +func (m *IndexSelector) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *IndexSelector) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *IndexSelector) XXX_Merge(src proto.Message) { + xxx_messageInfo_IndexSelector.Merge(m, src) +} +func (m *IndexSelector) XXX_Size() int { + return m.Size() +} +func (m *IndexSelector) XXX_DiscardUnknown() { + xxx_messageInfo_IndexSelector.DiscardUnknown(m) +} + +var xxx_messageInfo_IndexSelector proto.InternalMessageInfo + +func (m *IndexSelectorRequirement) Reset() { *m = IndexSelectorRequirement{} } +func (*IndexSelectorRequirement) ProtoMessage() {} +func (*IndexSelectorRequirement) Descriptor() ([]byte, []int) { + return fileDescriptor_e26b7f7bbc391025, []int{53} +} +func (m *IndexSelectorRequirement) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *IndexSelectorRequirement) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *IndexSelectorRequirement) XXX_Merge(src proto.Message) { + xxx_messageInfo_IndexSelectorRequirement.Merge(m, src) +} +func (m *IndexSelectorRequirement) XXX_Size() int { + return m.Size() +} +func (m *IndexSelectorRequirement) XXX_DiscardUnknown() { + xxx_messageInfo_IndexSelectorRequirement.DiscardUnknown(m) +} + +var xxx_messageInfo_IndexSelectorRequirement proto.InternalMessageInfo + func (m *Project) Reset() { *m = Project{} } func (*Project) ProtoMessage() {} func (*Project) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{49} + return fileDescriptor_e26b7f7bbc391025, []int{54} } func (m *Project) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1433,7 +1573,7 @@ var xxx_messageInfo_Project proto.InternalMessageInfo func (m *ProjectConfig) Reset() { *m = ProjectConfig{} } func (*ProjectConfig) ProtoMessage() {} func (*ProjectConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{50} + return fileDescriptor_e26b7f7bbc391025, []int{55} } func (m *ProjectConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1461,7 +1601,7 @@ var xxx_messageInfo_ProjectConfig proto.InternalMessageInfo func (m *ProjectConfigList) Reset() { *m = ProjectConfigList{} } func (*ProjectConfigList) ProtoMessage() {} func (*ProjectConfigList) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{51} + return fileDescriptor_e26b7f7bbc391025, []int{56} } func (m *ProjectConfigList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1489,7 +1629,7 @@ var xxx_messageInfo_ProjectConfigList proto.InternalMessageInfo func (m *ProjectConfigSpec) Reset() { *m = ProjectConfigSpec{} } func (*ProjectConfigSpec) ProtoMessage() {} func (*ProjectConfigSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{52} + return fileDescriptor_e26b7f7bbc391025, []int{57} } func (m *ProjectConfigSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1517,7 +1657,7 @@ var xxx_messageInfo_ProjectConfigSpec proto.InternalMessageInfo func (m *ProjectConfigStatus) Reset() { *m = ProjectConfigStatus{} } func (*ProjectConfigStatus) ProtoMessage() {} func (*ProjectConfigStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{53} + return fileDescriptor_e26b7f7bbc391025, []int{58} } func (m *ProjectConfigStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1545,7 +1685,7 @@ var xxx_messageInfo_ProjectConfigStatus proto.InternalMessageInfo func (m *ProjectList) Reset() { *m = ProjectList{} } func (*ProjectList) ProtoMessage() {} func (*ProjectList) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{54} + return fileDescriptor_e26b7f7bbc391025, []int{59} } func (m *ProjectList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1573,7 +1713,7 @@ var xxx_messageInfo_ProjectList proto.InternalMessageInfo func (m *ProjectStats) Reset() { *m = ProjectStats{} } func (*ProjectStats) ProtoMessage() {} func (*ProjectStats) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{55} + return fileDescriptor_e26b7f7bbc391025, []int{60} } func (m *ProjectStats) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1601,7 +1741,7 @@ var xxx_messageInfo_ProjectStats proto.InternalMessageInfo func (m *ProjectStatus) Reset() { *m = ProjectStatus{} } func (*ProjectStatus) ProtoMessage() {} func (*ProjectStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{56} + return fileDescriptor_e26b7f7bbc391025, []int{61} } func (m *ProjectStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1629,7 +1769,7 @@ var xxx_messageInfo_ProjectStatus proto.InternalMessageInfo func (m *Promotion) Reset() { *m = Promotion{} } func (*Promotion) ProtoMessage() {} func (*Promotion) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{57} + return fileDescriptor_e26b7f7bbc391025, []int{62} } func (m *Promotion) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1657,7 +1797,7 @@ var xxx_messageInfo_Promotion proto.InternalMessageInfo func (m *PromotionList) Reset() { *m = PromotionList{} } func (*PromotionList) ProtoMessage() {} func (*PromotionList) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{58} + return fileDescriptor_e26b7f7bbc391025, []int{63} } func (m *PromotionList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1685,7 +1825,7 @@ var xxx_messageInfo_PromotionList proto.InternalMessageInfo func (m *PromotionPolicy) Reset() { *m = PromotionPolicy{} } func (*PromotionPolicy) ProtoMessage() {} func (*PromotionPolicy) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{59} + return fileDescriptor_e26b7f7bbc391025, []int{64} } func (m *PromotionPolicy) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1713,7 +1853,7 @@ var xxx_messageInfo_PromotionPolicy proto.InternalMessageInfo func (m *PromotionPolicySelector) Reset() { *m = PromotionPolicySelector{} } func (*PromotionPolicySelector) ProtoMessage() {} func (*PromotionPolicySelector) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{60} + return fileDescriptor_e26b7f7bbc391025, []int{65} } func (m *PromotionPolicySelector) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1741,7 +1881,7 @@ var xxx_messageInfo_PromotionPolicySelector proto.InternalMessageInfo func (m *PromotionReference) Reset() { *m = PromotionReference{} } func (*PromotionReference) ProtoMessage() {} func (*PromotionReference) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{61} + return fileDescriptor_e26b7f7bbc391025, []int{66} } func (m *PromotionReference) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1769,7 +1909,7 @@ var xxx_messageInfo_PromotionReference proto.InternalMessageInfo func (m *PromotionSpec) Reset() { *m = PromotionSpec{} } func (*PromotionSpec) ProtoMessage() {} func (*PromotionSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{62} + return fileDescriptor_e26b7f7bbc391025, []int{67} } func (m *PromotionSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1797,7 +1937,7 @@ var xxx_messageInfo_PromotionSpec proto.InternalMessageInfo func (m *PromotionStatus) Reset() { *m = PromotionStatus{} } func (*PromotionStatus) ProtoMessage() {} func (*PromotionStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{63} + return fileDescriptor_e26b7f7bbc391025, []int{68} } func (m *PromotionStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1825,7 +1965,7 @@ var xxx_messageInfo_PromotionStatus proto.InternalMessageInfo func (m *PromotionStep) Reset() { *m = PromotionStep{} } func (*PromotionStep) ProtoMessage() {} func (*PromotionStep) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{64} + return fileDescriptor_e26b7f7bbc391025, []int{69} } func (m *PromotionStep) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1853,7 +1993,7 @@ var xxx_messageInfo_PromotionStep proto.InternalMessageInfo func (m *PromotionStepRetry) Reset() { *m = PromotionStepRetry{} } func (*PromotionStepRetry) ProtoMessage() {} func (*PromotionStepRetry) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{65} + return fileDescriptor_e26b7f7bbc391025, []int{70} } func (m *PromotionStepRetry) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1881,7 +2021,7 @@ var xxx_messageInfo_PromotionStepRetry proto.InternalMessageInfo func (m *PromotionTask) Reset() { *m = PromotionTask{} } func (*PromotionTask) ProtoMessage() {} func (*PromotionTask) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{66} + return fileDescriptor_e26b7f7bbc391025, []int{71} } func (m *PromotionTask) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1909,7 +2049,7 @@ var xxx_messageInfo_PromotionTask proto.InternalMessageInfo func (m *PromotionTaskList) Reset() { *m = PromotionTaskList{} } func (*PromotionTaskList) ProtoMessage() {} func (*PromotionTaskList) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{67} + return fileDescriptor_e26b7f7bbc391025, []int{72} } func (m *PromotionTaskList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1937,7 +2077,7 @@ var xxx_messageInfo_PromotionTaskList proto.InternalMessageInfo func (m *PromotionTaskReference) Reset() { *m = PromotionTaskReference{} } func (*PromotionTaskReference) ProtoMessage() {} func (*PromotionTaskReference) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{68} + return fileDescriptor_e26b7f7bbc391025, []int{73} } func (m *PromotionTaskReference) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1965,7 +2105,7 @@ var xxx_messageInfo_PromotionTaskReference proto.InternalMessageInfo func (m *PromotionTaskSpec) Reset() { *m = PromotionTaskSpec{} } func (*PromotionTaskSpec) ProtoMessage() {} func (*PromotionTaskSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{69} + return fileDescriptor_e26b7f7bbc391025, []int{74} } func (m *PromotionTaskSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1993,7 +2133,7 @@ var xxx_messageInfo_PromotionTaskSpec proto.InternalMessageInfo func (m *PromotionTemplate) Reset() { *m = PromotionTemplate{} } func (*PromotionTemplate) ProtoMessage() {} func (*PromotionTemplate) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{70} + return fileDescriptor_e26b7f7bbc391025, []int{75} } func (m *PromotionTemplate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2021,7 +2161,7 @@ var xxx_messageInfo_PromotionTemplate proto.InternalMessageInfo func (m *PromotionTemplateSpec) Reset() { *m = PromotionTemplateSpec{} } func (*PromotionTemplateSpec) ProtoMessage() {} func (*PromotionTemplateSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{71} + return fileDescriptor_e26b7f7bbc391025, []int{76} } func (m *PromotionTemplateSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2049,7 +2189,7 @@ var xxx_messageInfo_PromotionTemplateSpec proto.InternalMessageInfo func (m *QuayWebhookReceiverConfig) Reset() { *m = QuayWebhookReceiverConfig{} } func (*QuayWebhookReceiverConfig) ProtoMessage() {} func (*QuayWebhookReceiverConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{72} + return fileDescriptor_e26b7f7bbc391025, []int{77} } func (m *QuayWebhookReceiverConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2077,7 +2217,7 @@ var xxx_messageInfo_QuayWebhookReceiverConfig proto.InternalMessageInfo func (m *RepoSubscription) Reset() { *m = RepoSubscription{} } func (*RepoSubscription) ProtoMessage() {} func (*RepoSubscription) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{73} + return fileDescriptor_e26b7f7bbc391025, []int{78} } func (m *RepoSubscription) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2105,7 +2245,7 @@ var xxx_messageInfo_RepoSubscription proto.InternalMessageInfo func (m *Stage) Reset() { *m = Stage{} } func (*Stage) ProtoMessage() {} func (*Stage) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{74} + return fileDescriptor_e26b7f7bbc391025, []int{79} } func (m *Stage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2133,7 +2273,7 @@ var xxx_messageInfo_Stage proto.InternalMessageInfo func (m *StageList) Reset() { *m = StageList{} } func (*StageList) ProtoMessage() {} func (*StageList) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{75} + return fileDescriptor_e26b7f7bbc391025, []int{80} } func (m *StageList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2161,7 +2301,7 @@ var xxx_messageInfo_StageList proto.InternalMessageInfo func (m *StageSpec) Reset() { *m = StageSpec{} } func (*StageSpec) ProtoMessage() {} func (*StageSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{76} + return fileDescriptor_e26b7f7bbc391025, []int{81} } func (m *StageSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2189,7 +2329,7 @@ var xxx_messageInfo_StageSpec proto.InternalMessageInfo func (m *StageStats) Reset() { *m = StageStats{} } func (*StageStats) ProtoMessage() {} func (*StageStats) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{77} + return fileDescriptor_e26b7f7bbc391025, []int{82} } func (m *StageStats) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2217,7 +2357,7 @@ var xxx_messageInfo_StageStats proto.InternalMessageInfo func (m *StageStatus) Reset() { *m = StageStatus{} } func (*StageStatus) ProtoMessage() {} func (*StageStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{78} + return fileDescriptor_e26b7f7bbc391025, []int{83} } func (m *StageStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2245,7 +2385,7 @@ var xxx_messageInfo_StageStatus proto.InternalMessageInfo func (m *StepExecutionMetadata) Reset() { *m = StepExecutionMetadata{} } func (*StepExecutionMetadata) ProtoMessage() {} func (*StepExecutionMetadata) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{79} + return fileDescriptor_e26b7f7bbc391025, []int{84} } func (m *StepExecutionMetadata) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2273,7 +2413,7 @@ var xxx_messageInfo_StepExecutionMetadata proto.InternalMessageInfo func (m *Verification) Reset() { *m = Verification{} } func (*Verification) ProtoMessage() {} func (*Verification) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{80} + return fileDescriptor_e26b7f7bbc391025, []int{85} } func (m *Verification) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2301,7 +2441,7 @@ var xxx_messageInfo_Verification proto.InternalMessageInfo func (m *VerificationInfo) Reset() { *m = VerificationInfo{} } func (*VerificationInfo) ProtoMessage() {} func (*VerificationInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{81} + return fileDescriptor_e26b7f7bbc391025, []int{86} } func (m *VerificationInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2329,7 +2469,7 @@ var xxx_messageInfo_VerificationInfo proto.InternalMessageInfo func (m *VerifiedStage) Reset() { *m = VerifiedStage{} } func (*VerifiedStage) ProtoMessage() {} func (*VerifiedStage) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{82} + return fileDescriptor_e26b7f7bbc391025, []int{87} } func (m *VerifiedStage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2357,7 +2497,7 @@ var xxx_messageInfo_VerifiedStage proto.InternalMessageInfo func (m *Warehouse) Reset() { *m = Warehouse{} } func (*Warehouse) ProtoMessage() {} func (*Warehouse) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{83} + return fileDescriptor_e26b7f7bbc391025, []int{88} } func (m *Warehouse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2385,7 +2525,7 @@ var xxx_messageInfo_Warehouse proto.InternalMessageInfo func (m *WarehouseList) Reset() { *m = WarehouseList{} } func (*WarehouseList) ProtoMessage() {} func (*WarehouseList) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{84} + return fileDescriptor_e26b7f7bbc391025, []int{89} } func (m *WarehouseList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2413,7 +2553,7 @@ var xxx_messageInfo_WarehouseList proto.InternalMessageInfo func (m *WarehouseSpec) Reset() { *m = WarehouseSpec{} } func (*WarehouseSpec) ProtoMessage() {} func (*WarehouseSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{85} + return fileDescriptor_e26b7f7bbc391025, []int{90} } func (m *WarehouseSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2441,7 +2581,7 @@ var xxx_messageInfo_WarehouseSpec proto.InternalMessageInfo func (m *WarehouseStats) Reset() { *m = WarehouseStats{} } func (*WarehouseStats) ProtoMessage() {} func (*WarehouseStats) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{86} + return fileDescriptor_e26b7f7bbc391025, []int{91} } func (m *WarehouseStats) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2469,7 +2609,7 @@ var xxx_messageInfo_WarehouseStats proto.InternalMessageInfo func (m *WarehouseStatus) Reset() { *m = WarehouseStatus{} } func (*WarehouseStatus) ProtoMessage() {} func (*WarehouseStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{87} + return fileDescriptor_e26b7f7bbc391025, []int{92} } func (m *WarehouseStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2497,7 +2637,7 @@ var xxx_messageInfo_WarehouseStatus proto.InternalMessageInfo func (m *WebhookReceiverConfig) Reset() { *m = WebhookReceiverConfig{} } func (*WebhookReceiverConfig) ProtoMessage() {} func (*WebhookReceiverConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{88} + return fileDescriptor_e26b7f7bbc391025, []int{93} } func (m *WebhookReceiverConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2525,7 +2665,7 @@ var xxx_messageInfo_WebhookReceiverConfig proto.InternalMessageInfo func (m *WebhookReceiverDetails) Reset() { *m = WebhookReceiverDetails{} } func (*WebhookReceiverDetails) ProtoMessage() {} func (*WebhookReceiverDetails) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{89} + return fileDescriptor_e26b7f7bbc391025, []int{94} } func (m *WebhookReceiverDetails) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2595,6 +2735,10 @@ func init() { proto.RegisterMapType((map[string]CurrentStage)(nil), "github.com.akuity.kargo.api.v1alpha1.FreightStatus.CurrentlyInEntry") proto.RegisterMapType((map[string]v12.JSON)(nil), "github.com.akuity.kargo.api.v1alpha1.FreightStatus.MetadataEntry") proto.RegisterMapType((map[string]VerifiedStage)(nil), "github.com.akuity.kargo.api.v1alpha1.FreightStatus.VerifiedInEntry") + proto.RegisterType((*GenericWebhookAction)(nil), "github.com.akuity.kargo.api.v1alpha1.GenericWebhookAction") + proto.RegisterMapType((map[string]string)(nil), "github.com.akuity.kargo.api.v1alpha1.GenericWebhookAction.ParametersEntry") + proto.RegisterType((*GenericWebhookReceiverConfig)(nil), "github.com.akuity.kargo.api.v1alpha1.GenericWebhookReceiverConfig") + proto.RegisterType((*GenericWebhookTarget)(nil), "github.com.akuity.kargo.api.v1alpha1.GenericWebhookTarget") proto.RegisterType((*GitCommit)(nil), "github.com.akuity.kargo.api.v1alpha1.GitCommit") proto.RegisterType((*GitDiscoveryResult)(nil), "github.com.akuity.kargo.api.v1alpha1.GitDiscoveryResult") proto.RegisterType((*GitHubWebhookReceiverConfig)(nil), "github.com.akuity.kargo.api.v1alpha1.GitHubWebhookReceiverConfig") @@ -2609,6 +2753,8 @@ func init() { proto.RegisterMapType((map[string]string)(nil), "github.com.akuity.kargo.api.v1alpha1.Image.AnnotationsEntry") proto.RegisterType((*ImageDiscoveryResult)(nil), "github.com.akuity.kargo.api.v1alpha1.ImageDiscoveryResult") proto.RegisterType((*ImageSubscription)(nil), "github.com.akuity.kargo.api.v1alpha1.ImageSubscription") + proto.RegisterType((*IndexSelector)(nil), "github.com.akuity.kargo.api.v1alpha1.IndexSelector") + proto.RegisterType((*IndexSelectorRequirement)(nil), "github.com.akuity.kargo.api.v1alpha1.IndexSelectorRequirement") proto.RegisterType((*Project)(nil), "github.com.akuity.kargo.api.v1alpha1.Project") proto.RegisterType((*ProjectConfig)(nil), "github.com.akuity.kargo.api.v1alpha1.ProjectConfig") proto.RegisterType((*ProjectConfigList)(nil), "github.com.akuity.kargo.api.v1alpha1.ProjectConfigList") @@ -2658,330 +2804,350 @@ func init() { } var fileDescriptor_e26b7f7bbc391025 = []byte{ - // 5167 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5d, 0xcb, 0x6f, 0x24, 0xc7, - 0x79, 0xdf, 0x9e, 0xe1, 0x6b, 0xbe, 0xe1, 0xb3, 0x96, 0xab, 0xa5, 0x28, 0x8b, 0xdc, 0xb4, 0x14, - 0x41, 0x8a, 0xa4, 0x61, 0xb4, 0x7a, 0xad, 0x5e, 0x6b, 0xcd, 0x0c, 0xf7, 0x41, 0x99, 0xd2, 0xd2, - 0x35, 0xab, 0x95, 0xb5, 0x92, 0xa0, 0x14, 0x67, 0x8a, 0x33, 0x6d, 0xce, 0x4c, 0x8f, 0xba, 0xab, - 0xb9, 0x4b, 0x29, 0x48, 0x14, 0x3b, 0x09, 0x7c, 0x10, 0x02, 0x1d, 0x1c, 0xc8, 0x87, 0x04, 0x08, - 0xe2, 0x53, 0x60, 0xc0, 0xfe, 0x03, 0x02, 0xc4, 0x01, 0x72, 0x91, 0x1d, 0x39, 0x10, 0x94, 0x43, - 0x14, 0xc0, 0x20, 0x22, 0x1a, 0xc8, 0x2d, 0x40, 0x0e, 0x39, 0x2d, 0x10, 0x20, 0xa8, 0x47, 0x77, - 0x57, 0xf7, 0xf4, 0x2c, 0xbb, 0x67, 0x49, 0x6a, 0x83, 0xe4, 0xc6, 0xa9, 0xaf, 0xea, 0xf7, 0x75, - 0xbd, 0xbe, 0xfa, 0x5e, 0x55, 0x84, 0xa7, 0x9a, 0x16, 0x6b, 0x79, 0x9b, 0xa5, 0xba, 0xdd, 0x59, - 0x21, 0xdb, 0x9e, 0xc5, 0x76, 0x57, 0xb6, 0x89, 0xd3, 0xb4, 0x57, 0x48, 0xcf, 0x5a, 0xd9, 0x79, - 0x82, 0xb4, 0x7b, 0x2d, 0xf2, 0xc4, 0x4a, 0x93, 0x76, 0xa9, 0x43, 0x18, 0x6d, 0x94, 0x7a, 0x8e, - 0xcd, 0x6c, 0xf4, 0x60, 0xd8, 0xaa, 0x24, 0x5b, 0x95, 0x44, 0xab, 0x12, 0xe9, 0x59, 0x25, 0xbf, - 0xd5, 0xe2, 0xe3, 0x1a, 0x76, 0xd3, 0x6e, 0xda, 0x2b, 0xa2, 0xf1, 0xa6, 0xb7, 0x25, 0x7e, 0x89, - 0x1f, 0xe2, 0x2f, 0x09, 0xba, 0x68, 0x6e, 0x9f, 0x73, 0x4b, 0x96, 0xe4, 0x5c, 0xb7, 0x1d, 0xba, - 0xb2, 0xd3, 0xc7, 0x78, 0xf1, 0x72, 0x58, 0x87, 0xde, 0x64, 0xb4, 0xeb, 0x5a, 0x76, 0xd7, 0x7d, - 0x9c, 0xf4, 0x2c, 0x97, 0x3a, 0x3b, 0xd4, 0x59, 0xe9, 0x6d, 0x37, 0x39, 0xcd, 0x8d, 0x56, 0x48, - 0x42, 0x7a, 0x2a, 0x44, 0xea, 0x90, 0x7a, 0xcb, 0xea, 0x52, 0x67, 0x37, 0x6c, 0xde, 0xa1, 0x8c, - 0x24, 0xb5, 0x5a, 0x19, 0xd4, 0xca, 0xf1, 0xba, 0xcc, 0xea, 0xd0, 0xbe, 0x06, 0xcf, 0x1c, 0xd4, - 0xc0, 0xad, 0xb7, 0x68, 0x87, 0xc4, 0xdb, 0x99, 0x6f, 0xc3, 0xc9, 0x72, 0x97, 0xb4, 0x77, 0x5d, - 0xcb, 0xc5, 0x5e, 0xb7, 0xec, 0x34, 0xbd, 0x0e, 0xed, 0x32, 0x74, 0x06, 0x46, 0xba, 0xa4, 0x43, - 0x17, 0x8c, 0x33, 0xc6, 0xc3, 0x85, 0xca, 0xe4, 0xa7, 0x7b, 0xcb, 0x27, 0xf6, 0xf7, 0x96, 0x47, - 0x5e, 0x23, 0x1d, 0x8a, 0x05, 0x05, 0x3d, 0x00, 0xa3, 0x3b, 0xa4, 0xed, 0xd1, 0x85, 0x9c, 0xa8, - 0x32, 0xa5, 0xaa, 0x8c, 0x5e, 0xe3, 0x85, 0x58, 0xd2, 0xcc, 0xef, 0xe7, 0x23, 0xf0, 0xaf, 0x52, - 0x46, 0x1a, 0x84, 0x11, 0xd4, 0x81, 0xb1, 0x36, 0xd9, 0xa4, 0x6d, 0x77, 0xc1, 0x38, 0x93, 0x7f, - 0xb8, 0x78, 0xf6, 0x42, 0x29, 0xcd, 0x44, 0x97, 0x12, 0xa0, 0x4a, 0xeb, 0x02, 0xe7, 0x42, 0x97, - 0x39, 0xbb, 0x95, 0x69, 0xf5, 0x11, 0x63, 0xb2, 0x10, 0x2b, 0x26, 0xe8, 0x8f, 0x0c, 0x28, 0x92, - 0x6e, 0xd7, 0x66, 0x84, 0xf1, 0x69, 0x5a, 0xc8, 0x09, 0xa6, 0xaf, 0x0c, 0xcf, 0xb4, 0x1c, 0x82, - 0x49, 0xce, 0x27, 0x15, 0xe7, 0xa2, 0x46, 0xc1, 0x3a, 0xcf, 0xc5, 0xe7, 0xa0, 0xa8, 0x7d, 0x2a, - 0x9a, 0x85, 0xfc, 0x36, 0xdd, 0x95, 0xe3, 0x8b, 0xf9, 0x9f, 0x68, 0x3e, 0x32, 0xa0, 0x6a, 0x04, - 0x9f, 0xcf, 0x9d, 0x33, 0x16, 0xcf, 0xc3, 0x6c, 0x9c, 0x61, 0x96, 0xf6, 0xe6, 0x9f, 0x19, 0x30, - 0xaf, 0xf5, 0x02, 0xd3, 0x2d, 0xea, 0xd0, 0x6e, 0x9d, 0xa2, 0x15, 0x28, 0xf0, 0xb9, 0x74, 0x7b, - 0xa4, 0xee, 0x4f, 0xf5, 0x9c, 0xea, 0x48, 0xe1, 0x35, 0x9f, 0x80, 0xc3, 0x3a, 0xc1, 0xb2, 0xc8, - 0xdd, 0x6e, 0x59, 0xf4, 0x5a, 0xc4, 0xa5, 0x0b, 0xf9, 0xe8, 0xb2, 0xd8, 0xe0, 0x85, 0x58, 0xd2, - 0xcc, 0x77, 0xe1, 0x5e, 0xff, 0x7b, 0xae, 0xd2, 0x4e, 0xaf, 0x4d, 0x18, 0x0d, 0x3f, 0xea, 0xe0, - 0xa5, 0x77, 0x06, 0x46, 0xb6, 0xad, 0x6e, 0x23, 0xfe, 0x15, 0xdf, 0xb2, 0xba, 0x0d, 0x2c, 0x28, - 0xe6, 0x36, 0x4c, 0x95, 0x7b, 0x3d, 0xc7, 0xde, 0xa1, 0x8d, 0x1a, 0x23, 0x4d, 0x8a, 0xae, 0x03, - 0x10, 0x55, 0x50, 0x66, 0x02, 0xba, 0x78, 0xf6, 0x77, 0x4a, 0x72, 0xcf, 0x94, 0xf4, 0x3d, 0x53, - 0xea, 0x6d, 0x37, 0x79, 0x81, 0x5b, 0xe2, 0x5b, 0xb3, 0xb4, 0xf3, 0x44, 0xe9, 0xaa, 0xd5, 0xa1, - 0x95, 0xe9, 0xfd, 0xbd, 0x65, 0x28, 0x07, 0x08, 0x58, 0x43, 0x33, 0xbf, 0x67, 0xc0, 0xa9, 0xb2, - 0xd3, 0xb4, 0xab, 0xab, 0xe5, 0x5e, 0xef, 0x32, 0x25, 0x6d, 0xd6, 0xaa, 0x31, 0xc2, 0x3c, 0x17, - 0x9d, 0x87, 0x31, 0x57, 0xfc, 0xa5, 0x3a, 0xf3, 0x90, 0xbf, 0x3e, 0x25, 0xfd, 0xd6, 0xde, 0xf2, - 0x7c, 0x42, 0x43, 0x8a, 0x55, 0x2b, 0xf4, 0x08, 0x8c, 0x77, 0xa8, 0xeb, 0x92, 0xa6, 0x3f, 0xe2, - 0x33, 0x0a, 0x60, 0xfc, 0x55, 0x59, 0x8c, 0x7d, 0xba, 0xf9, 0xcb, 0x1c, 0xcc, 0x04, 0x58, 0x8a, - 0xfd, 0x11, 0x4c, 0xaf, 0x07, 0x93, 0x2d, 0xad, 0x87, 0x62, 0x96, 0x8b, 0x67, 0x5f, 0x48, 0xb9, - 0x93, 0x92, 0x06, 0xa9, 0x32, 0xaf, 0xd8, 0x4c, 0xea, 0xa5, 0x38, 0xc2, 0x06, 0x75, 0x00, 0xdc, - 0xdd, 0x6e, 0x5d, 0x31, 0x1d, 0x11, 0x4c, 0x9f, 0xcb, 0xc8, 0xb4, 0x16, 0x00, 0x54, 0x90, 0x62, - 0x09, 0x61, 0x19, 0xd6, 0x18, 0x98, 0x3f, 0x35, 0xe0, 0x64, 0x42, 0x3b, 0xf4, 0x62, 0x6c, 0x3e, - 0x1f, 0xec, 0x9b, 0x4f, 0xd4, 0xd7, 0x2c, 0x9c, 0xcd, 0xc7, 0x60, 0xc2, 0xa1, 0x3b, 0x16, 0x3f, - 0x29, 0xd4, 0x08, 0xcf, 0xaa, 0xf6, 0x13, 0x58, 0x95, 0xe3, 0xa0, 0x06, 0x7a, 0x14, 0x0a, 0xfe, - 0xdf, 0x7c, 0x98, 0xf3, 0x7c, 0x33, 0xf1, 0x89, 0xf3, 0xab, 0xba, 0x38, 0xa4, 0x9b, 0x7f, 0x6f, - 0xc0, 0x99, 0xb2, 0xc3, 0xac, 0x2d, 0x52, 0x67, 0xb6, 0xb3, 0xfb, 0x06, 0xdd, 0x6c, 0xd9, 0xf6, - 0x36, 0xa6, 0x75, 0x6a, 0xed, 0x50, 0xa7, 0x6a, 0x77, 0xb7, 0xac, 0x26, 0x7a, 0x13, 0x0a, 0x2e, - 0xad, 0x3b, 0x94, 0x61, 0xba, 0xa5, 0xb6, 0xc0, 0xc3, 0xda, 0x16, 0x28, 0xf1, 0xb3, 0x90, 0x2f, - 0xf8, 0x75, 0xbb, 0x4e, 0xda, 0x57, 0x36, 0xbf, 0x4b, 0xeb, 0x2c, 0xd8, 0x95, 0xe1, 0xc2, 0xa9, - 0xf9, 0x10, 0x38, 0x44, 0x43, 0x65, 0x98, 0xd9, 0xb1, 0x1c, 0xe6, 0x91, 0x36, 0xa6, 0x3d, 0xfb, - 0xb5, 0x70, 0x0d, 0x9d, 0x56, 0xcd, 0x66, 0xae, 0x45, 0xc9, 0x38, 0x5e, 0xdf, 0xdc, 0x85, 0xf9, - 0xb2, 0xc7, 0xec, 0x0d, 0xc7, 0xee, 0xd8, 0x5c, 0xce, 0x5d, 0xe9, 0x09, 0x69, 0x87, 0x08, 0xcc, - 0xb8, 0xb4, 0x4d, 0xeb, 0xfc, 0xd7, 0x86, 0xdd, 0xb6, 0xea, 0x4a, 0xe8, 0x55, 0x9e, 0xf5, 0xa1, - 0x6b, 0x51, 0xf2, 0xad, 0xbd, 0xe5, 0x6f, 0x44, 0x90, 0x62, 0x74, 0x1c, 0xc7, 0x33, 0x6f, 0xc0, - 0x62, 0xf9, 0x7d, 0xcf, 0xa1, 0xc7, 0x3d, 0x6c, 0xe6, 0x07, 0xb0, 0x54, 0xb1, 0xd8, 0xa6, 0x57, - 0xdf, 0xa6, 0xec, 0xd8, 0x99, 0xff, 0x21, 0x8c, 0x56, 0x5b, 0xc4, 0x61, 0x5c, 0xca, 0x38, 0xb4, - 0x67, 0xbf, 0x8e, 0xd7, 0xd5, 0xc8, 0x06, 0x52, 0x06, 0xcb, 0x62, 0xec, 0xd3, 0x53, 0x08, 0x88, - 0x47, 0x60, 0x7c, 0x87, 0x3a, 0x62, 0x8d, 0xe7, 0xa3, 0x60, 0xd7, 0x64, 0x31, 0xf6, 0xe9, 0xe6, - 0x3f, 0x1b, 0x30, 0x2f, 0xbe, 0x60, 0xd5, 0x72, 0xeb, 0xf6, 0x0e, 0x75, 0x76, 0x31, 0x75, 0xbd, - 0xf6, 0x21, 0x7f, 0xd0, 0x2a, 0xcc, 0xba, 0xb4, 0x23, 0x47, 0xd4, 0x65, 0x0e, 0xb1, 0xba, 0x4c, - 0x7d, 0xd9, 0x82, 0xaa, 0x3d, 0x5b, 0x8b, 0xd1, 0x71, 0x5f, 0x0b, 0xf4, 0x30, 0x4c, 0xa8, 0xcf, - 0xe6, 0xe2, 0x87, 0x6f, 0xc6, 0x49, 0xbe, 0x6f, 0x55, 0x9f, 0x5c, 0x1c, 0x50, 0xcd, 0x7f, 0x37, - 0x60, 0x4e, 0xf4, 0xaa, 0xe6, 0x6d, 0xba, 0x75, 0xc7, 0x12, 0xcb, 0xf8, 0x6e, 0xec, 0xd2, 0x79, - 0x98, 0x6e, 0xf8, 0x03, 0xbf, 0x6e, 0x75, 0x2c, 0x26, 0xe4, 0xea, 0x68, 0xe5, 0x1e, 0x85, 0x31, - 0xbd, 0x1a, 0xa1, 0xe2, 0x58, 0x6d, 0xf3, 0x67, 0x39, 0x98, 0xaa, 0xb6, 0x3d, 0x97, 0x05, 0x8b, - 0xf5, 0xf7, 0x60, 0xa2, 0xa3, 0x34, 0x24, 0xb5, 0x56, 0x7f, 0x37, 0xdd, 0x11, 0x2b, 0x17, 0x2e, - 0xd7, 0xae, 0x42, 0xd1, 0x1c, 0x96, 0xe1, 0x00, 0x15, 0xbd, 0x09, 0x23, 0x6e, 0x8f, 0xd6, 0xc5, - 0xd8, 0x14, 0xcf, 0x3e, 0x9b, 0xee, 0x04, 0x88, 0x7c, 0x64, 0xad, 0x47, 0xeb, 0xe1, 0xa0, 0xf2, - 0x5f, 0x58, 0x40, 0x22, 0x12, 0xc8, 0xf6, 0x7c, 0x96, 0xe3, 0x25, 0x0a, 0x2e, 0x8f, 0x97, 0xe9, - 0xe8, 0xb1, 0xe0, 0x1f, 0x00, 0xe6, 0x3f, 0xf2, 0xa5, 0xa1, 0xd7, 0x5f, 0xb7, 0x5c, 0x86, 0xde, - 0xee, 0x1b, 0xb5, 0x52, 0xba, 0x51, 0xe3, 0xad, 0xc5, 0x98, 0x05, 0xc7, 0x88, 0x5f, 0xa2, 0x8d, - 0xd8, 0x77, 0x60, 0xd4, 0x62, 0xb4, 0xe3, 0xeb, 0xbc, 0x4f, 0x0e, 0xd1, 0xab, 0x50, 0x89, 0x5b, - 0xe3, 0x48, 0x58, 0x02, 0x9a, 0x9f, 0xc4, 0x7b, 0xc3, 0x07, 0x93, 0xab, 0xda, 0xb3, 0x37, 0xa2, - 0xa2, 0xcc, 0x57, 0xf2, 0x53, 0x6a, 0x09, 0x89, 0x82, 0x30, 0x5c, 0xd9, 0x31, 0xb2, 0x8b, 0xfb, - 0xd8, 0x99, 0x9f, 0xe4, 0xe1, 0x64, 0xc2, 0xbc, 0xa0, 0x3a, 0x40, 0xdd, 0xee, 0x36, 0x2c, 0x69, - 0x04, 0xc8, 0x8f, 0x5a, 0x49, 0x37, 0xd6, 0x55, 0xbf, 0x5d, 0xb8, 0x40, 0x83, 0x22, 0x17, 0x6b, - 0xb0, 0xe8, 0x15, 0x40, 0xf6, 0xa6, 0xb0, 0x12, 0x1b, 0x97, 0xa4, 0xad, 0xe5, 0xcb, 0xc2, 0x7c, - 0x65, 0x51, 0xb5, 0x45, 0x57, 0xfa, 0x6a, 0xe0, 0x84, 0x56, 0x1c, 0xab, 0x4d, 0x5c, 0x76, 0x99, - 0x74, 0x1b, 0x6d, 0xda, 0xc0, 0x74, 0xcb, 0xa1, 0x6e, 0x4b, 0x6c, 0xd3, 0x42, 0x88, 0xb5, 0xde, - 0x57, 0x03, 0x27, 0xb4, 0x42, 0xdf, 0x4b, 0x9a, 0x18, 0xb9, 0x28, 0x5e, 0x1c, 0x6a, 0x62, 0x56, - 0x29, 0x23, 0x56, 0xdb, 0xcd, 0x34, 0x33, 0x42, 0xe4, 0xcb, 0x99, 0x09, 0x8e, 0xe7, 0xab, 0xc4, - 0xdd, 0xbe, 0x5b, 0x45, 0x47, 0xe4, 0x23, 0x07, 0x89, 0x0e, 0xf3, 0x5f, 0x0d, 0x58, 0x48, 0xea, - 0xd5, 0x31, 0x6c, 0xef, 0x77, 0xa3, 0xdb, 0xfb, 0xf9, 0x4c, 0xdb, 0x3b, 0xf2, 0xb1, 0x03, 0x76, - 0xf9, 0x5b, 0x30, 0x59, 0xf5, 0x1c, 0x87, 0x76, 0x99, 0x34, 0xa4, 0xbe, 0x05, 0xa3, 0xae, 0xd5, - 0x55, 0xf6, 0x44, 0x36, 0x1b, 0xaa, 0xc0, 0xc1, 0x6b, 0xbc, 0x31, 0x96, 0x18, 0xe6, 0x5f, 0xe4, - 0xe1, 0xa4, 0x7f, 0xca, 0xd0, 0x86, 0xaf, 0xc0, 0xba, 0xa8, 0x01, 0x93, 0x8d, 0xb0, 0x98, 0x29, - 0x85, 0x3f, 0x0b, 0xaf, 0xc0, 0xa8, 0xd0, 0xe0, 0x19, 0x8e, 0xa0, 0xa2, 0x37, 0x20, 0xdf, 0xb4, - 0x98, 0x92, 0x03, 0xe7, 0xd2, 0x8d, 0xdc, 0x25, 0x2b, 0xae, 0xad, 0x54, 0x8a, 0x8a, 0x55, 0xfe, - 0x92, 0xc5, 0x30, 0x47, 0x44, 0x9b, 0x30, 0x66, 0x75, 0x48, 0x93, 0x66, 0x9c, 0x95, 0x35, 0xde, - 0x26, 0x8e, 0x1e, 0x9c, 0x25, 0x82, 0xea, 0x62, 0x85, 0xcc, 0x79, 0xd4, 0xb9, 0x96, 0x21, 0x6d, - 0x83, 0xf4, 0x33, 0x9f, 0xa0, 0x6f, 0x85, 0x3c, 0x04, 0xd5, 0xc5, 0x0a, 0xd9, 0xfc, 0x32, 0x07, - 0xb3, 0xe1, 0xf8, 0x55, 0xed, 0x4e, 0xc7, 0x62, 0x68, 0x11, 0x72, 0x56, 0x43, 0x29, 0x31, 0xa0, - 0x1a, 0xe6, 0xd6, 0x56, 0x71, 0xce, 0x6a, 0xa0, 0x87, 0x60, 0x6c, 0xd3, 0x21, 0xdd, 0x7a, 0x4b, - 0x29, 0x2f, 0x01, 0x70, 0x45, 0x94, 0x62, 0x45, 0x45, 0xf7, 0x43, 0x9e, 0x91, 0xa6, 0xd2, 0x59, - 0x82, 0xf1, 0xbb, 0x4a, 0x9a, 0x98, 0x97, 0x73, 0x65, 0xc9, 0xf5, 0xc4, 0x1e, 0x56, 0xb2, 0x2e, - 0x50, 0x96, 0x6a, 0xb2, 0x18, 0xfb, 0x74, 0xce, 0x91, 0x78, 0xac, 0x65, 0x3b, 0x0b, 0xa3, 0x51, - 0x8e, 0x65, 0x51, 0x8a, 0x15, 0x95, 0x9b, 0xc2, 0x75, 0xf1, 0xfd, 0x8c, 0x3a, 0x0b, 0x63, 0x51, - 0x53, 0xb8, 0xea, 0x13, 0x70, 0x58, 0x07, 0xbd, 0x03, 0xc5, 0xba, 0x43, 0x09, 0xb3, 0x9d, 0x55, - 0xc2, 0xe8, 0xc2, 0x78, 0xe6, 0x15, 0x38, 0xb3, 0xbf, 0xb7, 0x5c, 0xac, 0x86, 0x10, 0x58, 0xc7, - 0x33, 0xbf, 0x9f, 0x87, 0x85, 0x70, 0x68, 0xc5, 0xdc, 0x86, 0x1e, 0x10, 0x35, 0x3c, 0xc6, 0x80, - 0xe1, 0x79, 0x08, 0xc6, 0x1a, 0x56, 0x93, 0xba, 0x2c, 0x3e, 0xca, 0xab, 0xa2, 0x14, 0x2b, 0x2a, - 0xfa, 0xd3, 0x98, 0xd7, 0x6b, 0x54, 0x2c, 0x94, 0x2b, 0xe9, 0x16, 0xca, 0xa0, 0x8f, 0x1b, 0xc2, - 0xf5, 0x85, 0xde, 0x80, 0x82, 0xe8, 0xfb, 0x90, 0x7b, 0x59, 0x98, 0xbd, 0x55, 0x1f, 0x00, 0x87, - 0x58, 0x77, 0xec, 0x18, 0xfb, 0x00, 0x96, 0x56, 0xed, 0xfa, 0x36, 0x75, 0x2e, 0x7b, 0x9b, 0xc7, - 0x6e, 0x7f, 0xbd, 0x05, 0xe8, 0xc2, 0xcd, 0x9e, 0x43, 0x5d, 0x6e, 0x37, 0x5c, 0x23, 0x8e, 0x45, - 0x36, 0xdb, 0xf4, 0xb0, 0x1c, 0xaf, 0x9f, 0x8f, 0xc0, 0xf8, 0x45, 0x87, 0x5a, 0xcd, 0x16, 0x3b, - 0x86, 0xb3, 0xf5, 0x01, 0x18, 0x25, 0x6d, 0x8b, 0xb8, 0x62, 0x9b, 0x68, 0x9f, 0x54, 0xe6, 0x85, - 0x58, 0xd2, 0xd0, 0x5b, 0x30, 0x66, 0x3b, 0x56, 0xd3, 0xea, 0x2e, 0x14, 0xc4, 0x47, 0xa4, 0x54, - 0x45, 0x55, 0x2f, 0xae, 0x88, 0xa6, 0xe1, 0x5a, 0x97, 0xbf, 0xb1, 0x82, 0x44, 0xd7, 0x61, 0x5c, - 0xee, 0x5d, 0x5f, 0x1e, 0xae, 0xa4, 0x96, 0xe7, 0x72, 0xfb, 0x87, 0x32, 0x46, 0xfe, 0x76, 0xb1, - 0x0f, 0x88, 0x6a, 0x81, 0x38, 0x1f, 0x11, 0xd0, 0x8f, 0x66, 0x10, 0xe7, 0x03, 0xe5, 0x77, 0x2d, - 0x90, 0xdf, 0xa3, 0x59, 0x40, 0x85, 0x84, 0x1e, 0x24, 0xb0, 0xf9, 0x10, 0x2b, 0x1b, 0x66, 0x6c, - 0x88, 0x21, 0x3e, 0xc0, 0x7a, 0xf9, 0x61, 0x1e, 0xe6, 0x54, 0xcd, 0xaa, 0xdd, 0x56, 0x1e, 0x14, - 0x75, 0x1c, 0xe4, 0x13, 0x8f, 0x03, 0xcb, 0x57, 0x4e, 0xe4, 0x11, 0x5b, 0xc9, 0xf4, 0x35, 0x21, - 0x8f, 0x92, 0x50, 0x48, 0xa4, 0xb0, 0x09, 0x66, 0x49, 0xd5, 0x52, 0x6a, 0x0a, 0xfa, 0x13, 0x03, - 0x4e, 0xee, 0x50, 0xc7, 0xda, 0xb2, 0xea, 0x42, 0x18, 0x5c, 0xb6, 0x5c, 0x66, 0x3b, 0xbb, 0xea, - 0x00, 0x7e, 0x26, 0x1d, 0xe7, 0x6b, 0x1a, 0xc0, 0x5a, 0x77, 0xcb, 0xae, 0xdc, 0xa7, 0xb8, 0x9d, - 0xbc, 0xd6, 0x0f, 0x8d, 0x93, 0xf8, 0x2d, 0xf6, 0x00, 0xc2, 0xaf, 0x4d, 0x90, 0x45, 0xeb, 0xfa, - 0xe6, 0x4d, 0xfd, 0x61, 0x7e, 0x67, 0x7d, 0xc9, 0xa2, 0xcb, 0xb0, 0x57, 0xe1, 0xb4, 0x3f, 0x62, - 0x5c, 0x2e, 0x5a, 0x76, 0xb7, 0xea, 0x58, 0x8c, 0x3a, 0x16, 0x41, 0x67, 0x01, 0x68, 0x20, 0x61, - 0x94, 0x44, 0x09, 0x36, 0x72, 0x28, 0x7b, 0xb0, 0x56, 0xcb, 0xfc, 0xb9, 0x01, 0x45, 0x85, 0x77, - 0x0c, 0xea, 0x2b, 0x8e, 0xaa, 0xaf, 0x8f, 0x67, 0x1a, 0x8e, 0x01, 0x1a, 0xab, 0x03, 0x53, 0x11, - 0x99, 0x81, 0x9e, 0x56, 0xe1, 0x02, 0x39, 0x00, 0xbf, 0xa5, 0x87, 0x0b, 0x6e, 0xed, 0x2d, 0xcf, - 0x45, 0x2a, 0x87, 0x31, 0x84, 0x83, 0xfd, 0x30, 0xcf, 0x4f, 0xfc, 0xe8, 0xaf, 0x96, 0x4f, 0x7c, - 0xf8, 0xeb, 0x33, 0x27, 0xb8, 0xc5, 0x39, 0x1b, 0x9f, 0xa4, 0x14, 0xa2, 0x3c, 0x14, 0x89, 0x13, - 0x47, 0x2a, 0x12, 0x73, 0x47, 0x27, 0x12, 0xf3, 0x47, 0x21, 0x12, 0x47, 0x0e, 0x4d, 0x24, 0x9a, - 0xff, 0x64, 0xc0, 0x74, 0x30, 0x33, 0xef, 0x79, 0x5c, 0x2f, 0x0a, 0x47, 0xdd, 0x38, 0xfc, 0x51, - 0x7f, 0x17, 0xc6, 0x5d, 0xdb, 0x73, 0xea, 0x42, 0xf9, 0xe7, 0xe8, 0x4f, 0x65, 0x93, 0xc1, 0xb2, - 0xad, 0xa6, 0xf1, 0xca, 0x02, 0xec, 0xa3, 0x9a, 0xbf, 0xcc, 0x07, 0x1d, 0x52, 0x34, 0xa9, 0x10, - 0x3a, 0x5c, 0x5d, 0xe6, 0x1d, 0x9a, 0xd0, 0x15, 0x42, 0x5e, 0x8a, 0x15, 0x15, 0x99, 0xe2, 0x78, - 0xf0, 0xed, 0x92, 0x42, 0x05, 0x94, 0x94, 0x17, 0x93, 0x20, 0x29, 0xa8, 0x07, 0xb3, 0x0e, 0x7d, - 0xcf, 0xb3, 0x1c, 0xda, 0xa8, 0xd9, 0x64, 0x9b, 0x2b, 0x60, 0xca, 0x21, 0x96, 0x72, 0xdf, 0xaf, - 0x7a, 0xd2, 0x79, 0x51, 0x99, 0xdf, 0xdf, 0x5b, 0x9e, 0xc5, 0x31, 0x2c, 0xdc, 0x87, 0x8e, 0x6c, - 0x98, 0x27, 0x3b, 0xc4, 0x6a, 0x93, 0x4d, 0xab, 0x6d, 0xb1, 0xdd, 0x1a, 0x73, 0x08, 0xa3, 0xcd, - 0x5d, 0xa5, 0xfa, 0xbf, 0xa0, 0xfa, 0x32, 0x5f, 0x4e, 0xa8, 0x73, 0x6b, 0x6f, 0xf9, 0x3e, 0x35, - 0x16, 0x49, 0x64, 0x9c, 0x08, 0x8c, 0x7e, 0x60, 0xc0, 0x3c, 0x49, 0x08, 0x35, 0x08, 0x13, 0x22, - 0xb5, 0x25, 0x95, 0x14, 0xac, 0xa8, 0x2c, 0x88, 0x2f, 0x4d, 0xa0, 0xe0, 0x44, 0x8e, 0xe6, 0xaf, - 0xc6, 0x03, 0x61, 0xa5, 0x7c, 0x54, 0x1f, 0x40, 0xb1, 0x2e, 0xed, 0xed, 0xf6, 0xee, 0x5a, 0x57, - 0x6d, 0xaf, 0xd5, 0x21, 0xce, 0xf1, 0x52, 0x35, 0x84, 0x89, 0x29, 0xea, 0x1a, 0x05, 0xeb, 0xdc, - 0xd0, 0x0d, 0x00, 0x79, 0xa8, 0xd1, 0xc6, 0x5a, 0x57, 0x9d, 0xda, 0xd5, 0x61, 0x78, 0x5f, 0x0b, - 0x50, 0x24, 0xeb, 0xe0, 0xd4, 0x09, 0x09, 0x58, 0x63, 0xc5, 0x7b, 0xed, 0x07, 0x54, 0x2f, 0xda, - 0x8e, 0x92, 0x57, 0x43, 0xf5, 0xba, 0x1c, 0xc2, 0xc4, 0xcd, 0x93, 0x90, 0x82, 0x75, 0x6e, 0xc8, - 0xd6, 0x8e, 0x38, 0x29, 0x79, 0xca, 0xc3, 0x70, 0xf6, 0x93, 0x03, 0x24, 0xdb, 0xe0, 0xd4, 0xf3, - 0x8b, 0xc3, 0x53, 0x6f, 0xd1, 0x81, 0xd9, 0xf8, 0xe4, 0x24, 0xa8, 0x0a, 0x97, 0xa3, 0xaa, 0xc2, - 0xd9, 0x94, 0xd2, 0x50, 0x73, 0xd6, 0xe8, 0x39, 0x04, 0x0e, 0xcc, 0xc4, 0x26, 0x25, 0x81, 0xe5, - 0x5a, 0x94, 0xe5, 0x93, 0x59, 0xd4, 0x26, 0x15, 0x69, 0xd7, 0x79, 0xba, 0x30, 0x1b, 0x9f, 0x8e, - 0x43, 0x63, 0x1a, 0x09, 0xef, 0xeb, 0x4c, 0x3f, 0x80, 0xa9, 0xc8, 0x4c, 0x24, 0x70, 0xbc, 0x1a, - 0xe5, 0x78, 0x5e, 0x13, 0x6c, 0x61, 0x2e, 0xcf, 0xbb, 0x41, 0xb2, 0x4f, 0x28, 0xe3, 0x22, 0x15, - 0xb8, 0xb0, 0x7b, 0xa5, 0x76, 0xe5, 0x35, 0x5d, 0x19, 0xfb, 0xcb, 0x1c, 0x14, 0x82, 0xf3, 0x33, - 0x4b, 0xd0, 0x47, 0xaa, 0xd1, 0xb9, 0x03, 0xbc, 0x2a, 0xf9, 0x34, 0x5e, 0x95, 0x91, 0xc1, 0x5e, - 0x15, 0x3f, 0x99, 0x60, 0xec, 0xf6, 0xc9, 0x04, 0x9a, 0x57, 0x65, 0x3c, 0xbd, 0x57, 0x65, 0xe2, - 0x60, 0xaf, 0x8a, 0xf9, 0xd7, 0x06, 0xa0, 0x7e, 0x17, 0x5a, 0x96, 0x81, 0x22, 0x71, 0xad, 0xe6, - 0x99, 0xac, 0xfe, 0x8c, 0x83, 0x94, 0x1b, 0xf3, 0x26, 0xdc, 0x77, 0xc9, 0x62, 0x5f, 0x87, 0x4b, - 0x40, 0x72, 0x5e, 0x27, 0xc7, 0xcf, 0xf9, 0xa3, 0x71, 0x98, 0xb9, 0x64, 0x0d, 0x1d, 0xb3, 0x64, - 0x70, 0x5a, 0x8e, 0x5e, 0x10, 0x6b, 0x0f, 0x8e, 0x71, 0xb9, 0xa6, 0x9f, 0x57, 0x4d, 0x4f, 0x57, - 0x93, 0xab, 0xdd, 0x1a, 0x4c, 0xc2, 0x83, 0xa0, 0x53, 0x6f, 0x8c, 0x17, 0x60, 0xca, 0x65, 0x8e, - 0x55, 0x67, 0x32, 0x2a, 0xea, 0x2e, 0x14, 0x85, 0x9a, 0x74, 0x4a, 0x55, 0x9f, 0xaa, 0xe9, 0x44, - 0x1c, 0xad, 0x9b, 0x18, 0x6c, 0x1d, 0xc9, 0x1c, 0x6c, 0x5d, 0x81, 0x02, 0x69, 0xb7, 0xed, 0x1b, - 0x57, 0x49, 0xd3, 0x55, 0xae, 0xca, 0x60, 0x42, 0xca, 0x3e, 0x01, 0x87, 0x75, 0xd0, 0xcb, 0x30, - 0x1b, 0xfc, 0xc0, 0xb4, 0x49, 0x6f, 0x52, 0x77, 0x61, 0x4a, 0x68, 0x6d, 0x42, 0xaf, 0x2a, 0xc7, - 0x68, 0xb8, 0xaf, 0x36, 0x2a, 0x01, 0x58, 0xcd, 0xae, 0xed, 0x50, 0xc1, 0x73, 0x4c, 0xb4, 0x15, - 0x69, 0x4c, 0x6b, 0x41, 0x29, 0xd6, 0x6a, 0xa0, 0x2a, 0xcc, 0x85, 0xbf, 0x7c, 0x96, 0xd3, 0xa2, - 0xd9, 0xa9, 0xfd, 0xbd, 0xe5, 0xb9, 0xb5, 0x38, 0x11, 0xf7, 0xd7, 0xe7, 0xa3, 0x15, 0x1a, 0x93, - 0x17, 0xad, 0x36, 0x17, 0x0c, 0x93, 0xd1, 0xd1, 0xba, 0x10, 0xa3, 0xe3, 0xbe, 0x16, 0xa8, 0x06, - 0xa7, 0xac, 0xae, 0x4b, 0xeb, 0x9e, 0x43, 0x6b, 0xdb, 0x56, 0xef, 0xea, 0x7a, 0x4d, 0x9c, 0x31, - 0xbb, 0x42, 0x1c, 0x4d, 0x54, 0xee, 0x57, 0x50, 0xa7, 0xd6, 0x92, 0x2a, 0xe1, 0xe4, 0xb6, 0xe8, - 0x29, 0x98, 0xb4, 0xba, 0xf5, 0xb6, 0xd7, 0xa0, 0x1b, 0x84, 0xb5, 0xdc, 0x85, 0x09, 0xd1, 0xb5, - 0xd9, 0xfd, 0xbd, 0xe5, 0xc9, 0x35, 0xad, 0x1c, 0x47, 0x6a, 0xf1, 0x56, 0xf4, 0xa6, 0xd6, 0xaa, - 0x10, 0xb6, 0xba, 0x70, 0x53, 0x6f, 0xa5, 0xd7, 0x4a, 0x88, 0xad, 0x43, 0xa6, 0xd8, 0xfa, 0x0d, - 0x58, 0xbc, 0x64, 0x31, 0x4a, 0xbe, 0x0e, 0x09, 0x74, 0x99, 0x38, 0x9b, 0xb6, 0x73, 0xec, 0x9c, - 0x7f, 0x92, 0x83, 0x31, 0x99, 0x01, 0x86, 0x9e, 0x8e, 0xa5, 0x59, 0xdd, 0xdf, 0x97, 0x66, 0x55, - 0x4c, 0xca, 0x96, 0x33, 0x61, 0xcc, 0x72, 0x5d, 0x2f, 0x6a, 0xde, 0xac, 0x89, 0x12, 0xac, 0x28, - 0x22, 0x6c, 0x22, 0xba, 0xa2, 0xfc, 0xd0, 0x77, 0x78, 0xf6, 0x4b, 0x1e, 0x72, 0x70, 0xb0, 0x42, - 0xe6, 0x3c, 0x6c, 0x8f, 0xf5, 0x3c, 0xa6, 0x0c, 0x8a, 0x43, 0xe1, 0x71, 0x45, 0x20, 0x62, 0x85, - 0x6c, 0x7e, 0x62, 0xc0, 0x8c, 0x1c, 0x83, 0x6a, 0x8b, 0xd6, 0xb7, 0x6b, 0x8c, 0xf6, 0xd0, 0x19, - 0x18, 0xf1, 0x5c, 0xea, 0xc6, 0xfd, 0x0d, 0xaf, 0xbb, 0xd4, 0xc5, 0x82, 0xa2, 0xf5, 0x3e, 0x77, - 0x54, 0xbd, 0x37, 0xcf, 0x81, 0x36, 0x39, 0x22, 0x85, 0x51, 0x66, 0xf2, 0x49, 0x0d, 0x2c, 0x1f, - 0x1e, 0x22, 0xb2, 0xd6, 0x2e, 0xf6, 0xe9, 0xe6, 0x4f, 0x73, 0x30, 0x2a, 0x5c, 0x02, 0x59, 0x4e, - 0x9e, 0x03, 0x42, 0x49, 0x61, 0xac, 0x64, 0xe4, 0xb6, 0xb1, 0x12, 0x37, 0x29, 0x54, 0xf2, 0x62, - 0x06, 0xaf, 0xc6, 0x30, 0x29, 0xc1, 0x77, 0x1a, 0xbe, 0xf8, 0x8d, 0x01, 0xf3, 0x49, 0x41, 0xc3, - 0x2c, 0xe3, 0xf7, 0x18, 0x4c, 0xf4, 0xda, 0x84, 0x6d, 0xd9, 0x4e, 0x27, 0x9e, 0x94, 0xb8, 0xa1, - 0xca, 0x71, 0x50, 0x03, 0x39, 0x00, 0x8e, 0xbf, 0x9f, 0x7d, 0xdf, 0xcf, 0xf9, 0x3b, 0x0b, 0x28, - 0x85, 0xb6, 0x61, 0x50, 0xe4, 0x62, 0x8d, 0x8b, 0xf9, 0xd9, 0x28, 0xcc, 0x89, 0x26, 0xc3, 0x2a, - 0x27, 0x3d, 0xb8, 0x47, 0x78, 0x98, 0xfa, 0x75, 0x13, 0xb9, 0x6a, 0xce, 0xa9, 0x96, 0xf7, 0xac, - 0x25, 0xd6, 0xba, 0x35, 0x90, 0x82, 0x07, 0xe0, 0xf6, 0x2b, 0x1c, 0x90, 0x41, 0xe1, 0x38, 0x2b, - 0xb2, 0x54, 0x7c, 0x55, 0xa3, 0x18, 0xf5, 0xda, 0x6a, 0x4a, 0x86, 0x56, 0xeb, 0xff, 0x8c, 0x7a, - 0xa1, 0xaf, 0xd6, 0xf1, 0x03, 0x57, 0xeb, 0x40, 0x35, 0x62, 0xe2, 0x0e, 0xd4, 0x88, 0xfe, 0xa3, - 0xbd, 0x90, 0xe9, 0x68, 0xff, 0xd4, 0x80, 0xf1, 0x0d, 0xc7, 0x16, 0xd1, 0xeb, 0xa3, 0x8f, 0xcc, - 0xbd, 0x15, 0xcb, 0x6a, 0x7b, 0x32, 0x75, 0xde, 0x0b, 0x07, 0x3b, 0x20, 0x22, 0xf4, 0xb3, 0x1c, - 0x4c, 0xa9, 0x9a, 0x77, 0x77, 0x06, 0x60, 0xe4, 0x23, 0x0f, 0x3b, 0x03, 0x30, 0x0a, 0x7e, 0x70, - 0x06, 0x60, 0xa4, 0xfe, 0x5d, 0x9b, 0x01, 0x18, 0xf9, 0xca, 0x41, 0x19, 0x80, 0xb9, 0x58, 0x6f, - 0x44, 0x06, 0xe0, 0x1f, 0xc0, 0x5c, 0xcf, 0xf7, 0x73, 0x8a, 0x04, 0x6b, 0x8b, 0xfa, 0x11, 0xc0, - 0xa7, 0x33, 0x66, 0x5d, 0xc9, 0xfc, 0xec, 0xca, 0xbd, 0x8a, 0xfb, 0xdc, 0x46, 0x1c, 0x17, 0xf7, - 0xb3, 0x4a, 0xce, 0x40, 0xcc, 0x1d, 0x7f, 0x06, 0x62, 0xc2, 0xba, 0xf8, 0xff, 0x0c, 0xc4, 0xaf, - 0x3d, 0x03, 0xf1, 0xe7, 0x06, 0x14, 0xd5, 0xcc, 0xdc, 0xb5, 0xf1, 0x4d, 0xf5, 0x7d, 0x03, 0x76, - 0xdd, 0x17, 0x06, 0x4c, 0x6a, 0xf2, 0xd9, 0x45, 0x2d, 0x80, 0x1b, 0xc4, 0xa1, 0x2d, 0x3b, 0xd0, - 0xfe, 0x53, 0x47, 0x9d, 0xde, 0xf0, 0xdb, 0x09, 0xa4, 0x70, 0x65, 0x05, 0xe5, 0x2e, 0xd6, 0xb0, - 0xd1, 0x77, 0xb4, 0x00, 0x92, 0x14, 0xee, 0xa9, 0xb8, 0x08, 0x1f, 0xad, 0xe4, 0xa0, 0x0b, 0x46, - 0x2d, 0xec, 0x64, 0xfe, 0xc2, 0x08, 0x8e, 0x92, 0xc4, 0xad, 0x92, 0x3f, 0x9a, 0xad, 0x52, 0x83, - 0x51, 0x2e, 0x99, 0xfd, 0x2b, 0x45, 0x67, 0x33, 0x9f, 0x8e, 0xae, 0xca, 0x6a, 0xe4, 0x7f, 0x62, - 0x89, 0x65, 0xfe, 0x38, 0x07, 0x85, 0x40, 0x52, 0x1d, 0xc3, 0x91, 0xf8, 0x7a, 0xe4, 0x48, 0x7c, - 0x32, 0xa3, 0x8c, 0x1d, 0x78, 0x1c, 0xbe, 0x13, 0x3b, 0x0e, 0xb3, 0x0a, 0xef, 0x03, 0x8e, 0xc2, - 0x7f, 0x90, 0x33, 0x2e, 0xeb, 0x1e, 0xc3, 0x56, 0xbc, 0x1a, 0xdd, 0x8a, 0x2b, 0x19, 0x7b, 0x33, - 0x60, 0x33, 0x7e, 0x98, 0x83, 0x99, 0xd8, 0x71, 0x85, 0x1e, 0x10, 0x8b, 0xaa, 0xe9, 0x07, 0xfe, - 0x83, 0x86, 0x2a, 0x54, 0x21, 0x68, 0x68, 0x87, 0x9b, 0x08, 0x81, 0xf1, 0x60, 0x3b, 0x6a, 0x90, - 0x5f, 0x1a, 0xea, 0x84, 0xf4, 0x41, 0x2a, 0x73, 0xd2, 0xba, 0xd0, 0x70, 0x71, 0x94, 0x0d, 0xda, - 0x88, 0xc5, 0x3e, 0x2f, 0x74, 0xc9, 0x66, 0x9b, 0xca, 0xd0, 0xc3, 0x44, 0xe5, 0x1b, 0x41, 0xb4, - 0x35, 0xa1, 0x0e, 0x4e, 0x6c, 0x69, 0xfe, 0x8d, 0x01, 0xa7, 0x07, 0x7c, 0x4f, 0x8a, 0x14, 0x88, - 0x36, 0x4c, 0x89, 0x4b, 0xba, 0xc1, 0x38, 0xf8, 0xab, 0x38, 0xdd, 0xcc, 0xeb, 0x4d, 0x65, 0xef, - 0x23, 0x45, 0x38, 0x0a, 0x6e, 0x7e, 0x96, 0x03, 0x14, 0x7c, 0x6b, 0x96, 0x4c, 0x8d, 0x77, 0x60, - 0x7c, 0x4b, 0x46, 0xfb, 0xee, 0x2c, 0x73, 0xa7, 0x52, 0xd4, 0x93, 0x97, 0x7c, 0x4c, 0xf4, 0xe6, - 0xe1, 0xec, 0x35, 0xe8, 0xdf, 0x67, 0xe8, 0x3a, 0xc0, 0x96, 0xd5, 0xb5, 0xdc, 0xd6, 0x90, 0xd9, - 0x97, 0xc2, 0xa6, 0xbb, 0x18, 0x20, 0x60, 0x0d, 0xcd, 0xfc, 0xf3, 0x9c, 0xb6, 0x87, 0x85, 0xf2, - 0x97, 0x6a, 0xed, 0x3f, 0x12, 0x1d, 0xcc, 0x42, 0x7f, 0x56, 0x57, 0x30, 0x30, 0xd7, 0x61, 0x64, - 0x87, 0x38, 0x7e, 0x46, 0x48, 0xca, 0x24, 0xed, 0xfe, 0xb4, 0xca, 0x70, 0x4e, 0xaf, 0x11, 0xc7, - 0xc5, 0x02, 0x93, 0x2b, 0xc6, 0x2e, 0xa3, 0x3d, 0xff, 0x70, 0xc9, 0x2c, 0x38, 0x19, 0xed, 0xe9, - 0x1d, 0xa4, 0x3d, 0x71, 0x02, 0xd0, 0x9e, 0x6b, 0xfe, 0xc7, 0xb8, 0x26, 0x15, 0xd4, 0x79, 0x76, - 0x98, 0x9a, 0xd4, 0xd3, 0xfe, 0x25, 0x6b, 0x39, 0xca, 0xcb, 0x91, 0x4b, 0xd6, 0xb7, 0xf6, 0x96, - 0xa7, 0xc3, 0xfd, 0xa8, 0x5d, 0xbb, 0xce, 0x70, 0x9d, 0x58, 0x5f, 0xef, 0xa3, 0x47, 0xb0, 0xde, - 0x7f, 0x1f, 0xe6, 0xb6, 0xe2, 0x69, 0x7e, 0x2a, 0xc7, 0xfa, 0xd9, 0x21, 0xb3, 0x04, 0xa5, 0x17, - 0xa1, 0xaf, 0x18, 0xf7, 0x33, 0x42, 0xb6, 0x7f, 0x89, 0x59, 0xf8, 0x4e, 0x65, 0x24, 0x20, 0xf5, - 0x9e, 0x8b, 0x79, 0x5d, 0xe3, 0xd7, 0x97, 0x25, 0x24, 0x8e, 0x30, 0x40, 0x6f, 0x40, 0xc1, 0x65, - 0xc4, 0x91, 0x09, 0xd0, 0x93, 0xc3, 0x25, 0x40, 0xd7, 0x7c, 0x00, 0x1c, 0x62, 0xc5, 0x36, 0xf7, - 0xd8, 0x61, 0x6e, 0x6e, 0xf4, 0x74, 0x90, 0x89, 0xc2, 0xfb, 0x29, 0xbc, 0x1c, 0xf9, 0xbe, 0x1c, - 0x12, 0x4e, 0xc2, 0x7a, 0x3d, 0xf4, 0xb1, 0x01, 0xa7, 0xf8, 0x2e, 0xb8, 0x70, 0x93, 0xd6, 0x3d, - 0x3e, 0xdc, 0x7e, 0x34, 0x7e, 0xa1, 0x98, 0xc5, 0x06, 0xab, 0x25, 0x41, 0x84, 0x2e, 0x9b, 0x44, - 0x32, 0x4e, 0x66, 0x8c, 0xde, 0x95, 0x5a, 0x1e, 0x15, 0x6e, 0xb8, 0x3b, 0xf7, 0x7a, 0x07, 0x1a, - 0x9f, 0x14, 0x68, 0x8c, 0x9a, 0x3f, 0x1e, 0xd1, 0xe5, 0x60, 0x3a, 0x5f, 0xfc, 0x75, 0x18, 0x61, - 0xc4, 0xdd, 0x56, 0xdb, 0xeb, 0xc5, 0x21, 0xee, 0x23, 0x85, 0x9b, 0x6c, 0x82, 0x63, 0x8b, 0x22, - 0x81, 0x89, 0x16, 0x21, 0x47, 0xdc, 0x78, 0x36, 0x41, 0xd9, 0xc5, 0x39, 0xe2, 0x8a, 0x4c, 0x83, - 0x2d, 0xe5, 0x3c, 0x0b, 0x33, 0x0d, 0xb6, 0x70, 0xce, 0x12, 0xd7, 0xb8, 0xeb, 0x76, 0x97, 0x59, - 0x5d, 0x8f, 0x5e, 0xe9, 0x5e, 0x70, 0x1c, 0xdb, 0x51, 0xae, 0xb2, 0xe0, 0x1a, 0x77, 0x35, 0x4a, - 0xc6, 0xf1, 0xfa, 0xe8, 0x4d, 0x18, 0x75, 0x28, 0x73, 0x76, 0xd5, 0x49, 0x73, 0x6e, 0x08, 0xa1, - 0x8a, 0x79, 0x7b, 0x39, 0xca, 0xe2, 0x4f, 0x2c, 0x11, 0x83, 0xb3, 0x60, 0xec, 0x08, 0xce, 0x82, - 0x30, 0x32, 0x92, 0x3f, 0xb2, 0xc8, 0xc8, 0x4f, 0x0c, 0x4d, 0xf9, 0x08, 0x3a, 0x8a, 0x5e, 0x87, - 0x71, 0x66, 0x75, 0xa8, 0xed, 0xb1, 0x6c, 0x5a, 0x6f, 0x90, 0x68, 0x27, 0x44, 0xec, 0x55, 0x09, - 0x81, 0x7d, 0x2c, 0x74, 0x1e, 0xa6, 0x29, 0x9f, 0x91, 0xab, 0x2d, 0x7e, 0x64, 0xd8, 0x6d, 0xa9, - 0xe2, 0x4d, 0x85, 0x7e, 0xca, 0x0b, 0x11, 0x2a, 0x8e, 0xd5, 0x36, 0x3f, 0xd3, 0xf5, 0xf3, 0xff, - 0xfd, 0x77, 0xf4, 0x94, 0xe7, 0xed, 0x58, 0x2f, 0xe7, 0x0d, 0xed, 0x79, 0x3b, 0xf0, 0x56, 0xde, - 0xdb, 0x70, 0x4f, 0xb2, 0x28, 0x38, 0x94, 0xd7, 0x53, 0x7e, 0x11, 0x1f, 0x2b, 0xa1, 0xda, 0xf9, - 0xdb, 0xcf, 0x38, 0x4a, 0x55, 0x2c, 0x77, 0xd8, 0xaa, 0x98, 0xa3, 0x77, 0x45, 0xbd, 0x35, 0x83, - 0xde, 0x51, 0xeb, 0xcc, 0xc8, 0xf2, 0x7a, 0x49, 0x1f, 0xcc, 0xc0, 0xb5, 0xf6, 0x2b, 0x03, 0x4e, - 0x25, 0xd6, 0x0e, 0xc6, 0x30, 0x77, 0x94, 0x63, 0x68, 0x1c, 0xf6, 0x18, 0xee, 0xc0, 0xbd, 0xdf, - 0xf6, 0xc8, 0xb1, 0xbf, 0x2a, 0x62, 0xfe, 0x28, 0x07, 0xb3, 0x98, 0xf6, 0xec, 0x48, 0xe0, 0x6f, - 0xc3, 0xbf, 0xb5, 0x99, 0xc1, 0x4e, 0x8a, 0x65, 0x36, 0x55, 0xc6, 0x23, 0xd7, 0x35, 0xf9, 0x36, - 0xed, 0xf8, 0x4a, 0x71, 0x6a, 0xb1, 0xd3, 0x17, 0x92, 0x94, 0x27, 0x96, 0x0c, 0x6e, 0x4a, 0x40, - 0x8e, 0x2c, 0xd2, 0xd0, 0xd5, 0xa1, 0xf2, 0x6c, 0x86, 0x84, 0xf6, 0x7e, 0x64, 0x51, 0x8c, 0x25, - 0xa0, 0xf9, 0x49, 0x0e, 0xa4, 0x4d, 0x75, 0x0c, 0x52, 0xf9, 0xdb, 0x11, 0xa9, 0xbc, 0x92, 0xc5, - 0xe7, 0x37, 0xc8, 0xb7, 0x14, 0xb7, 0x77, 0x9f, 0xc8, 0xe8, 0x48, 0xbc, 0x8d, 0x5f, 0xe9, 0x6f, - 0x0d, 0x28, 0x88, 0x7a, 0xc7, 0x20, 0xe0, 0x37, 0xa2, 0x02, 0xfe, 0xd1, 0x0c, 0xbd, 0x18, 0x20, - 0xd8, 0xff, 0x33, 0xaf, 0xbe, 0x3e, 0xb0, 0xa6, 0x5b, 0xc4, 0x69, 0x28, 0x33, 0x31, 0xdc, 0x9d, - 0xbc, 0x10, 0x4b, 0x5a, 0x20, 0x53, 0xc6, 0x8f, 0x40, 0xa6, 0xbc, 0x2f, 0x6f, 0x03, 0x50, 0x97, - 0xd1, 0xc6, 0xc5, 0xc0, 0x1e, 0xcc, 0x67, 0xbe, 0xd6, 0xa0, 0xae, 0x5e, 0x84, 0x9e, 0x7a, 0x1c, - 0x43, 0xc5, 0x7d, 0x7c, 0xb8, 0x8d, 0xd8, 0x8b, 0x0b, 0x51, 0x65, 0xe2, 0x3c, 0x3b, 0xa4, 0xc4, - 0x96, 0x36, 0x62, 0x5f, 0x31, 0xee, 0x67, 0x84, 0x5a, 0x30, 0xa9, 0xdf, 0xef, 0x52, 0xeb, 0xf4, - 0x6c, 0xf6, 0x8b, 0x64, 0x32, 0x57, 0x4c, 0x2f, 0xc1, 0x11, 0x64, 0xf3, 0x23, 0x03, 0x20, 0xf4, - 0x90, 0xf3, 0x39, 0xaf, 0xdb, 0x5e, 0x57, 0xba, 0x46, 0xf2, 0xe1, 0x9c, 0x57, 0x79, 0x21, 0x96, - 0x34, 0xbe, 0x7f, 0xa4, 0x81, 0xa9, 0x16, 0xf5, 0x13, 0x59, 0x6c, 0xd7, 0x98, 0x27, 0x5e, 0x16, - 0x62, 0x05, 0x68, 0xfe, 0xdd, 0x04, 0x14, 0xb5, 0x7d, 0x16, 0xf3, 0xc3, 0x4f, 0x1d, 0x59, 0xc8, - 0x2a, 0xc1, 0x39, 0x52, 0x1c, 0xca, 0x39, 0xe2, 0xc2, 0xb4, 0x32, 0xf9, 0xfd, 0x4b, 0x80, 0xd2, - 0x79, 0x34, 0xb4, 0x63, 0x01, 0x71, 0x6d, 0xf9, 0x62, 0x04, 0x12, 0xc7, 0x58, 0x70, 0x6d, 0x5b, - 0x95, 0xd4, 0xbc, 0x4e, 0x87, 0x38, 0xbb, 0x2a, 0xeb, 0x31, 0xd0, 0xb6, 0x2f, 0x46, 0xa8, 0x38, - 0x56, 0x1b, 0x6d, 0x04, 0x13, 0x2a, 0x6f, 0x82, 0x3d, 0x96, 0x65, 0x42, 0xa5, 0xb5, 0x11, 0x9d, - 0xc7, 0x01, 0x51, 0xc0, 0xb1, 0xa1, 0xa2, 0x80, 0xef, 0xc3, 0xac, 0x32, 0xf1, 0x83, 0xbd, 0xa3, - 0xbc, 0x35, 0x59, 0xed, 0xbb, 0xf0, 0xe8, 0x17, 0x79, 0x26, 0xd5, 0x18, 0x2a, 0xee, 0xe3, 0x83, - 0xde, 0x83, 0x29, 0x3e, 0xc9, 0x21, 0x63, 0xb8, 0x43, 0xc6, 0xca, 0x4b, 0xac, 0x41, 0xe2, 0x28, - 0x87, 0x81, 0x3e, 0xf2, 0xe9, 0x61, 0x7d, 0xe4, 0xa8, 0xa3, 0x1d, 0x43, 0x33, 0x62, 0x35, 0x7e, - 0x33, 0xf3, 0x89, 0x97, 0xe1, 0x82, 0xc9, 0xd7, 0x7a, 0x07, 0xe2, 0x8b, 0x3c, 0x24, 0xbb, 0x67, - 0xc2, 0x6b, 0xe2, 0xc6, 0x6d, 0xae, 0x89, 0x47, 0x7c, 0x65, 0xb9, 0x23, 0xf3, 0x95, 0xe5, 0x0f, - 0xd5, 0x57, 0x76, 0x16, 0x40, 0x98, 0xcf, 0x42, 0x48, 0x8b, 0xd3, 0x7a, 0x4a, 0xbb, 0x69, 0x1b, - 0x50, 0xb0, 0x56, 0x0b, 0xbd, 0x14, 0xe8, 0x40, 0x32, 0x61, 0xeb, 0xb7, 0xfb, 0xb2, 0x5c, 0x4f, - 0x46, 0x94, 0xf3, 0x98, 0x5f, 0x3f, 0xc3, 0x75, 0x8e, 0x04, 0xb7, 0xce, 0x78, 0x36, 0xb7, 0x8e, - 0xf9, 0xdf, 0x39, 0x88, 0x9c, 0x61, 0xe8, 0x07, 0x06, 0xcc, 0x91, 0xd8, 0x1b, 0x9e, 0xbe, 0xe9, - 0xf1, 0xcd, 0x6c, 0x0f, 0xab, 0xf6, 0x3d, 0x01, 0x1a, 0x26, 0x7c, 0xc4, 0xab, 0xb8, 0xb8, 0x9f, - 0x29, 0xfa, 0x63, 0x03, 0x4e, 0x92, 0xfe, 0x47, 0x5a, 0xd5, 0xe2, 0x79, 0x6e, 0xe8, 0x57, 0x5e, - 0x2b, 0xa7, 0xf7, 0xf7, 0x96, 0x93, 0x9e, 0xaf, 0xc5, 0x49, 0xec, 0xd0, 0x5b, 0x30, 0x42, 0x9c, - 0xa6, 0x1f, 0x4d, 0xc8, 0xce, 0xd6, 0x7f, 0x7b, 0x37, 0x54, 0xc4, 0xca, 0x4e, 0xd3, 0xc5, 0x02, - 0xd4, 0xfc, 0x75, 0x1e, 0x66, 0xe3, 0xd7, 0xd3, 0xd5, 0xa5, 0xa1, 0x91, 0xc4, 0x4b, 0x43, 0x7c, - 0xaf, 0x89, 0x78, 0x5a, 0xfc, 0x49, 0x06, 0x11, 0x16, 0x93, 0xb4, 0x60, 0xaf, 0x89, 0x5b, 0x9e, - 0xa3, 0x77, 0xb0, 0xd7, 0xc4, 0xd5, 0xce, 0x10, 0x0b, 0x9d, 0x8b, 0x06, 0x28, 0xcc, 0x78, 0x80, - 0x62, 0x4e, 0xef, 0xcb, 0xb0, 0x31, 0x8a, 0x0e, 0x14, 0xb5, 0x79, 0x50, 0x3b, 0xfa, 0xf9, 0xcc, - 0xe3, 0x1e, 0x2e, 0xbb, 0x19, 0x99, 0xad, 0x1b, 0x52, 0x74, 0xfc, 0x50, 0x7e, 0x88, 0xd1, 0xba, - 0x23, 0x5f, 0xbb, 0x18, 0x2e, 0x0d, 0xcd, 0xfc, 0x17, 0x03, 0xa6, 0x22, 0xd7, 0xe8, 0x38, 0x37, - 0xff, 0x7e, 0xe4, 0xf0, 0x0f, 0xd6, 0x5e, 0x0b, 0x10, 0xb0, 0x86, 0x86, 0xbe, 0x0b, 0xc5, 0xb6, - 0xdd, 0x6d, 0x52, 0x97, 0xd5, 0x6c, 0xb2, 0xad, 0xf6, 0x49, 0x56, 0xaf, 0xa3, 0xb8, 0xea, 0xba, - 0x2e, 0x61, 0xaa, 0x76, 0xa7, 0xd7, 0xa6, 0x4c, 0x5e, 0xea, 0xc5, 0x3a, 0xb8, 0x48, 0x86, 0x08, - 0xb2, 0x49, 0xee, 0xd6, 0x64, 0x88, 0x30, 0x0d, 0xe6, 0x90, 0x93, 0x21, 0x22, 0xf9, 0x35, 0x07, - 0x24, 0x43, 0x04, 0x75, 0xef, 0xda, 0x64, 0x88, 0xe0, 0x0b, 0x07, 0x18, 0xaf, 0x1f, 0x8d, 0x68, - 0xbd, 0x88, 0x1a, 0xb0, 0xb9, 0xdb, 0x18, 0xb0, 0x6f, 0xc3, 0x84, 0xd5, 0x65, 0xd4, 0xd9, 0x21, - 0x6d, 0x15, 0x35, 0xc8, 0xba, 0x16, 0x83, 0xae, 0xae, 0x29, 0x1c, 0x1c, 0x20, 0xa2, 0x36, 0x9c, - 0xda, 0x8a, 0xbe, 0x8f, 0xa1, 0x5e, 0x91, 0x95, 0xc9, 0xdf, 0xcf, 0xf8, 0x11, 0xa5, 0x8b, 0x49, - 0x95, 0x6e, 0x0d, 0x22, 0xe0, 0x64, 0x50, 0xe4, 0xc2, 0x94, 0xab, 0x79, 0x6e, 0xfc, 0x13, 0x31, - 0x65, 0xf4, 0x34, 0xee, 0xec, 0xd2, 0x32, 0xc6, 0x75, 0x50, 0x1c, 0xe5, 0x81, 0x7e, 0x68, 0xc0, - 0xe9, 0xad, 0xe4, 0x37, 0x40, 0x94, 0x54, 0x7f, 0x29, 0x9b, 0xed, 0x13, 0x03, 0xa9, 0xdc, 0xb7, - 0xbf, 0xb7, 0x3c, 0xe8, 0x95, 0x11, 0x3c, 0x88, 0xb5, 0xf9, 0xb1, 0x01, 0xd3, 0xd1, 0x04, 0xb3, - 0xaf, 0xdd, 0xb8, 0xfd, 0x22, 0x0f, 0x33, 0xb1, 0x3d, 0x19, 0x33, 0x70, 0x0b, 0xc7, 0x69, 0xe0, - 0x8e, 0x0d, 0x65, 0xe0, 0x26, 0x5b, 0x76, 0x23, 0x43, 0x59, 0x76, 0x2f, 0x48, 0xeb, 0x4a, 0xcd, - 0xed, 0xda, 0xaa, 0xba, 0xc5, 0x1b, 0xac, 0xbb, 0x75, 0x9d, 0x88, 0xa3, 0x75, 0x85, 0xe2, 0xd5, - 0xe8, 0x7f, 0xbe, 0x4f, 0x99, 0x86, 0xcf, 0x65, 0xbd, 0x17, 0x12, 0x00, 0x48, 0xc5, 0x2b, 0x81, - 0x80, 0x93, 0xd8, 0x99, 0xff, 0x35, 0x0e, 0xa7, 0x92, 0x7d, 0xd3, 0x07, 0x07, 0x43, 0xde, 0x83, - 0xc2, 0xa6, 0xff, 0x02, 0xb3, 0xda, 0x2b, 0x29, 0x9f, 0x1d, 0xb8, 0xfd, 0xc3, 0xcd, 0x52, 0x37, - 0x0a, 0xea, 0xe0, 0x90, 0x0b, 0x67, 0xd9, 0x10, 0x8f, 0x8e, 0xb5, 0xbc, 0x4d, 0xa5, 0x46, 0xa4, - 0x64, 0x79, 0xfb, 0xb7, 0xca, 0x24, 0xcb, 0xa0, 0x0e, 0x0e, 0xb9, 0x20, 0x0a, 0x63, 0x92, 0x81, - 0x3a, 0x16, 0xcb, 0xa9, 0xdd, 0xe6, 0x03, 0x99, 0x09, 0x97, 0x83, 0xac, 0x80, 0x15, 0xb8, 0x62, - 0xd3, 0x26, 0x9b, 0xea, 0x90, 0x4c, 0xcf, 0x66, 0xd0, 0x95, 0xe7, 0x80, 0xcd, 0x3a, 0x91, 0x6c, - 0xda, 0x44, 0xb0, 0x69, 0x89, 0x3b, 0x8a, 0xca, 0x15, 0x90, 0x92, 0xcd, 0x6d, 0xee, 0x35, 0x2a, - 0x07, 0x8a, 0xa8, 0x80, 0x15, 0x38, 0x7a, 0x07, 0x46, 0xde, 0xf3, 0x88, 0x1f, 0xc8, 0x4e, 0x69, - 0xd3, 0x0c, 0x8c, 0x93, 0xc8, 0x18, 0x3d, 0x27, 0x63, 0x01, 0x8b, 0x76, 0xa1, 0x48, 0xc2, 0x17, - 0xdb, 0xd5, 0x9b, 0x68, 0x17, 0xd3, 0xbe, 0x69, 0x7f, 0xfb, 0xa7, 0xde, 0x95, 0x26, 0x1b, 0xd6, - 0xc2, 0x3a, 0x2f, 0x44, 0x60, 0x94, 0xbc, 0xef, 0x39, 0x54, 0xf9, 0x9a, 0x5e, 0x4e, 0xc9, 0x74, - 0xe0, 0x13, 0xe9, 0x32, 0x3e, 0x21, 0xe8, 0x58, 0x22, 0x73, 0x16, 0x4d, 0x8b, 0x51, 0xa2, 0x64, - 0xc1, 0xcb, 0xa9, 0x57, 0xc2, 0x80, 0x3b, 0xaf, 0x92, 0x85, 0xa0, 0x63, 0x89, 0x6c, 0x7e, 0x00, - 0xf7, 0x24, 0xe7, 0x83, 0xa7, 0x8b, 0x81, 0xf6, 0x08, 0xf3, 0xef, 0x8d, 0x07, 0x35, 0x36, 0x08, - 0x6b, 0x61, 0x41, 0x41, 0xf7, 0x43, 0xde, 0x73, 0xda, 0xf1, 0xc7, 0x14, 0x5e, 0xc7, 0xeb, 0x98, - 0x97, 0x57, 0x5e, 0xf9, 0xf4, 0xab, 0xa5, 0x13, 0x9f, 0x7f, 0xb5, 0x74, 0xe2, 0xcb, 0xaf, 0x96, - 0x4e, 0x7c, 0xb8, 0xbf, 0x64, 0x7c, 0xba, 0xbf, 0x64, 0x7c, 0xbe, 0xbf, 0x64, 0x7c, 0xb9, 0xbf, - 0x64, 0xfc, 0xdb, 0xfe, 0x92, 0xf1, 0xf1, 0x6f, 0x96, 0x4e, 0x5c, 0x7f, 0x30, 0xcd, 0x3f, 0xbd, - 0xf9, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdb, 0xbb, 0xda, 0x16, 0x1b, 0x67, 0x00, 0x00, + // 5479 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5d, 0x4b, 0x6c, 0x24, 0xc7, + 0x79, 0xde, 0x9e, 0xe1, 0xf3, 0x1f, 0x3e, 0x6b, 0xb9, 0x5a, 0x8a, 0x92, 0xc8, 0x4d, 0x5b, 0x11, + 0x56, 0x91, 0x34, 0x8c, 0x56, 0xaf, 0xd5, 0x4a, 0x5a, 0x6b, 0x86, 0xdc, 0x07, 0x25, 0x4a, 0x4b, + 0xd7, 0x50, 0x2b, 0x6b, 0x25, 0x41, 0x29, 0xce, 0x14, 0x67, 0xda, 0x9c, 0xe9, 0x1e, 0x75, 0xf7, + 0x70, 0x97, 0x52, 0xe0, 0x28, 0x76, 0x12, 0x38, 0x80, 0x10, 0xe8, 0xe0, 0x40, 0x3e, 0x24, 0x40, + 0x10, 0x9f, 0x02, 0x03, 0x76, 0xee, 0x01, 0xe2, 0x04, 0xb9, 0xc8, 0x8e, 0x1c, 0x08, 0xca, 0x21, + 0x4a, 0x60, 0x30, 0x16, 0x0d, 0xe4, 0x16, 0x20, 0xe7, 0x05, 0x02, 0x04, 0xf5, 0xe8, 0xae, 0xea, + 0x9e, 0x1e, 0xb2, 0x7b, 0x96, 0xa4, 0x36, 0x48, 0x6e, 0x9c, 0xfa, 0xab, 0xbe, 0xbf, 0xeb, 0xf5, + 0xd7, 0xff, 0xaa, 0x22, 0x3c, 0x59, 0xb7, 0xfc, 0x46, 0x67, 0xa3, 0x58, 0x75, 0x5a, 0x8b, 0x64, + 0xab, 0x63, 0xf9, 0x3b, 0x8b, 0x5b, 0xc4, 0xad, 0x3b, 0x8b, 0xa4, 0x6d, 0x2d, 0x6e, 0x3f, 0x4e, + 0x9a, 0xed, 0x06, 0x79, 0x7c, 0xb1, 0x4e, 0x6d, 0xea, 0x12, 0x9f, 0xd6, 0x8a, 0x6d, 0xd7, 0xf1, + 0x1d, 0xf4, 0xa0, 0x6a, 0x55, 0x14, 0xad, 0x8a, 0xbc, 0x55, 0x91, 0xb4, 0xad, 0x62, 0xd0, 0x6a, + 0xee, 0x31, 0x0d, 0xbb, 0xee, 0xd4, 0x9d, 0x45, 0xde, 0x78, 0xa3, 0xb3, 0xc9, 0x7f, 0xf1, 0x1f, + 0xfc, 0x2f, 0x01, 0x3a, 0x67, 0x6e, 0x9d, 0xf7, 0x8a, 0x96, 0xe0, 0x5c, 0x75, 0x5c, 0xba, 0xb8, + 0xdd, 0xc5, 0x78, 0xee, 0xaa, 0xaa, 0x43, 0x6f, 0xf9, 0xd4, 0xf6, 0x2c, 0xc7, 0xf6, 0x1e, 0x23, + 0x6d, 0xcb, 0xa3, 0xee, 0x36, 0x75, 0x17, 0xdb, 0x5b, 0x75, 0x46, 0xf3, 0xa2, 0x15, 0x92, 0x90, + 0x9e, 0x54, 0x48, 0x2d, 0x52, 0x6d, 0x58, 0x36, 0x75, 0x77, 0x54, 0xf3, 0x16, 0xf5, 0x49, 0x52, + 0xab, 0xc5, 0x5e, 0xad, 0xdc, 0x8e, 0xed, 0x5b, 0x2d, 0xda, 0xd5, 0xe0, 0xe9, 0x83, 0x1a, 0x78, + 0xd5, 0x06, 0x6d, 0x91, 0x78, 0x3b, 0xf3, 0x2d, 0x38, 0x59, 0xb2, 0x49, 0x73, 0xc7, 0xb3, 0x3c, + 0xdc, 0xb1, 0x4b, 0x6e, 0xbd, 0xd3, 0xa2, 0xb6, 0x8f, 0xce, 0xc0, 0x80, 0x4d, 0x5a, 0x74, 0xd6, + 0x38, 0x63, 0x9c, 0x1d, 0x2d, 0x8f, 0x7d, 0xb2, 0xbb, 0x70, 0x62, 0x6f, 0x77, 0x61, 0xe0, 0x55, + 0xd2, 0xa2, 0x98, 0x53, 0xd0, 0xd7, 0x60, 0x70, 0x9b, 0x34, 0x3b, 0x74, 0x36, 0xc7, 0xab, 0x8c, + 0xcb, 0x2a, 0x83, 0xd7, 0x59, 0x21, 0x16, 0x34, 0xf3, 0xbb, 0xf9, 0x08, 0xfc, 0x2b, 0xd4, 0x27, + 0x35, 0xe2, 0x13, 0xd4, 0x82, 0xa1, 0x26, 0xd9, 0xa0, 0x4d, 0x6f, 0xd6, 0x38, 0x93, 0x3f, 0x5b, + 0x38, 0x77, 0xa9, 0x98, 0x66, 0xa2, 0x8b, 0x09, 0x50, 0xc5, 0x55, 0x8e, 0x73, 0xc9, 0xf6, 0xdd, + 0x9d, 0xf2, 0x84, 0xfc, 0x88, 0x21, 0x51, 0x88, 0x25, 0x13, 0xf4, 0xfb, 0x06, 0x14, 0x88, 0x6d, + 0x3b, 0x3e, 0xf1, 0xd9, 0x34, 0xcd, 0xe6, 0x38, 0xd3, 0x97, 0xfa, 0x67, 0x5a, 0x52, 0x60, 0x82, + 0xf3, 0x49, 0xc9, 0xb9, 0xa0, 0x51, 0xb0, 0xce, 0x73, 0xee, 0x59, 0x28, 0x68, 0x9f, 0x8a, 0xa6, + 0x20, 0xbf, 0x45, 0x77, 0xc4, 0xf8, 0x62, 0xf6, 0x27, 0x9a, 0x89, 0x0c, 0xa8, 0x1c, 0xc1, 0x0b, + 0xb9, 0xf3, 0xc6, 0xdc, 0x45, 0x98, 0x8a, 0x33, 0xcc, 0xd2, 0xde, 0xfc, 0x13, 0x03, 0x66, 0xb4, + 0x5e, 0x60, 0xba, 0x49, 0x5d, 0x6a, 0x57, 0x29, 0x5a, 0x84, 0x51, 0x36, 0x97, 0x5e, 0x9b, 0x54, + 0x83, 0xa9, 0x9e, 0x96, 0x1d, 0x19, 0x7d, 0x35, 0x20, 0x60, 0x55, 0x27, 0x5c, 0x16, 0xb9, 0xfd, + 0x96, 0x45, 0xbb, 0x41, 0x3c, 0x3a, 0x9b, 0x8f, 0x2e, 0x8b, 0x35, 0x56, 0x88, 0x05, 0xcd, 0x7c, + 0x07, 0xee, 0x0d, 0xbe, 0x67, 0x9d, 0xb6, 0xda, 0x4d, 0xe2, 0x53, 0xf5, 0x51, 0x07, 0x2f, 0xbd, + 0x33, 0x30, 0xb0, 0x65, 0xd9, 0xb5, 0xf8, 0x57, 0xbc, 0x6c, 0xd9, 0x35, 0xcc, 0x29, 0xe6, 0x16, + 0x8c, 0x97, 0xda, 0x6d, 0xd7, 0xd9, 0xa6, 0xb5, 0x8a, 0x4f, 0xea, 0x14, 0xdd, 0x00, 0x20, 0xb2, + 0xa0, 0xe4, 0x73, 0xe8, 0xc2, 0xb9, 0xdf, 0x2a, 0x8a, 0x3d, 0x53, 0xd4, 0xf7, 0x4c, 0xb1, 0xbd, + 0x55, 0x67, 0x05, 0x5e, 0x91, 0x6d, 0xcd, 0xe2, 0xf6, 0xe3, 0xc5, 0x75, 0xab, 0x45, 0xcb, 0x13, + 0x7b, 0xbb, 0x0b, 0x50, 0x0a, 0x11, 0xb0, 0x86, 0x66, 0x7e, 0xc7, 0x80, 0x53, 0x25, 0xb7, 0xee, + 0x2c, 0x2d, 0x97, 0xda, 0xed, 0xab, 0x94, 0x34, 0xfd, 0x46, 0xc5, 0x27, 0x7e, 0xc7, 0x43, 0x17, + 0x61, 0xc8, 0xe3, 0x7f, 0xc9, 0xce, 0x3c, 0x14, 0xac, 0x4f, 0x41, 0xbf, 0xbd, 0xbb, 0x30, 0x93, + 0xd0, 0x90, 0x62, 0xd9, 0x0a, 0x3d, 0x0c, 0xc3, 0x2d, 0xea, 0x79, 0xa4, 0x1e, 0x8c, 0xf8, 0xa4, + 0x04, 0x18, 0x7e, 0x45, 0x14, 0xe3, 0x80, 0x6e, 0xfe, 0x3c, 0x07, 0x93, 0x21, 0x96, 0x64, 0x7f, + 0x04, 0xd3, 0xdb, 0x81, 0xb1, 0x86, 0xd6, 0x43, 0x3e, 0xcb, 0x85, 0x73, 0xcf, 0xa5, 0xdc, 0x49, + 0x49, 0x83, 0x54, 0x9e, 0x91, 0x6c, 0xc6, 0xf4, 0x52, 0x1c, 0x61, 0x83, 0x5a, 0x00, 0xde, 0x8e, + 0x5d, 0x95, 0x4c, 0x07, 0x38, 0xd3, 0x67, 0x33, 0x32, 0xad, 0x84, 0x00, 0x65, 0x24, 0x59, 0x82, + 0x2a, 0xc3, 0x1a, 0x03, 0xf3, 0xc7, 0x06, 0x9c, 0x4c, 0x68, 0x87, 0x9e, 0x8f, 0xcd, 0xe7, 0x83, + 0x5d, 0xf3, 0x89, 0xba, 0x9a, 0xa9, 0xd9, 0x7c, 0x14, 0x46, 0x5c, 0xba, 0x6d, 0xb1, 0x93, 0x42, + 0x8e, 0xf0, 0x94, 0x6c, 0x3f, 0x82, 0x65, 0x39, 0x0e, 0x6b, 0xa0, 0x47, 0x60, 0x34, 0xf8, 0x9b, + 0x0d, 0x73, 0x9e, 0x6d, 0x26, 0x36, 0x71, 0x41, 0x55, 0x0f, 0x2b, 0xba, 0xf9, 0x77, 0x06, 0x9c, + 0x29, 0xb9, 0xbe, 0xb5, 0x49, 0xaa, 0xbe, 0xe3, 0xee, 0xbc, 0x4e, 0x37, 0x1a, 0x8e, 0xb3, 0x85, + 0x69, 0x95, 0x5a, 0xdb, 0xd4, 0x5d, 0x72, 0xec, 0x4d, 0xab, 0x8e, 0xde, 0x80, 0x51, 0x8f, 0x56, + 0x5d, 0xea, 0x63, 0xba, 0x29, 0xb7, 0xc0, 0x59, 0x6d, 0x0b, 0x14, 0xd9, 0x59, 0xc8, 0x16, 0xfc, + 0xaa, 0x53, 0x25, 0xcd, 0x6b, 0x1b, 0xdf, 0xa2, 0x55, 0x3f, 0xdc, 0x95, 0x6a, 0xe1, 0x54, 0x02, + 0x08, 0xac, 0xd0, 0x50, 0x09, 0x26, 0xb7, 0x2d, 0xd7, 0xef, 0x90, 0x26, 0xa6, 0x6d, 0xe7, 0x55, + 0xb5, 0x86, 0x4e, 0xcb, 0x66, 0x93, 0xd7, 0xa3, 0x64, 0x1c, 0xaf, 0x6f, 0xee, 0xc0, 0x4c, 0xa9, + 0xe3, 0x3b, 0x6b, 0xae, 0xd3, 0x72, 0x98, 0x9c, 0xbb, 0xd6, 0xe6, 0xd2, 0x0e, 0x11, 0x98, 0xf4, + 0x68, 0x93, 0x56, 0xd9, 0xaf, 0x35, 0xa7, 0x69, 0x55, 0xa5, 0xd0, 0x2b, 0x3f, 0x13, 0x40, 0x57, + 0xa2, 0xe4, 0xdb, 0xbb, 0x0b, 0xf7, 0x47, 0x90, 0x62, 0x74, 0x1c, 0xc7, 0x33, 0x6f, 0xc2, 0x5c, + 0xe9, 0xbd, 0x8e, 0x4b, 0x8f, 0x7b, 0xd8, 0xcc, 0xf7, 0x61, 0xbe, 0x6c, 0xf9, 0x1b, 0x9d, 0xea, + 0x16, 0xf5, 0x8f, 0x9d, 0xf9, 0xef, 0xc1, 0xe0, 0x52, 0x83, 0xb8, 0x3e, 0x93, 0x32, 0x2e, 0x6d, + 0x3b, 0xaf, 0xe1, 0x55, 0x39, 0xb2, 0xa1, 0x94, 0xc1, 0xa2, 0x18, 0x07, 0xf4, 0x14, 0x02, 0xe2, + 0x61, 0x18, 0xde, 0xa6, 0x2e, 0x5f, 0xe3, 0xf9, 0x28, 0xd8, 0x75, 0x51, 0x8c, 0x03, 0xba, 0xf9, + 0xcf, 0x06, 0xcc, 0xf0, 0x2f, 0x58, 0xb6, 0xbc, 0xaa, 0xb3, 0x4d, 0xdd, 0x1d, 0x4c, 0xbd, 0x4e, + 0xf3, 0x90, 0x3f, 0x68, 0x19, 0xa6, 0x3c, 0xda, 0x12, 0x23, 0xea, 0xf9, 0x2e, 0xb1, 0x6c, 0x5f, + 0x7e, 0xd9, 0xac, 0xac, 0x3d, 0x55, 0x89, 0xd1, 0x71, 0x57, 0x0b, 0x74, 0x16, 0x46, 0xe4, 0x67, + 0x33, 0xf1, 0xc3, 0x36, 0xe3, 0x18, 0xdb, 0xb7, 0xb2, 0x4f, 0x1e, 0x0e, 0xa9, 0xe6, 0x7f, 0x18, + 0x30, 0xcd, 0x7b, 0x55, 0xe9, 0x6c, 0x78, 0x55, 0xd7, 0xe2, 0xcb, 0xf8, 0x6e, 0xec, 0xd2, 0x45, + 0x98, 0xa8, 0x05, 0x03, 0xbf, 0x6a, 0xb5, 0x2c, 0x9f, 0xcb, 0xd5, 0xc1, 0xf2, 0x3d, 0x12, 0x63, + 0x62, 0x39, 0x42, 0xc5, 0xb1, 0xda, 0xe6, 0x4f, 0x72, 0x30, 0xbe, 0xd4, 0xec, 0x78, 0x7e, 0xb8, + 0x58, 0x7f, 0x07, 0x46, 0x5a, 0x52, 0x43, 0x92, 0x6b, 0xf5, 0xb7, 0xd3, 0x1d, 0xb1, 0x62, 0xe1, + 0x32, 0xed, 0x4a, 0x89, 0x66, 0x55, 0x86, 0x43, 0x54, 0xf4, 0x06, 0x0c, 0x78, 0x6d, 0x5a, 0xe5, + 0x63, 0x53, 0x38, 0xf7, 0x4c, 0xba, 0x13, 0x20, 0xf2, 0x91, 0x95, 0x36, 0xad, 0xaa, 0x41, 0x65, + 0xbf, 0x30, 0x87, 0x44, 0x24, 0x94, 0xed, 0xf9, 0x2c, 0xc7, 0x4b, 0x14, 0x5c, 0x1c, 0x2f, 0x13, + 0xd1, 0x63, 0x21, 0x38, 0x00, 0xcc, 0x7f, 0x64, 0x4b, 0x43, 0xaf, 0xbf, 0x6a, 0x79, 0x3e, 0x7a, + 0xab, 0x6b, 0xd4, 0x8a, 0xe9, 0x46, 0x8d, 0xb5, 0xe6, 0x63, 0x16, 0x1e, 0x23, 0x41, 0x89, 0x36, + 0x62, 0xdf, 0x84, 0x41, 0xcb, 0xa7, 0xad, 0x40, 0xe7, 0x7d, 0xa2, 0x8f, 0x5e, 0x29, 0x25, 0x6e, + 0x85, 0x21, 0x61, 0x01, 0x68, 0x7e, 0x1c, 0xef, 0x0d, 0x1b, 0x4c, 0xa6, 0x6a, 0x4f, 0xdd, 0x8c, + 0x8a, 0xb2, 0x40, 0xc9, 0x4f, 0xa9, 0x25, 0x24, 0x0a, 0x42, 0xb5, 0xb2, 0x63, 0x64, 0x0f, 0x77, + 0xb1, 0x33, 0x3f, 0xce, 0xc3, 0xc9, 0x84, 0x79, 0x41, 0x55, 0x80, 0xaa, 0x63, 0xd7, 0x2c, 0x61, + 0x04, 0x88, 0x8f, 0x5a, 0x4c, 0x37, 0xd6, 0x4b, 0x41, 0x3b, 0xb5, 0x40, 0xc3, 0x22, 0x0f, 0x6b, + 0xb0, 0xe8, 0x25, 0x40, 0xce, 0x06, 0xb7, 0x12, 0x6b, 0x57, 0x84, 0xad, 0x15, 0xc8, 0xc2, 0x7c, + 0x79, 0x4e, 0xb6, 0x45, 0xd7, 0xba, 0x6a, 0xe0, 0x84, 0x56, 0x0c, 0xab, 0x49, 0x3c, 0xff, 0x2a, + 0xb1, 0x6b, 0x4d, 0x5a, 0xc3, 0x74, 0xd3, 0xa5, 0x5e, 0x83, 0x6f, 0xd3, 0x51, 0x85, 0xb5, 0xda, + 0x55, 0x03, 0x27, 0xb4, 0x42, 0xdf, 0x49, 0x9a, 0x18, 0xb1, 0x28, 0x9e, 0xef, 0x6b, 0x62, 0x96, + 0xa9, 0x4f, 0xac, 0xa6, 0x97, 0x69, 0x66, 0xb8, 0xc8, 0x17, 0x33, 0x13, 0x1e, 0xcf, 0xeb, 0xc4, + 0xdb, 0xba, 0x5b, 0x45, 0x47, 0xe4, 0x23, 0x7b, 0x89, 0x0e, 0xf3, 0x5f, 0x0d, 0x98, 0x4d, 0xea, + 0xd5, 0x31, 0x6c, 0xef, 0x77, 0xa2, 0xdb, 0xfb, 0x42, 0xa6, 0xed, 0x1d, 0xf9, 0xd8, 0x1e, 0xbb, + 0xfc, 0x4d, 0x18, 0x5b, 0xea, 0xb8, 0x2e, 0xb5, 0x7d, 0x61, 0x48, 0xbd, 0x0c, 0x83, 0x9e, 0x65, + 0x4b, 0x7b, 0x22, 0x9b, 0x0d, 0x35, 0xca, 0xc0, 0x2b, 0xac, 0x31, 0x16, 0x18, 0xe6, 0x9f, 0xe5, + 0xe1, 0x64, 0x70, 0xca, 0xd0, 0x5a, 0xa0, 0xc0, 0x7a, 0xa8, 0x06, 0x63, 0x35, 0x55, 0xec, 0x4b, + 0x85, 0x3f, 0x0b, 0xaf, 0xd0, 0xa8, 0xd0, 0xe0, 0x7d, 0x1c, 0x41, 0x45, 0xaf, 0x43, 0xbe, 0x6e, + 0xf9, 0x52, 0x0e, 0x9c, 0x4f, 0x37, 0x72, 0x57, 0xac, 0xb8, 0xb6, 0x52, 0x2e, 0x48, 0x56, 0xf9, + 0x2b, 0x96, 0x8f, 0x19, 0x22, 0xda, 0x80, 0x21, 0xab, 0x45, 0xea, 0x34, 0xe3, 0xac, 0xac, 0xb0, + 0x36, 0x71, 0xf4, 0xf0, 0x2c, 0xe1, 0x54, 0x0f, 0x4b, 0x64, 0xc6, 0xa3, 0xca, 0xb4, 0x0c, 0x61, + 0x1b, 0xa4, 0x9f, 0xf9, 0x04, 0x7d, 0x4b, 0xf1, 0xe0, 0x54, 0x0f, 0x4b, 0x64, 0xf3, 0x8b, 0x1c, + 0x4c, 0xa9, 0xf1, 0x5b, 0x72, 0x5a, 0x2d, 0xcb, 0x47, 0x73, 0x90, 0xb3, 0x6a, 0x52, 0x89, 0x01, + 0xd9, 0x30, 0xb7, 0xb2, 0x8c, 0x73, 0x56, 0x0d, 0x3d, 0x04, 0x43, 0x1b, 0x2e, 0xb1, 0xab, 0x0d, + 0xa9, 0xbc, 0x84, 0xc0, 0x65, 0x5e, 0x8a, 0x25, 0x15, 0x3d, 0x00, 0x79, 0x9f, 0xd4, 0xa5, 0xce, + 0x12, 0x8e, 0xdf, 0x3a, 0xa9, 0x63, 0x56, 0xce, 0x94, 0x25, 0xaf, 0xc3, 0xf7, 0xb0, 0x94, 0x75, + 0xa1, 0xb2, 0x54, 0x11, 0xc5, 0x38, 0xa0, 0x33, 0x8e, 0xa4, 0xe3, 0x37, 0x1c, 0x77, 0x76, 0x30, + 0xca, 0xb1, 0xc4, 0x4b, 0xb1, 0xa4, 0x32, 0x53, 0xb8, 0xca, 0xbf, 0xdf, 0xa7, 0xee, 0xec, 0x50, + 0xd4, 0x14, 0x5e, 0x0a, 0x08, 0x58, 0xd5, 0x41, 0x6f, 0x43, 0xa1, 0xea, 0x52, 0xe2, 0x3b, 0xee, + 0x32, 0xf1, 0xe9, 0xec, 0x70, 0xe6, 0x15, 0x38, 0xb9, 0xb7, 0xbb, 0x50, 0x58, 0x52, 0x10, 0x58, + 0xc7, 0x33, 0xbf, 0x9b, 0x87, 0x59, 0x35, 0xb4, 0x7c, 0x6e, 0x95, 0x07, 0x44, 0x0e, 0x8f, 0xd1, + 0x63, 0x78, 0x1e, 0x82, 0xa1, 0x9a, 0x55, 0xa7, 0x9e, 0x1f, 0x1f, 0xe5, 0x65, 0x5e, 0x8a, 0x25, + 0x15, 0xfd, 0x51, 0xcc, 0xeb, 0x35, 0xc8, 0x17, 0xca, 0xb5, 0x74, 0x0b, 0xa5, 0xd7, 0xc7, 0xf5, + 0xe1, 0xfa, 0x42, 0xaf, 0xc3, 0x28, 0xef, 0x7b, 0x9f, 0x7b, 0x99, 0x9b, 0xbd, 0x4b, 0x01, 0x00, + 0x56, 0x58, 0x77, 0xec, 0x18, 0x7b, 0x1f, 0xe6, 0x97, 0x9d, 0xea, 0x16, 0x75, 0xaf, 0x76, 0x36, + 0x8e, 0xdd, 0xfe, 0x7a, 0x13, 0xd0, 0xa5, 0x5b, 0x6d, 0x97, 0x7a, 0xcc, 0x6e, 0xb8, 0x4e, 0x5c, + 0x8b, 0x6c, 0x34, 0xe9, 0x61, 0x39, 0x5e, 0x3f, 0x1b, 0x80, 0xe1, 0xcb, 0x2e, 0xb5, 0xea, 0x0d, + 0xff, 0x18, 0xce, 0xd6, 0xaf, 0xc1, 0x20, 0x69, 0x5a, 0xc4, 0xe3, 0xdb, 0x44, 0xfb, 0xa4, 0x12, + 0x2b, 0xc4, 0x82, 0x86, 0xde, 0x84, 0x21, 0xc7, 0xb5, 0xea, 0x96, 0x3d, 0x3b, 0xca, 0x3f, 0x22, + 0xa5, 0x2a, 0x2a, 0x7b, 0x71, 0x8d, 0x37, 0x55, 0x6b, 0x5d, 0xfc, 0xc6, 0x12, 0x12, 0xdd, 0x80, + 0x61, 0xb1, 0x77, 0x03, 0x79, 0xb8, 0x98, 0x5a, 0x9e, 0x8b, 0xed, 0xaf, 0x64, 0x8c, 0xf8, 0xed, + 0xe1, 0x00, 0x10, 0x55, 0x42, 0x71, 0x3e, 0xc0, 0xa1, 0x1f, 0xc9, 0x20, 0xce, 0x7b, 0xca, 0xef, + 0x4a, 0x28, 0xbf, 0x07, 0xb3, 0x80, 0x72, 0x09, 0xdd, 0x4b, 0x60, 0xb3, 0x21, 0x96, 0x36, 0xcc, + 0x50, 0x1f, 0x43, 0x7c, 0x80, 0xf5, 0xf2, 0xfd, 0x3c, 0x4c, 0xcb, 0x9a, 0x4b, 0x4e, 0x53, 0x7a, + 0x50, 0xe4, 0x71, 0x90, 0x4f, 0x3c, 0x0e, 0xac, 0x40, 0x39, 0x11, 0x47, 0x6c, 0x39, 0xd3, 0xd7, + 0x28, 0x1e, 0x45, 0xae, 0x90, 0x08, 0x61, 0x13, 0xce, 0x92, 0xac, 0x25, 0xd5, 0x14, 0xf4, 0x87, + 0x06, 0x9c, 0xdc, 0xa6, 0xae, 0xb5, 0x69, 0x55, 0xb9, 0x30, 0xb8, 0x6a, 0x79, 0xbe, 0xe3, 0xee, + 0xc8, 0x03, 0xf8, 0xe9, 0x74, 0x9c, 0xaf, 0x6b, 0x00, 0x2b, 0xf6, 0xa6, 0x53, 0xbe, 0x4f, 0x72, + 0x3b, 0x79, 0xbd, 0x1b, 0x1a, 0x27, 0xf1, 0x9b, 0x6b, 0x03, 0xa8, 0xaf, 0x4d, 0x90, 0x45, 0xab, + 0xfa, 0xe6, 0x4d, 0xfd, 0x61, 0x41, 0x67, 0x03, 0xc9, 0xa2, 0xcb, 0xb0, 0x57, 0xe0, 0x74, 0x30, + 0x62, 0x4c, 0x2e, 0x5a, 0x8e, 0xbd, 0xe4, 0x5a, 0x3e, 0x75, 0x2d, 0x82, 0xce, 0x01, 0xd0, 0x50, + 0xc2, 0x48, 0x89, 0x12, 0x6e, 0x64, 0x25, 0x7b, 0xb0, 0x56, 0xcb, 0xfc, 0xa9, 0x01, 0x05, 0x89, + 0x77, 0x0c, 0xea, 0x2b, 0x8e, 0xaa, 0xaf, 0x8f, 0x65, 0x1a, 0x8e, 0x1e, 0x1a, 0xab, 0x0b, 0xe3, + 0x11, 0x99, 0x81, 0x9e, 0x92, 0xe1, 0x02, 0x31, 0x00, 0xbf, 0xa1, 0x87, 0x0b, 0x6e, 0xef, 0x2e, + 0x4c, 0x47, 0x2a, 0xab, 0x18, 0xc2, 0xc1, 0x7e, 0x98, 0x0b, 0x23, 0x3f, 0xf8, 0x8b, 0x85, 0x13, + 0x1f, 0xfc, 0xf2, 0xcc, 0x09, 0x66, 0x71, 0x4e, 0xc5, 0x27, 0x29, 0x85, 0x28, 0x57, 0x22, 0x71, + 0xe4, 0x48, 0x45, 0x62, 0xee, 0xe8, 0x44, 0x62, 0xfe, 0x28, 0x44, 0xe2, 0xc0, 0xa1, 0x89, 0x44, + 0xf3, 0x9f, 0x0c, 0x98, 0x08, 0x67, 0xe6, 0xdd, 0x0e, 0xd3, 0x8b, 0xd4, 0xa8, 0x1b, 0x87, 0x3f, + 0xea, 0xef, 0xc0, 0xb0, 0xe7, 0x74, 0xdc, 0x2a, 0x57, 0xfe, 0x19, 0xfa, 0x93, 0xd9, 0x64, 0xb0, + 0x68, 0xab, 0x69, 0xbc, 0xa2, 0x00, 0x07, 0xa8, 0xe6, 0xcf, 0xf3, 0x61, 0x87, 0x24, 0x4d, 0x28, + 0x84, 0x2e, 0x53, 0x97, 0x59, 0x87, 0x46, 0x74, 0x85, 0x90, 0x95, 0x62, 0x49, 0x45, 0x26, 0x3f, + 0x1e, 0x02, 0xbb, 0x64, 0xb4, 0x0c, 0x52, 0xca, 0xf3, 0x49, 0x10, 0x14, 0xd4, 0x86, 0x29, 0x97, + 0xbe, 0xdb, 0xb1, 0x5c, 0x5a, 0xab, 0x38, 0x64, 0x8b, 0x29, 0x60, 0xd2, 0x21, 0x96, 0x72, 0xdf, + 0x2f, 0x77, 0x84, 0xf3, 0xa2, 0x3c, 0xb3, 0xb7, 0xbb, 0x30, 0x85, 0x63, 0x58, 0xb8, 0x0b, 0x1d, + 0x39, 0x30, 0x43, 0xb6, 0x89, 0xd5, 0x24, 0x1b, 0x56, 0xd3, 0xf2, 0x77, 0x2a, 0xbe, 0x4b, 0x7c, + 0x5a, 0xdf, 0x91, 0xaa, 0xff, 0x73, 0xb2, 0x2f, 0x33, 0xa5, 0x84, 0x3a, 0xb7, 0x77, 0x17, 0xee, + 0x93, 0x63, 0x91, 0x44, 0xc6, 0x89, 0xc0, 0xe8, 0x7b, 0x06, 0xcc, 0x90, 0x84, 0x50, 0x03, 0x37, + 0x21, 0x52, 0x5b, 0x52, 0x49, 0xc1, 0x8a, 0xf2, 0x2c, 0xff, 0xd2, 0x04, 0x0a, 0x4e, 0xe4, 0x68, + 0xfe, 0x62, 0x38, 0x14, 0x56, 0xd2, 0x47, 0xf5, 0x3e, 0x14, 0xaa, 0xc2, 0xde, 0x6e, 0xee, 0xac, + 0xd8, 0x72, 0x7b, 0x2d, 0xf7, 0x71, 0x8e, 0x17, 0x97, 0x14, 0x4c, 0x4c, 0x51, 0xd7, 0x28, 0x58, + 0xe7, 0x86, 0x6e, 0x02, 0x88, 0x43, 0x8d, 0xd6, 0x56, 0x6c, 0x79, 0x6a, 0x2f, 0xf5, 0xc3, 0xfb, + 0x7a, 0x88, 0x22, 0x58, 0x87, 0xa7, 0x8e, 0x22, 0x60, 0x8d, 0x15, 0xeb, 0x75, 0x10, 0x50, 0xbd, + 0xec, 0xb8, 0x52, 0x5e, 0xf5, 0xd5, 0xeb, 0x92, 0x82, 0x89, 0x9b, 0x27, 0x8a, 0x82, 0x75, 0x6e, + 0xc8, 0xd1, 0x8e, 0x38, 0x21, 0x79, 0x4a, 0xfd, 0x70, 0x0e, 0x92, 0x03, 0x04, 0xdb, 0xf0, 0xd4, + 0x0b, 0x8a, 0xd5, 0xa9, 0x37, 0xe7, 0xc2, 0x54, 0x7c, 0x72, 0x12, 0x54, 0x85, 0xab, 0x51, 0x55, + 0xe1, 0x5c, 0x4a, 0x69, 0xa8, 0x39, 0x6b, 0xf4, 0x1c, 0x02, 0x17, 0x26, 0x63, 0x93, 0x92, 0xc0, + 0x72, 0x25, 0xca, 0xf2, 0x89, 0x2c, 0x6a, 0x93, 0x8c, 0xb4, 0xeb, 0x3c, 0x3d, 0x98, 0x8a, 0x4f, + 0xc7, 0xa1, 0x31, 0x8d, 0x84, 0xf7, 0x75, 0xa6, 0xef, 0xc3, 0x78, 0x64, 0x26, 0x12, 0x38, 0xae, + 0x47, 0x39, 0x5e, 0xd4, 0x04, 0x9b, 0xca, 0xe5, 0x79, 0x27, 0x4c, 0xf6, 0x51, 0x32, 0x2e, 0x52, + 0x81, 0x09, 0xbb, 0x97, 0x2a, 0xd7, 0x5e, 0xd5, 0x95, 0xb1, 0xbf, 0xcf, 0xc3, 0x0c, 0xf7, 0xdf, + 0x5a, 0x55, 0x69, 0x4f, 0x96, 0x84, 0x9a, 0xfc, 0x22, 0x0c, 0x11, 0xfe, 0x97, 0xd4, 0x06, 0xce, + 0xea, 0xda, 0xc0, 0xed, 0xdd, 0x85, 0xd9, 0xa4, 0x56, 0x5c, 0x53, 0x90, 0xed, 0x50, 0x09, 0x26, + 0x5b, 0xc4, 0xaf, 0x36, 0x94, 0xde, 0x16, 0x0f, 0xb1, 0xbe, 0x12, 0x25, 0xe3, 0x78, 0x7d, 0xf4, + 0x6d, 0x80, 0x36, 0x71, 0x49, 0x8b, 0xfa, 0xd4, 0x0d, 0x4e, 0xee, 0x94, 0x49, 0x30, 0x49, 0x9f, + 0x57, 0x5c, 0x0b, 0xc1, 0x62, 0xbb, 0x5c, 0x11, 0xb0, 0xc6, 0x11, 0x51, 0x18, 0xf6, 0x89, 0x5b, + 0xa7, 0xe1, 0x09, 0x7f, 0xa1, 0x1f, 0xe6, 0xeb, 0x1c, 0x42, 0x9d, 0x90, 0xe2, 0xb7, 0x87, 0x03, + 0xec, 0xb9, 0x17, 0x60, 0x32, 0xf6, 0x65, 0x99, 0x9c, 0x02, 0xbf, 0x32, 0xe0, 0xfe, 0x28, 0xc7, + 0xe3, 0x8b, 0xa3, 0x53, 0x18, 0x16, 0xd3, 0x9d, 0xd1, 0x75, 0x98, 0x34, 0x3d, 0x6a, 0x84, 0xc4, + 0x6f, 0x0f, 0x07, 0xd8, 0xe6, 0xbf, 0xe5, 0xe2, 0xcb, 0x54, 0x0c, 0x22, 0x7a, 0x3e, 0xa2, 0x2a, + 0x9f, 0x8d, 0xa9, 0xca, 0xb3, 0x49, 0x6d, 0xb2, 0x68, 0xcc, 0xa8, 0x0d, 0xe3, 0x3c, 0x25, 0x4b, + 0x84, 0xe4, 0x1d, 0x57, 0xaa, 0x16, 0x4f, 0xa4, 0x34, 0x29, 0xf4, 0xa6, 0xe5, 0x53, 0x12, 0x7f, + 0x3c, 0x52, 0x8c, 0xa3, 0x0c, 0x18, 0x47, 0xcb, 0xae, 0xd1, 0x5b, 0x21, 0xc7, 0x81, 0x2c, 0x52, + 0x66, 0x45, 0x6f, 0xaa, 0x38, 0x46, 0x8a, 0x71, 0x94, 0x81, 0xf9, 0xe7, 0x39, 0x18, 0x0d, 0x75, + 0xe8, 0x2c, 0x81, 0x5f, 0x61, 0x4a, 0xe7, 0x0e, 0xf0, 0xac, 0xe6, 0xd3, 0x78, 0x56, 0x07, 0x7a, + 0x7b, 0x56, 0x83, 0x84, 0xa2, 0xa1, 0xfd, 0x13, 0x8a, 0x34, 0xcf, 0xea, 0x70, 0x7a, 0xcf, 0xea, + 0xc8, 0xc1, 0x9e, 0x55, 0xf3, 0x2f, 0x0d, 0x40, 0xdd, 0x6e, 0xf4, 0x2c, 0x03, 0x45, 0xe2, 0x96, + 0xcd, 0xd3, 0x59, 0x7d, 0x9a, 0x07, 0x19, 0x38, 0xe6, 0x2d, 0xb8, 0xef, 0x8a, 0xe5, 0x7f, 0x15, + 0x6e, 0x41, 0xc1, 0x79, 0x95, 0x1c, 0x3f, 0xe7, 0x0f, 0x87, 0x61, 0xf2, 0x8a, 0xd5, 0x77, 0xde, + 0x82, 0x0f, 0xa7, 0xc5, 0xe8, 0x85, 0xf9, 0x36, 0xa1, 0x2a, 0x2f, 0xd6, 0xf4, 0x05, 0xd9, 0xf4, + 0xf4, 0x52, 0x72, 0xb5, 0xdb, 0xbd, 0x49, 0xb8, 0x17, 0x74, 0xea, 0x8d, 0xf1, 0x1c, 0x8c, 0x7b, + 0xbe, 0x6b, 0x55, 0x7d, 0x91, 0x19, 0xe1, 0xcd, 0x16, 0xb8, 0xa9, 0x14, 0x6e, 0xe9, 0x8a, 0x4e, + 0xc4, 0xd1, 0xba, 0x89, 0x09, 0x17, 0x03, 0x99, 0x13, 0x2e, 0x16, 0x61, 0x94, 0x34, 0x9b, 0xce, + 0xcd, 0x75, 0x52, 0xf7, 0x64, 0xb8, 0x22, 0x9c, 0x90, 0x52, 0x40, 0xc0, 0xaa, 0x0e, 0x7a, 0x11, + 0xa6, 0xc2, 0x1f, 0x98, 0xd6, 0xe9, 0x2d, 0xea, 0xcd, 0x8e, 0x73, 0xcb, 0x8d, 0xdb, 0x56, 0xa5, + 0x18, 0x0d, 0x77, 0xd5, 0x46, 0x45, 0x00, 0xab, 0x6e, 0x3b, 0x2e, 0xe5, 0x3c, 0x87, 0x78, 0x5b, + 0x9e, 0xca, 0xb8, 0x12, 0x96, 0x62, 0xad, 0x06, 0x5a, 0x82, 0x69, 0xf5, 0x2b, 0x60, 0x39, 0xc1, + 0x9b, 0x9d, 0xda, 0xdb, 0x5d, 0x98, 0x5e, 0x89, 0x13, 0x71, 0x77, 0x7d, 0x36, 0x5a, 0xca, 0xa1, + 0x74, 0xd9, 0x6a, 0x32, 0xc1, 0x30, 0x16, 0x1d, 0xad, 0x4b, 0x31, 0x3a, 0xee, 0x6a, 0x81, 0x2a, + 0x70, 0xca, 0xb2, 0x3d, 0x5a, 0xed, 0xb8, 0xb4, 0xb2, 0x65, 0xb5, 0xd7, 0x57, 0x2b, 0x5c, 0xcf, + 0xdc, 0xe1, 0xe2, 0x68, 0xa4, 0xfc, 0x80, 0x84, 0x3a, 0xb5, 0x92, 0x54, 0x09, 0x27, 0xb7, 0x45, + 0x4f, 0xc2, 0x98, 0x65, 0x57, 0x9b, 0x9d, 0x1a, 0x5d, 0x23, 0x7e, 0xc3, 0x9b, 0x1d, 0xe1, 0x5d, + 0x9b, 0xda, 0xdb, 0x5d, 0x18, 0x5b, 0xd1, 0xca, 0x71, 0xa4, 0x16, 0x6b, 0x45, 0x6f, 0x69, 0xad, + 0x46, 0x55, 0xab, 0x4b, 0xb7, 0xf4, 0x56, 0x7a, 0xad, 0x84, 0xfc, 0x1a, 0xc8, 0x94, 0x5f, 0x73, + 0x13, 0xe6, 0xae, 0x58, 0x3e, 0x25, 0x5f, 0x85, 0x04, 0xba, 0x4a, 0xdc, 0x0d, 0xc7, 0x3d, 0x76, + 0xce, 0x3f, 0xca, 0xc1, 0x90, 0xc8, 0x02, 0x45, 0x4f, 0xc5, 0x52, 0x2d, 0x1f, 0xe8, 0x4a, 0xb5, + 0x2c, 0x24, 0x65, 0xcc, 0x9a, 0x30, 0x64, 0x79, 0x5e, 0x27, 0xea, 0xe2, 0x58, 0xe1, 0x25, 0x58, + 0x52, 0x78, 0xe8, 0x94, 0x77, 0x45, 0xea, 0x02, 0x77, 0xa8, 0xff, 0x0b, 0x1e, 0x62, 0x70, 0xb0, + 0x44, 0x66, 0x3c, 0x9c, 0x8e, 0xdf, 0xee, 0xf8, 0xd2, 0xa9, 0x70, 0x28, 0x3c, 0xae, 0x71, 0x44, + 0x2c, 0x91, 0xcd, 0x8f, 0x0d, 0x98, 0x14, 0x63, 0xb0, 0xd4, 0xa0, 0xd5, 0xad, 0x8a, 0x4f, 0xdb, + 0x4c, 0x05, 0xeb, 0x78, 0xd4, 0x8b, 0xfb, 0x1c, 0x5f, 0xf3, 0xa8, 0x87, 0x39, 0x45, 0xeb, 0x7d, + 0xee, 0xa8, 0x7a, 0x6f, 0x9e, 0x07, 0x6d, 0x72, 0x78, 0x1a, 0xb3, 0xc8, 0xe6, 0x15, 0x1a, 0x78, + 0x5e, 0x1d, 0x22, 0xa2, 0xd6, 0x0e, 0x0e, 0xe8, 0xe6, 0x8f, 0x73, 0x30, 0xc8, 0xdd, 0x82, 0x59, + 0x4e, 0x9e, 0x03, 0xc2, 0xc9, 0x2a, 0x5e, 0x3a, 0xb0, 0x6f, 0xbc, 0xd4, 0x4b, 0x0a, 0x97, 0x3e, + 0x9f, 0xc1, 0xb3, 0xd9, 0xcf, 0xb5, 0x80, 0x3b, 0x0d, 0x61, 0xfe, 0xda, 0x80, 0x99, 0xa4, 0xc4, + 0x81, 0x2c, 0xe3, 0xf7, 0x28, 0x8c, 0xb4, 0x9b, 0xc4, 0xdf, 0x74, 0xdc, 0x56, 0x3c, 0x31, 0x79, + 0x4d, 0x96, 0xe3, 0xb0, 0x06, 0x72, 0x01, 0xdc, 0x60, 0x3f, 0x07, 0x56, 0xe4, 0xc5, 0x3b, 0x0b, + 0x2a, 0x2b, 0xcb, 0x31, 0x2c, 0xf2, 0xb0, 0xc6, 0xc5, 0xfc, 0x74, 0x10, 0xa6, 0x79, 0x93, 0x7e, + 0x95, 0x93, 0x36, 0xdc, 0xc3, 0xbd, 0xcc, 0xdd, 0xba, 0x89, 0x58, 0x35, 0xe7, 0x65, 0xcb, 0x7b, + 0x56, 0x12, 0x6b, 0xdd, 0xee, 0x49, 0xc1, 0x3d, 0x70, 0xbb, 0x15, 0x0e, 0xc8, 0xa0, 0x70, 0x9c, + 0xe3, 0x99, 0x6a, 0x81, 0xaa, 0x51, 0x88, 0x46, 0x6e, 0x34, 0x25, 0x43, 0xab, 0xf5, 0x7f, 0x46, + 0xbd, 0xd0, 0x57, 0xeb, 0xf0, 0x81, 0xab, 0xb5, 0xa7, 0x1a, 0x31, 0x72, 0x07, 0x6a, 0x44, 0xf7, + 0xd1, 0x3e, 0x9a, 0xe9, 0x68, 0xff, 0x63, 0x03, 0xa2, 0x36, 0x24, 0xba, 0x05, 0x63, 0xdc, 0x5b, + 0xb3, 0x62, 0xd7, 0xac, 0x2a, 0x0d, 0x22, 0xa6, 0x17, 0xfb, 0xb0, 0x52, 0xa5, 0xc7, 0xbd, 0x45, + 0x6d, 0x5f, 0x65, 0x41, 0xbd, 0xa2, 0x61, 0xe3, 0x08, 0x27, 0xf3, 0xaf, 0x0d, 0x98, 0xed, 0x05, + 0xc0, 0x24, 0x6b, 0x28, 0x89, 0x94, 0x64, 0x7d, 0x99, 0xee, 0x08, 0xb1, 0xb4, 0x06, 0x23, 0x4e, + 0x9b, 0xba, 0xc4, 0xe7, 0x3e, 0x5b, 0x56, 0xe7, 0xc9, 0x60, 0x2a, 0xae, 0xc9, 0xf2, 0xdb, 0xbb, + 0x0b, 0x67, 0x7a, 0xc1, 0x07, 0x75, 0x70, 0x88, 0xa2, 0x92, 0x1b, 0xf2, 0xfb, 0x24, 0x37, 0x7c, + 0x62, 0xc0, 0xf0, 0x9a, 0xeb, 0xf0, 0x04, 0xa0, 0xa3, 0x4f, 0x6e, 0x78, 0x33, 0x96, 0x18, 0xfc, + 0x44, 0xea, 0xd4, 0x41, 0x06, 0x76, 0x40, 0x50, 0xfd, 0x27, 0x39, 0x18, 0x97, 0x35, 0xef, 0xee, + 0x24, 0xea, 0xc8, 0x47, 0x1e, 0x76, 0x12, 0x75, 0x14, 0xfc, 0xe0, 0x24, 0xea, 0x48, 0xfd, 0xbb, + 0x36, 0x89, 0x3a, 0xf2, 0x95, 0xbd, 0x92, 0xa8, 0x73, 0xb1, 0xde, 0xf0, 0x24, 0xea, 0x6f, 0xc3, + 0x74, 0x3b, 0x08, 0x15, 0xf1, 0x3b, 0x2a, 0x56, 0x28, 0x12, 0x9e, 0xca, 0x98, 0xb8, 0x2a, 0xae, + 0xb8, 0x94, 0xef, 0x95, 0xdc, 0xa7, 0xd7, 0xe2, 0xb8, 0xb8, 0x9b, 0x55, 0x72, 0x12, 0x77, 0xee, + 0xf8, 0x93, 0xb8, 0x13, 0xd6, 0xc5, 0xff, 0x27, 0x71, 0x7f, 0xe5, 0x49, 0xdc, 0x3f, 0x35, 0xa0, + 0x20, 0x67, 0xe6, 0xae, 0x4d, 0x11, 0x91, 0xdf, 0xd7, 0x63, 0xd7, 0x7d, 0x6e, 0xc0, 0x98, 0x26, + 0x9f, 0x3d, 0xd4, 0x00, 0xb8, 0x49, 0x5c, 0xda, 0x70, 0x42, 0xe3, 0x29, 0x75, 0xe0, 0xfe, 0xf5, + 0xa0, 0x1d, 0x47, 0x52, 0x2b, 0x2b, 0x2c, 0xf7, 0xb0, 0x86, 0x8d, 0xbe, 0xa9, 0xc5, 0xe0, 0x85, + 0x70, 0x4f, 0xc5, 0x85, 0x87, 0xb9, 0x04, 0x07, 0x5d, 0x30, 0x6a, 0x91, 0x7b, 0xf3, 0x67, 0x46, + 0x78, 0x94, 0x24, 0x6e, 0x95, 0xfc, 0xd1, 0x6c, 0x95, 0x0a, 0x0c, 0x32, 0xc9, 0x1c, 0xdc, 0xca, + 0x3c, 0x97, 0xf9, 0x74, 0xf4, 0x64, 0x62, 0x38, 0xfb, 0x13, 0x0b, 0x2c, 0xf3, 0x87, 0x39, 0x18, + 0x0d, 0x25, 0xd5, 0x31, 0x1c, 0x89, 0xaf, 0x45, 0x8e, 0xc4, 0x27, 0x32, 0xca, 0xd8, 0x9e, 0xc7, + 0xe1, 0xdb, 0xb1, 0xe3, 0x30, 0xab, 0xf0, 0x3e, 0xe0, 0x28, 0xfc, 0x07, 0x31, 0xe3, 0xa2, 0xee, + 0x31, 0x6c, 0xc5, 0xf5, 0xe8, 0x56, 0x5c, 0xcc, 0xd8, 0x9b, 0x1e, 0x9b, 0xf1, 0x83, 0x1c, 0x4c, + 0xc6, 0x8e, 0x2b, 0xa6, 0x06, 0xf2, 0x55, 0x2d, 0x35, 0xcf, 0xb0, 0xa1, 0x8c, 0xf6, 0x72, 0x1a, + 0xda, 0x66, 0x16, 0x56, 0x68, 0x7b, 0x85, 0xc1, 0xa4, 0x17, 0xfa, 0x3a, 0x21, 0xc3, 0x20, 0xcf, + 0xb4, 0x30, 0xce, 0x34, 0x5c, 0x1c, 0x65, 0x83, 0xd6, 0x62, 0xe9, 0x23, 0x97, 0x6c, 0xb2, 0xd1, + 0xa4, 0x22, 0x72, 0x33, 0x52, 0xbe, 0x3f, 0x4c, 0x58, 0x49, 0xa8, 0x83, 0x13, 0x5b, 0x9a, 0x7f, + 0x65, 0xc0, 0xe9, 0x1e, 0xdf, 0x93, 0x22, 0x8b, 0xac, 0x19, 0x0f, 0xaa, 0xe5, 0xfa, 0x0f, 0xaa, + 0x4d, 0x1f, 0x14, 0x50, 0x33, 0x3f, 0xcd, 0x01, 0x0a, 0xbf, 0x35, 0x4b, 0xb2, 0xdb, 0xdb, 0x30, + 0xbc, 0x29, 0x12, 0x26, 0xee, 0x2c, 0xf9, 0xb1, 0x5c, 0xd0, 0xf3, 0x3f, 0x03, 0x4c, 0xf4, 0xc6, + 0xe1, 0xec, 0x35, 0xe8, 0xde, 0x67, 0xe8, 0x06, 0xc0, 0xa6, 0x65, 0x5b, 0x5e, 0xa3, 0xcf, 0x04, + 0x76, 0x6e, 0x12, 0x5f, 0x0e, 0x11, 0xb0, 0x86, 0x66, 0xfe, 0x69, 0x4e, 0xdb, 0xc3, 0x5c, 0xf9, + 0x4b, 0xb5, 0xf6, 0x1f, 0x8e, 0x0e, 0xe6, 0x68, 0x77, 0x62, 0x6c, 0x38, 0x30, 0x37, 0x60, 0x60, + 0x9b, 0xb8, 0x41, 0xc8, 0x3d, 0xe5, 0x3d, 0x97, 0xee, 0xcc, 0x74, 0x35, 0xa7, 0xd7, 0x89, 0xeb, + 0x61, 0x8e, 0xc9, 0x14, 0x63, 0xcf, 0xa7, 0xed, 0xe0, 0x70, 0xc9, 0x2c, 0x38, 0x7d, 0xda, 0xd6, + 0x3b, 0x48, 0xdb, 0xfc, 0x04, 0xa0, 0x6d, 0xcf, 0xfc, 0xcf, 0x61, 0x4d, 0x2a, 0xc8, 0xf3, 0xec, + 0x30, 0x35, 0xa9, 0xa7, 0x82, 0x77, 0x2a, 0xc4, 0x28, 0x2f, 0x44, 0xde, 0xa9, 0xb8, 0xbd, 0xbb, + 0x30, 0xa1, 0xf6, 0xa3, 0xf6, 0x72, 0x45, 0x86, 0x17, 0x19, 0xf4, 0xf5, 0x3e, 0x78, 0x04, 0xeb, + 0xfd, 0x77, 0x61, 0x7a, 0x33, 0x9e, 0x29, 0x2d, 0xaf, 0xa9, 0x3c, 0xd3, 0x67, 0xa2, 0xb5, 0x70, + 0xc2, 0x74, 0x15, 0xe3, 0x6e, 0x46, 0xc8, 0x09, 0xde, 0x81, 0xe0, 0xae, 0x67, 0x11, 0x48, 0x49, + 0xbd, 0xe7, 0x62, 0x4e, 0xeb, 0xf8, 0x0b, 0x10, 0x02, 0x12, 0x47, 0x18, 0xa0, 0xd7, 0x61, 0xd4, + 0xf3, 0x89, 0x2b, 0xee, 0x90, 0x8c, 0xf5, 0x77, 0x87, 0xa4, 0x12, 0x00, 0x60, 0x85, 0x15, 0xdb, + 0xdc, 0x43, 0x87, 0xb9, 0xb9, 0xd1, 0x53, 0x61, 0x32, 0x1f, 0xeb, 0x27, 0x77, 0x12, 0xe5, 0xbb, + 0xd2, 0xf0, 0x18, 0x09, 0xeb, 0xf5, 0xd0, 0x47, 0x06, 0x9c, 0x62, 0xbb, 0xe0, 0xd2, 0x2d, 0x5a, + 0xed, 0xb0, 0xe1, 0x0e, 0x12, 0x9a, 0x66, 0x0b, 0x59, 0x6c, 0xb0, 0x4a, 0x12, 0x84, 0xf2, 0x78, + 0x25, 0x92, 0x71, 0x32, 0x63, 0xf4, 0x8e, 0xd0, 0xf2, 0x28, 0xf7, 0x62, 0xde, 0x79, 0xd0, 0x20, + 0xd4, 0xf8, 0x84, 0x40, 0xf3, 0xa9, 0xf9, 0xc3, 0x01, 0x5d, 0x0e, 0xa6, 0x0b, 0x65, 0xdc, 0x80, + 0x01, 0x9f, 0x78, 0x5b, 0x72, 0x7b, 0x3d, 0xdf, 0xc7, 0x95, 0x4e, 0xb5, 0xc9, 0x46, 0x18, 0x36, + 0x2f, 0xe2, 0x98, 0x68, 0x0e, 0x72, 0xc4, 0x8b, 0x27, 0x63, 0x94, 0x3c, 0x9c, 0x23, 0x1e, 0x4f, + 0xd4, 0xd8, 0x94, 0xbe, 0x47, 0x95, 0xa8, 0xb1, 0x89, 0x73, 0x16, 0x7f, 0x09, 0xa3, 0xea, 0xd8, + 0xbe, 0x65, 0x77, 0xe8, 0x35, 0xfb, 0x92, 0xeb, 0x3a, 0xae, 0xf4, 0x34, 0x86, 0x69, 0x5a, 0x4b, + 0x51, 0x32, 0x8e, 0xd7, 0x47, 0x6f, 0xc0, 0xa0, 0x4b, 0x7d, 0x77, 0x47, 0x9e, 0x34, 0xe7, 0xfb, + 0x10, 0xaa, 0x98, 0xb5, 0x17, 0xa3, 0xcc, 0xff, 0xc4, 0x02, 0x31, 0x3c, 0x0b, 0x86, 0x8e, 0xe0, + 0x2c, 0x50, 0x81, 0xa5, 0xfc, 0x91, 0x05, 0x96, 0x7e, 0x64, 0x68, 0xca, 0x47, 0xd8, 0x51, 0xf4, + 0x1a, 0x0c, 0xfb, 0x56, 0x8b, 0x3a, 0x1d, 0x3f, 0x9b, 0xd6, 0x1b, 0xe6, 0x2a, 0x73, 0x11, 0xbb, + 0x2e, 0x20, 0x70, 0x80, 0x85, 0x2e, 0xc2, 0x04, 0x65, 0x33, 0xb2, 0xde, 0x60, 0x47, 0x86, 0xd3, + 0x14, 0x2a, 0xde, 0xb8, 0x72, 0xf3, 0x5e, 0x8a, 0x50, 0x71, 0xac, 0xb6, 0xf9, 0xa9, 0xae, 0x9f, + 0xff, 0xef, 0xbf, 0xe6, 0x2c, 0x3d, 0x6f, 0xc7, 0x7a, 0xbf, 0xb9, 0x6f, 0xcf, 0xdb, 0x81, 0x17, + 0x9b, 0xdf, 0x82, 0x7b, 0x92, 0x45, 0xc1, 0xa1, 0x3c, 0x40, 0xf5, 0xb3, 0xf8, 0x58, 0x71, 0xd5, + 0x2e, 0xd8, 0x7e, 0xc6, 0x51, 0xaa, 0x62, 0xb9, 0xc3, 0x56, 0xc5, 0x5c, 0xbd, 0x2b, 0xf2, 0xb9, + 0x2e, 0xf4, 0xb6, 0x5c, 0x67, 0x46, 0x96, 0x07, 0xa0, 0xba, 0x60, 0x7a, 0xae, 0xb5, 0x5f, 0x18, + 0x70, 0x2a, 0xb1, 0x76, 0x38, 0x86, 0xb9, 0xa3, 0x1c, 0x43, 0xe3, 0xb0, 0xc7, 0x70, 0x1b, 0xee, + 0xfd, 0x46, 0x87, 0x1c, 0xfb, 0xc3, 0x4c, 0xe6, 0x0f, 0x72, 0x30, 0x85, 0x69, 0xdb, 0x89, 0xc4, + 0x4d, 0xd7, 0x82, 0x8b, 0xef, 0x19, 0xec, 0xa4, 0x58, 0x62, 0x58, 0x79, 0x38, 0x72, 0xe3, 0x9d, + 0x6d, 0xd3, 0x56, 0xa0, 0x14, 0xa7, 0x16, 0x3b, 0x5d, 0x11, 0x5d, 0x71, 0x62, 0x89, 0xd8, 0xb0, + 0x00, 0x64, 0xc8, 0xfc, 0x26, 0x8f, 0x3c, 0x54, 0x9e, 0xc9, 0x70, 0x27, 0xa8, 0x1b, 0x99, 0x17, + 0x63, 0x01, 0x68, 0x7e, 0x9c, 0x03, 0x61, 0x53, 0x1d, 0x83, 0x54, 0xfe, 0x46, 0x44, 0x2a, 0x2f, + 0x66, 0xf1, 0xf9, 0xf5, 0xf2, 0x2d, 0xc5, 0xed, 0xdd, 0xc7, 0x33, 0x3a, 0x12, 0xf7, 0xf1, 0x2b, + 0xfd, 0x8d, 0x01, 0xa3, 0xbc, 0xde, 0x31, 0x08, 0xf8, 0xb5, 0xa8, 0x80, 0x7f, 0x24, 0x43, 0x2f, + 0x7a, 0x08, 0xf6, 0xff, 0xca, 0xcb, 0xaf, 0x0f, 0xad, 0xe9, 0x06, 0x71, 0x6b, 0xd2, 0x4c, 0x54, + 0xbb, 0x93, 0x15, 0x62, 0x41, 0x0b, 0x65, 0xca, 0xf0, 0x11, 0xc8, 0x94, 0xf7, 0xc4, 0x85, 0x2a, + 0xea, 0xf9, 0xb4, 0x76, 0x39, 0xb4, 0x07, 0xf3, 0x99, 0x6f, 0x86, 0xc9, 0xdb, 0x6b, 0xca, 0x53, + 0x8f, 0x63, 0xa8, 0xb8, 0x8b, 0x0f, 0xb3, 0x11, 0xdb, 0x71, 0x21, 0x2a, 0x4d, 0x9c, 0x67, 0xfa, + 0x94, 0xd8, 0xc2, 0x46, 0xec, 0x2a, 0xc6, 0xdd, 0x8c, 0x50, 0x03, 0xc6, 0xf4, 0x2b, 0xb2, 0x72, + 0x9d, 0x9e, 0xcb, 0x7e, 0x17, 0x57, 0xa4, 0xda, 0xe9, 0x25, 0x38, 0x82, 0x6c, 0x7e, 0x68, 0x00, + 0x28, 0x0f, 0x39, 0x9b, 0xf3, 0xaa, 0xd3, 0xb1, 0x85, 0x6b, 0x24, 0xaf, 0xe6, 0x7c, 0x89, 0x15, + 0x62, 0x41, 0x63, 0xfb, 0x47, 0x18, 0x98, 0x72, 0x51, 0x3f, 0x9e, 0xc5, 0x76, 0x8d, 0x79, 0xe2, + 0x45, 0x21, 0x96, 0x80, 0xe6, 0xdf, 0x8e, 0x40, 0x41, 0xdb, 0x67, 0x31, 0x3f, 0xfc, 0xf8, 0x91, + 0x85, 0xac, 0x12, 0x9c, 0x23, 0x85, 0xbe, 0x9c, 0x23, 0x1e, 0x4c, 0x48, 0x93, 0x3f, 0xb8, 0x47, + 0x2d, 0x9c, 0x47, 0x7d, 0x3b, 0x16, 0x10, 0xd3, 0x96, 0x2f, 0x47, 0x20, 0x71, 0x8c, 0x05, 0xd3, + 0xb6, 0x65, 0x49, 0xa5, 0xd3, 0x6a, 0x11, 0x77, 0x47, 0x26, 0x8d, 0x86, 0xda, 0xf6, 0xe5, 0x08, + 0x15, 0xc7, 0x6a, 0xa3, 0xb5, 0x70, 0x42, 0xc5, 0x65, 0xda, 0x47, 0xb3, 0x4c, 0xa8, 0xb0, 0x36, + 0xa2, 0xf3, 0xd8, 0x23, 0x0a, 0x38, 0xd4, 0x57, 0x14, 0xf0, 0x3d, 0x98, 0x92, 0x26, 0x7e, 0xb8, + 0x77, 0xa4, 0xb7, 0x26, 0xab, 0x7d, 0xa7, 0x8e, 0x7e, 0x9e, 0xa6, 0xb3, 0x14, 0x43, 0xc5, 0x5d, + 0x7c, 0xd0, 0xbb, 0x30, 0xce, 0x26, 0x59, 0x31, 0x86, 0x3b, 0x64, 0x2c, 0xbd, 0xc4, 0x1a, 0x24, + 0x8e, 0x72, 0xe8, 0xe9, 0x23, 0x9f, 0xe8, 0xd7, 0x47, 0x8e, 0x5a, 0xda, 0x31, 0x34, 0xc9, 0x57, + 0xe3, 0xd7, 0x33, 0x9f, 0x78, 0x19, 0xee, 0xe8, 0x7d, 0xa5, 0xd7, 0xc8, 0x3e, 0xcf, 0x43, 0xb2, + 0x7b, 0x46, 0xbd, 0xb4, 0x61, 0xec, 0xf3, 0xd2, 0x46, 0xc4, 0x57, 0x96, 0x3b, 0x32, 0x5f, 0x59, + 0xfe, 0x50, 0x7d, 0x65, 0xe7, 0x00, 0xb8, 0xf9, 0xcc, 0x85, 0x34, 0x3f, 0xad, 0xc7, 0xb5, 0xc7, + 0x0a, 0x42, 0x0a, 0xd6, 0x6a, 0xa1, 0x17, 0x42, 0x1d, 0x48, 0xe4, 0xbb, 0xfd, 0x66, 0x57, 0x92, + 0xf0, 0xc9, 0x88, 0x72, 0x1e, 0xf3, 0xeb, 0x67, 0xb8, 0x0d, 0x93, 0xe0, 0xd6, 0x19, 0xce, 0xe6, + 0xd6, 0x31, 0xff, 0x3b, 0x07, 0x91, 0x33, 0x0c, 0x7d, 0xcf, 0x80, 0x69, 0x12, 0x7b, 0x06, 0x39, + 0x30, 0x3d, 0xbe, 0x9e, 0xed, 0x6d, 0xea, 0xae, 0x57, 0x94, 0x55, 0xc2, 0x47, 0xbc, 0x8a, 0x87, + 0xbb, 0x99, 0xa2, 0x3f, 0x30, 0xe0, 0x24, 0xe9, 0x7e, 0xe7, 0x5a, 0x2e, 0x9e, 0x67, 0xfb, 0x7e, + 0x28, 0xbb, 0x7c, 0x7a, 0x6f, 0x77, 0x21, 0xe9, 0x05, 0x70, 0x9c, 0xc4, 0x0e, 0xbd, 0x09, 0x03, + 0xc4, 0xad, 0x07, 0xd1, 0x84, 0xec, 0x6c, 0x83, 0xe7, 0xcb, 0x95, 0x22, 0x56, 0x72, 0xeb, 0x1e, + 0xe6, 0xa0, 0xe6, 0x2f, 0xf3, 0x30, 0x15, 0x7f, 0xe1, 0x43, 0xde, 0xb9, 0x1a, 0x48, 0xbc, 0x73, + 0xc5, 0xf6, 0x1a, 0x8f, 0xa7, 0xc5, 0x5f, 0xb5, 0xe1, 0x61, 0x31, 0x41, 0x0b, 0xf7, 0x1a, 0xbf, + 0x28, 0x3f, 0x78, 0x07, 0x7b, 0x8d, 0xdf, 0x8e, 0x57, 0x58, 0xe8, 0x7c, 0x34, 0x40, 0x61, 0xc6, + 0x03, 0x14, 0xd3, 0x7a, 0x5f, 0xfa, 0x8d, 0x51, 0xb4, 0xa0, 0xa0, 0xcd, 0x83, 0xdc, 0xd1, 0x17, + 0x32, 0x8f, 0xbb, 0x5a, 0x76, 0x93, 0x22, 0xd9, 0x59, 0x51, 0x74, 0x7c, 0x25, 0x3f, 0xf8, 0x68, + 0xdd, 0x91, 0xaf, 0x9d, 0x0f, 0x97, 0x86, 0x66, 0xfe, 0x8b, 0x01, 0xe3, 0x91, 0x9b, 0xc8, 0x8c, + 0x5b, 0x70, 0xc5, 0xbc, 0xff, 0x37, 0xbf, 0xaf, 0x87, 0x08, 0x58, 0x43, 0x43, 0xdf, 0x82, 0x42, + 0xd3, 0xb1, 0xeb, 0xd4, 0xf3, 0x2b, 0x0e, 0xd9, 0x92, 0xfb, 0x24, 0xab, 0xd7, 0x91, 0xbf, 0x16, + 0xb0, 0x2a, 0x60, 0x96, 0x9c, 0x56, 0xbb, 0x49, 0x7d, 0xf1, 0x2e, 0x02, 0xd6, 0xc1, 0x79, 0x32, + 0x44, 0x98, 0x4d, 0x72, 0xb7, 0x26, 0x43, 0xa8, 0x34, 0x98, 0x43, 0x4e, 0x86, 0x88, 0xe4, 0xd7, + 0x1c, 0x90, 0x0c, 0x11, 0xd6, 0xbd, 0x6b, 0x93, 0x21, 0xc2, 0x2f, 0xec, 0x61, 0xbc, 0x7e, 0x38, + 0xa0, 0xf5, 0x22, 0x6a, 0xc0, 0xe6, 0xf6, 0x31, 0x60, 0xdf, 0x82, 0x11, 0xcb, 0xf6, 0xa9, 0xbb, + 0x4d, 0x9a, 0x32, 0x6a, 0x90, 0x75, 0x2d, 0x86, 0x5d, 0x5d, 0x91, 0x38, 0x38, 0x44, 0x44, 0x4d, + 0x38, 0xb5, 0x19, 0x7d, 0x62, 0x48, 0x3e, 0xc4, 0x2d, 0x92, 0x74, 0x9f, 0x0e, 0x22, 0x4a, 0x97, + 0x93, 0x2a, 0xdd, 0xee, 0x45, 0xc0, 0xc9, 0xa0, 0xc8, 0x83, 0x71, 0x4f, 0xf3, 0xdc, 0x04, 0x27, + 0x62, 0xca, 0xe8, 0x69, 0xdc, 0xd9, 0xa5, 0x25, 0xdc, 0xeb, 0xa0, 0x38, 0xca, 0x03, 0x7d, 0xdf, + 0x80, 0xd3, 0x9b, 0xc9, 0xcf, 0x28, 0x49, 0xa9, 0xfe, 0x42, 0x36, 0xdb, 0x27, 0x06, 0x52, 0xbe, + 0x6f, 0x6f, 0x77, 0xa1, 0xd7, 0x43, 0x4d, 0xb8, 0x17, 0x6b, 0xf3, 0x23, 0x03, 0x26, 0xa2, 0x09, + 0x66, 0x5f, 0xb9, 0x71, 0xfb, 0x79, 0x1e, 0x26, 0x63, 0x7b, 0x32, 0x66, 0xe0, 0x8e, 0x1e, 0xa7, + 0x81, 0x3b, 0xd4, 0x97, 0x81, 0x9b, 0x6c, 0xd9, 0x0d, 0xf4, 0x65, 0xd9, 0x3d, 0x27, 0xac, 0x2b, + 0x39, 0xb7, 0x2b, 0xcb, 0xf2, 0x12, 0xb4, 0x76, 0x3d, 0x5d, 0x23, 0xe2, 0x68, 0x5d, 0xae, 0x78, + 0xd5, 0xba, 0x5f, 0x40, 0x95, 0xa6, 0xe1, 0xb3, 0x59, 0xaf, 0xd5, 0x84, 0x00, 0x42, 0xf1, 0x4a, + 0x20, 0xe0, 0x24, 0x76, 0xe6, 0xbf, 0x8f, 0xc0, 0xa9, 0x64, 0xdf, 0xf4, 0xc1, 0xc1, 0x90, 0x77, + 0x61, 0x74, 0x23, 0x78, 0xc4, 0x5e, 0xee, 0x95, 0x94, 0x2f, 0xb7, 0xec, 0xff, 0xf6, 0xbd, 0xd0, + 0x8d, 0xc2, 0x3a, 0x58, 0x71, 0x61, 0x2c, 0x6b, 0xfc, 0xdd, 0xc6, 0x46, 0x67, 0x43, 0xaa, 0x11, + 0x29, 0x59, 0xee, 0xff, 0xdc, 0xa3, 0x60, 0x19, 0xd6, 0xc1, 0x8a, 0x0b, 0xa2, 0x30, 0x24, 0x18, + 0xc8, 0x63, 0xb1, 0x94, 0xda, 0x6d, 0xde, 0x93, 0x19, 0x77, 0x39, 0x88, 0x0a, 0x58, 0x82, 0x4b, + 0x36, 0x4d, 0xb2, 0x21, 0x0f, 0xc9, 0xf4, 0x6c, 0x7a, 0xdd, 0x18, 0x0f, 0xd9, 0xac, 0x12, 0xc1, + 0xa6, 0x49, 0x38, 0x9b, 0x06, 0xbf, 0xe2, 0x29, 0x5d, 0x01, 0x29, 0xd9, 0xec, 0x73, 0x2d, 0x54, + 0x3a, 0x50, 0x78, 0x05, 0x2c, 0xc1, 0xd1, 0xdb, 0x30, 0xf0, 0x6e, 0x87, 0x04, 0x81, 0xec, 0x94, + 0x36, 0x4d, 0xcf, 0x38, 0x89, 0x88, 0xd1, 0x33, 0x32, 0xe6, 0xb0, 0x68, 0x07, 0x0a, 0x44, 0xfd, + 0xd3, 0x0b, 0xf9, 0xac, 0xe4, 0xe5, 0xb4, 0xff, 0x16, 0x64, 0xff, 0xff, 0x96, 0x21, 0x35, 0x59, + 0x55, 0x0b, 0xeb, 0xbc, 0x10, 0x81, 0x41, 0xf2, 0x5e, 0xc7, 0xa5, 0xd2, 0xd7, 0xf4, 0x62, 0x4a, + 0xa6, 0x3d, 0xff, 0xcb, 0x84, 0x88, 0x4f, 0x70, 0x3a, 0x16, 0xc8, 0x8c, 0x45, 0xdd, 0xf2, 0x29, + 0x91, 0xb2, 0xe0, 0xc5, 0xd4, 0x2b, 0xa1, 0xc7, 0x95, 0x61, 0xc1, 0x82, 0xd3, 0xb1, 0x40, 0x46, + 0x16, 0x0c, 0xd7, 0xc5, 0x93, 0x1e, 0xdc, 0x51, 0x98, 0xfa, 0x89, 0xc6, 0xfd, 0x9e, 0x47, 0x11, + 0xb1, 0x74, 0x59, 0x03, 0x07, 0xf8, 0xe6, 0xfb, 0x70, 0x4f, 0x72, 0xea, 0x79, 0xba, 0x70, 0x6b, + 0x9b, 0xf8, 0xc1, 0x0d, 0xff, 0xb0, 0xc6, 0x1a, 0xf1, 0x1b, 0x98, 0x53, 0xd0, 0x03, 0x90, 0xef, + 0xb8, 0xcd, 0xf8, 0xb3, 0x17, 0xaf, 0xe1, 0x55, 0xcc, 0xca, 0xcb, 0x2f, 0x7d, 0xf2, 0xe5, 0xfc, + 0x89, 0xcf, 0xbe, 0x9c, 0x3f, 0xf1, 0xc5, 0x97, 0xf3, 0x27, 0x3e, 0xd8, 0x9b, 0x37, 0x3e, 0xd9, + 0x9b, 0x37, 0x3e, 0xdb, 0x9b, 0x37, 0xbe, 0xd8, 0x9b, 0x37, 0x7e, 0xb5, 0x37, 0x6f, 0x7c, 0xf4, + 0xeb, 0xf9, 0x13, 0x37, 0x1e, 0x4c, 0xf3, 0x2f, 0xca, 0xfe, 0x27, 0x00, 0x00, 0xff, 0xff, 0x7b, + 0xe5, 0xbd, 0x86, 0xc9, 0x6c, 0x00, 0x00, } func (m *AnalysisRunArgument) Marshal() (dAtA []byte, err error) { @@ -4786,7 +4952,7 @@ func (m *FreightStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *GitCommit) Marshal() (dAtA []byte, err error) { +func (m *GenericWebhookAction) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -4796,55 +4962,68 @@ func (m *GitCommit) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *GitCommit) MarshalTo(dAtA []byte) (int, error) { +func (m *GenericWebhookAction) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *GitCommit) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *GenericWebhookAction) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - i -= len(m.Committer) - copy(dAtA[i:], m.Committer) - i = encodeVarintGenerated(dAtA, i, uint64(len(m.Committer))) - i-- - dAtA[i] = 0x42 - i -= len(m.Author) - copy(dAtA[i:], m.Author) - i = encodeVarintGenerated(dAtA, i, uint64(len(m.Author))) - i-- - dAtA[i] = 0x3a - i -= len(m.Message) - copy(dAtA[i:], m.Message) - i = encodeVarintGenerated(dAtA, i, uint64(len(m.Message))) - i-- - dAtA[i] = 0x32 - i -= len(m.Tag) - copy(dAtA[i:], m.Tag) - i = encodeVarintGenerated(dAtA, i, uint64(len(m.Tag))) - i-- - dAtA[i] = 0x22 - i -= len(m.Branch) - copy(dAtA[i:], m.Branch) - i = encodeVarintGenerated(dAtA, i, uint64(len(m.Branch))) - i-- - dAtA[i] = 0x1a - i -= len(m.ID) - copy(dAtA[i:], m.ID) - i = encodeVarintGenerated(dAtA, i, uint64(len(m.ID))) + if len(m.Targets) > 0 { + for iNdEx := len(m.Targets) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Targets[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + if len(m.Parameters) > 0 { + keysForParameters := make([]string, 0, len(m.Parameters)) + for k := range m.Parameters { + keysForParameters = append(keysForParameters, string(k)) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForParameters) + for iNdEx := len(keysForParameters) - 1; iNdEx >= 0; iNdEx-- { + v := m.Parameters[string(keysForParameters[iNdEx])] + baseI := i + i -= len(v) + copy(dAtA[i:], v) + i = encodeVarintGenerated(dAtA, i, uint64(len(v))) + i-- + dAtA[i] = 0x12 + i -= len(keysForParameters[iNdEx]) + copy(dAtA[i:], keysForParameters[iNdEx]) + i = encodeVarintGenerated(dAtA, i, uint64(len(keysForParameters[iNdEx]))) + i-- + dAtA[i] = 0xa + i = encodeVarintGenerated(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0x1a + } + } + i -= len(m.MatchExpression) + copy(dAtA[i:], m.MatchExpression) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.MatchExpression))) i-- dAtA[i] = 0x12 - i -= len(m.RepoURL) - copy(dAtA[i:], m.RepoURL) - i = encodeVarintGenerated(dAtA, i, uint64(len(m.RepoURL))) + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name))) i-- dAtA[i] = 0xa return len(dAtA) - i, nil } -func (m *GitDiscoveryResult) Marshal() (dAtA []byte, err error) { +func (m *GenericWebhookReceiverConfig) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -4854,20 +5033,178 @@ func (m *GitDiscoveryResult) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *GitDiscoveryResult) MarshalTo(dAtA []byte) (int, error) { +func (m *GenericWebhookReceiverConfig) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *GitDiscoveryResult) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *GenericWebhookReceiverConfig) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if len(m.Commits) > 0 { - for iNdEx := len(m.Commits) - 1; iNdEx >= 0; iNdEx-- { + if len(m.Actions) > 0 { + for iNdEx := len(m.Actions) - 1; iNdEx >= 0; iNdEx-- { { - size, err := m.Commits[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + size, err := m.Actions[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + { + size, err := m.SecretRef.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *GenericWebhookTarget) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GenericWebhookTarget) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenericWebhookTarget) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.IndexSelector.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + { + size, err := m.LabelSelector.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0x12 + i -= len(m.Kind) + copy(dAtA[i:], m.Kind) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Kind))) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *GitCommit) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GitCommit) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GitCommit) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + i -= len(m.Committer) + copy(dAtA[i:], m.Committer) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Committer))) + i-- + dAtA[i] = 0x42 + i -= len(m.Author) + copy(dAtA[i:], m.Author) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Author))) + i-- + dAtA[i] = 0x3a + i -= len(m.Message) + copy(dAtA[i:], m.Message) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Message))) + i-- + dAtA[i] = 0x32 + i -= len(m.Tag) + copy(dAtA[i:], m.Tag) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Tag))) + i-- + dAtA[i] = 0x22 + i -= len(m.Branch) + copy(dAtA[i:], m.Branch) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Branch))) + i-- + dAtA[i] = 0x1a + i -= len(m.ID) + copy(dAtA[i:], m.ID) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.ID))) + i-- + dAtA[i] = 0x12 + i -= len(m.RepoURL) + copy(dAtA[i:], m.RepoURL) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.RepoURL))) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *GitDiscoveryResult) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GitDiscoveryResult) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GitDiscoveryResult) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Commits) > 0 { + for iNdEx := len(m.Commits) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Commits[iNdEx].MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } @@ -5465,6 +5802,81 @@ func (m *ImageSubscription) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *IndexSelector) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *IndexSelector) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *IndexSelector) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.MatchIndices) > 0 { + for iNdEx := len(m.MatchIndices) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.MatchIndices[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *IndexSelectorRequirement) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *IndexSelectorRequirement) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *IndexSelectorRequirement) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + i -= len(m.Value) + copy(dAtA[i:], m.Value) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Value))) + i-- + dAtA[i] = 0x1a + i -= len(m.Operator) + copy(dAtA[i:], m.Operator) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Operator))) + i-- + dAtA[i] = 0x12 + i -= len(m.Key) + copy(dAtA[i:], m.Key) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Key))) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + func (m *Project) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -7685,6 +8097,18 @@ func (m *WebhookReceiverConfig) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Generic != nil { + { + size, err := m.Generic.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x5a + } if m.Harbor != nil { { size, err := m.Harbor.MarshalToSizedBuffer(dAtA[:i]) @@ -8510,39 +8934,43 @@ func (m *FreightStatus) Size() (n int) { return n } -func (m *GitCommit) Size() (n int) { +func (m *GenericWebhookAction) Size() (n int) { if m == nil { return 0 } var l int _ = l - l = len(m.RepoURL) - n += 1 + l + sovGenerated(uint64(l)) - l = len(m.ID) - n += 1 + l + sovGenerated(uint64(l)) - l = len(m.Branch) - n += 1 + l + sovGenerated(uint64(l)) - l = len(m.Tag) - n += 1 + l + sovGenerated(uint64(l)) - l = len(m.Message) - n += 1 + l + sovGenerated(uint64(l)) - l = len(m.Author) + l = len(m.Name) n += 1 + l + sovGenerated(uint64(l)) - l = len(m.Committer) + l = len(m.MatchExpression) n += 1 + l + sovGenerated(uint64(l)) + if len(m.Parameters) > 0 { + for k, v := range m.Parameters { + _ = k + _ = v + mapEntrySize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + len(v) + sovGenerated(uint64(len(v))) + n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize)) + } + } + if len(m.Targets) > 0 { + for _, e := range m.Targets { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } return n } -func (m *GitDiscoveryResult) Size() (n int) { +func (m *GenericWebhookReceiverConfig) Size() (n int) { if m == nil { return 0 } var l int _ = l - l = len(m.RepoURL) + l = m.SecretRef.Size() n += 1 + l + sovGenerated(uint64(l)) - if len(m.Commits) > 0 { - for _, e := range m.Commits { + if len(m.Actions) > 0 { + for _, e := range m.Actions { l = e.Size() n += 1 + l + sovGenerated(uint64(l)) } @@ -8550,16 +8978,73 @@ func (m *GitDiscoveryResult) Size() (n int) { return n } -func (m *GitHubWebhookReceiverConfig) Size() (n int) { +func (m *GenericWebhookTarget) Size() (n int) { if m == nil { return 0 } var l int _ = l - l = m.SecretRef.Size() + l = len(m.Kind) n += 1 + l + sovGenerated(uint64(l)) - return n -} + l = len(m.Name) + n += 1 + l + sovGenerated(uint64(l)) + l = m.LabelSelector.Size() + n += 1 + l + sovGenerated(uint64(l)) + l = m.IndexSelector.Size() + n += 1 + l + sovGenerated(uint64(l)) + return n +} + +func (m *GitCommit) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.RepoURL) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.ID) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Branch) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Tag) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Message) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Author) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Committer) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + +func (m *GitDiscoveryResult) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.RepoURL) + n += 1 + l + sovGenerated(uint64(l)) + if len(m.Commits) > 0 { + for _, e := range m.Commits { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + +func (m *GitHubWebhookReceiverConfig) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.SecretRef.Size() + n += 1 + l + sovGenerated(uint64(l)) + return n +} func (m *GitLabWebhookReceiverConfig) Size() (n int) { if m == nil { @@ -8780,6 +9265,36 @@ func (m *ImageSubscription) Size() (n int) { return n } +func (m *IndexSelector) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.MatchIndices) > 0 { + for _, e := range m.MatchIndices { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + +func (m *IndexSelectorRequirement) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Key) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Operator) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Value) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + func (m *Project) Size() (n int) { if m == nil { return 0 @@ -9610,6 +10125,10 @@ func (m *WebhookReceiverConfig) Size() (n int) { l = m.Harbor.Size() n += 1 + l + sovGenerated(uint64(l)) } + if m.Generic != nil { + l = m.Generic.Size() + n += 1 + l + sovGenerated(uint64(l)) + } return n } @@ -10206,6 +10725,63 @@ func (this *FreightStatus) String() string { }, "") return s } +func (this *GenericWebhookAction) String() string { + if this == nil { + return "nil" + } + repeatedStringForTargets := "[]GenericWebhookTarget{" + for _, f := range this.Targets { + repeatedStringForTargets += strings.Replace(strings.Replace(f.String(), "GenericWebhookTarget", "GenericWebhookTarget", 1), `&`, ``, 1) + "," + } + repeatedStringForTargets += "}" + keysForParameters := make([]string, 0, len(this.Parameters)) + for k := range this.Parameters { + keysForParameters = append(keysForParameters, k) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForParameters) + mapStringForParameters := "map[string]string{" + for _, k := range keysForParameters { + mapStringForParameters += fmt.Sprintf("%v: %v,", k, this.Parameters[k]) + } + mapStringForParameters += "}" + s := strings.Join([]string{`&GenericWebhookAction{`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `MatchExpression:` + fmt.Sprintf("%v", this.MatchExpression) + `,`, + `Parameters:` + mapStringForParameters + `,`, + `Targets:` + repeatedStringForTargets + `,`, + `}`, + }, "") + return s +} +func (this *GenericWebhookReceiverConfig) String() string { + if this == nil { + return "nil" + } + repeatedStringForActions := "[]GenericWebhookAction{" + for _, f := range this.Actions { + repeatedStringForActions += strings.Replace(strings.Replace(f.String(), "GenericWebhookAction", "GenericWebhookAction", 1), `&`, ``, 1) + "," + } + repeatedStringForActions += "}" + s := strings.Join([]string{`&GenericWebhookReceiverConfig{`, + `SecretRef:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.SecretRef), "LocalObjectReference", "v11.LocalObjectReference", 1), `&`, ``, 1) + `,`, + `Actions:` + repeatedStringForActions + `,`, + `}`, + }, "") + return s +} +func (this *GenericWebhookTarget) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&GenericWebhookTarget{`, + `Kind:` + fmt.Sprintf("%v", this.Kind) + `,`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `LabelSelector:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.LabelSelector), "LabelSelector", "v1.LabelSelector", 1), `&`, ``, 1) + `,`, + `IndexSelector:` + strings.Replace(strings.Replace(this.IndexSelector.String(), "IndexSelector", "IndexSelector", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} func (this *GitCommit) String() string { if this == nil { return "nil" @@ -10395,6 +10971,33 @@ func (this *ImageSubscription) String() string { }, "") return s } +func (this *IndexSelector) String() string { + if this == nil { + return "nil" + } + repeatedStringForMatchIndices := "[]IndexSelectorRequirement{" + for _, f := range this.MatchIndices { + repeatedStringForMatchIndices += strings.Replace(strings.Replace(f.String(), "IndexSelectorRequirement", "IndexSelectorRequirement", 1), `&`, ``, 1) + "," + } + repeatedStringForMatchIndices += "}" + s := strings.Join([]string{`&IndexSelector{`, + `MatchIndices:` + repeatedStringForMatchIndices + `,`, + `}`, + }, "") + return s +} +func (this *IndexSelectorRequirement) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&IndexSelectorRequirement{`, + `Key:` + fmt.Sprintf("%v", this.Key) + `,`, + `Operator:` + fmt.Sprintf("%v", this.Operator) + `,`, + `Value:` + fmt.Sprintf("%v", this.Value) + `,`, + `}`, + }, "") + return s +} func (this *Project) String() string { if this == nil { return "nil" @@ -11042,6 +11645,7 @@ func (this *WebhookReceiverConfig) String() string { `Azure:` + strings.Replace(this.Azure.String(), "AzureWebhookReceiverConfig", "AzureWebhookReceiverConfig", 1) + `,`, `Artifactory:` + strings.Replace(this.Artifactory.String(), "ArtifactoryWebhookReceiverConfig", "ArtifactoryWebhookReceiverConfig", 1) + `,`, `Harbor:` + strings.Replace(this.Harbor.String(), "HarborWebhookReceiverConfig", "HarborWebhookReceiverConfig", 1) + `,`, + `Generic:` + strings.Replace(this.Generic.String(), "GenericWebhookReceiverConfig", "GenericWebhookReceiverConfig", 1) + `,`, `}`, }, "") return s @@ -16820,7 +17424,579 @@ func (m *FreightStatus) Unmarshal(dAtA []byte) error { iNdEx += skippy } } - m.Metadata[mapkey] = *mapvalue + m.Metadata[mapkey] = *mapvalue + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GenericWebhookAction) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GenericWebhookAction: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenericWebhookAction: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = GenericWebhookActionName(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MatchExpression", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MatchExpression = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Parameters", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Parameters == nil { + m.Parameters = make(map[string]string) + } + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthGenerated + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return ErrInvalidLengthGenerated + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthGenerated + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue < 0 { + return ErrInvalidLengthGenerated + } + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.Parameters[mapkey] = mapvalue + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Targets", 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.Targets = append(m.Targets, GenericWebhookTarget{}) + if err := m.Targets[len(m.Targets)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GenericWebhookReceiverConfig) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GenericWebhookReceiverConfig: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenericWebhookReceiverConfig: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SecretRef", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.SecretRef.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Actions", 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.Actions = append(m.Actions, GenericWebhookAction{}) + if err := m.Actions[len(m.Actions)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GenericWebhookTarget) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GenericWebhookTarget: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenericWebhookTarget: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Kind", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Kind = GenericWebhookTargetKind(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LabelSelector", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.LabelSelector.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IndexSelector", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.IndexSelector.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex default: iNdEx = preIndex @@ -19185,6 +20361,236 @@ func (m *ImageSubscription) Unmarshal(dAtA []byte) error { } return nil } +func (m *IndexSelector) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: IndexSelector: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: IndexSelector: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MatchIndices", 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.MatchIndices = append(m.MatchIndices, IndexSelectorRequirement{}) + if err := m.MatchIndices[len(m.MatchIndices)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *IndexSelectorRequirement) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: IndexSelectorRequirement: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: IndexSelectorRequirement: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Key = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Operator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Operator = IndexSelectorRequirementOperator(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Value = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *Project) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -25874,6 +27280,42 @@ func (m *WebhookReceiverConfig) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Generic", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Generic == nil { + m.Generic = &GenericWebhookReceiverConfig{} + } + if err := m.Generic.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 bb42a2fe0e..0c3dc64137 100644 --- a/api/v1alpha1/generated.proto +++ b/api/v1alpha1/generated.proto @@ -688,6 +688,93 @@ message FreightStatus { map metadata = 4; } +// GenericWebhookAction describes an action to be performed on a resource +// and the conditions under which it should be performed. +message GenericWebhookAction { + // Name is the name of the action to be performed. `Refresh` is the only + // action currently supported. + // + // +kubebuilder:validation:Enum=Refresh; + optional string action = 1; + + // MatchExpression defines criteria that a request must meet to trigger this + // action. + // + // +optional + optional string matchExpression = 2; + + // Parameters contains additional parameters for the action. + // + // +optional + map parameters = 3; + + // Targets is a list of selection criteria for the resources on which the + // action should be performed. + // + // +kubebuilder:validation:MinItems=1 + repeated GenericWebhookTarget targets = 4; +} + +// GenericWebhookReceiverConfig describes a generic webhook receiver that can be +// configured to respond to any arbitrary POST by applying user-defined actions +// on user-defined sets of resources selected by name, labels and/or values in pre-built indices. +// Both types of selectors support using values extracted from the request by +// means of expressions. Currently, refreshing resources is the only supported +// action and Warehouse is the only supported kind. "Refreshing" means +// immediately enqueuing the target resource for reconciliation by its +// controller. The practical effect of refreshing a Warehouses is triggering its +// artifact discovery process. +message GenericWebhookReceiverConfig { + // SecretRef contains a reference to a Secret. For Project-scoped webhook + // receivers, the referenced Secret must be in the same namespace as the + // ProjectConfig. + // + // For cluster-scoped webhook receivers, the referenced Secret must be in the + // designated "cluster Secrets" namespace. + // + // The Secret's data map is expected to contain a `secret` key whose value + // does NOT need to be shared directly with the sender. It is used only by + // Kargo to create a complex, hard-to-guess URL, which implicitly serves as a + // shared secret. + // + // +kubebuilder:validation:Required + optional .k8s.io.api.core.v1.LocalObjectReference secretRef = 1; + + // Actions is a list of actions to be performed when a webhook event is received. + // + // +kubebuilder:validation:MinItems=1 + repeated GenericWebhookAction actions = 2; +} + +// GenericWebhookTarget describes selection criteria for resources to which some +// action is to be applied. Name, LabelSelector, and IndexSelector are all optional +// however, at least one must be specified. When multiple criteria are specified, the +// results are the combined (logical AND) of the criteria. +message GenericWebhookTarget { + // Kind is the kind of the target resource. + // + // +kubebuilder:validation:Enum=Warehouse; + optional string kind = 1; + + // Name is the name of the target resource. If LabelSelector and/or IndexSelectors + // are also specified, the results are the combined (logical AND) of the criteria. + // + // +optional + optional string name = 2; + + // LabelSelector is a label selector to identify the target resources. + // If used with IndexSelector and/or Name, the results are the combined (logical AND) of all the criteria. + // + // +optional + optional .k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector labelSelector = 3; + + // IndexSelector is a selector used to identify cached target resources by cache key. + // If used with LabelSelector and/or Name, the results are the combined (logical AND) of all the criteria. + // + // +optional + optional IndexSelector indexSelector = 4; +} + // GitCommit describes a specific commit from a specific Git repository. message GitCommit { // RepoURL is the URL of a Git repository. @@ -1229,6 +1316,35 @@ message ImageSubscription { optional int32 discoveryLimit = 9; } +// IndexSelector encapsulates a selector used to derive index keys +// based on expressions. +message IndexSelector { + // MatchIndices is a list of index selector requirements. + // + // +kubebuilder:validation:MinItems=1 + repeated IndexSelectorRequirement matchIndices = 1; +} + +// IndexSelectorRequirement encapsulates a requirement used to select indexes +// based on specific criteria. +message IndexSelectorRequirement { + // Key is the key of the index. + // + // +kubebuilder:validation:Enum=subscribedURLs;receiverPaths + optional string key = 1; + + // Operator indicates the operation that should be used to evaluate + // whether the selection requirement is satisfied. + // + // kubebuilder:validation:Enum=Equal;NotEqual; + optional string operator = 2; + + // Value can be a static string or an expression that will be evaluated. + // + // kubebuilder:validation:Required + optional string value = 3; +} + // Project is a resource type that reconciles to a specially labeled namespace // and other TODO: TBD project-level resources. message Project { @@ -2083,6 +2199,9 @@ message WebhookReceiverConfig { // Gitea contains the configuration for a webhook receiver that is compatible // with Gitea payloads. optional GiteaWebhookReceiverConfig gitea = 7; + + // Generic contains the configuration for a generic webhook receiver. + optional GenericWebhookReceiverConfig generic = 11; } // WebhookReceiverDetails encapsulates the details of a webhook receiver. diff --git a/api/v1alpha1/project_config_types.go b/api/v1alpha1/project_config_types.go index 3113366608..1d808d90b7 100644 --- a/api/v1alpha1/project_config_types.go +++ b/api/v1alpha1/project_config_types.go @@ -132,6 +132,8 @@ type WebhookReceiverConfig struct { // Gitea contains the configuration for a webhook receiver that is compatible // with Gitea payloads. Gitea *GiteaWebhookReceiverConfig `json:"gitea,omitempty" protobuf:"bytes,7,opt,name=gitea"` + // Generic contains the configuration for a generic webhook receiver. + Generic *GenericWebhookReceiverConfig `json:"generic,omitempty" protobuf:"bytes,11,opt,name=generic"` } // GiteaWebhookReceiverConfig describes a webhook receiver that is compatible @@ -342,6 +344,146 @@ type AzureWebhookReceiverConfig struct { SecretRef corev1.LocalObjectReference `json:"secretRef" protobuf:"bytes,1,opt,name=secretRef"` } +// GenericWebhookReceiverConfig describes a generic webhook receiver that can be +// configured to respond to any arbitrary POST by applying user-defined actions +// on user-defined sets of resources selected by name, labels and/or values in pre-built indices. +// Both types of selectors support using values extracted from the request by +// means of expressions. Currently, refreshing resources is the only supported +// action and Warehouse is the only supported kind. "Refreshing" means +// immediately enqueuing the target resource for reconciliation by its +// controller. The practical effect of refreshing a Warehouses is triggering its +// artifact discovery process. +type GenericWebhookReceiverConfig struct { + // SecretRef contains a reference to a Secret. For Project-scoped webhook + // receivers, the referenced Secret must be in the same namespace as the + // ProjectConfig. + // + // For cluster-scoped webhook receivers, the referenced Secret must be in the + // designated "cluster Secrets" namespace. + // + // The Secret's data map is expected to contain a `secret` key whose value + // does NOT need to be shared directly with the sender. It is used only by + // Kargo to create a complex, hard-to-guess URL, which implicitly serves as a + // shared secret. + // + // +kubebuilder:validation:Required + SecretRef corev1.LocalObjectReference `json:"secretRef" protobuf:"bytes,1,opt,name=secretRef"` + + // Actions is a list of actions to be performed when a webhook event is received. + // + // +kubebuilder:validation:MinItems=1 + Actions []GenericWebhookAction `json:"actions,omitempty" protobuf:"bytes,2,rep,name=actions"` +} + +// GenericWebhookAction describes an action to be performed on a resource +// and the conditions under which it should be performed. +type GenericWebhookAction struct { + // Name is the name of the action to be performed. `Refresh` is the only + // action currently supported. + // + // +kubebuilder:validation:Enum=Refresh; + Name GenericWebhookActionName `json:"action" protobuf:"bytes,1,opt,name=action"` + + // MatchExpression defines criteria that a request must meet to trigger this + // action. + // + // +optional + MatchExpression string `json:"matchExpression,omitempty" protobuf:"bytes,2,opt,name=matchExpression"` + + // Parameters contains additional parameters for the action. + // + // +optional + Parameters map[string]string `json:"parameters,omitempty" protobuf:"bytes,3,rep,name=parameters" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + + // Targets is a list of selection criteria for the resources on which the + // action should be performed. + // + // +kubebuilder:validation:MinItems=1 + Targets []GenericWebhookTarget `json:"targets,omitempty" protobuf:"bytes,4,rep,name=targets"` +} + +// GenericWebhookActionName represents the name of an action to be performed on a resource. +type GenericWebhookActionName string + +const ( + // GenericWebhookActionNameRefresh indicates a request to refresh the resource. + GenericWebhookActionNameRefresh GenericWebhookActionName = "Refresh" +) + +// GenericWebhookTarget describes selection criteria for resources to which some +// action is to be applied. Name, LabelSelector, and IndexSelector are all optional +// however, at least one must be specified. When multiple criteria are specified, the +// results are the combined (logical AND) of the criteria. +type GenericWebhookTarget struct { + // Kind is the kind of the target resource. + // + // +kubebuilder:validation:Enum=Warehouse; + Kind GenericWebhookTargetKind `json:"kind" protobuf:"bytes,1,opt,name=kind"` + + // Name is the name of the target resource. If LabelSelector and/or IndexSelectors + // are also specified, the results are the combined (logical AND) of the criteria. + // + // +optional + Name string `json:"name,omitempty" protobuf:"bytes,2,opt,name=name"` + + // LabelSelector is a label selector to identify the target resources. + // If used with IndexSelector and/or Name, the results are the combined (logical AND) of all the criteria. + // + // +optional + LabelSelector metav1.LabelSelector `json:"labelSelector,omitempty" protobuf:"bytes,3,opt,name=labelSelector"` + + // IndexSelector is a selector used to identify cached target resources by cache key. + // If used with LabelSelector and/or Name, the results are the combined (logical AND) of all the criteria. + // + // +optional + IndexSelector IndexSelector `json:"indexSelector,omitempty" protobuf:"bytes,4,opt,name=indexSelector"` +} + +// GenericWebhookTargetKind represents the kind of a target resource. +type GenericWebhookTargetKind string + +const ( + GenericWebhookTargetKindWarehouse GenericWebhookTargetKind = "Warehouse" +) + +// IndexSelector encapsulates a selector used to derive index keys +// based on expressions. +type IndexSelector struct { + // MatchIndices is a list of index selector requirements. + // + // +kubebuilder:validation:MinItems=1 + MatchIndices []IndexSelectorRequirement `json:"matchIndicies,omitempty" protobuf:"bytes,1,rep,name=matchIndices"` +} + +// IndexSelectorRequirement encapsulates a requirement used to select indexes +// based on specific criteria. +type IndexSelectorRequirement struct { + // Key is the key of the index. + // + // +kubebuilder:validation:Enum=subscribedURLs;receiverPaths + Key string `json:"key" protobuf:"bytes,1,opt,name=key"` + + // Operator indicates the operation that should be used to evaluate + // whether the selection requirement is satisfied. + // + // kubebuilder:validation:Enum=Equal;NotEqual; + Operator IndexSelectorRequirementOperator `json:"operator" protobuf:"bytes,2,opt,name=operator"` + + // Value can be a static string or an expression that will be evaluated. + // + // kubebuilder:validation:Required + Value string `json:"value" protobuf:"bytes,3,opt,name=value"` +} + +// IndexSelectorRequirementOperator represents a set of operators that can be +// used in an index selector requirement. +type IndexSelectorRequirementOperator string + +const ( + IndexSelectorRequirementOperatorEqual IndexSelectorRequirementOperator = "Equal" + IndexSelectorRequirementOperatorNotEqual IndexSelectorRequirementOperator = "NotEqual" +) + // WebhookReceiverDetails encapsulates the details of a webhook receiver. type WebhookReceiverDetails struct { // Name is the name of the webhook receiver. diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 10db5dd003..1740a52e26 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -849,6 +849,75 @@ func (in *FreightStatus) DeepCopy() *FreightStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GenericWebhookAction) DeepCopyInto(out *GenericWebhookAction) { + *out = *in + if in.Parameters != nil { + in, out := &in.Parameters, &out.Parameters + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Targets != nil { + in, out := &in.Targets, &out.Targets + *out = make([]GenericWebhookTarget, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GenericWebhookAction. +func (in *GenericWebhookAction) DeepCopy() *GenericWebhookAction { + if in == nil { + return nil + } + out := new(GenericWebhookAction) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GenericWebhookReceiverConfig) DeepCopyInto(out *GenericWebhookReceiverConfig) { + *out = *in + out.SecretRef = in.SecretRef + if in.Actions != nil { + in, out := &in.Actions, &out.Actions + *out = make([]GenericWebhookAction, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GenericWebhookReceiverConfig. +func (in *GenericWebhookReceiverConfig) DeepCopy() *GenericWebhookReceiverConfig { + if in == nil { + return nil + } + out := new(GenericWebhookReceiverConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GenericWebhookTarget) DeepCopyInto(out *GenericWebhookTarget) { + *out = *in + in.LabelSelector.DeepCopyInto(&out.LabelSelector) + in.IndexSelector.DeepCopyInto(&out.IndexSelector) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GenericWebhookTarget. +func (in *GenericWebhookTarget) DeepCopy() *GenericWebhookTarget { + if in == nil { + return nil + } + out := new(GenericWebhookTarget) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GitCommit) DeepCopyInto(out *GitCommit) { *out = *in @@ -1129,6 +1198,41 @@ func (in *ImageSubscription) DeepCopy() *ImageSubscription { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IndexSelector) DeepCopyInto(out *IndexSelector) { + *out = *in + if in.MatchIndices != nil { + in, out := &in.MatchIndices, &out.MatchIndices + *out = make([]IndexSelectorRequirement, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IndexSelector. +func (in *IndexSelector) DeepCopy() *IndexSelector { + if in == nil { + return nil + } + out := new(IndexSelector) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IndexSelectorRequirement) DeepCopyInto(out *IndexSelectorRequirement) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IndexSelectorRequirement. +func (in *IndexSelectorRequirement) DeepCopy() *IndexSelectorRequirement { + if in == nil { + return nil + } + out := new(IndexSelectorRequirement) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Project) DeepCopyInto(out *Project) { *out = *in @@ -2289,6 +2393,11 @@ func (in *WebhookReceiverConfig) DeepCopyInto(out *WebhookReceiverConfig) { *out = new(GiteaWebhookReceiverConfig) **out = **in } + if in.Generic != nil { + in, out := &in.Generic, &out.Generic + *out = new(GenericWebhookReceiverConfig) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookReceiverConfig. diff --git a/charts/kargo/resources/crds/kargo.akuity.io_clusterconfigs.yaml b/charts/kargo/resources/crds/kargo.akuity.io_clusterconfigs.yaml index 342c1f627a..306d268994 100644 --- a/charts/kargo/resources/crds/kargo.akuity.io_clusterconfigs.yaml +++ b/charts/kargo/resources/crds/kargo.akuity.io_clusterconfigs.yaml @@ -224,6 +224,186 @@ spec: required: - secretRef type: object + generic: + description: Generic contains the configuration for a generic + webhook receiver. + properties: + actions: + description: Actions is a list of actions to be performed + when a webhook event is received. + items: + description: |- + GenericWebhookAction describes an action to be performed on a resource + and the conditions under which it should be performed. + properties: + action: + description: |- + Name is the name of the action to be performed. `Refresh` is the only + action currently supported. + enum: + - Refresh + type: string + matchExpression: + description: |- + MatchExpression defines criteria that a request must meet to trigger this + action. + type: string + parameters: + additionalProperties: + type: string + description: Parameters contains additional parameters + for the action. + type: object + targets: + description: |- + Targets is a list of selection criteria for the resources on which the + action should be performed. + items: + description: |- + GenericWebhookTarget describes selection criteria for resources to which some + action is to be applied. Name, LabelSelector, and IndexSelector are all optional + however, at least one must be specified. When multiple criteria are specified, the + results are the combined (logical AND) of the criteria. + properties: + indexSelector: + description: |- + IndexSelector is a selector used to identify cached target resources by cache key. + If used with LabelSelector and/or Name, the results are the combined (logical AND) of all the criteria. + properties: + matchIndicies: + description: MatchIndices is a list of index + selector requirements. + items: + description: |- + IndexSelectorRequirement encapsulates a requirement used to select indexes + based on specific criteria. + properties: + key: + description: Key is the key of the + index. + enum: + - subscribedURLs + - receiverPaths + type: string + operator: + description: |- + Operator indicates the operation that should be used to evaluate + whether the selection requirement is satisfied. + + kubebuilder:validation:Enum=Equal;NotEqual; + type: string + value: + description: |- + Value can be a static string or an expression that will be evaluated. + + kubebuilder:validation:Required + type: string + required: + - key + - operator + - value + type: object + minItems: 1 + type: array + type: object + kind: + description: Kind is the kind of the target + resource. + enum: + - Warehouse + type: string + labelSelector: + description: |- + LabelSelector is a label selector to identify the target resources. + If used with IndexSelector and/or Name, the results are the combined (logical AND) of all the criteria. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Name is the name of the target resource. If LabelSelector and/or IndexSelectors + are also specified, the results are the combined (logical AND) of the criteria. + type: string + required: + - kind + type: object + minItems: 1 + type: array + required: + - action + type: object + minItems: 1 + type: array + secretRef: + description: |- + SecretRef contains a reference to a Secret. For Project-scoped webhook + receivers, the referenced Secret must be in the same namespace as the + ProjectConfig. + + For cluster-scoped webhook receivers, the referenced Secret must be in the + designated "cluster Secrets" namespace. + + The Secret's data map is expected to contain a `secret` key whose value + does NOT need to be shared directly with the sender. It is used only by + Kargo to create a complex, hard-to-guess URL, which implicitly serves as a + shared secret. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + required: + - secretRef + type: object gitea: description: |- Gitea contains the configuration for a webhook receiver that is compatible diff --git a/charts/kargo/resources/crds/kargo.akuity.io_projectconfigs.yaml b/charts/kargo/resources/crds/kargo.akuity.io_projectconfigs.yaml index 73d14a7a80..b4006a51fc 100644 --- a/charts/kargo/resources/crds/kargo.akuity.io_projectconfigs.yaml +++ b/charts/kargo/resources/crds/kargo.akuity.io_projectconfigs.yaml @@ -319,6 +319,186 @@ spec: required: - secretRef type: object + generic: + description: Generic contains the configuration for a generic + webhook receiver. + properties: + actions: + description: Actions is a list of actions to be performed + when a webhook event is received. + items: + description: |- + GenericWebhookAction describes an action to be performed on a resource + and the conditions under which it should be performed. + properties: + action: + description: |- + Name is the name of the action to be performed. `Refresh` is the only + action currently supported. + enum: + - Refresh + type: string + matchExpression: + description: |- + MatchExpression defines criteria that a request must meet to trigger this + action. + type: string + parameters: + additionalProperties: + type: string + description: Parameters contains additional parameters + for the action. + type: object + targets: + description: |- + Targets is a list of selection criteria for the resources on which the + action should be performed. + items: + description: |- + GenericWebhookTarget describes selection criteria for resources to which some + action is to be applied. Name, LabelSelector, and IndexSelector are all optional + however, at least one must be specified. When multiple criteria are specified, the + results are the combined (logical AND) of the criteria. + properties: + indexSelector: + description: |- + IndexSelector is a selector used to identify cached target resources by cache key. + If used with LabelSelector and/or Name, the results are the combined (logical AND) of all the criteria. + properties: + matchIndicies: + description: MatchIndices is a list of index + selector requirements. + items: + description: |- + IndexSelectorRequirement encapsulates a requirement used to select indexes + based on specific criteria. + properties: + key: + description: Key is the key of the + index. + enum: + - subscribedURLs + - receiverPaths + type: string + operator: + description: |- + Operator indicates the operation that should be used to evaluate + whether the selection requirement is satisfied. + + kubebuilder:validation:Enum=Equal;NotEqual; + type: string + value: + description: |- + Value can be a static string or an expression that will be evaluated. + + kubebuilder:validation:Required + type: string + required: + - key + - operator + - value + type: object + minItems: 1 + type: array + type: object + kind: + description: Kind is the kind of the target + resource. + enum: + - Warehouse + type: string + labelSelector: + description: |- + LabelSelector is a label selector to identify the target resources. + If used with IndexSelector and/or Name, the results are the combined (logical AND) of all the criteria. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Name is the name of the target resource. If LabelSelector and/or IndexSelectors + are also specified, the results are the combined (logical AND) of the criteria. + type: string + required: + - kind + type: object + minItems: 1 + type: array + required: + - action + type: object + minItems: 1 + type: array + secretRef: + description: |- + SecretRef contains a reference to a Secret. For Project-scoped webhook + receivers, the referenced Secret must be in the same namespace as the + ProjectConfig. + + For cluster-scoped webhook receivers, the referenced Secret must be in the + designated "cluster Secrets" namespace. + + The Secret's data map is expected to contain a `secret` key whose value + does NOT need to be shared directly with the sender. It is used only by + Kargo to create a complex, hard-to-guess URL, which implicitly serves as a + shared secret. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + required: + - secretRef + type: object gitea: description: |- Gitea contains the configuration for a webhook receiver that is compatible diff --git a/docs/docs/50-user-guide/60-reference-docs/80-webhook-receivers/generic.md b/docs/docs/50-user-guide/60-reference-docs/80-webhook-receivers/generic.md index b805867d8d..835041b4aa 100644 --- a/docs/docs/50-user-guide/60-reference-docs/80-webhook-receivers/generic.md +++ b/docs/docs/50-user-guide/60-reference-docs/80-webhook-receivers/generic.md @@ -4,8 +4,216 @@ sidebar_label: Generic # Generic Webhook Receiver +The Generic webhook receiver responds to events originating from arbitrary +repositories by performing `Action`s on `Target`s. Consider the example of a +`Warehouse` refresh. In this example, the `Action` is the refresh and the +`Target` is the `Warehouse`. + +:::note +A generic webhook receiver is not limited to a single `Action` and `Action`'s +are not limited to a single `Target`. +::: + :::info -__Coming soon!__ +"Refreshing" a `Warehouse` resource means enqueuing it for immediate +reconciliation by the Kargo controller, which will execute the discovery of new +artifacts from all repositories to which that `Warehouse` subscribes. +::: + +## Configuring the Receiver + +A Generic webhook receiver must reference a Kubernetes `Secret` resource with +a `secret` key in its data map. + +:::info +Kargo incorporates the secret into the generation of a hard-to-guess URL for the +receiver. This URL serves as a _de facto_ +[shared secret](https://en.wikipedia.org/wiki/Shared_secret) and authentication +mechanism. +::: + +:::note +The following commands are suggested for generating and base64-encoding a +complex secret: + +```shell +secret=$(openssl rand -base64 48 | tr -d '=+/' | head -c 32) +echo "Secret: $secret" +echo "Encoded secret: $(echo -n $secret | base64)" +``` + +::: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: wh-secret + namespace: kargo-demo + labels: + kargo.akuity.io/cred-type: generic +data: + secret: +--- +apiVersion: kargo.akuity.io/v1alpha1 +kind: ProjectConfig +metadata: + name: kargo-demo + namespace: kargo-demo +spec: + webhookReceivers: + - name: my-receiver + generic: + secretRef: + name: wh-secret + actions: + - action: Refresh + # Parameters can optionally be defined for use in expressions + parameters: + - targetEvent: "push" + - headerKey: "X-Event-Type" + # Only perform this action if this expression is satisfied + matchExpression: "${{ request.header(params.headerKey) == params.targetEvent }}" + targets: + # This target is designated via static name + - kind: Warehouse + name: my-warehouse + # This target is designated via expression derived name + - kind: Warehouse + name: "${{ request.body.repository.name }}" + # This target omits the name all together and designates any + # resources that fulfill the label and index selector criteria + - kind: Warehouse + labelSelector: + matchLabels: + environment: production + matchExpressions: + - key: tier + operator: In + values: ["critical", "high"] + indexSelector: + matchExpressions: + - key: subscribedURL + operator: In + value: "${{ normalize("git", request.body.repository.url) }}" +``` + +:::note +`name`, `labelSelector`, and `indexSelector` are all +optional. However, at least one of them must be specified. +::: + +## Designating Targets + +There are 3 different ways of designating `Target`s: + +1. [Static](#static) +1. [Expression-Derived](#expression-derived) +1. [Selector-Based](#selector-based) + +### Static + +The simplest way of designating a `Target` is by setting a static `name` +to identify the resource. + +### Expression-Derived + +The Generic webhook receiver extends +[built-in expr-lang support](https://expr-lang.org/docs/language-definition) +with various expression functions and objects. These functions and objects can +be used to help users derive `Target` information from incoming requests. + +The following expression functions are available: + +`normalize(urlType, url)` -Expected in v1.7.0 +Function that normalizes `url` based on `urlType`. + +It has two arguments: +- `urlType` (Required): One of either `git`, `image`, or `chart`. +- `url` (Required): The URL of a git, image, or chart repository. + +The returned value is a `string`. If `urlType` is not one of `git`, `image`, or +`chart`, `url` will be returned as is. + +`request.header(headerKey)` + +Function that retrieves first value for `headerKey`. + +It has one argument: +- `headerKey` (Required): Case-insensitive header key. + +If `headerKey` is not present in the request headers, an empty `string` will +be returned. + +`request.headers(headerKey)` + +Function that retrieves all values for `headerKey`. + +It has one argument: +- `headerKey` (Required): Case-insensitive header key. + +If `headerKey` is not present in the request headers, an empty `string` array +will be returned. + +`body` + +Generic object derived from incoming requests whose fields can be accessed using standard bracket or dot-notation. For example, `data.address.city` would access +the `city` property nested within the address object, and `data.users[0]` would +access the first item in a users array. + +### Selector-Based + +Generic webhook receivers use label and index selectors. If both are defined +targets must adhere to the logical AND of the two sets of constraints. + +#### Label Selectors + +Label selectors contain support for both `matchLabels` and `matchExpressions`. +A static list of key/value pairs should be used for `matchLabels`. For +`matchExpressions`, you must specify a `key`, `operator` and `values` where +`values` supports static and/or expression derived values. + +``` +labelSelector: + matchLabels: + environment: production + matchExpressions: + - key: env + operator: In + values: ["critical", "high"] +``` + +#### Index Selectors + +Index Selectors have `matchExpression` support. They use a `key`, `operator`, +and `value` combination. Supported operators include `Equal` and `NotEqual`. The +only supported `key` at this time is `subscribedURLs`. Expressions are supported +for `value`. + +:::note +`subscribedURLs` refers to `Warehouse`' that contain subscriptions that that +subscribe to the provided repository URL. ::: + +``` +indexSelector: + matchExpressions: + - key: subscribedURLs + operator: Equal + value: "${{ normalize("git", request.body.repository.url) }}" +``` + + +## Retrieving the Receiver's URL + +Kargo will generate a hard-to-guess URL from the receiver's configuration. This +URL can be obtained using a command such as the following: + +```shell +kubectl get projectconfigs kargo-demo \ + -n kargo-demo \ + -o=jsonpath='{.status.webhookReceivers}' +``` + +This URL can then be used anywhere webhooks can be configured. diff --git a/docs/docs/90-api-documentation.md b/docs/docs/90-api-documentation.md index 8d57150208..c1a164744c 100644 --- a/docs/docs/90-api-documentation.md +++ b/docs/docs/90-api-documentation.md @@ -2078,6 +2078,46 @@ RawFormat specifies the format for raw resource representation. | key | [string](#string) | | | value | [VerifiedStage](#github-com-akuity-kargo-api-v1alpha1-VerifiedStage) | | + + +### GenericWebhookAction + GenericWebhookAction describes an action to be performed on a resource and the conditions under which it should be performed. +| Field | Type | Description | +| ----- | ---- | ----------- | +| action | [string](#string) | Name is the name of the action to be performed. `Refresh` is the only action currently supported. | +| matchExpression | [string](#string) | MatchExpression defines criteria that a request must meet to trigger this action. +optional | +| parameters | [GenericWebhookAction.ParametersEntry](#github-com-akuity-kargo-api-v1alpha1-GenericWebhookAction-ParametersEntry) | Parameters contains additional parameters for the action. +optional | +| targets | [GenericWebhookTarget](#github-com-akuity-kargo-api-v1alpha1-GenericWebhookTarget) | Targets is a list of selection criteria for the resources on which the action should be performed. | + + + +### GenericWebhookAction.ParametersEntry + +| Field | Type | Description | +| ----- | ---- | ----------- | +| key | [string](#string) | | +| value | [string](#string) | | + + + +### GenericWebhookReceiverConfig + GenericWebhookReceiverConfig describes a generic webhook receiver that can be configured to respond to any arbitrary POST by applying user-defined actions on user-defined sets of resources selected by name, labels and/or values in pre-built indices. Both types of selectors support using values extracted from the request by means of expressions. Currently, refreshing resources is the only supported action and Warehouse is the only supported kind. "Refreshing" means immediately enqueuing the target resource for reconciliation by its controller. The practical effect of refreshing a Warehouses is triggering its artifact discovery process. +| Field | Type | Description | +| ----- | ---- | ----------- | +| secretRef | k8s.io.api.core.v1.LocalObjectReference | SecretRef contains a reference to a Secret. For Project-scoped webhook receivers, the referenced Secret must be in the same namespace as the ProjectConfig. For cluster-scoped webhook receivers, the referenced Secret must be in the designated "cluster Secrets" namespace. The Secret's data map is expected to contain a `secret` key whose value does NOT need to be shared directly with the sender. It is used only by Kargo to create a complex, hard-to-guess URL, which implicitly serves as a shared secret. | +| actions | [GenericWebhookAction](#github-com-akuity-kargo-api-v1alpha1-GenericWebhookAction) | Actions is a list of actions to be performed when a webhook event is received. | + + + +### GenericWebhookTarget + GenericWebhookTarget describes selection criteria for resources to which some action is to be applied. Name, LabelSelector, and IndexSelector are all optional however, at least one must be specified. When multiple criteria are specified, the results are the combined (logical AND) of the criteria. +| Field | Type | Description | +| ----- | ---- | ----------- | +| kind | [string](#string) | Kind is the kind of the target resource. | +| name | [string](#string) | Name is the name of the target resource. If LabelSelector and/or IndexSelectors are also specified, the results are the combined (logical AND) of the criteria. +optional | +| labelSelector | k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector | LabelSelector is a label selector to identify the target resources. If used with IndexSelector and/or Name, the results are the combined (logical AND) of all the criteria. +optional | +| indexSelector | [IndexSelector](#github-com-akuity-kargo-api-v1alpha1-IndexSelector) | IndexSelector is a selector used to identify cached target resources by cache key. If used with LabelSelector and/or Name, the results are the combined (logical AND) of all the criteria. +optional | + ### GitCommit @@ -2230,6 +2270,24 @@ RawFormat specifies the format for raw resource representation. | insecureSkipTLSVerify | [bool](#bool) | InsecureSkipTLSVerify specifies whether certificate verification errors should be ignored when connecting to the repository. This should be enabled only with great caution. | | discoveryLimit | [int32](#int32) | DiscoveryLimit is an optional limit on the number of image references that can be discovered for this subscription. The limit is applied after filtering images based on the AllowTagsRegexes and IgnoreTagsRegexes fields. When left unspecified, the field is implicitly treated as if its value were "20". The upper limit for this field is 100. | + + +### IndexSelector + IndexSelector encapsulates a selector used to derive index keys based on expressions. +| Field | Type | Description | +| ----- | ---- | ----------- | +| matchIndices | [IndexSelectorRequirement](#github-com-akuity-kargo-api-v1alpha1-IndexSelectorRequirement) | MatchIndices is a list of index selector requirements. | + + + +### IndexSelectorRequirement + IndexSelectorRequirement encapsulates a requirement used to select indexes based on specific criteria. +| Field | Type | Description | +| ----- | ---- | ----------- | +| key | [string](#string) | Key is the key of the index. | +| operator | [string](#string) | Operator indicates the operation that should be used to evaluate whether the selection requirement is satisfied. | +| value | [string](#string) | Value can be a static string or an expression that will be evaluated. | + ### Project @@ -2659,6 +2717,7 @@ RawFormat specifies the format for raw resource representation. | artifactory | [ArtifactoryWebhookReceiverConfig](#github-com-akuity-kargo-api-v1alpha1-ArtifactoryWebhookReceiverConfig) | Artifactory contains the configuration for a webhook receiver that is compatible with JFrog Artifactory payloads. | | azure | [AzureWebhookReceiverConfig](#github-com-akuity-kargo-api-v1alpha1-AzureWebhookReceiverConfig) | Azure contains the configuration for a webhook receiver that is compatible with Azure Container Registry (ACR) and Azure DevOps payloads. | | gitea | [GiteaWebhookReceiverConfig](#github-com-akuity-kargo-api-v1alpha1-GiteaWebhookReceiverConfig) | Gitea contains the configuration for a webhook receiver that is compatible with Gitea payloads. | +| generic | [GenericWebhookReceiverConfig](#github-com-akuity-kargo-api-v1alpha1-GenericWebhookReceiverConfig) | Generic contains the configuration for a generic webhook receiver. | diff --git a/pkg/expressions/function/functions.go b/pkg/expressions/function/functions.go index fb9f3b0a43..54d583cdc4 100644 --- a/pkg/expressions/function/functions.go +++ b/pkg/expressions/function/functions.go @@ -90,6 +90,40 @@ func UtilityOperations() []expr.Option { } } +// Normalize returns an expr.Option that provides a `normalize()` function for +// use in expressions. +func NormalizeURL() expr.Option { + return expr.Function( + "normalize", + normalizeURL, + new(func(urlType string, url string) string), + ) +} + +func normalizeURL(a ...any) (any, error) { + if len(a) != 2 { + return nil, fmt.Errorf("expected 2 arguments, got %d", len(a)) + } + urlType, ok := a[0].(string) + if !ok { + return nil, fmt.Errorf("first argument must be string, got %T", a[0]) + } + urlStr, ok := a[1].(string) + if !ok { + return nil, fmt.Errorf("second argument must be string, got %T", a[1]) + } + switch strings.ToLower(urlType) { + case "git": + return urls.NormalizeGit(urlStr), nil + case "image": + return urls.NormalizeImage(urlStr), nil + case "chart": + return urls.NormalizeChart(urlStr), nil + default: + return urlStr, nil + } +} + // StatusOperations returns a slice of expr.Option containing functions for // assessing the status of all preceding steps. func StatusOperations( diff --git a/pkg/expressions/function/functions_test.go b/pkg/expressions/function/functions_test.go index 06c256bd9b..3d1ae74091 100644 --- a/pkg/expressions/function/functions_test.go +++ b/pkg/expressions/function/functions_test.go @@ -2,6 +2,7 @@ package function import ( "context" + "errors" "testing" "time" @@ -17,6 +18,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/pkg/expressions" ) func Test_warehouse(t *testing.T) { @@ -1928,3 +1930,63 @@ func Test_semverParse(t *testing.T) { }) } } + +func TestNormalizeURL(t *testing.T) { + testCases := []struct { + name string + expression string + expected string + err error + }{ + { + name: "wrong number of arguments", + expression: "${{ normalize('git') }}", + err: errors.New("not enough arguments to call normalize"), + }, + { + name: "urlType not a string", + expression: "${{ normalize(123, 'doesntmatter') }}", + err: errors.New("cannot use int as argument (type string) to call normalize"), + }, + { + name: "url not a string", + expression: "${{ normalize('git', 456) }}", + err: errors.New("cannot use int as argument (type string) to call normalize"), + }, + { + name: "normalize git", + expression: "${{ normalize('git', 'https://github.com/user/repo.git' ) }}", + expected: "https://github.com/user/repo", + }, + { + name: "normalize image", + expression: "${{ normalize('image', 'docker.io/library/nginx:latest' )}}", + expected: "nginx", + }, + { + name: "normalize chart", + expression: "${{ normalize('chart', 'oci://ghcr.io/user/chart:1.0.0') }}", + expected: "ghcr.io/user/chart", + }, + { + name: "unsupported urlType should return url as is", + expression: "${{ normalize('unsupported', 'https://fakeurl') }}", + expected: "https://fakeurl", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result, err := expressions.EvaluateTemplate(tc.expression, nil, NormalizeURL()) + if tc.err != nil { + require.Error(t, err) + require.ErrorContains(t, err, tc.err.Error()) + return + } + require.NoError(t, err) + resultStr, ok := result.(string) + require.True(t, ok) + require.Equal(t, tc.expected, resultStr) + }) + } +} diff --git a/pkg/webhook/external/generic.go b/pkg/webhook/external/generic.go new file mode 100644 index 0000000000..5ccf307e71 --- /dev/null +++ b/pkg/webhook/external/generic.go @@ -0,0 +1,204 @@ +package external + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "maps" + "net/http" + "slices" + + "sigs.k8s.io/controller-runtime/pkg/client" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/pkg/expressions" + "github.com/akuity/kargo/pkg/expressions/function" + xhttp "github.com/akuity/kargo/pkg/http" + "github.com/akuity/kargo/pkg/logging" +) + +const ( + genericSecretDataKey = "secret" + generic = "generic" +) + +func init() { + defaultWebhookReceiverRegistry.MustRegister( + webhookReceiverRegistration{ + Predicate: func(_ context.Context, cfg kargoapi.WebhookReceiverConfig) (bool, error) { + return cfg.Generic != nil, nil + }, + Value: newGenericWebhookReceiver, + }, + ) +} + +// genericWebhookReceiver is an implementation of WebhookReceiver that +// handles inbound webhook events from generic providers. +type genericWebhookReceiver struct { + *baseWebhookReceiver + config *kargoapi.GenericWebhookReceiverConfig +} + +// newGenericWebhookReceiver returns a new instance of genericWebhookReceiver. +func newGenericWebhookReceiver( + c client.Client, + project string, + cfg kargoapi.WebhookReceiverConfig, +) WebhookReceiver { + return &genericWebhookReceiver{ + baseWebhookReceiver: &baseWebhookReceiver{ + client: c, + project: project, + secretName: cfg.Generic.SecretRef.Name, + }, + config: cfg.Generic, + } +} + +// getReceiverType implements WebhookReceiver. +func (g *genericWebhookReceiver) getReceiverType() string { + return generic +} + +// getSecretValues implements WebhookReceiver. +func (g *genericWebhookReceiver) getSecretValues( + secretData map[string][]byte, +) ([]string, error) { + secretValue, ok := secretData[genericSecretDataKey] + if !ok { + return nil, + errors.New("secret data is not valid for a Generic WebhookReceiver") + } + return []string{string(secretValue)}, nil +} + +// getHandler implements WebhookReceiver. +func (g *genericWebhookReceiver) getHandler(requestBody []byte) http.HandlerFunc { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + logger := logging.LoggerFromContext(ctx) + ctx = logging.ContextWithLogger(ctx, logger) + + sharedEnv, err := newSharedEnv(requestBody, r) + if err != nil { + logger.Error(err, "error creating global environment") + // this can only fail if the request body is invalid json + xhttp.WriteErrorJSON(w, xhttp.Error(err, http.StatusBadRequest)) + return + } + + actionResults := make([]actionResult, len(g.config.Actions)) + for i, action := range g.config.Actions { + aLogger := logger.WithValues("action", action.Name, "expression", action.MatchExpression) + actionResults[i].ActionName = action.Name + actionResults[i].ConditionResult = conditionResult{Expression: action.MatchExpression} + + satisfied, err := conditionSatisfied(action.MatchExpression, sharedEnv) + if err != nil { + aLogger.Error(err, "failed to evaluate criteria; skipping action") + actionResults[i].ConditionResult.EvalError = fmt.Sprintf("%v", err) + continue + } + + actionResults[i].ConditionResult.Satisfied = satisfied + if !satisfied { + aLogger.Info("condition not satisfied; skipping action") + continue + } + + ctx = logging.ContextWithLogger(ctx, aLogger) + actionEnv := newActionEnv(action.Parameters, sharedEnv) + switch action.Name { + case kargoapi.GenericWebhookActionNameRefresh: + actionResults[i].TargetResults = refreshTargets( + ctx, g.client, g.project, actionEnv, action.Targets, + ) + } + // add new action handlers here + } + resp := map[string]any{"actionResults": actionResults} + if shouldReportAsError(actionResults) { + xhttp.WriteResponseJSON(w, http.StatusInternalServerError, resp) + return + } + xhttp.WriteResponseJSON(w, http.StatusOK, resp) + }) +} + +type actionResult struct { + ActionName kargoapi.GenericWebhookActionName `json:"actionName"` + ConditionResult conditionResult `json:"conditionResult"` + TargetResults []targetResult `json:"targetResults,omitempty"` +} + +type conditionResult struct { + Expression string `json:"expression"` + Satisfied bool `json:"satisfied"` + EvalError string `json:"evalError,omitempty"` +} + +func newSharedEnv(requestBody []byte, r *http.Request) (map[string]any, error) { + var body any + if err := json.Unmarshal(requestBody, &body); err != nil { + return nil, fmt.Errorf("invalid request body: %w", err) + } + return map[string]any{ + "request": map[string]any{ + "header": r.Header.Get, + "headers": r.Header.Values, + "body": body, + "method": r.Method, + "url": r.URL.String(), + }, + }, nil +} + +func newActionEnv(params map[string]string, globalEnv map[string]any) map[string]any { + actionEnv := maps.Clone(globalEnv) + m := make(map[string]any, len(params)) + for paramKey, paramValue := range params { + m[paramKey] = paramValue + } + actionEnv["params"] = m + return actionEnv +} + +func conditionSatisfied(expression string, env map[string]any) (bool, error) { + result, err := expressions.EvaluateTemplate(expression, env, function.NormalizeURL()) + if err != nil { + return false, err + } + satisfied, ok := result.(bool) + if !ok { + return false, fmt.Errorf("match expression result %q is of type %T; expected bool", result, result) + } + return satisfied, nil +} + +// should reportAsError determines whether the overall webhook processing should be +// reported as an error based on the action results. Returns true if any action +// resulted in an expression evaluation error or any of its underlying +// targets had errors. +func shouldReportAsError(actionResults []actionResult) bool { + return slices.ContainsFunc(actionResults, func(ar actionResult) bool { + return ar.ConditionResult.EvalError != "" || hasTargetErrors(ar) + }) +} + +func hasTargetErrors(ar actionResult) bool { + for _, tr := range ar.TargetResults { + if tr.ListError != nil { + return true + } + switch ar.ActionName { + case kargoapi.GenericWebhookActionNameRefresh: + refreshFailure := func(rr refreshResult) bool { return rr.Failure != "" } + if slices.ContainsFunc(tr.RefreshResults, refreshFailure) { + return true + } + } + } + return false +} diff --git a/pkg/webhook/external/generic_list_options.go b/pkg/webhook/external/generic_list_options.go new file mode 100644 index 0000000000..a4f8acdf2c --- /dev/null +++ b/pkg/webhook/external/generic_list_options.go @@ -0,0 +1,147 @@ +package external + +import ( + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/selection" + "sigs.k8s.io/controller-runtime/pkg/client" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/pkg/expressions" + "github.com/akuity/kargo/pkg/expressions/function" +) + +// buildListOptionsForTarget builds a list of client.ListOption based on the +// provided GenericWebhookTarget's selectors. The returned ListOptions can be +// used to list Kubernetes resources that match the target's selection criteria. +func buildListOptionsForTarget( + project string, + t kargoapi.GenericWebhookTarget, + env map[string]any, +) ([]client.ListOption, error) { + listOpts := []client.ListOption{client.InNamespace(project)} + + indexSelectorListOpts, err := newListOptionsForIndexSelector(t.IndexSelector, env) + if err != nil { + return nil, fmt.Errorf("failed to create field selector: %w", err) + } + listOpts = append(listOpts, indexSelectorListOpts...) + + labelSelectorListOpts, err := newListOptionsForLabelSelector(t.LabelSelector, env) + if err != nil { + return nil, fmt.Errorf("failed to create label selector: %w", err) + } + listOpts = append(listOpts, labelSelectorListOpts...) + return listOpts, nil +} + +// newListOptionsForIndexSelector creates a list of client.ListOption based on +// the provided IndexSelector and environment for expression evaluation. +func newListOptionsForIndexSelector( + is kargoapi.IndexSelector, + env map[string]any, +) ([]client.ListOption, error) { + var listOpts []client.ListOption + for _, expr := range is.MatchIndices { + resultStr, err := evalAsString(expr.Value, env) + if err != nil { + return nil, fmt.Errorf("failed to evaluate values expression as string: %w", err) + } + var s fields.Selector + switch expr.Operator { + case kargoapi.IndexSelectorRequirementOperatorEqual: + s = fields.OneTermEqualSelector(expr.Key, resultStr) + case kargoapi.IndexSelectorRequirementOperatorNotEqual: + s = fields.OneTermNotEqualSelector(expr.Key, resultStr) + default: + return nil, fmt.Errorf("unsupported operator %q in index selector expression", expr.Operator) + } + listOpts = append(listOpts, client.MatchingFieldsSelector{Selector: s}) + } + return listOpts, nil +} + +// newListOptionsForLabelSelector creates a list of client.ListOption based on +// the provided LabelSelector. +func newListOptionsForLabelSelector(ls metav1.LabelSelector, env map[string]any) ([]client.ListOption, error) { + var labelReqs []labels.Requirement + for _, expr := range ls.MatchExpressions { + op, err := labelOpToSelectionOp(expr.Operator) + if err != nil { + return nil, fmt.Errorf("failed to convert label selector operator: %w", err) + } + values, err := evalValues(expr.Values, env) + if err != nil { + return nil, fmt.Errorf("failed to parse matchExpression values: %w", err) + } + labelReq, err := labels.NewRequirement(expr.Key, op, values) + if err != nil { + return nil, fmt.Errorf("failed to create label requirement: %w", err) + } + labelReqs = append(labelReqs, *labelReq) + } + for k, v := range ls.MatchLabels { + req, err := labels.NewRequirement(k, selection.Equals, []string{v}) + if err != nil { + return nil, fmt.Errorf("failed to create label requirement: %w", err) + } + labelReqs = append(labelReqs, *req) + } + if len(labelReqs) == 0 { + return nil, nil + } + return []client.ListOption{ + client.MatchingLabelsSelector{ + Selector: labels.NewSelector().Add(labelReqs...), + }, + }, nil +} + +// labelOpToSelectionOp converts a metav1.LabelSelectorOperator +// into a selection.Operator, which is used to build label requirements. +// Returns an error if the operator is not recognized. GT and LT operators +// are not supported. +func labelOpToSelectionOp(op metav1.LabelSelectorOperator) (selection.Operator, error) { + switch op { + case metav1.LabelSelectorOpIn: + return selection.In, nil + case metav1.LabelSelectorOpNotIn: + return selection.NotIn, nil + case metav1.LabelSelectorOpExists: + return selection.Exists, nil + case metav1.LabelSelectorOpDoesNotExist: + return selection.DoesNotExist, nil + default: + // selection.GreaterThan, selection.LessThan, selection.Equal, and + // selection.NotEquals don't have a label selector operator equivalent so + // they're not supported. + return "", fmt.Errorf("unsupported LabelSelectorOperator: %q", op) + } +} + +func evalValues(vals []string, env map[string]any) ([]string, error) { + values := make([]string, len(vals)) + for i, v := range vals { + s, err := evalAsString(v, env) + if err != nil { + return nil, fmt.Errorf("failed to evaluate value %q as string: %w", v, err) + } + values[i] = s + } + return values, nil +} + +func evalAsString(expr string, env map[string]any) (string, error) { + result, err := expressions.EvaluateTemplate(expr, env, function.NormalizeURL()) + if err != nil { + return "", fmt.Errorf("failed to evaluate expression: %w", err) + } + s, ok := result.(string) + if !ok { + return "", fmt.Errorf("expression result %q evaluated to %T; not a string", result, result) + } + return s, nil +} diff --git a/pkg/webhook/external/generic_list_options_test.go b/pkg/webhook/external/generic_list_options_test.go new file mode 100644 index 0000000000..f73fed4292 --- /dev/null +++ b/pkg/webhook/external/generic_list_options_test.go @@ -0,0 +1,381 @@ +package external + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/selection" + "sigs.k8s.io/controller-runtime/pkg/client" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" +) + +func Test_buildListOptionsTarget(t *testing.T) { + tests := []struct { + name string + project string + target kargoapi.GenericWebhookTarget + expected []client.ListOption + env map[string]any + err error + }{ + { + name: "no selectors defined", + project: "demo-project", + target: kargoapi.GenericWebhookTarget{ + Kind: kargoapi.GenericWebhookTargetKindWarehouse, + }, + env: map[string]any{}, + expected: []client.ListOption{ + // only the default selector should be present + client.InNamespace("demo-project"), + }, + err: nil, + }, + { + name: "index selector with invalid expression", + project: "test-project", + target: kargoapi.GenericWebhookTarget{ + Kind: kargoapi.GenericWebhookTargetKindWarehouse, + IndexSelector: kargoapi.IndexSelector{ + MatchIndices: []kargoapi.IndexSelectorRequirement{ + { + Key: "env", + Operator: kargoapi.IndexSelectorRequirementOperatorEqual, + Value: "${{ invalid expression }}", + }, + }, + }, + }, + env: map[string]any{}, + expected: nil, + err: errors.New("failed to evaluate values expression"), + }, + { + name: "index selector with non-string expression result", + project: "test-project", + target: kargoapi.GenericWebhookTarget{ + Kind: kargoapi.GenericWebhookTargetKindWarehouse, + IndexSelector: kargoapi.IndexSelector{ + MatchIndices: []kargoapi.IndexSelectorRequirement{ + { + Key: "env", + Operator: kargoapi.IndexSelectorRequirementOperatorEqual, + Value: "${{ 12345 }}", + }, + }, + }, + }, + env: map[string]any{}, + expected: nil, + err: errors.New("expression result"), + }, + { + name: "index selector with unsupported operator", + project: "test-project", + target: kargoapi.GenericWebhookTarget{ + Kind: kargoapi.GenericWebhookTargetKindWarehouse, + IndexSelector: kargoapi.IndexSelector{ + MatchIndices: []kargoapi.IndexSelectorRequirement{ + { + Key: "env", + Operator: "UnsupportedOperator", + Value: "prod", + }, + }, + }, + }, + env: map[string]any{}, + expected: nil, + err: errors.New("unsupported operator"), + }, + { + name: "index selector success", + project: "sample-project", + target: kargoapi.GenericWebhookTarget{ + Kind: kargoapi.GenericWebhookTargetKindWarehouse, + IndexSelector: kargoapi.IndexSelector{ + MatchIndices: []kargoapi.IndexSelectorRequirement{ + { + Key: "region", + Operator: kargoapi.IndexSelectorRequirementOperatorEqual, + Value: "us-west-1", + }, + { + Key: "status", + Operator: kargoapi.IndexSelectorRequirementOperatorNotEqual, + Value: "inactive", + }, + }, + }, + }, + env: map[string]any{}, + expected: []client.ListOption{ + client.InNamespace("sample-project"), + client.MatchingFieldsSelector{ + Selector: fields.OneTermEqualSelector("region", "us-west-1"), + }, + client.MatchingFieldsSelector{ + Selector: fields.OneTermNotEqualSelector("status", "inactive"), + }, + }, + err: nil, + }, + { + name: "label selector match expressions with invalid operator", + project: "test-project", + target: kargoapi.GenericWebhookTarget{ + Kind: kargoapi.GenericWebhookTargetKindWarehouse, + LabelSelector: metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "env", + Operator: "InvalidOperator", + Values: []string{"prod", "staging"}, + }, + }, + }, + }, + env: map[string]any{}, + expected: nil, + err: errors.New("unsupported LabelSelectorOperator: \"InvalidOperator\""), + }, + { + name: "label selector match expressions with invalid requirement (empty values for In operator)", + project: "example-project", + target: kargoapi.GenericWebhookTarget{ + Kind: kargoapi.GenericWebhookTargetKindWarehouse, + LabelSelector: metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "env", + Operator: metav1.LabelSelectorOpIn, + Values: []string{}, + }, + }, + }, + }, + env: map[string]any{}, + expected: nil, + err: errors.New("Invalid value: []: for 'in', 'notin' operators, values set can't be empty"), + }, + { + name: "label selector match expressions with invalid expression result", + project: "example-project", + target: kargoapi.GenericWebhookTarget{ + Kind: kargoapi.GenericWebhookTargetKindWarehouse, + LabelSelector: metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "env", + Operator: metav1.LabelSelectorOpIn, + Values: []string{"${{ undefined() }}"}, + }, + }, + }, + }, + env: map[string]any{}, + expected: nil, + err: errors.New("failed to evaluate expression"), + }, + { + name: "label selector match expressions with non-string result", + project: "example-project", + target: kargoapi.GenericWebhookTarget{ + Kind: kargoapi.GenericWebhookTargetKindWarehouse, + LabelSelector: metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "env", + Operator: metav1.LabelSelectorOpIn, + Values: []string{"${{ 12345 }}"}, + }, + }, + }, + }, + env: map[string]any{}, + expected: nil, + err: errors.New( + "failed to parse matchExpression values: failed to evaluate value \"${{ 12345 }}\" as string", + ), + }, + { + name: "label selector match labels invalid requirement (empty key)", + project: "sample-project", + target: kargoapi.GenericWebhookTarget{ + Kind: kargoapi.GenericWebhookTargetKindWarehouse, + LabelSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{"": ""}, + }, + }, + env: map[string]any{}, + expected: nil, + err: errors.New("key: Invalid value: \"\": name part must be non-empty;"), + }, + { + name: "simple label selector", + project: "test-project", + target: kargoapi.GenericWebhookTarget{ + Kind: kargoapi.GenericWebhookTargetKindWarehouse, + LabelSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "app": "my-app", + "foo": "bar", + }, + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "env", + Operator: metav1.LabelSelectorOpIn, + Values: []string{"prod", "staging"}, + }, + { + Key: "tier", + Operator: metav1.LabelSelectorOpIn, + Values: []string{"backend", "frontend"}, + }, + }, + }, + }, + env: map[string]any{}, + expected: []client.ListOption{ + client.InNamespace("test-project"), + client.MatchingLabelsSelector{ + Selector: labels.NewSelector().Add( + newLabelRequirement(t, "app", selection.Equals, []string{"my-app"}), + newLabelRequirement(t, "foo", selection.Equals, []string{"bar"}), + newLabelRequirement(t, "env", selection.In, []string{"prod", "staging"}), + newLabelRequirement(t, "tier", selection.In, []string{"backend", "frontend"}), + ), + }, + }, + err: nil, + }, + { + name: "combined index and label selectors", + project: "combined-project", + target: kargoapi.GenericWebhookTarget{ + Kind: kargoapi.GenericWebhookTargetKindWarehouse, + IndexSelector: kargoapi.IndexSelector{ + MatchIndices: []kargoapi.IndexSelectorRequirement{ + { + Key: "region", + Operator: kargoapi.IndexSelectorRequirementOperatorEqual, + Value: "us-east-1", + }, + }, + }, + LabelSelector: metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "app", + Operator: metav1.LabelSelectorOpIn, + Values: []string{"combined-app"}, + }, + }, + MatchLabels: map[string]string{ + "env": "staging", + }, + }, + }, + env: map[string]any{}, + expected: []client.ListOption{ + client.InNamespace("combined-project"), + client.MatchingFieldsSelector{ + Selector: fields.OneTermEqualSelector("region", "us-east-1"), + }, + client.MatchingLabelsSelector{ + Selector: labels.NewSelector().Add( + newLabelRequirement(t, "app", selection.In, []string{"combined-app"}), + newLabelRequirement(t, "env", selection.Equals, []string{"staging"}), + ), + }, + }, + err: nil, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := buildListOptionsForTarget(tt.project, tt.target, tt.env) + if tt.err != nil { + require.ErrorContains(t, err, tt.err.Error()) + return + } + require.NoError(t, err) + require.Equal(t, tt.expected, got) + }) + } +} + +func Test_labelOpToSelectionOp(t *testing.T) { + tests := []struct { + name string + operator metav1.LabelSelectorOperator + expected selection.Operator + err error + }{ + { + name: "in operator", + operator: metav1.LabelSelectorOpIn, + expected: selection.In, + err: nil, + }, + { + name: "not in operator", + operator: metav1.LabelSelectorOpNotIn, + expected: selection.NotIn, + err: nil, + }, + { + name: "exists operator", + operator: metav1.LabelSelectorOpExists, + expected: selection.Exists, + err: nil, + }, + { + name: "does not exist operator", + operator: metav1.LabelSelectorOpDoesNotExist, + expected: selection.DoesNotExist, + err: nil, + }, + { + name: "greater than operator", + operator: "GreaterThan", + expected: "", + err: errors.New("unsupported LabelSelectorOperator: \"GreaterThan\""), + }, + { + name: "less than operator", + operator: "LessThan", + expected: "", + err: errors.New("unsupported LabelSelectorOperator: \"LessThan\""), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := labelOpToSelectionOp(tt.operator) + if tt.err != nil { + require.ErrorContains(t, err, tt.err.Error()) + return + } + require.NoError(t, err) + require.Equal(t, tt.expected, got) + }) + } +} + +func newLabelRequirement( + t *testing.T, + key string, + operator selection.Operator, + values []string, +) labels.Requirement { + req, err := labels.NewRequirement(key, operator, values) + require.NoError(t, err) + return *req +} diff --git a/pkg/webhook/external/generic_test.go b/pkg/webhook/external/generic_test.go new file mode 100644 index 0000000000..700dbb92f3 --- /dev/null +++ b/pkg/webhook/external/generic_test.go @@ -0,0 +1,442 @@ +package external + +import ( + "bytes" + "context" + "errors" + "io" + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + "sigs.k8s.io/controller-runtime/pkg/client/interceptor" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/pkg/indexer" +) + +func TestGenericHandler(t *testing.T) { + const testURL = "https://webhooks.kargo.example.com/nonsense" + testScheme := runtime.NewScheme() + require.NoError(t, kargoapi.AddToScheme(testScheme)) + + testCases := []struct { + name string + kClient client.Client + config *kargoapi.GenericWebhookReceiverConfig + req func() *http.Request + assertions func(*testing.T, *httptest.ResponseRecorder) + }{ + { + name: "failure creating global env", + kClient: fake.NewClientBuilder().WithScheme(testScheme).Build(), + config: &kargoapi.GenericWebhookReceiverConfig{}, + req: func() *http.Request { + return httptest.NewRequest( + http.MethodPost, + "/", + bytes.NewBuffer([]byte(`"invalid-json`)), + ) + }, + assertions: func(t *testing.T, w *httptest.ResponseRecorder) { + require.Equal(t, http.StatusBadRequest, w.Code) + require.Contains(t, w.Body.String(), "invalid request body") + }, + }, + { + name: "condition not met - failed to evaluate", + kClient: fake.NewClientBuilder().WithScheme(testScheme).Build(), + config: &kargoapi.GenericWebhookReceiverConfig{ + Actions: []kargoapi.GenericWebhookAction{ + { + Name: kargoapi.GenericWebhookActionNameRefresh, + // foo is not defined, so evaluation will fail + MatchExpression: "${{ foo() }}", + }, + }, + }, + req: func() *http.Request { + return httptest.NewRequest( + http.MethodPost, + testURL, + bytes.NewBuffer([]byte(`{"some": "data"}`)), + ) + }, + assertions: func(t *testing.T, w *httptest.ResponseRecorder) { + require.Equal(t, http.StatusInternalServerError, w.Code) + expected := `{ + "actionResults":[ + { + "actionName":"Refresh", + "conditionResult":{ + "expression":"${{ foo() }}", + "satisfied":false, + "evalError": "reflect: call of reflect.Value.Call on zero Value (1:2)\n | foo() \n | .^" + } + } + ]} + ` + require.JSONEq(t, expected, w.Body.String()) + }, + }, + { + name: "condition not met - evaluated to false", + kClient: fake.NewClientBuilder().WithScheme(testScheme).Build(), + config: &kargoapi.GenericWebhookReceiverConfig{ + Actions: []kargoapi.GenericWebhookAction{ + { + Name: kargoapi.GenericWebhookActionNameRefresh, + MatchExpression: `${{ request.header('X-Event-Type') == 'push' }}`, + }, + }, + }, + req: func() *http.Request { + req := httptest.NewRequest( + http.MethodPost, + testURL, + bytes.NewBuffer([]byte(`{"some": "data"}`)), + ) + req.Header.Set("X-Event-Type", "pull_request") + return req + }, + assertions: func(t *testing.T, w *httptest.ResponseRecorder) { + require.Equal(t, http.StatusOK, w.Code) + expected := `{ + "actionResults":[ + { + "actionName":"Refresh", + "conditionResult":{ + "expression":"${{ request.header('X-Event-Type') == 'push' }}", + "satisfied":false + } + } + ]} + ` + require.JSONEq(t, expected, w.Body.String()) + }, + }, + { + name: "condition not met - evaluated to non-boolean type", + kClient: fake.NewClientBuilder().WithScheme(testScheme).Build(), + config: &kargoapi.GenericWebhookReceiverConfig{ + Actions: []kargoapi.GenericWebhookAction{ + { + Name: kargoapi.GenericWebhookActionNameRefresh, + MatchExpression: `${{ request.header('X-Event-Type') }}`, + }, + }, + }, + req: func() *http.Request { + req := httptest.NewRequest( + http.MethodPost, + testURL, + bytes.NewBuffer([]byte(`{"some": "data"}`)), + ) + req.Header.Set("X-Event-Type", "pull_request") + return req + }, + assertions: func(t *testing.T, w *httptest.ResponseRecorder) { + require.Equal(t, http.StatusInternalServerError, w.Code) + expected := `{ + "actionResults":[ + { + "actionName":"Refresh", + "conditionResult":{ + "expression":"${{ request.header('X-Event-Type') }}", + "satisfied":false, + "evalError": "match expression result \"pull_request\" is of type string; expected bool" + } + } + ]} + ` + require.JSONEq(t, expected, w.Body.String()) + }, + }, + { + name: "partial success", + kClient: fake.NewClientBuilder().WithScheme(testScheme).WithObjects( + // this warehouse will be refreshed successfully + &kargoapi.Warehouse{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-project", + Name: "api-warehouse", + Labels: map[string]string{ + "foo": "bar", // satisfies labelSelector.MatchLabels + "tier": "backend", // satisfies labelSelector.MatchExpressions + }, + }, + Spec: kargoapi.WarehouseSpec{ + Subscriptions: []kargoapi.RepoSubscription{{ + Git: &kargoapi.GitSubscription{ + RepoURL: "http://github.com/example/repo.git", // satisfies index selector + }, + }}, + }, + }, + // this warehouse will fully satisfy the label selector but not the index selector + &kargoapi.Warehouse{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-project", + Name: "other-api-warehouse", + Labels: map[string]string{ + "foo": "bar", + "tier": "backend", + }, + }, + Spec: kargoapi.WarehouseSpec{ + Subscriptions: []kargoapi.RepoSubscription{{ + Git: &kargoapi.GitSubscription{ + RepoURL: "http://github.com/example/other-repo.git", // does NOT satisfy index selector + }, + }}, + }, + }, + // this label will satisfy the indexSelector, labelSelector.MatchLabels, + // but not labelSelector.MatchExpressions + &kargoapi.Warehouse{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-project", + Name: "ui-warehouse", + Labels: map[string]string{ + "foo": "bar", + // "tier": "frontend", // missing + }, + }, + Spec: kargoapi.WarehouseSpec{ + Subscriptions: []kargoapi.RepoSubscription{{ + Git: &kargoapi.GitSubscription{ + RepoURL: "http://github.com/example/repo.git", + }, + }}, + }, + }, + // this warehouse will satisfy all selectors but fail during refresh + &kargoapi.Warehouse{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-project", + Name: "failure-warehouse", + Labels: map[string]string{ + "foo": "bar", // satisfies labelSelector.MatchLabels + "tier": "backend", // satisfies labelSelector.MatchExpressions + }, + }, + Spec: kargoapi.WarehouseSpec{ + Subscriptions: []kargoapi.RepoSubscription{{ + Git: &kargoapi.GitSubscription{ + RepoURL: "http://github.com/example/repo.git", // satisfies index selector + }, + }}, + }, + }, + ).WithIndex( + &kargoapi.Warehouse{}, + indexer.WarehousesBySubscribedURLsField, + indexer.WarehousesBySubscribedURLs, + ).WithInterceptorFuncs( + interceptor.Funcs{ + Patch: func( + _ context.Context, + _ client.WithWatch, + obj client.Object, + _ client.Patch, + _ ...client.PatchOption, + ) error { + if obj.GetName() == "failure-warehouse" { + return errors.New("something went wrong") + } + return nil + }, + }, + ).Build(), + config: &kargoapi.GenericWebhookReceiverConfig{ + Actions: []kargoapi.GenericWebhookAction{ + { + Name: kargoapi.GenericWebhookActionNameRefresh, + MatchExpression: `${{ request.header('X-Event-Type') == 'push' }}`, + // use complex combination of both label and index selectors + Targets: []kargoapi.GenericWebhookTarget{ + { + Kind: kargoapi.GenericWebhookTargetKindWarehouse, + LabelSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{"foo": "bar"}, + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "tier", + Operator: metav1.LabelSelectorOpIn, + Values: []string{"backend", "frontend"}, + }, + }, + }, + IndexSelector: kargoapi.IndexSelector{ + MatchIndices: []kargoapi.IndexSelectorRequirement{ + { + Key: indexer.WarehousesBySubscribedURLsField, + Operator: kargoapi.IndexSelectorRequirementOperatorEqual, + Value: `${{ normalize("git", request.body.repository.url) }}`, + }, + }, + }, + }, + }, + }, + }, + }, + req: func() *http.Request { + // not normalized so the index selector can only work if 'normalize' function is used + b := []byte(`{"repository": {"url": "http://github.com/example/repo.git"}}`) + req := httptest.NewRequest( + http.MethodPost, + testURL, + bytes.NewBuffer(b), + ) + req.Header.Set("X-Event-Type", "push") + return req + }, + assertions: func(t *testing.T, w *httptest.ResponseRecorder) { + t.Logf("response body: %s", w.Body.String()) + require.Equal(t, http.StatusInternalServerError, w.Code) + expected := ` + { + "actionResults":[ + { + "actionName":"Refresh", + "conditionResult":{ + "expression":"${{ request.header('X-Event-Type') == 'push' }}", + "satisfied":true + }, + "targetResults":[ + { + "kind":"Warehouse", + "refreshResults":[ + {"success":"test-project/api-warehouse"}, + {"failure":"test-project/failure-warehouse"} + ] + } + ] + } + ] + }` + require.JSONEq(t, expected, w.Body.String()) + }, + }, + { + name: "success", + kClient: fake.NewClientBuilder().WithScheme(testScheme).WithObjects( + // this warehouse will be refreshed successfully + &kargoapi.Warehouse{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-project", + Name: "api-warehouse", + Labels: map[string]string{ + "foo": "bar", // satisfies labelSelector.MatchLabels + "tier": "backend", // satisfies labelSelector.MatchExpressions + }, + }, + Spec: kargoapi.WarehouseSpec{ + Subscriptions: []kargoapi.RepoSubscription{{ + Git: &kargoapi.GitSubscription{ + RepoURL: "http://github.com/example/repo.git", // satisfies index selector + }, + }}, + }, + }, + ).WithIndex( + &kargoapi.Warehouse{}, + indexer.WarehousesBySubscribedURLsField, + indexer.WarehousesBySubscribedURLs, + ).Build(), + config: &kargoapi.GenericWebhookReceiverConfig{ + Actions: []kargoapi.GenericWebhookAction{ + { + Name: kargoapi.GenericWebhookActionNameRefresh, + MatchExpression: `${{ request.header('X-Event-Type') == 'push' }}`, + // use complex combination of both label and index selectors + Targets: []kargoapi.GenericWebhookTarget{ + { + Kind: kargoapi.GenericWebhookTargetKindWarehouse, + LabelSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{"foo": "bar"}, + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "tier", + Operator: metav1.LabelSelectorOpIn, + Values: []string{"backend", "frontend"}, + }, + }, + }, + IndexSelector: kargoapi.IndexSelector{ + MatchIndices: []kargoapi.IndexSelectorRequirement{ + { + Key: indexer.WarehousesBySubscribedURLsField, + Operator: kargoapi.IndexSelectorRequirementOperatorEqual, + Value: `${{ normalize("git", request.body.repository.url) }}`, + }, + }, + }, + }, + }, + }, + }, + }, + req: func() *http.Request { + // not normalized so the index selector can only work if 'normalize' function is used + b := []byte(`{"repository": {"url": "http://github.com/example/repo.git"}}`) + req := httptest.NewRequest( + http.MethodPost, + testURL, + bytes.NewBuffer(b), + ) + req.Header.Set("X-Event-Type", "push") + return req + }, + assertions: func(t *testing.T, w *httptest.ResponseRecorder) { + require.Equal(t, http.StatusOK, w.Code) + expected := ` + { + "actionResults":[ + { + "actionName":"Refresh", + "conditionResult":{ + "expression":"${{ request.header('X-Event-Type') == 'push' }}", + "satisfied":true + }, + "targetResults":[ + { + "kind":"Warehouse", + "refreshResults":[ + {"success":"test-project/api-warehouse"} + ] + } + ] + } + ] + }` + require.JSONEq(t, expected, w.Body.String()) + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + requestBody, err := io.ReadAll(tc.req().Body) + require.NoError(t, err) + t.Cleanup(func() { + _ = tc.req().Body.Close() + }) + w := httptest.NewRecorder() + (&genericWebhookReceiver{ + baseWebhookReceiver: &baseWebhookReceiver{ + client: tc.kClient, + project: "test-project", + }, + config: tc.config, + }).getHandler(requestBody).ServeHTTP(w, tc.req()) + tc.assertions(t, w) + }) + } +} diff --git a/pkg/webhook/external/refresh.go b/pkg/webhook/external/refresh.go index 8d0db3974a..345deecf69 100644 --- a/pkg/webhook/external/refresh.go +++ b/pkg/webhook/external/refresh.go @@ -19,6 +19,76 @@ import ( "github.com/akuity/kargo/pkg/urls" ) +type targetResult struct { + Kind kargoapi.GenericWebhookTargetKind `json:"kind"` + ListError error `json:"listError,omitempty"` + RefreshResults []refreshResult `json:"refreshResults,omitempty"` +} + +type refreshResult struct { + Success string `json:"success,omitempty"` + Failure string `json:"failure,omitempty"` +} + +func refreshTargets( + ctx context.Context, + c client.Client, + project string, + actionEnv map[string]any, + targets []kargoapi.GenericWebhookTarget, +) []targetResult { + logger := logging.LoggerFromContext(ctx) + targetResults := make([]targetResult, len(targets)) + for i, target := range targets { + tLogger := logger.WithValues("targetKind", target.Kind) + targetResults[i] = targetResult{Kind: target.Kind} + switch target.Kind { + case kargoapi.GenericWebhookTargetKindWarehouse: + listOpts, err := buildListOptionsForTarget(project, target, actionEnv) + if err != nil { + tLogger.Error(err, "failed to build list options for warehouse target") + targetResults[i].ListError = fmt.Errorf("failed to build list options for warehouse target: %w", err) + continue + } + + var whList kargoapi.WarehouseList + if err := c.List(ctx, &whList, listOpts...); err != nil { + tLogger.Error(err, "error listing warehouse targets") + targetResults[i].ListError = fmt.Errorf("error listing warehouse targets: %w", err) + continue + } + + tLogger.Info("found Warehouses to refresh", "count", len(whList.Items)) + + var refreshResults []refreshResult + for _, wh := range whList.Items { + whKey := client.ObjectKeyFromObject(&wh) + whLogger := tLogger.WithValues( + "namespace", whKey.Namespace, + "name", whKey.Name, + ) + if target.Name != "" && whKey.Name != target.Name { + whLogger.Debug("skipping warehouse due to name mismatch") + continue + } + var rr refreshResult + if _, err := api.RefreshWarehouse(ctx, c, whKey); err != nil { + whLogger.Error(err, "error refreshing") + rr.Failure = whKey.String() + } else { + whLogger.Debug("successfully refreshed Warehouse") + rr.Success = whKey.String() + } + refreshResults = append(refreshResults, rr) + } + targetResults[i].RefreshResults = refreshResults + default: + targetResults[i].ListError = fmt.Errorf("skipped listing of unsupported target type: %q", target.Kind) + } + } + return targetResults +} + // refreshWarehouses refreshes all Warehouses in the given namespace that are // subscribed to any of the given repository URLs. If the namespace is empty, // all Warehouses in the cluster subscribed to the given repository URLs are diff --git a/pkg/webhook/external/refresh_test.go b/pkg/webhook/external/refresh_test.go index 0a61909bf0..a0c6b731f7 100644 --- a/pkg/webhook/external/refresh_test.go +++ b/pkg/webhook/external/refresh_test.go @@ -19,6 +19,320 @@ import ( "github.com/akuity/kargo/pkg/urls" ) +func TestHandleRefreshAction(t *testing.T) { + testScheme := runtime.NewScheme() + require.NoError(t, kargoapi.AddToScheme(testScheme)) + + testCases := []struct { + name string + client client.Client + project string + targets []kargoapi.GenericWebhookTarget + actionEnv map[string]any + assertions func(*testing.T, []targetResult) + }{ + { + name: "error listing Warehouses", + client: fake.NewClientBuilder().WithScheme(testScheme).WithInterceptorFuncs( + interceptor.Funcs{ + List: func( + context.Context, + client.WithWatch, + client.ObjectList, + ...client.ListOption, + ) error { + return errors.New("something went wrong") + }, + }, + ).Build(), + targets: []kargoapi.GenericWebhookTarget{{ + Kind: kargoapi.GenericWebhookTargetKindWarehouse, + }}, + assertions: func(t *testing.T, results []targetResult) { + require.Len(t, results, 1) + require.Equal(t, kargoapi.GenericWebhookTargetKindWarehouse, results[0].Kind) + require.Error(t, results[0].ListError) + require.Contains(t, results[0].ListError.Error(), "error listing warehouse targets") + }, + }, + { + name: "full success refreshing warehouses with complex mixed index and label selector combo", + client: fake.NewClientBuilder().WithScheme(testScheme). + WithIndex( + &kargoapi.Warehouse{}, + indexer.WarehousesBySubscribedURLsField, + indexer.WarehousesBySubscribedURLs, + ).WithObjects( + // this warehouse satisifies both index and label selectors + &kargoapi.Warehouse{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-project", + Name: "warehouse-1", + Labels: map[string]string{ + "env": "prod", + "tier": "backend", + }, + }, + Spec: kargoapi.WarehouseSpec{ + Subscriptions: []kargoapi.RepoSubscription{{ + Git: &kargoapi.GitSubscription{ + RepoURL: "https://github.com/example/repo.git", + }, + }}, + }, + }, + // label selector should not match this Warehouse + &kargoapi.Warehouse{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-project", + Name: "warehouse-with-mismatching-labels", + Labels: map[string]string{"doesnt": "match"}, + }, + Spec: kargoapi.WarehouseSpec{ + Subscriptions: []kargoapi.RepoSubscription{{ + Git: &kargoapi.GitSubscription{ + RepoURL: "https://github.com/example/repo.git", + }, + }}, + }, + }, + // index selector should not match this Warehouse + &kargoapi.Warehouse{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-project", + Name: "warehouse-with-mismatching-index", + Labels: map[string]string{ + "env": "prod", + "tier": "frontend", + }, + }, + Spec: kargoapi.WarehouseSpec{ + Subscriptions: []kargoapi.RepoSubscription{{ + Git: &kargoapi.GitSubscription{ + RepoURL: "https://github.com/example/wrong-repo.git", + }, + }}, + }, + }, + ).Build(), + project: "test-project", + targets: []kargoapi.GenericWebhookTarget{{ + Kind: kargoapi.GenericWebhookTargetKindWarehouse, + IndexSelector: kargoapi.IndexSelector{ + MatchIndices: []kargoapi.IndexSelectorRequirement{{ + Key: indexer.WarehousesBySubscribedURLsField, + Operator: kargoapi.IndexSelectorRequirementOperatorEqual, + Value: "https://github.com/example/repo", + }}, + }, + LabelSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{"env": "prod"}, + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "tier", + Operator: metav1.LabelSelectorOpIn, + Values: []string{"backend", "frontend"}, + }, + }, + }, + }}, + assertions: func(t *testing.T, results []targetResult) { + require.Len(t, results, 1) + require.Equal(t, kargoapi.GenericWebhookTargetKindWarehouse, results[0].Kind) + require.NoError(t, results[0].ListError) + require.Len(t, results[0].RefreshResults, 1) + require.Equal(t, "test-project/warehouse-1", results[0].RefreshResults[0].Success) + }, + }, + { + name: "partial success refreshing warehouses", + client: fake.NewClientBuilder().WithScheme(testScheme).WithObjects( + // both warehouses satisfy the label selector + &kargoapi.Warehouse{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-namespace", + Name: "frontend-warehouse", + Labels: map[string]string{"tier": "frontend"}, + }, + Spec: kargoapi.WarehouseSpec{ + Subscriptions: []kargoapi.RepoSubscription{{ + Git: &kargoapi.GitSubscription{ + RepoURL: "https://github.com/example/frontend-repo.git", + }, + }}, + }, + }, + // this one will fail to refresh per the interceptor logic below + &kargoapi.Warehouse{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-namespace", + Name: "backend-warehouse", + Labels: map[string]string{"tier": "backend"}, + }, + Spec: kargoapi.WarehouseSpec{ + Subscriptions: []kargoapi.RepoSubscription{{ + Git: &kargoapi.GitSubscription{ + RepoURL: "https://github.com/example/backend-repo.git", + }, + }}, + }, + }, + ).WithInterceptorFuncs(interceptor.Funcs{ + Patch: func( + _ context.Context, + _ client.WithWatch, + obj client.Object, + _ client.Patch, + _ ...client.PatchOption, + ) error { + if obj.GetName() == "backend-warehouse" { + return nil + } + return errors.New("something went wrong") + }, + }).WithIndex( + &kargoapi.Warehouse{}, + indexer.WarehousesBySubscribedURLsField, + indexer.WarehousesBySubscribedURLs, + ).Build(), + targets: []kargoapi.GenericWebhookTarget{{ + Kind: kargoapi.GenericWebhookTargetKindWarehouse, + LabelSelector: metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{{ + Key: "tier", + Operator: metav1.LabelSelectorOpIn, + Values: []string{"frontend", "backend"}, + }}, + }, + }}, + assertions: func(t *testing.T, results []targetResult) { + require.Len(t, results, 1) + require.Len(t, results[0].RefreshResults, 2) + firstWhResult := results[0].RefreshResults[0] + require.Empty(t, firstWhResult.Failure) + require.Equal(t, firstWhResult.Success, "test-namespace/backend-warehouse") + secondResult := results[0].RefreshResults[1] + require.NotEmpty(t, secondResult.Failure) + require.Contains(t, secondResult.Failure, "test-namespace/frontend-warehouse") + }, + }, + { + name: "successful refresh using static name only", + client: fake.NewClientBuilder().WithScheme(testScheme).WithObjects( + // does not have the specified name + &kargoapi.Warehouse{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-namespace", + Name: "frontend-warehouse", + }, + }, + // has the specified name + &kargoapi.Warehouse{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-namespace", + Name: "backend-warehouse", + }, + }, + ).WithIndex( + &kargoapi.Warehouse{}, + indexer.WarehousesBySubscribedURLsField, + indexer.WarehousesBySubscribedURLs, + ).Build(), + targets: []kargoapi.GenericWebhookTarget{{ + Kind: kargoapi.GenericWebhookTargetKindWarehouse, + Name: "backend-warehouse", + }}, + assertions: func(t *testing.T, results []targetResult) { + require.Len(t, results, 1) + require.Len(t, results[0].RefreshResults, 1) + firstWhResult := results[0].RefreshResults[0] + require.Equal(t, firstWhResult.Success, "test-namespace/backend-warehouse") + }, + }, + { + name: "successful refresh using static name with label selector", + client: fake.NewClientBuilder().WithScheme(testScheme).WithObjects( + // this warehouse satisfies the label selector + // but does not have the specified name + &kargoapi.Warehouse{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-namespace", + Name: "frontend-warehouse", + Labels: map[string]string{"tier": "frontend"}, + }, + Spec: kargoapi.WarehouseSpec{ + Subscriptions: []kargoapi.RepoSubscription{{ + Git: &kargoapi.GitSubscription{ + RepoURL: "https://github.com/example/frontend-repo.git", + }, + }}, + }, + }, + // this warehouse has the specified name and satisfies the label selector + &kargoapi.Warehouse{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-namespace", + Name: "backend-warehouse", + Labels: map[string]string{"tier": "backend"}, + }, + Spec: kargoapi.WarehouseSpec{ + Subscriptions: []kargoapi.RepoSubscription{{ + Git: &kargoapi.GitSubscription{ + RepoURL: "https://github.com/example/backend-repo.git", + }, + }}, + }, + }, + ).WithIndex( + &kargoapi.Warehouse{}, + indexer.WarehousesBySubscribedURLsField, + indexer.WarehousesBySubscribedURLs, + ).Build(), + targets: []kargoapi.GenericWebhookTarget{{ + Kind: kargoapi.GenericWebhookTargetKindWarehouse, + Name: "backend-warehouse", + LabelSelector: metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{{ + Key: "tier", + Operator: metav1.LabelSelectorOpIn, + Values: []string{"frontend", "backend"}, + }}, + }, + }}, + assertions: func(t *testing.T, results []targetResult) { + require.Len(t, results, 1) + require.Len(t, results[0].RefreshResults, 1) + firstWhResult := results[0].RefreshResults[0] + require.Equal(t, firstWhResult.Success, "test-namespace/backend-warehouse") + }, + }, + { + name: "unsupported target kind", + client: fake.NewClientBuilder().WithScheme(testScheme).Build(), + targets: []kargoapi.GenericWebhookTarget{{ + Kind: "UnsupportedKind", + }}, + assertions: func(t *testing.T, results []targetResult) { + require.Len(t, results, 1) + require.Equal(t, "UnsupportedKind", string(results[0].Kind)) + require.Error(t, results[0].ListError) + require.ErrorContains(t, results[0].ListError, "skipped listing of unsupported target type") + }, + }, + } + for _, tt := range testCases { + t.Run(tt.name, func(t *testing.T) { + tt.assertions(t, refreshTargets( + t.Context(), + tt.client, + tt.project, + tt.actionEnv, + tt.targets, + )) + }) + } +} + func TestRefreshWarehouses(t *testing.T) { // Callers are responsible for normalizing the repository URL. testRepoURL := urls.NormalizeGit("https://github.com/example/repo.git") diff --git a/pkg/webhook/kubernetes/external/validation.go b/pkg/webhook/kubernetes/external/validation.go index 5be712270c..2a5b48bb88 100644 --- a/pkg/webhook/kubernetes/external/validation.go +++ b/pkg/webhook/kubernetes/external/validation.go @@ -15,9 +15,17 @@ func ValidateWebhookReceivers( errs := append(field.ErrorList{}, validateUniqueNames(f, webhookReceivers)..., ) - return append(errs, + errs = append(errs, validateMutuallyExclusive(f, webhookReceivers)..., ) + for i, r := range webhookReceivers { + if r.Generic != nil { + errs = append(errs, + validateGenericConfig(i, r.Generic)..., + ) + } + } + return errs } func validateMutuallyExclusive( @@ -51,6 +59,9 @@ func validateMutuallyExclusive( if r.Gitea != nil { receivers = append(receivers, "Gitea") } + if r.Generic != nil { + receivers = append(receivers, "Generic") + } if len(receivers) > 1 { errs = append(errs, field.Forbidden( f.Index(i), @@ -87,3 +98,40 @@ func validateUniqueNames( } return errs } + +func validateGenericConfig( + cfgIndex int, + cfg *kargoapi.GenericWebhookReceiverConfig, +) field.ErrorList { + var errs field.ErrorList + for aIndex, action := range cfg.Actions { + errs = append(errs, validateGenericTargets(cfgIndex, aIndex, action.Targets)...) + } + return errs +} + +func validateGenericTargets(cfgIndex, actionIndex int, targets []kargoapi.GenericWebhookTarget) []*field.Error { + var errs field.ErrorList + for tIndex, target := range targets { + if targetMisconfigured(&target) { + targetPath := fmt.Sprintf( + "spec.webhookReceivers[%d].generic.actions[%d].targets[%d]", + cfgIndex, actionIndex, tIndex, + ) + errs = append(errs, field.Invalid( + field.NewPath(targetPath), + target, + "at least one of name, labelSelector, or indexSelector must be specified for target", + )) + } + } + return errs +} + +func targetMisconfigured(t *kargoapi.GenericWebhookTarget) bool { + // these are all optional but at least one must be set + return t.Name == "" && + len(t.LabelSelector.MatchLabels) == 0 && + len(t.LabelSelector.MatchExpressions) == 0 && + len(t.IndexSelector.MatchIndices) == 0 +} diff --git a/pkg/webhook/kubernetes/projectconfig/webhook_test.go b/pkg/webhook/kubernetes/projectconfig/webhook_test.go index 8a439865bf..cf02fd9f39 100644 --- a/pkg/webhook/kubernetes/projectconfig/webhook_test.go +++ b/pkg/webhook/kubernetes/projectconfig/webhook_test.go @@ -586,6 +586,58 @@ func Test_webhook_ValidateCreate(t *testing.T) { "cannot define a receiver that is of more than one type, found 3: [GitHub GitLab Quay]") }, }, + { + name: "generic webhook receiver misconfiguration", + projectConfig: &kargoapi.ProjectConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: testProjectName, + Namespace: testProjectName, + }, + Spec: kargoapi.ProjectConfigSpec{ + WebhookReceivers: []kargoapi.WebhookReceiverConfig{ + { + Name: "my-generic-webhook-receiver", + Generic: &kargoapi.GenericWebhookReceiverConfig{ + Actions: []kargoapi.GenericWebhookAction{ + { + Targets: []kargoapi.GenericWebhookTarget{ + { + Kind: kargoapi.GenericWebhookTargetKindWarehouse, + // Name, Label Selector, and Index Selector + // are all optional but at least one must be set. + // Here, none are set, so this should trigger a validation error. + }, + }, + }, + }, + }, + }, + }, + }, + }, + objects: []client.Object{testNs}, + assertions: func(t *testing.T, warnings admission.Warnings, err error) { + assert.Empty(t, warnings) + require.Error(t, err) + + var statusErr *apierrors.StatusError + require.True(t, errors.As(err, &statusErr)) + + assert.Equal(t, metav1.StatusReasonInvalid, statusErr.ErrStatus.Reason) + assert.Equal(t, 1, len(statusErr.ErrStatus.Details.Causes)) + + // Sort errors for consistent testing + sort.Slice(statusErr.ErrStatus.Details.Causes, func(i, j int) bool { + return statusErr.ErrStatus.Details.Causes[i].Field < statusErr.ErrStatus.Details.Causes[j].Field + }) + + assert.Equal(t, "spec.webhookReceivers[0].generic.actions[0].targets[0]", + statusErr.ErrStatus.Details.Causes[0].Field) + assert.Equal(t, metav1.CauseTypeFieldValueInvalid, statusErr.ErrStatus.Details.Causes[0].Type) + assert.Contains(t, statusErr.ErrStatus.Details.Causes[0].Message, + "at least one of name, labelSelector, or indexSelector must be specified for target") + }, + }, } for _, tt := range tests { diff --git a/ui/src/gen/api/v1alpha1/generated_pb.ts b/ui/src/gen/api/v1alpha1/generated_pb.ts index 039cc92292..a688399386 100644 --- a/ui/src/gen/api/v1alpha1/generated_pb.ts +++ b/ui/src/gen/api/v1alpha1/generated_pb.ts @@ -20,7 +20,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file api/v1alpha1/generated.proto. */ export const file_api_v1alpha1_generated: GenFile = /*@__PURE__*/ - fileDesc("ChxhcGkvdjFhbHBoYTEvZ2VuZXJhdGVkLnByb3RvEiRnaXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEiMgoTQW5hbHlzaXNSdW5Bcmd1bWVudBIMCgRuYW1lGAEgASgJEg0KBXZhbHVlGAIgASgJIrACChNBbmFseXNpc1J1bk1ldGFkYXRhElUKBmxhYmVscxgBIAMoCzJFLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5BbmFseXNpc1J1bk1ldGFkYXRhLkxhYmVsc0VudHJ5El8KC2Fubm90YXRpb25zGAIgAygLMkouZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkFuYWx5c2lzUnVuTWV0YWRhdGEuQW5ub3RhdGlvbnNFbnRyeRotCgtMYWJlbHNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBGjIKEEFubm90YXRpb25zRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJOgI4ASJGChRBbmFseXNpc1J1blJlZmVyZW5jZRIRCgluYW1lc3BhY2UYASABKAkSDAoEbmFtZRgCIAEoCRINCgVwaGFzZRgDIAEoCSI3ChlBbmFseXNpc1RlbXBsYXRlUmVmZXJlbmNlEgwKBG5hbWUYASABKAkSDAoEa2luZBgCIAEoCSJPCg1BcHByb3ZlZFN0YWdlEj4KCmFwcHJvdmVkQXQYASABKAsyKi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuVGltZSI4ChVBcmdvQ0RBcHBIZWFsdGhTdGF0dXMSDgoGc3RhdHVzGAEgASgJEg8KB21lc3NhZ2UYAiABKAki1AEKD0FyZ29DREFwcFN0YXR1cxIRCgluYW1lc3BhY2UYASABKAkSDAoEbmFtZRgCIAEoCRJRCgxoZWFsdGhTdGF0dXMYAyABKAsyOy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuQXJnb0NEQXBwSGVhbHRoU3RhdHVzEk0KCnN5bmNTdGF0dXMYBCABKAsyOS5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuQXJnb0NEQXBwU3luY1N0YXR1cyJKChNBcmdvQ0RBcHBTeW5jU3RhdHVzEg4KBnN0YXR1cxgBIAEoCRIQCghyZXZpc2lvbhgCIAEoCRIRCglyZXZpc2lvbnMYAyADKAkieAogQXJ0aWZhY3RvcnlXZWJob29rUmVjZWl2ZXJDb25maWcSOwoJc2VjcmV0UmVmGAEgASgLMiguazhzLmlvLmFwaS5jb3JlLnYxLkxvY2FsT2JqZWN0UmVmZXJlbmNlEhcKD3ZpcnR1YWxSZXBvTmFtZRgCIAEoCSIvChRBdXRvUHJvbW90aW9uT3B0aW9ucxIXCg9zZWxlY3Rpb25Qb2xpY3kYASABKAkiWQoaQXp1cmVXZWJob29rUmVjZWl2ZXJDb25maWcSOwoJc2VjcmV0UmVmGAEgASgLMiguazhzLmlvLmFwaS5jb3JlLnYxLkxvY2FsT2JqZWN0UmVmZXJlbmNlIl0KHkJpdGJ1Y2tldFdlYmhvb2tSZWNlaXZlckNvbmZpZxI7CglzZWNyZXRSZWYYASABKAsyKC5rOHMuaW8uYXBpLmNvcmUudjEuTG9jYWxPYmplY3RSZWZlcmVuY2UiNwoFQ2hhcnQSDwoHcmVwb1VSTBgBIAEoCRIMCgRuYW1lGAIgASgJEg8KB3ZlcnNpb24YAyABKAkiYQoUQ2hhcnREaXNjb3ZlcnlSZXN1bHQSDwoHcmVwb1VSTBgBIAEoCRIMCgRuYW1lGAIgASgJEhgKEHNlbXZlckNvbnN0cmFpbnQYAyABKAkSEAoIdmVyc2lvbnMYBCADKAkiZAoRQ2hhcnRTdWJzY3JpcHRpb24SDwoHcmVwb1VSTBgBIAEoCRIMCgRuYW1lGAIgASgJEhgKEHNlbXZlckNvbnN0cmFpbnQYAyABKAkSFgoOZGlzY292ZXJ5TGltaXQYBCABKAUi5QEKDUNsdXN0ZXJDb25maWcSQgoIbWV0YWRhdGEYASABKAsyMC5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuT2JqZWN0TWV0YRJFCgRzcGVjGAIgASgLMjcuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkNsdXN0ZXJDb25maWdTcGVjEkkKBnN0YXR1cxgDIAEoCzI5LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5DbHVzdGVyQ29uZmlnU3RhdHVzIpkBChFDbHVzdGVyQ29uZmlnTGlzdBJACghtZXRhZGF0YRgBIAEoCzIuLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5MaXN0TWV0YRJCCgVpdGVtcxgCIAMoCzIzLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5DbHVzdGVyQ29uZmlnImoKEUNsdXN0ZXJDb25maWdTcGVjElUKEHdlYmhvb2tSZWNlaXZlcnMYASADKAsyOy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuV2ViaG9va1JlY2VpdmVyQ29uZmlnIuoBChNDbHVzdGVyQ29uZmlnU3RhdHVzEkMKCmNvbmRpdGlvbnMYASADKAsyLy5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuQ29uZGl0aW9uEhoKEm9ic2VydmVkR2VuZXJhdGlvbhgDIAEoAxIaChJsYXN0SGFuZGxlZFJlZnJlc2gYBCABKAkSVgoQd2ViaG9va1JlY2VpdmVycxgCIAMoCzI8LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5XZWJob29rUmVjZWl2ZXJEZXRhaWxzIqEBChRDbHVzdGVyUHJvbW90aW9uVGFzaxJCCghtZXRhZGF0YRgBIAEoCzIwLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5PYmplY3RNZXRhEkUKBHNwZWMYAiABKAsyNy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvbW90aW9uVGFza1NwZWMipwEKGENsdXN0ZXJQcm9tb3Rpb25UYXNrTGlzdBJACghtZXRhZGF0YRgBIAEoCzIuLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5MaXN0TWV0YRJJCgVpdGVtcxgCIAMoCzI6LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5DbHVzdGVyUHJvbW90aW9uVGFzayJJCgxDdXJyZW50U3RhZ2USOQoFc2luY2UYASABKAsyKi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuVGltZSK2AgoTRGlzY292ZXJlZEFydGlmYWN0cxJACgxkaXNjb3ZlcmVkQXQYBCABKAsyKi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuVGltZRJFCgNnaXQYASADKAsyOC5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuR2l0RGlzY292ZXJ5UmVzdWx0EkoKBmltYWdlcxgCIAMoCzI6LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5JbWFnZURpc2NvdmVyeVJlc3VsdBJKCgZjaGFydHMYAyADKAsyOi5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuQ2hhcnREaXNjb3ZlcnlSZXN1bHQisAEKEERpc2NvdmVyZWRDb21taXQSCgoCaWQYASABKAkSDgoGYnJhbmNoGAIgASgJEgsKA3RhZxgDIAEoCRIPCgdzdWJqZWN0GAQgASgJEg4KBmF1dGhvchgFIAEoCRIRCgljb21taXR0ZXIYBiABKAkSPwoLY3JlYXRvckRhdGUYByABKAsyKi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuVGltZSKQAgoYRGlzY292ZXJlZEltYWdlUmVmZXJlbmNlEgsKA3RhZxgBIAEoCRIOCgZkaWdlc3QYAiABKAkSZAoLYW5ub3RhdGlvbnMYBSADKAsyTy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuRGlzY292ZXJlZEltYWdlUmVmZXJlbmNlLkFubm90YXRpb25zRW50cnkSPQoJY3JlYXRlZEF0GAQgASgLMiouazhzLmlvLmFwaW1hY2hpbmVyeS5wa2cuYXBpcy5tZXRhLnYxLlRpbWUaMgoQQW5ub3RhdGlvbnNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBIl0KHkRvY2tlckh1YldlYmhvb2tSZWNlaXZlckNvbmZpZxI7CglzZWNyZXRSZWYYASABKAsyKC5rOHMuaW8uYXBpLmNvcmUudjEuTG9jYWxPYmplY3RSZWZlcmVuY2UiMQoSRXhwcmVzc2lvblZhcmlhYmxlEgwKBG5hbWUYASABKAkSDQoFdmFsdWUYAiABKAkiogMKB0ZyZWlnaHQSQgoIbWV0YWRhdGEYASABKAsyMC5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuT2JqZWN0TWV0YRINCgVhbGlhcxgHIAEoCRJDCgZvcmlnaW4YCSABKAsyMy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuRnJlaWdodE9yaWdpbhJACgdjb21taXRzGAMgAygLMi8uZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkdpdENvbW1pdBI7CgZpbWFnZXMYBCADKAsyKy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuSW1hZ2USOwoGY2hhcnRzGAUgAygLMisuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkNoYXJ0EkMKBnN0YXR1cxgGIAEoCzIzLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5GcmVpZ2h0U3RhdHVzIq0CChFGcmVpZ2h0Q29sbGVjdGlvbhIKCgJpZBgDIAEoCRJRCgVpdGVtcxgBIAMoCzJCLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5GcmVpZ2h0Q29sbGVjdGlvbi5JdGVtc0VudHJ5ElMKE3ZlcmlmaWNhdGlvbkhpc3RvcnkYAiADKAsyNi5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuVmVyaWZpY2F0aW9uSW5mbxpkCgpJdGVtc0VudHJ5EgsKA2tleRgBIAEoCRJFCgV2YWx1ZRgCIAEoCzI2LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5GcmVpZ2h0UmVmZXJlbmNlOgI4ASItChdGcmVpZ2h0Q3JlYXRpb25Dcml0ZXJpYRISCgpleHByZXNzaW9uGAEgASgJIo0BCgtGcmVpZ2h0TGlzdBJACghtZXRhZGF0YRgBIAEoCzIuLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5MaXN0TWV0YRI8CgVpdGVtcxgCIAMoCzItLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5GcmVpZ2h0IisKDUZyZWlnaHRPcmlnaW4SDAoEa2luZBgBIAEoCRIMCgRuYW1lGAIgASgJIqECChBGcmVpZ2h0UmVmZXJlbmNlEgwKBG5hbWUYASABKAkSQwoGb3JpZ2luGAggASgLMjMuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkZyZWlnaHRPcmlnaW4SQAoHY29tbWl0cxgCIAMoCzIvLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5HaXRDb21taXQSOwoGaW1hZ2VzGAMgAygLMisuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkltYWdlEjsKBmNoYXJ0cxgEIAMoCzIrLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5DaGFydCKcAQoORnJlaWdodFJlcXVlc3QSQwoGb3JpZ2luGAEgASgLMjMuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkZyZWlnaHRPcmlnaW4SRQoHc291cmNlcxgCIAEoCzI0LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5GcmVpZ2h0U291cmNlcyLyAQoORnJlaWdodFNvdXJjZXMSDgoGZGlyZWN0GAEgASgIEg4KBnN0YWdlcxgCIAMoCRJIChByZXF1aXJlZFNvYWtUaW1lGAMgASgLMi4uazhzLmlvLmFwaW1hY2hpbmVyeS5wa2cuYXBpcy5tZXRhLnYxLkR1cmF0aW9uEhwKFGF2YWlsYWJpbGl0eVN0cmF0ZWd5GAQgASgJElgKFGF1dG9Qcm9tb3Rpb25PcHRpb25zGAUgASgLMjouZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkF1dG9Qcm9tb3Rpb25PcHRpb25zIp0GCg1GcmVpZ2h0U3RhdHVzElkKC2N1cnJlbnRseUluGAMgAygLMkQuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkZyZWlnaHRTdGF0dXMuQ3VycmVudGx5SW5FbnRyeRJXCgp2ZXJpZmllZEluGAEgAygLMkMuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkZyZWlnaHRTdGF0dXMuVmVyaWZpZWRJbkVudHJ5ElkKC2FwcHJvdmVkRm9yGAIgAygLMkQuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkZyZWlnaHRTdGF0dXMuQXBwcm92ZWRGb3JFbnRyeRJTCghtZXRhZGF0YRgEIAMoCzJBLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5GcmVpZ2h0U3RhdHVzLk1ldGFkYXRhRW50cnkaZgoQQ3VycmVudGx5SW5FbnRyeRILCgNrZXkYASABKAkSQQoFdmFsdWUYAiABKAsyMi5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuQ3VycmVudFN0YWdlOgI4ARpmCg9WZXJpZmllZEluRW50cnkSCwoDa2V5GAEgASgJEkIKBXZhbHVlGAIgASgLMjMuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlZlcmlmaWVkU3RhZ2U6AjgBGmcKEEFwcHJvdmVkRm9yRW50cnkSCwoDa2V5GAEgASgJEkIKBXZhbHVlGAIgASgLMjMuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkFwcHJvdmVkU3RhZ2U6AjgBGm8KDU1ldGFkYXRhRW50cnkSCwoDa2V5GAEgASgJEk0KBXZhbHVlGAIgASgLMj4uazhzLmlvLmFwaWV4dGVuc2lvbnNfYXBpc2VydmVyLnBrZy5hcGlzLmFwaWV4dGVuc2lvbnMudjEuSlNPTjoCOAEieQoJR2l0Q29tbWl0Eg8KB3JlcG9VUkwYASABKAkSCgoCaWQYAiABKAkSDgoGYnJhbmNoGAMgASgJEgsKA3RhZxgEIAEoCRIPCgdtZXNzYWdlGAYgASgJEg4KBmF1dGhvchgHIAEoCRIRCgljb21taXR0ZXIYCCABKAkibgoSR2l0RGlzY292ZXJ5UmVzdWx0Eg8KB3JlcG9VUkwYASABKAkSRwoHY29tbWl0cxgCIAMoCzI2LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5EaXNjb3ZlcmVkQ29tbWl0IloKG0dpdEh1YldlYmhvb2tSZWNlaXZlckNvbmZpZxI7CglzZWNyZXRSZWYYASABKAsyKC5rOHMuaW8uYXBpLmNvcmUudjEuTG9jYWxPYmplY3RSZWZlcmVuY2UiWgobR2l0TGFiV2ViaG9va1JlY2VpdmVyQ29uZmlnEjsKCXNlY3JldFJlZhgBIAEoCzIoLms4cy5pby5hcGkuY29yZS52MS5Mb2NhbE9iamVjdFJlZmVyZW5jZSLdAgoPR2l0U3Vic2NyaXB0aW9uEg8KB3JlcG9VUkwYASABKAkSHwoXY29tbWl0U2VsZWN0aW9uU3RyYXRlZ3kYAiABKAkSDgoGYnJhbmNoGAMgASgJEhUKDXN0cmljdFNlbXZlcnMYCyABKAgSGAoQc2VtdmVyQ29uc3RyYWludBgEIAEoCRIRCglhbGxvd1RhZ3MYBSABKAkSGAoQYWxsb3dUYWdzUmVnZXhlcxgNIAMoCRISCgppZ25vcmVUYWdzGAYgAygJEhkKEWlnbm9yZVRhZ3NSZWdleGVzGA4gAygJEhgKEGV4cHJlc3Npb25GaWx0ZXIYDCABKAkSHQoVaW5zZWN1cmVTa2lwVExTVmVyaWZ5GAcgASgIEhQKDGluY2x1ZGVQYXRocxgIIAMoCRIUCgxleGNsdWRlUGF0aHMYCSADKAkSFgoOZGlzY292ZXJ5TGltaXQYCiABKAUiWQoaR2l0ZWFXZWJob29rUmVjZWl2ZXJDb25maWcSOwoJc2VjcmV0UmVmGAEgASgLMiguazhzLmlvLmFwaS5jb3JlLnYxLkxvY2FsT2JqZWN0UmVmZXJlbmNlIloKG0hhcmJvcldlYmhvb2tSZWNlaXZlckNvbmZpZxI7CglzZWNyZXRSZWYYASABKAsyKC5rOHMuaW8uYXBpLmNvcmUudjEuTG9jYWxPYmplY3RSZWZlcmVuY2UiyAEKBkhlYWx0aBIOCgZzdGF0dXMYASABKAkSDgoGaXNzdWVzGAIgAygJEk4KBmNvbmZpZxgEIAEoCzI+Lms4cy5pby5hcGlleHRlbnNpb25zX2FwaXNlcnZlci5wa2cuYXBpcy5hcGlleHRlbnNpb25zLnYxLkpTT04STgoGb3V0cHV0GAUgASgLMj4uazhzLmlvLmFwaWV4dGVuc2lvbnNfYXBpc2VydmVyLnBrZy5hcGlzLmFwaWV4dGVuc2lvbnMudjEuSlNPTiJvCg9IZWFsdGhDaGVja1N0ZXASDAoEdXNlcxgBIAEoCRJOCgZjb25maWcYAiABKAsyPi5rOHMuaW8uYXBpZXh0ZW5zaW9uc19hcGlzZXJ2ZXIucGtnLmFwaXMuYXBpZXh0ZW5zaW9ucy52MS5KU09OIh4KC0hlYWx0aFN0YXRzEg8KB2hlYWx0aHkYASABKAMivAEKBUltYWdlEg8KB3JlcG9VUkwYASABKAkSCwoDdGFnGAMgASgJEg4KBmRpZ2VzdBgEIAEoCRJRCgthbm5vdGF0aW9ucxgFIAMoCzI8LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5JbWFnZS5Bbm5vdGF0aW9uc0VudHJ5GjIKEEFubm90YXRpb25zRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJOgI4ASKNAQoUSW1hZ2VEaXNjb3ZlcnlSZXN1bHQSDwoHcmVwb1VSTBgBIAEoCRIQCghwbGF0Zm9ybRgCIAEoCRJSCgpyZWZlcmVuY2VzGAMgAygLMj4uZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkRpc2NvdmVyZWRJbWFnZVJlZmVyZW5jZSKUAgoRSW1hZ2VTdWJzY3JpcHRpb24SDwoHcmVwb1VSTBgBIAEoCRIeChZpbWFnZVNlbGVjdGlvblN0cmF0ZWd5GAMgASgJEhUKDXN0cmljdFNlbXZlcnMYCiABKAgSEgoKY29uc3RyYWludBgLIAEoCRIRCglhbGxvd1RhZ3MYBSABKAkSGAoQYWxsb3dUYWdzUmVnZXhlcxgNIAMoCRISCgppZ25vcmVUYWdzGAYgAygJEhkKEWlnbm9yZVRhZ3NSZWdleGVzGA4gAygJEhAKCHBsYXRmb3JtGAcgASgJEh0KFWluc2VjdXJlU2tpcFRMU1ZlcmlmeRgIIAEoCBIWCg5kaXNjb3ZlcnlMaW1pdBgJIAEoBSKSAQoHUHJvamVjdBJCCghtZXRhZGF0YRgBIAEoCzIwLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5PYmplY3RNZXRhEkMKBnN0YXR1cxgDIAEoCzIzLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5Qcm9qZWN0U3RhdHVzIuUBCg1Qcm9qZWN0Q29uZmlnEkIKCG1ldGFkYXRhGAEgASgLMjAuazhzLmlvLmFwaW1hY2hpbmVyeS5wa2cuYXBpcy5tZXRhLnYxLk9iamVjdE1ldGESRQoEc3BlYxgCIAEoCzI3LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5Qcm9qZWN0Q29uZmlnU3BlYxJJCgZzdGF0dXMYAyABKAsyOS5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvamVjdENvbmZpZ1N0YXR1cyKZAQoRUHJvamVjdENvbmZpZ0xpc3QSQAoIbWV0YWRhdGEYASABKAsyLi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuTGlzdE1ldGESQgoFaXRlbXMYAiADKAsyMy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvamVjdENvbmZpZyK8AQoRUHJvamVjdENvbmZpZ1NwZWMSUAoRcHJvbW90aW9uUG9saWNpZXMYASADKAsyNS5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvbW90aW9uUG9saWN5ElUKEHdlYmhvb2tSZWNlaXZlcnMYAiADKAsyOy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuV2ViaG9va1JlY2VpdmVyQ29uZmlnIuoBChNQcm9qZWN0Q29uZmlnU3RhdHVzEkMKCmNvbmRpdGlvbnMYASADKAsyLy5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuQ29uZGl0aW9uEhoKEm9ic2VydmVkR2VuZXJhdGlvbhgDIAEoAxIaChJsYXN0SGFuZGxlZFJlZnJlc2gYBCABKAkSVgoQd2ViaG9va1JlY2VpdmVycxgCIAMoCzI8LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5XZWJob29rUmVjZWl2ZXJEZXRhaWxzIo0BCgtQcm9qZWN0TGlzdBJACghtZXRhZGF0YRgBIAEoCzIuLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5MaXN0TWV0YRI8CgVpdGVtcxgCIAMoCzItLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5Qcm9qZWN0IpoBCgxQcm9qZWN0U3RhdHMSSAoKd2FyZWhvdXNlcxgBIAEoCzI0LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5XYXJlaG91c2VTdGF0cxJACgZzdGFnZXMYAiABKAsyMC5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuU3RhZ2VTdGF0cyKXAQoNUHJvamVjdFN0YXR1cxJDCgpjb25kaXRpb25zGAMgAygLMi8uazhzLmlvLmFwaW1hY2hpbmVyeS5wa2cuYXBpcy5tZXRhLnYxLkNvbmRpdGlvbhJBCgVzdGF0cxgEIAEoCzIyLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5Qcm9qZWN0U3RhdHMi2QEKCVByb21vdGlvbhJCCghtZXRhZGF0YRgBIAEoCzIwLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5PYmplY3RNZXRhEkEKBHNwZWMYAiABKAsyMy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvbW90aW9uU3BlYxJFCgZzdGF0dXMYAyABKAsyNS5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvbW90aW9uU3RhdHVzIpEBCg1Qcm9tb3Rpb25MaXN0EkAKCG1ldGFkYXRhGAEgASgLMi4uazhzLmlvLmFwaW1hY2hpbmVyeS5wa2cuYXBpcy5tZXRhLnYxLkxpc3RNZXRhEj4KBWl0ZW1zGAIgAygLMi8uZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlByb21vdGlvbiKUAQoPUHJvbW90aW9uUG9saWN5Eg0KBXN0YWdlGAEgASgJElQKDXN0YWdlU2VsZWN0b3IYAyABKAsyPS5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvbW90aW9uUG9saWN5U2VsZWN0b3ISHAoUYXV0b1Byb21vdGlvbkVuYWJsZWQYAiABKAgicwoXUHJvbW90aW9uUG9saWN5U2VsZWN0b3ISDAoEbmFtZRgBIAEoCRJKCg1sYWJlbFNlbGVjdG9yGAIgASgLMjMuazhzLmlvLmFwaW1hY2hpbmVyeS5wa2cuYXBpcy5tZXRhLnYxLkxhYmVsU2VsZWN0b3Ii8gEKElByb21vdGlvblJlZmVyZW5jZRIMCgRuYW1lGAEgASgJEkcKB2ZyZWlnaHQYAiABKAsyNi5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuRnJlaWdodFJlZmVyZW5jZRJFCgZzdGF0dXMYAyABKAsyNS5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvbW90aW9uU3RhdHVzEj4KCmZpbmlzaGVkQXQYBCABKAsyKi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuVGltZSK7AQoNUHJvbW90aW9uU3BlYxINCgVzdGFnZRgBIAEoCRIPCgdmcmVpZ2h0GAIgASgJEkYKBHZhcnMYBCADKAsyOC5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuRXhwcmVzc2lvblZhcmlhYmxlEkIKBXN0ZXBzGAMgAygLMjMuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlByb21vdGlvblN0ZXAi9gQKD1Byb21vdGlvblN0YXR1cxIaChJsYXN0SGFuZGxlZFJlZnJlc2gYBCABKAkSDQoFcGhhc2UYASABKAkSDwoHbWVzc2FnZRgCIAEoCRJHCgdmcmVpZ2h0GAUgASgLMjYuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkZyZWlnaHRSZWZlcmVuY2USUgoRZnJlaWdodENvbGxlY3Rpb24YByABKAsyNy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuRnJlaWdodENvbGxlY3Rpb24SSwoMaGVhbHRoQ2hlY2tzGAggAygLMjUuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkhlYWx0aENoZWNrU3RlcBI9CglzdGFydGVkQXQYDCABKAsyKi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuVGltZRI+CgpmaW5pc2hlZEF0GAYgASgLMiouazhzLmlvLmFwaW1hY2hpbmVyeS5wa2cuYXBpcy5tZXRhLnYxLlRpbWUSEwoLY3VycmVudFN0ZXAYCSABKAMSWgoVc3RlcEV4ZWN1dGlvbk1ldGFkYXRhGAsgAygLMjsuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlN0ZXBFeGVjdXRpb25NZXRhZGF0YRJNCgVzdGF0ZRgKIAEoCzI+Lms4cy5pby5hcGlleHRlbnNpb25zX2FwaXNlcnZlci5wa2cuYXBpcy5hcGlleHRlbnNpb25zLnYxLkpTT04i+wIKDVByb21vdGlvblN0ZXASDAoEdXNlcxgBIAEoCRJKCgR0YXNrGAUgASgLMjwuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlByb21vdGlvblRhc2tSZWZlcmVuY2USCgoCYXMYAiABKAkSCgoCaWYYByABKAkSFwoPY29udGludWVPbkVycm9yGAggASgIEkcKBXJldHJ5GAQgASgLMjguZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlByb21vdGlvblN0ZXBSZXRyeRJGCgR2YXJzGAYgAygLMjguZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkV4cHJlc3Npb25WYXJpYWJsZRJOCgZjb25maWcYAyABKAsyPi5rOHMuaW8uYXBpZXh0ZW5zaW9uc19hcGlzZXJ2ZXIucGtnLmFwaXMuYXBpZXh0ZW5zaW9ucy52MS5KU09OIm0KElByb21vdGlvblN0ZXBSZXRyeRI/Cgd0aW1lb3V0GAEgASgLMi4uazhzLmlvLmFwaW1hY2hpbmVyeS5wa2cuYXBpcy5tZXRhLnYxLkR1cmF0aW9uEhYKDmVycm9yVGhyZXNob2xkGAIgASgNIpoBCg1Qcm9tb3Rpb25UYXNrEkIKCG1ldGFkYXRhGAEgASgLMjAuazhzLmlvLmFwaW1hY2hpbmVyeS5wa2cuYXBpcy5tZXRhLnYxLk9iamVjdE1ldGESRQoEc3BlYxgCIAEoCzI3LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5Qcm9tb3Rpb25UYXNrU3BlYyKZAQoRUHJvbW90aW9uVGFza0xpc3QSQAoIbWV0YWRhdGEYASABKAsyLi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuTGlzdE1ldGESQgoFaXRlbXMYAiADKAsyMy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvbW90aW9uVGFzayI0ChZQcm9tb3Rpb25UYXNrUmVmZXJlbmNlEgwKBG5hbWUYASABKAkSDAoEa2luZBgCIAEoCSKfAQoRUHJvbW90aW9uVGFza1NwZWMSRgoEdmFycxgBIAMoCzI4LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5FeHByZXNzaW9uVmFyaWFibGUSQgoFc3RlcHMYAiADKAsyMy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvbW90aW9uU3RlcCJeChFQcm9tb3Rpb25UZW1wbGF0ZRJJCgRzcGVjGAEgASgLMjsuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlByb21vdGlvblRlbXBsYXRlU3BlYyKjAQoVUHJvbW90aW9uVGVtcGxhdGVTcGVjEkYKBHZhcnMYAiADKAsyOC5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuRXhwcmVzc2lvblZhcmlhYmxlEkIKBXN0ZXBzGAEgAygLMjMuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlByb21vdGlvblN0ZXAiWAoZUXVheVdlYmhvb2tSZWNlaXZlckNvbmZpZxI7CglzZWNyZXRSZWYYASABKAsyKC5rOHMuaW8uYXBpLmNvcmUudjEuTG9jYWxPYmplY3RSZWZlcmVuY2Ui5gEKEFJlcG9TdWJzY3JpcHRpb24SQgoDZ2l0GAEgASgLMjUuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkdpdFN1YnNjcmlwdGlvbhJGCgVpbWFnZRgCIAEoCzI3LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5JbWFnZVN1YnNjcmlwdGlvbhJGCgVjaGFydBgDIAEoCzI3LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5DaGFydFN1YnNjcmlwdGlvbiLNAQoFU3RhZ2USQgoIbWV0YWRhdGEYASABKAsyMC5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuT2JqZWN0TWV0YRI9CgRzcGVjGAIgASgLMi8uZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlN0YWdlU3BlYxJBCgZzdGF0dXMYAyABKAsyMS5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuU3RhZ2VTdGF0dXMiiQEKCVN0YWdlTGlzdBJACghtZXRhZGF0YRgBIAEoCzIuLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5MaXN0TWV0YRI6CgVpdGVtcxgCIAMoCzIrLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5TdGFnZSLQAgoJU3RhZ2VTcGVjEg0KBXNoYXJkGAQgASgJEkYKBHZhcnMYByADKAsyOC5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuRXhwcmVzc2lvblZhcmlhYmxlEk4KEHJlcXVlc3RlZEZyZWlnaHQYBSADKAsyNC5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuRnJlaWdodFJlcXVlc3QSUgoRcHJvbW90aW9uVGVtcGxhdGUYBiABKAsyNy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvbW90aW9uVGVtcGxhdGUSSAoMdmVyaWZpY2F0aW9uGAMgASgLMjIuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlZlcmlmaWNhdGlvbiJeCgpTdGFnZVN0YXRzEg0KBWNvdW50GAIgASgDEkEKBmhlYWx0aBgBIAEoCzIxLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5IZWFsdGhTdGF0cyK4BQoLU3RhZ2VTdGF0dXMSQwoKY29uZGl0aW9ucxgNIAMoCzIvLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5Db25kaXRpb24SGgoSbGFzdEhhbmRsZWRSZWZyZXNoGAsgASgJEk8KDmZyZWlnaHRIaXN0b3J5GAQgAygLMjcuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkZyZWlnaHRDb2xsZWN0aW9uEhYKDmZyZWlnaHRTdW1tYXJ5GAwgASgJEjwKBmhlYWx0aBgIIAEoCzIsLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5IZWFsdGgSGgoSb2JzZXJ2ZWRHZW5lcmF0aW9uGAYgASgDElIKEGN1cnJlbnRQcm9tb3Rpb24YByABKAsyOC5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvbW90aW9uUmVmZXJlbmNlEk8KDWxhc3RQcm9tb3Rpb24YCiABKAsyOC5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvbW90aW9uUmVmZXJlbmNlEhwKFGF1dG9Qcm9tb3Rpb25FbmFibGVkGA4gASgIElEKCG1ldGFkYXRhGA8gAygLMj8uZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlN0YWdlU3RhdHVzLk1ldGFkYXRhRW50cnkabwoNTWV0YWRhdGFFbnRyeRILCgNrZXkYASABKAkSTQoFdmFsdWUYAiABKAsyPi5rOHMuaW8uYXBpZXh0ZW5zaW9uc19hcGlzZXJ2ZXIucGtnLmFwaXMuYXBpZXh0ZW5zaW9ucy52MS5KU09OOgI4ASLzAQoVU3RlcEV4ZWN1dGlvbk1ldGFkYXRhEg0KBWFsaWFzGAEgASgJEj0KCXN0YXJ0ZWRBdBgCIAEoCzIqLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5UaW1lEj4KCmZpbmlzaGVkQXQYAyABKAsyKi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuVGltZRISCgplcnJvckNvdW50GAQgASgNEg4KBnN0YXR1cxgFIAEoCRIPCgdtZXNzYWdlGAYgASgJEhcKD2NvbnRpbnVlT25FcnJvchgHIAEoCCKLAgoMVmVyaWZpY2F0aW9uEloKEWFuYWx5c2lzVGVtcGxhdGVzGAEgAygLMj8uZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkFuYWx5c2lzVGVtcGxhdGVSZWZlcmVuY2USVgoTYW5hbHlzaXNSdW5NZXRhZGF0YRgCIAEoCzI5LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5BbmFseXNpc1J1bk1ldGFkYXRhEkcKBGFyZ3MYAyADKAsyOS5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuQW5hbHlzaXNSdW5Bcmd1bWVudCKdAgoQVmVyaWZpY2F0aW9uSW5mbxIKCgJpZBgEIAEoCRINCgVhY3RvchgHIAEoCRI9CglzdGFydFRpbWUYBSABKAsyKi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuVGltZRINCgVwaGFzZRgBIAEoCRIPCgdtZXNzYWdlGAIgASgJEk8KC2FuYWx5c2lzUnVuGAMgASgLMjouZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkFuYWx5c2lzUnVuUmVmZXJlbmNlEj4KCmZpbmlzaFRpbWUYBiABKAsyKi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuVGltZSKUAQoNVmVyaWZpZWRTdGFnZRI+Cgp2ZXJpZmllZEF0GAEgASgLMiouazhzLmlvLmFwaW1hY2hpbmVyeS5wa2cuYXBpcy5tZXRhLnYxLlRpbWUSQwoLbG9uZ2VzdFNvYWsYAiABKAsyLi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuRHVyYXRpb24i2QEKCVdhcmVob3VzZRJCCghtZXRhZGF0YRgBIAEoCzIwLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5PYmplY3RNZXRhEkEKBHNwZWMYAiABKAsyMy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuV2FyZWhvdXNlU3BlYxJFCgZzdGF0dXMYAyABKAsyNS5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuV2FyZWhvdXNlU3RhdHVzIpEBCg1XYXJlaG91c2VMaXN0EkAKCG1ldGFkYXRhGAEgASgLMi4uazhzLmlvLmFwaW1hY2hpbmVyeS5wa2cuYXBpcy5tZXRhLnYxLkxpc3RNZXRhEj4KBWl0ZW1zGAIgAygLMi8uZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLldhcmVob3VzZSKuAgoNV2FyZWhvdXNlU3BlYxINCgVzaGFyZBgCIAEoCRJACghpbnRlcnZhbBgEIAEoCzIuLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5EdXJhdGlvbhIdChVmcmVpZ2h0Q3JlYXRpb25Qb2xpY3kYAyABKAkSTQoNc3Vic2NyaXB0aW9ucxgBIAMoCzI2LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5SZXBvU3Vic2NyaXB0aW9uEl4KF2ZyZWlnaHRDcmVhdGlvbkNyaXRlcmlhGAUgASgLMj0uZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkZyZWlnaHRDcmVhdGlvbkNyaXRlcmlhImIKDldhcmVob3VzZVN0YXRzEg0KBWNvdW50GAIgASgDEkEKBmhlYWx0aBgBIAEoCzIxLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5IZWFsdGhTdGF0cyL9AQoPV2FyZWhvdXNlU3RhdHVzEkMKCmNvbmRpdGlvbnMYCSADKAsyLy5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuQ29uZGl0aW9uEhoKEmxhc3RIYW5kbGVkUmVmcmVzaBgGIAEoCRIaChJvYnNlcnZlZEdlbmVyYXRpb24YBCABKAMSFQoNbGFzdEZyZWlnaHRJRBgIIAEoCRJWChNkaXNjb3ZlcmVkQXJ0aWZhY3RzGAcgASgLMjkuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkRpc2NvdmVyZWRBcnRpZmFjdHMingYKFVdlYmhvb2tSZWNlaXZlckNvbmZpZxIMCgRuYW1lGAEgASgJElcKCWJpdGJ1Y2tldBgFIAEoCzJELmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5CaXRidWNrZXRXZWJob29rUmVjZWl2ZXJDb25maWcSVwoJZG9ja2VyaHViGAYgASgLMkQuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkRvY2tlckh1YldlYmhvb2tSZWNlaXZlckNvbmZpZxJRCgZnaXRodWIYAiABKAsyQS5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuR2l0SHViV2ViaG9va1JlY2VpdmVyQ29uZmlnElEKBmdpdGxhYhgDIAEoCzJBLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5HaXRMYWJXZWJob29rUmVjZWl2ZXJDb25maWcSUQoGaGFyYm9yGAogASgLMkEuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkhhcmJvcldlYmhvb2tSZWNlaXZlckNvbmZpZxJNCgRxdWF5GAQgASgLMj8uZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlF1YXlXZWJob29rUmVjZWl2ZXJDb25maWcSWwoLYXJ0aWZhY3RvcnkYCSABKAsyRi5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuQXJ0aWZhY3RvcnlXZWJob29rUmVjZWl2ZXJDb25maWcSTwoFYXp1cmUYCCABKAsyQC5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuQXp1cmVXZWJob29rUmVjZWl2ZXJDb25maWcSTwoFZ2l0ZWEYByABKAsyQC5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuR2l0ZWFXZWJob29rUmVjZWl2ZXJDb25maWciQQoWV2ViaG9va1JlY2VpdmVyRGV0YWlscxIMCgRuYW1lGAEgASgJEgwKBHBhdGgYAyABKAkSCwoDdXJsGAQgASgJQpcCCihjb20uZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExQg5HZW5lcmF0ZWRQcm90b1ABWiRnaXRodWIuY29tL2FrdWl0eS9rYXJnby9hcGkvdjFhbHBoYTGiAgVHQ0FLQaoCJEdpdGh1Yi5Db20uQWt1aXR5LkthcmdvLkFwaS5WMWFscGhhMcoCJEdpdGh1YlxDb21cQWt1aXR5XEthcmdvXEFwaVxWMWFscGhhMeICMEdpdGh1YlxDb21cQWt1aXR5XEthcmdvXEFwaVxWMWFscGhhMVxHUEJNZXRhZGF0YeoCKUdpdGh1Yjo6Q29tOjpBa3VpdHk6OkthcmdvOjpBcGk6OlYxYWxwaGEx", [file_k8s_io_api_core_v1_generated, file_k8s_io_apiextensions_apiserver_pkg_apis_apiextensions_v1_generated, file_k8s_io_apimachinery_pkg_apis_meta_v1_generated, file_k8s_io_apimachinery_pkg_runtime_generated, file_k8s_io_apimachinery_pkg_runtime_schema_generated]); + fileDesc("ChxhcGkvdjFhbHBoYTEvZ2VuZXJhdGVkLnByb3RvEiRnaXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEiMgoTQW5hbHlzaXNSdW5Bcmd1bWVudBIMCgRuYW1lGAEgASgJEg0KBXZhbHVlGAIgASgJIrACChNBbmFseXNpc1J1bk1ldGFkYXRhElUKBmxhYmVscxgBIAMoCzJFLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5BbmFseXNpc1J1bk1ldGFkYXRhLkxhYmVsc0VudHJ5El8KC2Fubm90YXRpb25zGAIgAygLMkouZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkFuYWx5c2lzUnVuTWV0YWRhdGEuQW5ub3RhdGlvbnNFbnRyeRotCgtMYWJlbHNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBGjIKEEFubm90YXRpb25zRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJOgI4ASJGChRBbmFseXNpc1J1blJlZmVyZW5jZRIRCgluYW1lc3BhY2UYASABKAkSDAoEbmFtZRgCIAEoCRINCgVwaGFzZRgDIAEoCSI3ChlBbmFseXNpc1RlbXBsYXRlUmVmZXJlbmNlEgwKBG5hbWUYASABKAkSDAoEa2luZBgCIAEoCSJPCg1BcHByb3ZlZFN0YWdlEj4KCmFwcHJvdmVkQXQYASABKAsyKi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuVGltZSI4ChVBcmdvQ0RBcHBIZWFsdGhTdGF0dXMSDgoGc3RhdHVzGAEgASgJEg8KB21lc3NhZ2UYAiABKAki1AEKD0FyZ29DREFwcFN0YXR1cxIRCgluYW1lc3BhY2UYASABKAkSDAoEbmFtZRgCIAEoCRJRCgxoZWFsdGhTdGF0dXMYAyABKAsyOy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuQXJnb0NEQXBwSGVhbHRoU3RhdHVzEk0KCnN5bmNTdGF0dXMYBCABKAsyOS5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuQXJnb0NEQXBwU3luY1N0YXR1cyJKChNBcmdvQ0RBcHBTeW5jU3RhdHVzEg4KBnN0YXR1cxgBIAEoCRIQCghyZXZpc2lvbhgCIAEoCRIRCglyZXZpc2lvbnMYAyADKAkieAogQXJ0aWZhY3RvcnlXZWJob29rUmVjZWl2ZXJDb25maWcSOwoJc2VjcmV0UmVmGAEgASgLMiguazhzLmlvLmFwaS5jb3JlLnYxLkxvY2FsT2JqZWN0UmVmZXJlbmNlEhcKD3ZpcnR1YWxSZXBvTmFtZRgCIAEoCSIvChRBdXRvUHJvbW90aW9uT3B0aW9ucxIXCg9zZWxlY3Rpb25Qb2xpY3kYASABKAkiWQoaQXp1cmVXZWJob29rUmVjZWl2ZXJDb25maWcSOwoJc2VjcmV0UmVmGAEgASgLMiguazhzLmlvLmFwaS5jb3JlLnYxLkxvY2FsT2JqZWN0UmVmZXJlbmNlIl0KHkJpdGJ1Y2tldFdlYmhvb2tSZWNlaXZlckNvbmZpZxI7CglzZWNyZXRSZWYYASABKAsyKC5rOHMuaW8uYXBpLmNvcmUudjEuTG9jYWxPYmplY3RSZWZlcmVuY2UiNwoFQ2hhcnQSDwoHcmVwb1VSTBgBIAEoCRIMCgRuYW1lGAIgASgJEg8KB3ZlcnNpb24YAyABKAkiYQoUQ2hhcnREaXNjb3ZlcnlSZXN1bHQSDwoHcmVwb1VSTBgBIAEoCRIMCgRuYW1lGAIgASgJEhgKEHNlbXZlckNvbnN0cmFpbnQYAyABKAkSEAoIdmVyc2lvbnMYBCADKAkiZAoRQ2hhcnRTdWJzY3JpcHRpb24SDwoHcmVwb1VSTBgBIAEoCRIMCgRuYW1lGAIgASgJEhgKEHNlbXZlckNvbnN0cmFpbnQYAyABKAkSFgoOZGlzY292ZXJ5TGltaXQYBCABKAUi5QEKDUNsdXN0ZXJDb25maWcSQgoIbWV0YWRhdGEYASABKAsyMC5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuT2JqZWN0TWV0YRJFCgRzcGVjGAIgASgLMjcuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkNsdXN0ZXJDb25maWdTcGVjEkkKBnN0YXR1cxgDIAEoCzI5LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5DbHVzdGVyQ29uZmlnU3RhdHVzIpkBChFDbHVzdGVyQ29uZmlnTGlzdBJACghtZXRhZGF0YRgBIAEoCzIuLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5MaXN0TWV0YRJCCgVpdGVtcxgCIAMoCzIzLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5DbHVzdGVyQ29uZmlnImoKEUNsdXN0ZXJDb25maWdTcGVjElUKEHdlYmhvb2tSZWNlaXZlcnMYASADKAsyOy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuV2ViaG9va1JlY2VpdmVyQ29uZmlnIuoBChNDbHVzdGVyQ29uZmlnU3RhdHVzEkMKCmNvbmRpdGlvbnMYASADKAsyLy5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuQ29uZGl0aW9uEhoKEm9ic2VydmVkR2VuZXJhdGlvbhgDIAEoAxIaChJsYXN0SGFuZGxlZFJlZnJlc2gYBCABKAkSVgoQd2ViaG9va1JlY2VpdmVycxgCIAMoCzI8LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5XZWJob29rUmVjZWl2ZXJEZXRhaWxzIqEBChRDbHVzdGVyUHJvbW90aW9uVGFzaxJCCghtZXRhZGF0YRgBIAEoCzIwLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5PYmplY3RNZXRhEkUKBHNwZWMYAiABKAsyNy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvbW90aW9uVGFza1NwZWMipwEKGENsdXN0ZXJQcm9tb3Rpb25UYXNrTGlzdBJACghtZXRhZGF0YRgBIAEoCzIuLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5MaXN0TWV0YRJJCgVpdGVtcxgCIAMoCzI6LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5DbHVzdGVyUHJvbW90aW9uVGFzayJJCgxDdXJyZW50U3RhZ2USOQoFc2luY2UYASABKAsyKi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuVGltZSK2AgoTRGlzY292ZXJlZEFydGlmYWN0cxJACgxkaXNjb3ZlcmVkQXQYBCABKAsyKi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuVGltZRJFCgNnaXQYASADKAsyOC5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuR2l0RGlzY292ZXJ5UmVzdWx0EkoKBmltYWdlcxgCIAMoCzI6LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5JbWFnZURpc2NvdmVyeVJlc3VsdBJKCgZjaGFydHMYAyADKAsyOi5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuQ2hhcnREaXNjb3ZlcnlSZXN1bHQisAEKEERpc2NvdmVyZWRDb21taXQSCgoCaWQYASABKAkSDgoGYnJhbmNoGAIgASgJEgsKA3RhZxgDIAEoCRIPCgdzdWJqZWN0GAQgASgJEg4KBmF1dGhvchgFIAEoCRIRCgljb21taXR0ZXIYBiABKAkSPwoLY3JlYXRvckRhdGUYByABKAsyKi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuVGltZSKQAgoYRGlzY292ZXJlZEltYWdlUmVmZXJlbmNlEgsKA3RhZxgBIAEoCRIOCgZkaWdlc3QYAiABKAkSZAoLYW5ub3RhdGlvbnMYBSADKAsyTy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuRGlzY292ZXJlZEltYWdlUmVmZXJlbmNlLkFubm90YXRpb25zRW50cnkSPQoJY3JlYXRlZEF0GAQgASgLMiouazhzLmlvLmFwaW1hY2hpbmVyeS5wa2cuYXBpcy5tZXRhLnYxLlRpbWUaMgoQQW5ub3RhdGlvbnNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBIl0KHkRvY2tlckh1YldlYmhvb2tSZWNlaXZlckNvbmZpZxI7CglzZWNyZXRSZWYYASABKAsyKC5rOHMuaW8uYXBpLmNvcmUudjEuTG9jYWxPYmplY3RSZWZlcmVuY2UiMQoSRXhwcmVzc2lvblZhcmlhYmxlEgwKBG5hbWUYASABKAkSDQoFdmFsdWUYAiABKAkiogMKB0ZyZWlnaHQSQgoIbWV0YWRhdGEYASABKAsyMC5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuT2JqZWN0TWV0YRINCgVhbGlhcxgHIAEoCRJDCgZvcmlnaW4YCSABKAsyMy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuRnJlaWdodE9yaWdpbhJACgdjb21taXRzGAMgAygLMi8uZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkdpdENvbW1pdBI7CgZpbWFnZXMYBCADKAsyKy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuSW1hZ2USOwoGY2hhcnRzGAUgAygLMisuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkNoYXJ0EkMKBnN0YXR1cxgGIAEoCzIzLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5GcmVpZ2h0U3RhdHVzIq0CChFGcmVpZ2h0Q29sbGVjdGlvbhIKCgJpZBgDIAEoCRJRCgVpdGVtcxgBIAMoCzJCLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5GcmVpZ2h0Q29sbGVjdGlvbi5JdGVtc0VudHJ5ElMKE3ZlcmlmaWNhdGlvbkhpc3RvcnkYAiADKAsyNi5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuVmVyaWZpY2F0aW9uSW5mbxpkCgpJdGVtc0VudHJ5EgsKA2tleRgBIAEoCRJFCgV2YWx1ZRgCIAEoCzI2LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5GcmVpZ2h0UmVmZXJlbmNlOgI4ASItChdGcmVpZ2h0Q3JlYXRpb25Dcml0ZXJpYRISCgpleHByZXNzaW9uGAEgASgJIo0BCgtGcmVpZ2h0TGlzdBJACghtZXRhZGF0YRgBIAEoCzIuLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5MaXN0TWV0YRI8CgVpdGVtcxgCIAMoCzItLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5GcmVpZ2h0IisKDUZyZWlnaHRPcmlnaW4SDAoEa2luZBgBIAEoCRIMCgRuYW1lGAIgASgJIqECChBGcmVpZ2h0UmVmZXJlbmNlEgwKBG5hbWUYASABKAkSQwoGb3JpZ2luGAggASgLMjMuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkZyZWlnaHRPcmlnaW4SQAoHY29tbWl0cxgCIAMoCzIvLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5HaXRDb21taXQSOwoGaW1hZ2VzGAMgAygLMisuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkltYWdlEjsKBmNoYXJ0cxgEIAMoCzIrLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5DaGFydCKcAQoORnJlaWdodFJlcXVlc3QSQwoGb3JpZ2luGAEgASgLMjMuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkZyZWlnaHRPcmlnaW4SRQoHc291cmNlcxgCIAEoCzI0LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5GcmVpZ2h0U291cmNlcyLyAQoORnJlaWdodFNvdXJjZXMSDgoGZGlyZWN0GAEgASgIEg4KBnN0YWdlcxgCIAMoCRJIChByZXF1aXJlZFNvYWtUaW1lGAMgASgLMi4uazhzLmlvLmFwaW1hY2hpbmVyeS5wa2cuYXBpcy5tZXRhLnYxLkR1cmF0aW9uEhwKFGF2YWlsYWJpbGl0eVN0cmF0ZWd5GAQgASgJElgKFGF1dG9Qcm9tb3Rpb25PcHRpb25zGAUgASgLMjouZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkF1dG9Qcm9tb3Rpb25PcHRpb25zIp0GCg1GcmVpZ2h0U3RhdHVzElkKC2N1cnJlbnRseUluGAMgAygLMkQuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkZyZWlnaHRTdGF0dXMuQ3VycmVudGx5SW5FbnRyeRJXCgp2ZXJpZmllZEluGAEgAygLMkMuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkZyZWlnaHRTdGF0dXMuVmVyaWZpZWRJbkVudHJ5ElkKC2FwcHJvdmVkRm9yGAIgAygLMkQuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkZyZWlnaHRTdGF0dXMuQXBwcm92ZWRGb3JFbnRyeRJTCghtZXRhZGF0YRgEIAMoCzJBLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5GcmVpZ2h0U3RhdHVzLk1ldGFkYXRhRW50cnkaZgoQQ3VycmVudGx5SW5FbnRyeRILCgNrZXkYASABKAkSQQoFdmFsdWUYAiABKAsyMi5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuQ3VycmVudFN0YWdlOgI4ARpmCg9WZXJpZmllZEluRW50cnkSCwoDa2V5GAEgASgJEkIKBXZhbHVlGAIgASgLMjMuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlZlcmlmaWVkU3RhZ2U6AjgBGmcKEEFwcHJvdmVkRm9yRW50cnkSCwoDa2V5GAEgASgJEkIKBXZhbHVlGAIgASgLMjMuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkFwcHJvdmVkU3RhZ2U6AjgBGm8KDU1ldGFkYXRhRW50cnkSCwoDa2V5GAEgASgJEk0KBXZhbHVlGAIgASgLMj4uazhzLmlvLmFwaWV4dGVuc2lvbnNfYXBpc2VydmVyLnBrZy5hcGlzLmFwaWV4dGVuc2lvbnMudjEuSlNPTjoCOAEinwIKFEdlbmVyaWNXZWJob29rQWN0aW9uEg4KBmFjdGlvbhgBIAEoCRIXCg9tYXRjaEV4cHJlc3Npb24YAiABKAkSXgoKcGFyYW1ldGVycxgDIAMoCzJKLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5HZW5lcmljV2ViaG9va0FjdGlvbi5QYXJhbWV0ZXJzRW50cnkSSwoHdGFyZ2V0cxgEIAMoCzI6LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5HZW5lcmljV2ViaG9va1RhcmdldBoxCg9QYXJhbWV0ZXJzRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJOgI4ASKoAQocR2VuZXJpY1dlYmhvb2tSZWNlaXZlckNvbmZpZxI7CglzZWNyZXRSZWYYASABKAsyKC5rOHMuaW8uYXBpLmNvcmUudjEuTG9jYWxPYmplY3RSZWZlcmVuY2USSwoHYWN0aW9ucxgCIAMoCzI6LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5HZW5lcmljV2ViaG9va0FjdGlvbiLKAQoUR2VuZXJpY1dlYmhvb2tUYXJnZXQSDAoEa2luZBgBIAEoCRIMCgRuYW1lGAIgASgJEkoKDWxhYmVsU2VsZWN0b3IYAyABKAsyMy5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuTGFiZWxTZWxlY3RvchJKCg1pbmRleFNlbGVjdG9yGAQgASgLMjMuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkluZGV4U2VsZWN0b3IieQoJR2l0Q29tbWl0Eg8KB3JlcG9VUkwYASABKAkSCgoCaWQYAiABKAkSDgoGYnJhbmNoGAMgASgJEgsKA3RhZxgEIAEoCRIPCgdtZXNzYWdlGAYgASgJEg4KBmF1dGhvchgHIAEoCRIRCgljb21taXR0ZXIYCCABKAkibgoSR2l0RGlzY292ZXJ5UmVzdWx0Eg8KB3JlcG9VUkwYASABKAkSRwoHY29tbWl0cxgCIAMoCzI2LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5EaXNjb3ZlcmVkQ29tbWl0IloKG0dpdEh1YldlYmhvb2tSZWNlaXZlckNvbmZpZxI7CglzZWNyZXRSZWYYASABKAsyKC5rOHMuaW8uYXBpLmNvcmUudjEuTG9jYWxPYmplY3RSZWZlcmVuY2UiWgobR2l0TGFiV2ViaG9va1JlY2VpdmVyQ29uZmlnEjsKCXNlY3JldFJlZhgBIAEoCzIoLms4cy5pby5hcGkuY29yZS52MS5Mb2NhbE9iamVjdFJlZmVyZW5jZSLdAgoPR2l0U3Vic2NyaXB0aW9uEg8KB3JlcG9VUkwYASABKAkSHwoXY29tbWl0U2VsZWN0aW9uU3RyYXRlZ3kYAiABKAkSDgoGYnJhbmNoGAMgASgJEhUKDXN0cmljdFNlbXZlcnMYCyABKAgSGAoQc2VtdmVyQ29uc3RyYWludBgEIAEoCRIRCglhbGxvd1RhZ3MYBSABKAkSGAoQYWxsb3dUYWdzUmVnZXhlcxgNIAMoCRISCgppZ25vcmVUYWdzGAYgAygJEhkKEWlnbm9yZVRhZ3NSZWdleGVzGA4gAygJEhgKEGV4cHJlc3Npb25GaWx0ZXIYDCABKAkSHQoVaW5zZWN1cmVTa2lwVExTVmVyaWZ5GAcgASgIEhQKDGluY2x1ZGVQYXRocxgIIAMoCRIUCgxleGNsdWRlUGF0aHMYCSADKAkSFgoOZGlzY292ZXJ5TGltaXQYCiABKAUiWQoaR2l0ZWFXZWJob29rUmVjZWl2ZXJDb25maWcSOwoJc2VjcmV0UmVmGAEgASgLMiguazhzLmlvLmFwaS5jb3JlLnYxLkxvY2FsT2JqZWN0UmVmZXJlbmNlIloKG0hhcmJvcldlYmhvb2tSZWNlaXZlckNvbmZpZxI7CglzZWNyZXRSZWYYASABKAsyKC5rOHMuaW8uYXBpLmNvcmUudjEuTG9jYWxPYmplY3RSZWZlcmVuY2UiyAEKBkhlYWx0aBIOCgZzdGF0dXMYASABKAkSDgoGaXNzdWVzGAIgAygJEk4KBmNvbmZpZxgEIAEoCzI+Lms4cy5pby5hcGlleHRlbnNpb25zX2FwaXNlcnZlci5wa2cuYXBpcy5hcGlleHRlbnNpb25zLnYxLkpTT04STgoGb3V0cHV0GAUgASgLMj4uazhzLmlvLmFwaWV4dGVuc2lvbnNfYXBpc2VydmVyLnBrZy5hcGlzLmFwaWV4dGVuc2lvbnMudjEuSlNPTiJvCg9IZWFsdGhDaGVja1N0ZXASDAoEdXNlcxgBIAEoCRJOCgZjb25maWcYAiABKAsyPi5rOHMuaW8uYXBpZXh0ZW5zaW9uc19hcGlzZXJ2ZXIucGtnLmFwaXMuYXBpZXh0ZW5zaW9ucy52MS5KU09OIh4KC0hlYWx0aFN0YXRzEg8KB2hlYWx0aHkYASABKAMivAEKBUltYWdlEg8KB3JlcG9VUkwYASABKAkSCwoDdGFnGAMgASgJEg4KBmRpZ2VzdBgEIAEoCRJRCgthbm5vdGF0aW9ucxgFIAMoCzI8LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5JbWFnZS5Bbm5vdGF0aW9uc0VudHJ5GjIKEEFubm90YXRpb25zRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJOgI4ASKNAQoUSW1hZ2VEaXNjb3ZlcnlSZXN1bHQSDwoHcmVwb1VSTBgBIAEoCRIQCghwbGF0Zm9ybRgCIAEoCRJSCgpyZWZlcmVuY2VzGAMgAygLMj4uZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkRpc2NvdmVyZWRJbWFnZVJlZmVyZW5jZSKUAgoRSW1hZ2VTdWJzY3JpcHRpb24SDwoHcmVwb1VSTBgBIAEoCRIeChZpbWFnZVNlbGVjdGlvblN0cmF0ZWd5GAMgASgJEhUKDXN0cmljdFNlbXZlcnMYCiABKAgSEgoKY29uc3RyYWludBgLIAEoCRIRCglhbGxvd1RhZ3MYBSABKAkSGAoQYWxsb3dUYWdzUmVnZXhlcxgNIAMoCRISCgppZ25vcmVUYWdzGAYgAygJEhkKEWlnbm9yZVRhZ3NSZWdleGVzGA4gAygJEhAKCHBsYXRmb3JtGAcgASgJEh0KFWluc2VjdXJlU2tpcFRMU1ZlcmlmeRgIIAEoCBIWCg5kaXNjb3ZlcnlMaW1pdBgJIAEoBSJlCg1JbmRleFNlbGVjdG9yElQKDG1hdGNoSW5kaWNlcxgBIAMoCzI+LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5JbmRleFNlbGVjdG9yUmVxdWlyZW1lbnQiSAoYSW5kZXhTZWxlY3RvclJlcXVpcmVtZW50EgsKA2tleRgBIAEoCRIQCghvcGVyYXRvchgCIAEoCRINCgV2YWx1ZRgDIAEoCSKSAQoHUHJvamVjdBJCCghtZXRhZGF0YRgBIAEoCzIwLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5PYmplY3RNZXRhEkMKBnN0YXR1cxgDIAEoCzIzLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5Qcm9qZWN0U3RhdHVzIuUBCg1Qcm9qZWN0Q29uZmlnEkIKCG1ldGFkYXRhGAEgASgLMjAuazhzLmlvLmFwaW1hY2hpbmVyeS5wa2cuYXBpcy5tZXRhLnYxLk9iamVjdE1ldGESRQoEc3BlYxgCIAEoCzI3LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5Qcm9qZWN0Q29uZmlnU3BlYxJJCgZzdGF0dXMYAyABKAsyOS5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvamVjdENvbmZpZ1N0YXR1cyKZAQoRUHJvamVjdENvbmZpZ0xpc3QSQAoIbWV0YWRhdGEYASABKAsyLi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuTGlzdE1ldGESQgoFaXRlbXMYAiADKAsyMy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvamVjdENvbmZpZyK8AQoRUHJvamVjdENvbmZpZ1NwZWMSUAoRcHJvbW90aW9uUG9saWNpZXMYASADKAsyNS5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvbW90aW9uUG9saWN5ElUKEHdlYmhvb2tSZWNlaXZlcnMYAiADKAsyOy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuV2ViaG9va1JlY2VpdmVyQ29uZmlnIuoBChNQcm9qZWN0Q29uZmlnU3RhdHVzEkMKCmNvbmRpdGlvbnMYASADKAsyLy5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuQ29uZGl0aW9uEhoKEm9ic2VydmVkR2VuZXJhdGlvbhgDIAEoAxIaChJsYXN0SGFuZGxlZFJlZnJlc2gYBCABKAkSVgoQd2ViaG9va1JlY2VpdmVycxgCIAMoCzI8LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5XZWJob29rUmVjZWl2ZXJEZXRhaWxzIo0BCgtQcm9qZWN0TGlzdBJACghtZXRhZGF0YRgBIAEoCzIuLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5MaXN0TWV0YRI8CgVpdGVtcxgCIAMoCzItLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5Qcm9qZWN0IpoBCgxQcm9qZWN0U3RhdHMSSAoKd2FyZWhvdXNlcxgBIAEoCzI0LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5XYXJlaG91c2VTdGF0cxJACgZzdGFnZXMYAiABKAsyMC5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuU3RhZ2VTdGF0cyKXAQoNUHJvamVjdFN0YXR1cxJDCgpjb25kaXRpb25zGAMgAygLMi8uazhzLmlvLmFwaW1hY2hpbmVyeS5wa2cuYXBpcy5tZXRhLnYxLkNvbmRpdGlvbhJBCgVzdGF0cxgEIAEoCzIyLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5Qcm9qZWN0U3RhdHMi2QEKCVByb21vdGlvbhJCCghtZXRhZGF0YRgBIAEoCzIwLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5PYmplY3RNZXRhEkEKBHNwZWMYAiABKAsyMy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvbW90aW9uU3BlYxJFCgZzdGF0dXMYAyABKAsyNS5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvbW90aW9uU3RhdHVzIpEBCg1Qcm9tb3Rpb25MaXN0EkAKCG1ldGFkYXRhGAEgASgLMi4uazhzLmlvLmFwaW1hY2hpbmVyeS5wa2cuYXBpcy5tZXRhLnYxLkxpc3RNZXRhEj4KBWl0ZW1zGAIgAygLMi8uZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlByb21vdGlvbiKUAQoPUHJvbW90aW9uUG9saWN5Eg0KBXN0YWdlGAEgASgJElQKDXN0YWdlU2VsZWN0b3IYAyABKAsyPS5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvbW90aW9uUG9saWN5U2VsZWN0b3ISHAoUYXV0b1Byb21vdGlvbkVuYWJsZWQYAiABKAgicwoXUHJvbW90aW9uUG9saWN5U2VsZWN0b3ISDAoEbmFtZRgBIAEoCRJKCg1sYWJlbFNlbGVjdG9yGAIgASgLMjMuazhzLmlvLmFwaW1hY2hpbmVyeS5wa2cuYXBpcy5tZXRhLnYxLkxhYmVsU2VsZWN0b3Ii8gEKElByb21vdGlvblJlZmVyZW5jZRIMCgRuYW1lGAEgASgJEkcKB2ZyZWlnaHQYAiABKAsyNi5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuRnJlaWdodFJlZmVyZW5jZRJFCgZzdGF0dXMYAyABKAsyNS5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvbW90aW9uU3RhdHVzEj4KCmZpbmlzaGVkQXQYBCABKAsyKi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuVGltZSK7AQoNUHJvbW90aW9uU3BlYxINCgVzdGFnZRgBIAEoCRIPCgdmcmVpZ2h0GAIgASgJEkYKBHZhcnMYBCADKAsyOC5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuRXhwcmVzc2lvblZhcmlhYmxlEkIKBXN0ZXBzGAMgAygLMjMuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlByb21vdGlvblN0ZXAi9gQKD1Byb21vdGlvblN0YXR1cxIaChJsYXN0SGFuZGxlZFJlZnJlc2gYBCABKAkSDQoFcGhhc2UYASABKAkSDwoHbWVzc2FnZRgCIAEoCRJHCgdmcmVpZ2h0GAUgASgLMjYuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkZyZWlnaHRSZWZlcmVuY2USUgoRZnJlaWdodENvbGxlY3Rpb24YByABKAsyNy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuRnJlaWdodENvbGxlY3Rpb24SSwoMaGVhbHRoQ2hlY2tzGAggAygLMjUuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkhlYWx0aENoZWNrU3RlcBI9CglzdGFydGVkQXQYDCABKAsyKi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuVGltZRI+CgpmaW5pc2hlZEF0GAYgASgLMiouazhzLmlvLmFwaW1hY2hpbmVyeS5wa2cuYXBpcy5tZXRhLnYxLlRpbWUSEwoLY3VycmVudFN0ZXAYCSABKAMSWgoVc3RlcEV4ZWN1dGlvbk1ldGFkYXRhGAsgAygLMjsuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlN0ZXBFeGVjdXRpb25NZXRhZGF0YRJNCgVzdGF0ZRgKIAEoCzI+Lms4cy5pby5hcGlleHRlbnNpb25zX2FwaXNlcnZlci5wa2cuYXBpcy5hcGlleHRlbnNpb25zLnYxLkpTT04i+wIKDVByb21vdGlvblN0ZXASDAoEdXNlcxgBIAEoCRJKCgR0YXNrGAUgASgLMjwuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlByb21vdGlvblRhc2tSZWZlcmVuY2USCgoCYXMYAiABKAkSCgoCaWYYByABKAkSFwoPY29udGludWVPbkVycm9yGAggASgIEkcKBXJldHJ5GAQgASgLMjguZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlByb21vdGlvblN0ZXBSZXRyeRJGCgR2YXJzGAYgAygLMjguZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkV4cHJlc3Npb25WYXJpYWJsZRJOCgZjb25maWcYAyABKAsyPi5rOHMuaW8uYXBpZXh0ZW5zaW9uc19hcGlzZXJ2ZXIucGtnLmFwaXMuYXBpZXh0ZW5zaW9ucy52MS5KU09OIm0KElByb21vdGlvblN0ZXBSZXRyeRI/Cgd0aW1lb3V0GAEgASgLMi4uazhzLmlvLmFwaW1hY2hpbmVyeS5wa2cuYXBpcy5tZXRhLnYxLkR1cmF0aW9uEhYKDmVycm9yVGhyZXNob2xkGAIgASgNIpoBCg1Qcm9tb3Rpb25UYXNrEkIKCG1ldGFkYXRhGAEgASgLMjAuazhzLmlvLmFwaW1hY2hpbmVyeS5wa2cuYXBpcy5tZXRhLnYxLk9iamVjdE1ldGESRQoEc3BlYxgCIAEoCzI3LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5Qcm9tb3Rpb25UYXNrU3BlYyKZAQoRUHJvbW90aW9uVGFza0xpc3QSQAoIbWV0YWRhdGEYASABKAsyLi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuTGlzdE1ldGESQgoFaXRlbXMYAiADKAsyMy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvbW90aW9uVGFzayI0ChZQcm9tb3Rpb25UYXNrUmVmZXJlbmNlEgwKBG5hbWUYASABKAkSDAoEa2luZBgCIAEoCSKfAQoRUHJvbW90aW9uVGFza1NwZWMSRgoEdmFycxgBIAMoCzI4LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5FeHByZXNzaW9uVmFyaWFibGUSQgoFc3RlcHMYAiADKAsyMy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvbW90aW9uU3RlcCJeChFQcm9tb3Rpb25UZW1wbGF0ZRJJCgRzcGVjGAEgASgLMjsuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlByb21vdGlvblRlbXBsYXRlU3BlYyKjAQoVUHJvbW90aW9uVGVtcGxhdGVTcGVjEkYKBHZhcnMYAiADKAsyOC5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuRXhwcmVzc2lvblZhcmlhYmxlEkIKBXN0ZXBzGAEgAygLMjMuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlByb21vdGlvblN0ZXAiWAoZUXVheVdlYmhvb2tSZWNlaXZlckNvbmZpZxI7CglzZWNyZXRSZWYYASABKAsyKC5rOHMuaW8uYXBpLmNvcmUudjEuTG9jYWxPYmplY3RSZWZlcmVuY2Ui5gEKEFJlcG9TdWJzY3JpcHRpb24SQgoDZ2l0GAEgASgLMjUuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkdpdFN1YnNjcmlwdGlvbhJGCgVpbWFnZRgCIAEoCzI3LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5JbWFnZVN1YnNjcmlwdGlvbhJGCgVjaGFydBgDIAEoCzI3LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5DaGFydFN1YnNjcmlwdGlvbiLNAQoFU3RhZ2USQgoIbWV0YWRhdGEYASABKAsyMC5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuT2JqZWN0TWV0YRI9CgRzcGVjGAIgASgLMi8uZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlN0YWdlU3BlYxJBCgZzdGF0dXMYAyABKAsyMS5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuU3RhZ2VTdGF0dXMiiQEKCVN0YWdlTGlzdBJACghtZXRhZGF0YRgBIAEoCzIuLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5MaXN0TWV0YRI6CgVpdGVtcxgCIAMoCzIrLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5TdGFnZSLQAgoJU3RhZ2VTcGVjEg0KBXNoYXJkGAQgASgJEkYKBHZhcnMYByADKAsyOC5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuRXhwcmVzc2lvblZhcmlhYmxlEk4KEHJlcXVlc3RlZEZyZWlnaHQYBSADKAsyNC5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuRnJlaWdodFJlcXVlc3QSUgoRcHJvbW90aW9uVGVtcGxhdGUYBiABKAsyNy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvbW90aW9uVGVtcGxhdGUSSAoMdmVyaWZpY2F0aW9uGAMgASgLMjIuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlZlcmlmaWNhdGlvbiJeCgpTdGFnZVN0YXRzEg0KBWNvdW50GAIgASgDEkEKBmhlYWx0aBgBIAEoCzIxLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5IZWFsdGhTdGF0cyK4BQoLU3RhZ2VTdGF0dXMSQwoKY29uZGl0aW9ucxgNIAMoCzIvLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5Db25kaXRpb24SGgoSbGFzdEhhbmRsZWRSZWZyZXNoGAsgASgJEk8KDmZyZWlnaHRIaXN0b3J5GAQgAygLMjcuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkZyZWlnaHRDb2xsZWN0aW9uEhYKDmZyZWlnaHRTdW1tYXJ5GAwgASgJEjwKBmhlYWx0aBgIIAEoCzIsLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5IZWFsdGgSGgoSb2JzZXJ2ZWRHZW5lcmF0aW9uGAYgASgDElIKEGN1cnJlbnRQcm9tb3Rpb24YByABKAsyOC5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvbW90aW9uUmVmZXJlbmNlEk8KDWxhc3RQcm9tb3Rpb24YCiABKAsyOC5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuUHJvbW90aW9uUmVmZXJlbmNlEhwKFGF1dG9Qcm9tb3Rpb25FbmFibGVkGA4gASgIElEKCG1ldGFkYXRhGA8gAygLMj8uZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlN0YWdlU3RhdHVzLk1ldGFkYXRhRW50cnkabwoNTWV0YWRhdGFFbnRyeRILCgNrZXkYASABKAkSTQoFdmFsdWUYAiABKAsyPi5rOHMuaW8uYXBpZXh0ZW5zaW9uc19hcGlzZXJ2ZXIucGtnLmFwaXMuYXBpZXh0ZW5zaW9ucy52MS5KU09OOgI4ASLzAQoVU3RlcEV4ZWN1dGlvbk1ldGFkYXRhEg0KBWFsaWFzGAEgASgJEj0KCXN0YXJ0ZWRBdBgCIAEoCzIqLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5UaW1lEj4KCmZpbmlzaGVkQXQYAyABKAsyKi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuVGltZRISCgplcnJvckNvdW50GAQgASgNEg4KBnN0YXR1cxgFIAEoCRIPCgdtZXNzYWdlGAYgASgJEhcKD2NvbnRpbnVlT25FcnJvchgHIAEoCCKLAgoMVmVyaWZpY2F0aW9uEloKEWFuYWx5c2lzVGVtcGxhdGVzGAEgAygLMj8uZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkFuYWx5c2lzVGVtcGxhdGVSZWZlcmVuY2USVgoTYW5hbHlzaXNSdW5NZXRhZGF0YRgCIAEoCzI5LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5BbmFseXNpc1J1bk1ldGFkYXRhEkcKBGFyZ3MYAyADKAsyOS5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuQW5hbHlzaXNSdW5Bcmd1bWVudCKdAgoQVmVyaWZpY2F0aW9uSW5mbxIKCgJpZBgEIAEoCRINCgVhY3RvchgHIAEoCRI9CglzdGFydFRpbWUYBSABKAsyKi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuVGltZRINCgVwaGFzZRgBIAEoCRIPCgdtZXNzYWdlGAIgASgJEk8KC2FuYWx5c2lzUnVuGAMgASgLMjouZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkFuYWx5c2lzUnVuUmVmZXJlbmNlEj4KCmZpbmlzaFRpbWUYBiABKAsyKi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuVGltZSKUAQoNVmVyaWZpZWRTdGFnZRI+Cgp2ZXJpZmllZEF0GAEgASgLMiouazhzLmlvLmFwaW1hY2hpbmVyeS5wa2cuYXBpcy5tZXRhLnYxLlRpbWUSQwoLbG9uZ2VzdFNvYWsYAiABKAsyLi5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuRHVyYXRpb24i2QEKCVdhcmVob3VzZRJCCghtZXRhZGF0YRgBIAEoCzIwLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5PYmplY3RNZXRhEkEKBHNwZWMYAiABKAsyMy5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuV2FyZWhvdXNlU3BlYxJFCgZzdGF0dXMYAyABKAsyNS5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuV2FyZWhvdXNlU3RhdHVzIpEBCg1XYXJlaG91c2VMaXN0EkAKCG1ldGFkYXRhGAEgASgLMi4uazhzLmlvLmFwaW1hY2hpbmVyeS5wa2cuYXBpcy5tZXRhLnYxLkxpc3RNZXRhEj4KBWl0ZW1zGAIgAygLMi8uZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLldhcmVob3VzZSKuAgoNV2FyZWhvdXNlU3BlYxINCgVzaGFyZBgCIAEoCRJACghpbnRlcnZhbBgEIAEoCzIuLms4cy5pby5hcGltYWNoaW5lcnkucGtnLmFwaXMubWV0YS52MS5EdXJhdGlvbhIdChVmcmVpZ2h0Q3JlYXRpb25Qb2xpY3kYAyABKAkSTQoNc3Vic2NyaXB0aW9ucxgBIAMoCzI2LmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5SZXBvU3Vic2NyaXB0aW9uEl4KF2ZyZWlnaHRDcmVhdGlvbkNyaXRlcmlhGAUgASgLMj0uZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkZyZWlnaHRDcmVhdGlvbkNyaXRlcmlhImIKDldhcmVob3VzZVN0YXRzEg0KBWNvdW50GAIgASgDEkEKBmhlYWx0aBgBIAEoCzIxLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5IZWFsdGhTdGF0cyL9AQoPV2FyZWhvdXNlU3RhdHVzEkMKCmNvbmRpdGlvbnMYCSADKAsyLy5rOHMuaW8uYXBpbWFjaGluZXJ5LnBrZy5hcGlzLm1ldGEudjEuQ29uZGl0aW9uEhoKEmxhc3RIYW5kbGVkUmVmcmVzaBgGIAEoCRIaChJvYnNlcnZlZEdlbmVyYXRpb24YBCABKAMSFQoNbGFzdEZyZWlnaHRJRBgIIAEoCRJWChNkaXNjb3ZlcmVkQXJ0aWZhY3RzGAcgASgLMjkuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkRpc2NvdmVyZWRBcnRpZmFjdHMi8wYKFVdlYmhvb2tSZWNlaXZlckNvbmZpZxIMCgRuYW1lGAEgASgJElcKCWJpdGJ1Y2tldBgFIAEoCzJELmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5CaXRidWNrZXRXZWJob29rUmVjZWl2ZXJDb25maWcSVwoJZG9ja2VyaHViGAYgASgLMkQuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkRvY2tlckh1YldlYmhvb2tSZWNlaXZlckNvbmZpZxJRCgZnaXRodWIYAiABKAsyQS5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuR2l0SHViV2ViaG9va1JlY2VpdmVyQ29uZmlnElEKBmdpdGxhYhgDIAEoCzJBLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5HaXRMYWJXZWJob29rUmVjZWl2ZXJDb25maWcSUQoGaGFyYm9yGAogASgLMkEuZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLkhhcmJvcldlYmhvb2tSZWNlaXZlckNvbmZpZxJNCgRxdWF5GAQgASgLMj8uZ2l0aHViLmNvbS5ha3VpdHkua2FyZ28uYXBpLnYxYWxwaGExLlF1YXlXZWJob29rUmVjZWl2ZXJDb25maWcSWwoLYXJ0aWZhY3RvcnkYCSABKAsyRi5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuQXJ0aWZhY3RvcnlXZWJob29rUmVjZWl2ZXJDb25maWcSTwoFYXp1cmUYCCABKAsyQC5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuQXp1cmVXZWJob29rUmVjZWl2ZXJDb25maWcSTwoFZ2l0ZWEYByABKAsyQC5naXRodWIuY29tLmFrdWl0eS5rYXJnby5hcGkudjFhbHBoYTEuR2l0ZWFXZWJob29rUmVjZWl2ZXJDb25maWcSUwoHZ2VuZXJpYxgLIAEoCzJCLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMS5HZW5lcmljV2ViaG9va1JlY2VpdmVyQ29uZmlnIkEKFldlYmhvb2tSZWNlaXZlckRldGFpbHMSDAoEbmFtZRgBIAEoCRIMCgRwYXRoGAMgASgJEgsKA3VybBgEIAEoCUKXAgooY29tLmdpdGh1Yi5jb20uYWt1aXR5LmthcmdvLmFwaS52MWFscGhhMUIOR2VuZXJhdGVkUHJvdG9QAVokZ2l0aHViLmNvbS9ha3VpdHkva2FyZ28vYXBpL3YxYWxwaGExogIFR0NBS0GqAiRHaXRodWIuQ29tLkFrdWl0eS5LYXJnby5BcGkuVjFhbHBoYTHKAiRHaXRodWJcQ29tXEFrdWl0eVxLYXJnb1xBcGlcVjFhbHBoYTHiAjBHaXRodWJcQ29tXEFrdWl0eVxLYXJnb1xBcGlcVjFhbHBoYTFcR1BCTWV0YWRhdGHqAilHaXRodWI6OkNvbTo6QWt1aXR5OjpLYXJnbzo6QXBpOjpWMWFscGhhMQ", [file_k8s_io_api_core_v1_generated, file_k8s_io_apiextensions_apiserver_pkg_apis_apiextensions_v1_generated, file_k8s_io_apimachinery_pkg_apis_meta_v1_generated, file_k8s_io_apimachinery_pkg_runtime_generated, file_k8s_io_apimachinery_pkg_runtime_schema_generated]); /** * AnalysisRunArgument represents an argument to be added to an AnalysisRun. @@ -1472,6 +1472,166 @@ export type FreightStatus = Message<"github.com.akuity.kargo.api.v1alpha1.Freigh export const FreightStatusSchema: GenMessage = /*@__PURE__*/ messageDesc(file_api_v1alpha1_generated, 35); +/** + * GenericWebhookAction describes an action to be performed on a resource + * and the conditions under which it should be performed. + * + * @generated from message github.com.akuity.kargo.api.v1alpha1.GenericWebhookAction + */ +export type GenericWebhookAction = Message<"github.com.akuity.kargo.api.v1alpha1.GenericWebhookAction"> & { + /** + * Name is the name of the action to be performed. `Refresh` is the only + * action currently supported. + * + * +kubebuilder:validation:Enum=Refresh; + * + * @generated from field: optional string action = 1; + */ + action: string; + + /** + * MatchExpression defines criteria that a request must meet to trigger this + * action. + * + * +optional + * + * @generated from field: optional string matchExpression = 2; + */ + matchExpression: string; + + /** + * Parameters contains additional parameters for the action. + * + * +optional + * + * @generated from field: map parameters = 3; + */ + parameters: { [key: string]: string }; + + /** + * Targets is a list of selection criteria for the resources on which the + * action should be performed. + * + * +kubebuilder:validation:MinItems=1 + * + * @generated from field: repeated github.com.akuity.kargo.api.v1alpha1.GenericWebhookTarget targets = 4; + */ + targets: GenericWebhookTarget[]; +}; + +/** + * Describes the message github.com.akuity.kargo.api.v1alpha1.GenericWebhookAction. + * Use `create(GenericWebhookActionSchema)` to create a new message. + */ +export const GenericWebhookActionSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_api_v1alpha1_generated, 36); + +/** + * GenericWebhookReceiverConfig describes a generic webhook receiver that can be + * configured to respond to any arbitrary POST by applying user-defined actions + * on user-defined sets of resources selected by name, labels and/or values in pre-built indices. + * Both types of selectors support using values extracted from the request by + * means of expressions. Currently, refreshing resources is the only supported + * action and Warehouse is the only supported kind. "Refreshing" means + * immediately enqueuing the target resource for reconciliation by its + * controller. The practical effect of refreshing a Warehouses is triggering its + * artifact discovery process. + * + * @generated from message github.com.akuity.kargo.api.v1alpha1.GenericWebhookReceiverConfig + */ +export type GenericWebhookReceiverConfig = Message<"github.com.akuity.kargo.api.v1alpha1.GenericWebhookReceiverConfig"> & { + /** + * SecretRef contains a reference to a Secret. For Project-scoped webhook + * receivers, the referenced Secret must be in the same namespace as the + * ProjectConfig. + * + * For cluster-scoped webhook receivers, the referenced Secret must be in the + * designated "cluster Secrets" namespace. + * + * The Secret's data map is expected to contain a `secret` key whose value + * does NOT need to be shared directly with the sender. It is used only by + * Kargo to create a complex, hard-to-guess URL, which implicitly serves as a + * shared secret. + * + * +kubebuilder:validation:Required + * + * @generated from field: optional k8s.io.api.core.v1.LocalObjectReference secretRef = 1; + */ + secretRef?: LocalObjectReference; + + /** + * Actions is a list of actions to be performed when a webhook event is received. + * + * +kubebuilder:validation:MinItems=1 + * + * @generated from field: repeated github.com.akuity.kargo.api.v1alpha1.GenericWebhookAction actions = 2; + */ + actions: GenericWebhookAction[]; +}; + +/** + * Describes the message github.com.akuity.kargo.api.v1alpha1.GenericWebhookReceiverConfig. + * Use `create(GenericWebhookReceiverConfigSchema)` to create a new message. + */ +export const GenericWebhookReceiverConfigSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_api_v1alpha1_generated, 37); + +/** + * GenericWebhookTarget describes selection criteria for resources to which some + * action is to be applied. Name, LabelSelector, and IndexSelector are all optional + * however, at least one must be specified. When multiple criteria are specified, the + * results are the combined (logical AND) of the criteria. + * + * @generated from message github.com.akuity.kargo.api.v1alpha1.GenericWebhookTarget + */ +export type GenericWebhookTarget = Message<"github.com.akuity.kargo.api.v1alpha1.GenericWebhookTarget"> & { + /** + * Kind is the kind of the target resource. + * + * +kubebuilder:validation:Enum=Warehouse; + * + * @generated from field: optional string kind = 1; + */ + kind: string; + + /** + * Name is the name of the target resource. If LabelSelector and/or IndexSelectors + * are also specified, the results are the combined (logical AND) of the criteria. + * + * +optional + * + * @generated from field: optional string name = 2; + */ + name: string; + + /** + * LabelSelector is a label selector to identify the target resources. + * If used with IndexSelector and/or Name, the results are the combined (logical AND) of all the criteria. + * + * +optional + * + * @generated from field: optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector labelSelector = 3; + */ + labelSelector?: LabelSelector; + + /** + * IndexSelector is a selector used to identify cached target resources by cache key. + * If used with LabelSelector and/or Name, the results are the combined (logical AND) of all the criteria. + * + * +optional + * + * @generated from field: optional github.com.akuity.kargo.api.v1alpha1.IndexSelector indexSelector = 4; + */ + indexSelector?: IndexSelector; +}; + +/** + * Describes the message github.com.akuity.kargo.api.v1alpha1.GenericWebhookTarget. + * Use `create(GenericWebhookTargetSchema)` to create a new message. + */ +export const GenericWebhookTargetSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_api_v1alpha1_generated, 38); + /** * GitCommit describes a specific commit from a specific Git repository. * @@ -1536,7 +1696,7 @@ export type GitCommit = Message<"github.com.akuity.kargo.api.v1alpha1.GitCommit" * Use `create(GitCommitSchema)` to create a new message. */ export const GitCommitSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 36); + messageDesc(file_api_v1alpha1_generated, 39); /** * GitDiscoveryResult represents the result of a Git discovery operation for a @@ -1573,7 +1733,7 @@ export type GitDiscoveryResult = Message<"github.com.akuity.kargo.api.v1alpha1.G * Use `create(GitDiscoveryResultSchema)` to create a new message. */ export const GitDiscoveryResultSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 37); + messageDesc(file_api_v1alpha1_generated, 40); /** * GitHubWebhookReceiverConfig describes a webhook receiver that is compatible @@ -1607,7 +1767,7 @@ export type GitHubWebhookReceiverConfig = Message<"github.com.akuity.kargo.api.v * Use `create(GitHubWebhookReceiverConfigSchema)` to create a new message. */ export const GitHubWebhookReceiverConfigSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 38); + messageDesc(file_api_v1alpha1_generated, 41); /** * GitLabWebhookReceiverConfig describes a webhook receiver that is compatible @@ -1641,7 +1801,7 @@ export type GitLabWebhookReceiverConfig = Message<"github.com.akuity.kargo.api.v * Use `create(GitLabWebhookReceiverConfigSchema)` to create a new message. */ export const GitLabWebhookReceiverConfigSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 39); + messageDesc(file_api_v1alpha1_generated, 42); /** * GitSubscription defines a subscription to a Git repository. @@ -1918,7 +2078,7 @@ export type GitSubscription = Message<"github.com.akuity.kargo.api.v1alpha1.GitS * Use `create(GitSubscriptionSchema)` to create a new message. */ export const GitSubscriptionSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 40); + messageDesc(file_api_v1alpha1_generated, 43); /** * GiteaWebhookReceiverConfig describes a webhook receiver that is compatible @@ -1952,7 +2112,7 @@ export type GiteaWebhookReceiverConfig = Message<"github.com.akuity.kargo.api.v1 * Use `create(GiteaWebhookReceiverConfigSchema)` to create a new message. */ export const GiteaWebhookReceiverConfigSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 41); + messageDesc(file_api_v1alpha1_generated, 44); /** * HarborWebhookReceiverConfig describes a webhook receiver that is compatible @@ -1986,7 +2146,7 @@ export type HarborWebhookReceiverConfig = Message<"github.com.akuity.kargo.api.v * Use `create(HarborWebhookReceiverConfigSchema)` to create a new message. */ export const HarborWebhookReceiverConfigSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 42); + messageDesc(file_api_v1alpha1_generated, 45); /** * Health describes the health of a Stage. @@ -2030,7 +2190,7 @@ export type Health = Message<"github.com.akuity.kargo.api.v1alpha1.Health"> & { * Use `create(HealthSchema)` to create a new message. */ export const HealthSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 43); + messageDesc(file_api_v1alpha1_generated, 46); /** * HealthCheckStep describes a health check directive which can be executed by @@ -2061,7 +2221,7 @@ export type HealthCheckStep = Message<"github.com.akuity.kargo.api.v1alpha1.Heal * Use `create(HealthCheckStepSchema)` to create a new message. */ export const HealthCheckStepSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 44); + messageDesc(file_api_v1alpha1_generated, 47); /** * HealthStats contains a summary of the collective health of some resource @@ -2083,7 +2243,7 @@ export type HealthStats = Message<"github.com.akuity.kargo.api.v1alpha1.HealthSt * Use `create(HealthStatsSchema)` to create a new message. */ export const HealthStatsSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 45); + messageDesc(file_api_v1alpha1_generated, 48); /** * Image describes a specific version of a container image. @@ -2127,7 +2287,7 @@ export type Image = Message<"github.com.akuity.kargo.api.v1alpha1.Image"> & { * Use `create(ImageSchema)` to create a new message. */ export const ImageSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 46); + messageDesc(file_api_v1alpha1_generated, 49); /** * ImageDiscoveryResult represents the result of an image discovery operation @@ -2173,7 +2333,7 @@ export type ImageDiscoveryResult = Message<"github.com.akuity.kargo.api.v1alpha1 * Use `create(ImageDiscoveryResultSchema)` to create a new message. */ export const ImageDiscoveryResultSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 47); + messageDesc(file_api_v1alpha1_generated, 50); /** * ImageSubscription defines a subscription to an image repository. @@ -2362,7 +2522,74 @@ export type ImageSubscription = Message<"github.com.akuity.kargo.api.v1alpha1.Im * Use `create(ImageSubscriptionSchema)` to create a new message. */ export const ImageSubscriptionSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 48); + messageDesc(file_api_v1alpha1_generated, 51); + +/** + * IndexSelector encapsulates a selector used to derive index keys + * based on expressions. + * + * @generated from message github.com.akuity.kargo.api.v1alpha1.IndexSelector + */ +export type IndexSelector = Message<"github.com.akuity.kargo.api.v1alpha1.IndexSelector"> & { + /** + * MatchIndices is a list of index selector requirements. + * + * +kubebuilder:validation:MinItems=1 + * + * @generated from field: repeated github.com.akuity.kargo.api.v1alpha1.IndexSelectorRequirement matchIndices = 1; + */ + matchIndices: IndexSelectorRequirement[]; +}; + +/** + * Describes the message github.com.akuity.kargo.api.v1alpha1.IndexSelector. + * Use `create(IndexSelectorSchema)` to create a new message. + */ +export const IndexSelectorSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_api_v1alpha1_generated, 52); + +/** + * IndexSelectorRequirement encapsulates a requirement used to select indexes + * based on specific criteria. + * + * @generated from message github.com.akuity.kargo.api.v1alpha1.IndexSelectorRequirement + */ +export type IndexSelectorRequirement = Message<"github.com.akuity.kargo.api.v1alpha1.IndexSelectorRequirement"> & { + /** + * Key is the key of the index. + * + * +kubebuilder:validation:Enum=subscribedURLs;receiverPaths + * + * @generated from field: optional string key = 1; + */ + key: string; + + /** + * Operator indicates the operation that should be used to evaluate + * whether the selection requirement is satisfied. + * + * kubebuilder:validation:Enum=Equal;NotEqual; + * + * @generated from field: optional string operator = 2; + */ + operator: string; + + /** + * Value can be a static string or an expression that will be evaluated. + * + * kubebuilder:validation:Required + * + * @generated from field: optional string value = 3; + */ + value: string; +}; + +/** + * Describes the message github.com.akuity.kargo.api.v1alpha1.IndexSelectorRequirement. + * Use `create(IndexSelectorRequirementSchema)` to create a new message. + */ +export const IndexSelectorRequirementSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_api_v1alpha1_generated, 53); /** * Project is a resource type that reconciles to a specially labeled namespace @@ -2389,7 +2616,7 @@ export type Project = Message<"github.com.akuity.kargo.api.v1alpha1.Project"> & * Use `create(ProjectSchema)` to create a new message. */ export const ProjectSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 49); + messageDesc(file_api_v1alpha1_generated, 54); /** * ProjectConfig is a resource type that describes the configuration of a @@ -2423,7 +2650,7 @@ export type ProjectConfig = Message<"github.com.akuity.kargo.api.v1alpha1.Projec * Use `create(ProjectConfigSchema)` to create a new message. */ export const ProjectConfigSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 50); + messageDesc(file_api_v1alpha1_generated, 55); /** * ProjectConfigList is a list of ProjectConfig resources. @@ -2447,7 +2674,7 @@ export type ProjectConfigList = Message<"github.com.akuity.kargo.api.v1alpha1.Pr * Use `create(ProjectConfigListSchema)` to create a new message. */ export const ProjectConfigListSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 51); + messageDesc(file_api_v1alpha1_generated, 56); /** * ProjectConfigSpec describes the configuration of a Project. @@ -2477,7 +2704,7 @@ export type ProjectConfigSpec = Message<"github.com.akuity.kargo.api.v1alpha1.Pr * Use `create(ProjectConfigSpecSchema)` to create a new message. */ export const ProjectConfigSpecSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 52); + messageDesc(file_api_v1alpha1_generated, 57); /** * ProjectConfigStatus describes the current status of a ProjectConfig. @@ -2530,7 +2757,7 @@ export type ProjectConfigStatus = Message<"github.com.akuity.kargo.api.v1alpha1. * Use `create(ProjectConfigStatusSchema)` to create a new message. */ export const ProjectConfigStatusSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 53); + messageDesc(file_api_v1alpha1_generated, 58); /** * ProjectList is a list of Project resources. @@ -2554,7 +2781,7 @@ export type ProjectList = Message<"github.com.akuity.kargo.api.v1alpha1.ProjectL * Use `create(ProjectListSchema)` to create a new message. */ export const ProjectListSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 54); + messageDesc(file_api_v1alpha1_generated, 59); /** * ProjectStats contains a summary of the collective state of a Project's @@ -2584,7 +2811,7 @@ export type ProjectStats = Message<"github.com.akuity.kargo.api.v1alpha1.Project * Use `create(ProjectStatsSchema)` to create a new message. */ export const ProjectStatsSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 55); + messageDesc(file_api_v1alpha1_generated, 60); /** * ProjectStatus describes a Project's current status. @@ -2618,7 +2845,7 @@ export type ProjectStatus = Message<"github.com.akuity.kargo.api.v1alpha1.Projec * Use `create(ProjectStatusSchema)` to create a new message. */ export const ProjectStatusSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 56); + messageDesc(file_api_v1alpha1_generated, 61); /** * Promotion represents a request to transition a particular Stage into a @@ -2656,7 +2883,7 @@ export type Promotion = Message<"github.com.akuity.kargo.api.v1alpha1.Promotion" * Use `create(PromotionSchema)` to create a new message. */ export const PromotionSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 57); + messageDesc(file_api_v1alpha1_generated, 62); /** * PromotionList contains a list of Promotion @@ -2680,7 +2907,7 @@ export type PromotionList = Message<"github.com.akuity.kargo.api.v1alpha1.Promot * Use `create(PromotionListSchema)` to create a new message. */ export const PromotionListSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 58); + messageDesc(file_api_v1alpha1_generated, 63); /** * PromotionPolicy defines policies governing the promotion of Freight to a @@ -2729,7 +2956,7 @@ export type PromotionPolicy = Message<"github.com.akuity.kargo.api.v1alpha1.Prom * Use `create(PromotionPolicySchema)` to create a new message. */ export const PromotionPolicySchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 59); + messageDesc(file_api_v1alpha1_generated, 64); /** * PromotionPolicySelector is a selector that matches the resource to which @@ -2785,7 +3012,7 @@ export type PromotionPolicySelector = Message<"github.com.akuity.kargo.api.v1alp * Use `create(PromotionPolicySelectorSchema)` to create a new message. */ export const PromotionPolicySelectorSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 60); + messageDesc(file_api_v1alpha1_generated, 65); /** * PromotionReference contains the relevant information about a Promotion @@ -2828,7 +3055,7 @@ export type PromotionReference = Message<"github.com.akuity.kargo.api.v1alpha1.P * Use `create(PromotionReferenceSchema)` to create a new message. */ export const PromotionReferenceSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 61); + messageDesc(file_api_v1alpha1_generated, 66); /** * PromotionSpec describes the desired transition of a specific Stage into a @@ -2893,7 +3120,7 @@ export type PromotionSpec = Message<"github.com.akuity.kargo.api.v1alpha1.Promot * Use `create(PromotionSpecSchema)` to create a new message. */ export const PromotionSpecSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 62); + messageDesc(file_api_v1alpha1_generated, 67); /** * PromotionStatus describes the current state of the transition represented by @@ -2998,7 +3225,7 @@ export type PromotionStatus = Message<"github.com.akuity.kargo.api.v1alpha1.Prom * Use `create(PromotionStatusSchema)` to create a new message. */ export const PromotionStatusSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 63); + messageDesc(file_api_v1alpha1_generated, 68); /** * PromotionStep describes a directive to be executed as part of a Promotion. @@ -3083,7 +3310,7 @@ export type PromotionStep = Message<"github.com.akuity.kargo.api.v1alpha1.Promot * Use `create(PromotionStepSchema)` to create a new message. */ export const PromotionStepSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 64); + messageDesc(file_api_v1alpha1_generated, 69); /** * PromotionStepRetry describes the retry policy for a PromotionStep. @@ -3142,7 +3369,7 @@ export type PromotionStepRetry = Message<"github.com.akuity.kargo.api.v1alpha1.P * Use `create(PromotionStepRetrySchema)` to create a new message. */ export const PromotionStepRetrySchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 65); + messageDesc(file_api_v1alpha1_generated, 70); /** * @generated from message github.com.akuity.kargo.api.v1alpha1.PromotionTask @@ -3169,7 +3396,7 @@ export type PromotionTask = Message<"github.com.akuity.kargo.api.v1alpha1.Promot * Use `create(PromotionTaskSchema)` to create a new message. */ export const PromotionTaskSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 66); + messageDesc(file_api_v1alpha1_generated, 71); /** * PromotionTaskList contains a list of PromotionTasks. @@ -3193,7 +3420,7 @@ export type PromotionTaskList = Message<"github.com.akuity.kargo.api.v1alpha1.Pr * Use `create(PromotionTaskListSchema)` to create a new message. */ export const PromotionTaskListSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 67); + messageDesc(file_api_v1alpha1_generated, 72); /** * PromotionTaskReference describes a reference to a PromotionTask. @@ -3231,7 +3458,7 @@ export type PromotionTaskReference = Message<"github.com.akuity.kargo.api.v1alph * Use `create(PromotionTaskReferenceSchema)` to create a new message. */ export const PromotionTaskReferenceSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 68); + messageDesc(file_api_v1alpha1_generated, 73); /** * @generated from message github.com.akuity.kargo.api.v1alpha1.PromotionTaskSpec @@ -3265,7 +3492,7 @@ export type PromotionTaskSpec = Message<"github.com.akuity.kargo.api.v1alpha1.Pr * Use `create(PromotionTaskSpecSchema)` to create a new message. */ export const PromotionTaskSpecSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 69); + messageDesc(file_api_v1alpha1_generated, 74); /** * PromotionTemplate defines a template for a Promotion that can be used to @@ -3285,7 +3512,7 @@ export type PromotionTemplate = Message<"github.com.akuity.kargo.api.v1alpha1.Pr * Use `create(PromotionTemplateSchema)` to create a new message. */ export const PromotionTemplateSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 70); + messageDesc(file_api_v1alpha1_generated, 75); /** * PromotionTemplateSpec describes the (partial) specification of a Promotion @@ -3323,7 +3550,7 @@ export type PromotionTemplateSpec = Message<"github.com.akuity.kargo.api.v1alpha * Use `create(PromotionTemplateSpecSchema)` to create a new message. */ export const PromotionTemplateSpecSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 71); + messageDesc(file_api_v1alpha1_generated, 76); /** * QuayWebhookReceiverConfig describes a webhook receiver that is compatible @@ -3359,7 +3586,7 @@ export type QuayWebhookReceiverConfig = Message<"github.com.akuity.kargo.api.v1a * Use `create(QuayWebhookReceiverConfigSchema)` to create a new message. */ export const QuayWebhookReceiverConfigSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 72); + messageDesc(file_api_v1alpha1_generated, 77); /** * RepoSubscription describes a subscription to ONE OF a Git repository, a @@ -3395,7 +3622,7 @@ export type RepoSubscription = Message<"github.com.akuity.kargo.api.v1alpha1.Rep * Use `create(RepoSubscriptionSchema)` to create a new message. */ export const RepoSubscriptionSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 73); + messageDesc(file_api_v1alpha1_generated, 78); /** * Stage is the Kargo API's main type. @@ -3431,7 +3658,7 @@ export type Stage = Message<"github.com.akuity.kargo.api.v1alpha1.Stage"> & { * Use `create(StageSchema)` to create a new message. */ export const StageSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 74); + messageDesc(file_api_v1alpha1_generated, 79); /** * StageList is a list of Stage resources. @@ -3455,7 +3682,7 @@ export type StageList = Message<"github.com.akuity.kargo.api.v1alpha1.StageList" * Use `create(StageListSchema)` to create a new message. */ export const StageListSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 75); + messageDesc(file_api_v1alpha1_generated, 80); /** * StageSpec describes the sources of Freight used by a Stage and how to @@ -3522,7 +3749,7 @@ export type StageSpec = Message<"github.com.akuity.kargo.api.v1alpha1.StageSpec" * Use `create(StageSpecSchema)` to create a new message. */ export const StageSpecSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 76); + messageDesc(file_api_v1alpha1_generated, 81); /** * StageStats contains a summary of the collective state of a Project's @@ -3551,7 +3778,7 @@ export type StageStats = Message<"github.com.akuity.kargo.api.v1alpha1.StageStat * Use `create(StageStatsSchema)` to create a new message. */ export const StageStatsSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 77); + messageDesc(file_api_v1alpha1_generated, 82); /** * StageStatus describes a Stages's current and recent Freight, health, and @@ -3660,7 +3887,7 @@ export type StageStatus = Message<"github.com.akuity.kargo.api.v1alpha1.StageSta * Use `create(StageStatusSchema)` to create a new message. */ export const StageStatusSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 78); + messageDesc(file_api_v1alpha1_generated, 83); /** * StepExecutionMetadata tracks metadata pertaining to the execution of @@ -3729,7 +3956,7 @@ export type StepExecutionMetadata = Message<"github.com.akuity.kargo.api.v1alpha * Use `create(StepExecutionMetadataSchema)` to create a new message. */ export const StepExecutionMetadataSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 79); + messageDesc(file_api_v1alpha1_generated, 84); /** * Verification describes how to verify that a Promotion has been successful @@ -3768,7 +3995,7 @@ export type Verification = Message<"github.com.akuity.kargo.api.v1alpha1.Verific * Use `create(VerificationSchema)` to create a new message. */ export const VerificationSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 80); + messageDesc(file_api_v1alpha1_generated, 85); /** * VerificationInfo contains the details of an instance of a Verification @@ -3838,7 +4065,7 @@ export type VerificationInfo = Message<"github.com.akuity.kargo.api.v1alpha1.Ver * Use `create(VerificationInfoSchema)` to create a new message. */ export const VerificationInfoSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 81); + messageDesc(file_api_v1alpha1_generated, 86); /** * VerifiedStage describes a Stage in which Freight has been verified. @@ -3870,7 +4097,7 @@ export type VerifiedStage = Message<"github.com.akuity.kargo.api.v1alpha1.Verifi * Use `create(VerifiedStageSchema)` to create a new message. */ export const VerifiedStageSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 82); + messageDesc(file_api_v1alpha1_generated, 87); /** * Warehouse is a source of Freight. @@ -3905,7 +4132,7 @@ export type Warehouse = Message<"github.com.akuity.kargo.api.v1alpha1.Warehouse" * Use `create(WarehouseSchema)` to create a new message. */ export const WarehouseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 83); + messageDesc(file_api_v1alpha1_generated, 88); /** * WarehouseList is a list of Warehouse resources. @@ -3929,7 +4156,7 @@ export type WarehouseList = Message<"github.com.akuity.kargo.api.v1alpha1.Wareho * Use `create(WarehouseListSchema)` to create a new message. */ export const WarehouseListSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 84); + messageDesc(file_api_v1alpha1_generated, 89); /** * WarehouseSpec describes sources of versioned artifacts to be included in @@ -4012,7 +4239,7 @@ export type WarehouseSpec = Message<"github.com.akuity.kargo.api.v1alpha1.Wareho * Use `create(WarehouseSpecSchema)` to create a new message. */ export const WarehouseSpecSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 85); + messageDesc(file_api_v1alpha1_generated, 90); /** * WarehouseStats contains a summary of the collective state of a Project's @@ -4042,7 +4269,7 @@ export type WarehouseStats = Message<"github.com.akuity.kargo.api.v1alpha1.Wareh * Use `create(WarehouseStatsSchema)` to create a new message. */ export const WarehouseStatsSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 86); + messageDesc(file_api_v1alpha1_generated, 91); /** * WarehouseStatus describes a Warehouse's most recently observed state. @@ -4101,7 +4328,7 @@ export type WarehouseStatus = Message<"github.com.akuity.kargo.api.v1alpha1.Ware * Use `create(WarehouseStatusSchema)` to create a new message. */ export const WarehouseStatusSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 87); + messageDesc(file_api_v1alpha1_generated, 92); /** * WebhookReceiverConfig describes the configuration for a single webhook @@ -4194,6 +4421,13 @@ export type WebhookReceiverConfig = Message<"github.com.akuity.kargo.api.v1alpha * @generated from field: optional github.com.akuity.kargo.api.v1alpha1.GiteaWebhookReceiverConfig gitea = 7; */ gitea?: GiteaWebhookReceiverConfig; + + /** + * Generic contains the configuration for a generic webhook receiver. + * + * @generated from field: optional github.com.akuity.kargo.api.v1alpha1.GenericWebhookReceiverConfig generic = 11; + */ + generic?: GenericWebhookReceiverConfig; }; /** @@ -4201,7 +4435,7 @@ export type WebhookReceiverConfig = Message<"github.com.akuity.kargo.api.v1alpha * Use `create(WebhookReceiverConfigSchema)` to create a new message. */ export const WebhookReceiverConfigSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 88); + messageDesc(file_api_v1alpha1_generated, 93); /** * WebhookReceiverDetails encapsulates the details of a webhook receiver. @@ -4236,5 +4470,5 @@ export type WebhookReceiverDetails = Message<"github.com.akuity.kargo.api.v1alph * Use `create(WebhookReceiverDetailsSchema)` to create a new message. */ export const WebhookReceiverDetailsSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1alpha1_generated, 89); + messageDesc(file_api_v1alpha1_generated, 94); diff --git a/ui/src/gen/schema/clusterconfigs.kargo.akuity.io_v1alpha1.json b/ui/src/gen/schema/clusterconfigs.kargo.akuity.io_v1alpha1.json index f62ba1a4ff..857160b92a 100644 --- a/ui/src/gen/schema/clusterconfigs.kargo.akuity.io_v1alpha1.json +++ b/ui/src/gen/schema/clusterconfigs.kargo.akuity.io_v1alpha1.json @@ -109,6 +109,167 @@ ], "type": "object" }, + "generic": { + "description": "Generic contains the configuration for a generic webhook receiver.", + "properties": { + "actions": { + "description": "Actions is a list of actions to be performed when a webhook event is received.", + "items": { + "description": "GenericWebhookAction describes an action to be performed on a resource\nand the conditions under which it should be performed.", + "properties": { + "action": { + "description": "Name is the name of the action to be performed. `Refresh` is the only\naction currently supported.", + "enum": [ + "Refresh" + ], + "type": "string" + }, + "matchExpression": { + "description": "MatchExpression defines criteria that a request must meet to trigger this\naction.", + "type": "string" + }, + "parameters": { + "additionalProperties": { + "type": "string" + }, + "description": "Parameters contains additional parameters for the action.", + "type": "object" + }, + "targets": { + "description": "Targets is a list of selection criteria for the resources on which the\naction should be performed.", + "items": { + "description": "GenericWebhookTarget describes selection criteria for resources to which some\naction is to be applied. Name, LabelSelector, and IndexSelector are all optional\nhowever, at least one must be specified. When multiple criteria are specified, the\nresults are the combined (logical AND) of the criteria.", + "properties": { + "indexSelector": { + "description": "IndexSelector is a selector used to identify cached target resources by cache key.\nIf used with LabelSelector and/or Name, the results are the combined (logical AND) of all the criteria.", + "properties": { + "matchIndicies": { + "description": "MatchIndices is a list of index selector requirements.", + "items": { + "description": "IndexSelectorRequirement encapsulates a requirement used to select indexes\nbased on specific criteria.", + "properties": { + "key": { + "description": "Key is the key of the index.", + "enum": [ + "subscribedURLs", + "receiverPaths" + ], + "type": "string" + }, + "operator": { + "description": "Operator indicates the operation that should be used to evaluate\nwhether the selection requirement is satisfied.\n\nkubebuilder:validation:Enum=Equal;NotEqual;", + "type": "string" + }, + "value": { + "description": "Value can be a static string or an expression that will be evaluated.\n\nkubebuilder:validation:Required", + "type": "string" + } + }, + "required": [ + "key", + "operator", + "value" + ], + "type": "object" + }, + "minItems": 1, + "type": "array" + } + }, + "type": "object" + }, + "kind": { + "description": "Kind is the kind of the target resource.", + "enum": [ + "Warehouse" + ], + "type": "string" + }, + "labelSelector": { + "description": "LabelSelector is a label selector to identify the target resources.\nIf used with IndexSelector and/or Name, the results are the combined (logical AND) of all the criteria.", + "properties": { + "matchExpressions": { + "description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.", + "items": { + "description": "A label selector requirement is a selector that contains values, a key, and an operator that\nrelates the key and values.", + "properties": { + "key": { + "description": "key is the label key that the selector applies to.", + "type": "string" + }, + "operator": { + "description": "operator represents a key's relationship to a set of values.\nValid operators are In, NotIn, Exists and DoesNotExist.", + "type": "string" + }, + "values": { + "description": "values is an array of string values. If the operator is In or NotIn,\nthe values array must be non-empty. If the operator is Exists or DoesNotExist,\nthe values array must be empty. This array is replaced during a strategic\nmerge patch.", + "items": { + "type": "string" + }, + "type": "array", + "x-kubernetes-list-type": "atomic" + } + }, + "required": [ + "key", + "operator" + ], + "type": "object" + }, + "type": "array", + "x-kubernetes-list-type": "atomic" + }, + "matchLabels": { + "additionalProperties": { + "type": "string" + }, + "description": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels\nmap is equivalent to an element of matchExpressions, whose key field is \"key\", the\noperator is \"In\", and the values array contains only \"value\". The requirements are ANDed.", + "type": "object" + } + }, + "type": "object", + "x-kubernetes-map-type": "atomic" + }, + "name": { + "description": "Name is the name of the target resource. If LabelSelector and/or IndexSelectors\nare also specified, the results are the combined (logical AND) of the criteria.", + "type": "string" + } + }, + "required": [ + "kind" + ], + "type": "object" + }, + "minItems": 1, + "type": "array" + } + }, + "required": [ + "action" + ], + "type": "object" + }, + "minItems": 1, + "type": "array" + }, + "secretRef": { + "description": "SecretRef contains a reference to a Secret. For Project-scoped webhook\nreceivers, the referenced Secret must be in the same namespace as the\nProjectConfig.\n\nFor cluster-scoped webhook receivers, the referenced Secret must be in the\ndesignated \"cluster Secrets\" namespace.\n\nThe Secret's data map is expected to contain a `secret` key whose value\ndoes NOT need to be shared directly with the sender. It is used only by\nKargo to create a complex, hard-to-guess URL, which implicitly serves as a\nshared secret.", + "properties": { + "name": { + "default": "", + "description": "Name of the referent.\nThis field is effectively required, but due to backwards compatibility is\nallowed to be empty. Instances of this type with an empty value here are\nalmost certainly wrong.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + } + }, + "type": "object", + "x-kubernetes-map-type": "atomic" + } + }, + "required": [ + "secretRef" + ], + "type": "object" + }, "gitea": { "description": "Gitea contains the configuration for a webhook receiver that is compatible\nwith Gitea payloads.", "properties": { diff --git a/ui/src/gen/schema/projectconfigs.kargo.akuity.io_v1alpha1.json b/ui/src/gen/schema/projectconfigs.kargo.akuity.io_v1alpha1.json index 43640896ed..5651c5be92 100644 --- a/ui/src/gen/schema/projectconfigs.kargo.akuity.io_v1alpha1.json +++ b/ui/src/gen/schema/projectconfigs.kargo.akuity.io_v1alpha1.json @@ -183,6 +183,167 @@ ], "type": "object" }, + "generic": { + "description": "Generic contains the configuration for a generic webhook receiver.", + "properties": { + "actions": { + "description": "Actions is a list of actions to be performed when a webhook event is received.", + "items": { + "description": "GenericWebhookAction describes an action to be performed on a resource\nand the conditions under which it should be performed.", + "properties": { + "action": { + "description": "Name is the name of the action to be performed. `Refresh` is the only\naction currently supported.", + "enum": [ + "Refresh" + ], + "type": "string" + }, + "matchExpression": { + "description": "MatchExpression defines criteria that a request must meet to trigger this\naction.", + "type": "string" + }, + "parameters": { + "additionalProperties": { + "type": "string" + }, + "description": "Parameters contains additional parameters for the action.", + "type": "object" + }, + "targets": { + "description": "Targets is a list of selection criteria for the resources on which the\naction should be performed.", + "items": { + "description": "GenericWebhookTarget describes selection criteria for resources to which some\naction is to be applied. Name, LabelSelector, and IndexSelector are all optional\nhowever, at least one must be specified. When multiple criteria are specified, the\nresults are the combined (logical AND) of the criteria.", + "properties": { + "indexSelector": { + "description": "IndexSelector is a selector used to identify cached target resources by cache key.\nIf used with LabelSelector and/or Name, the results are the combined (logical AND) of all the criteria.", + "properties": { + "matchIndicies": { + "description": "MatchIndices is a list of index selector requirements.", + "items": { + "description": "IndexSelectorRequirement encapsulates a requirement used to select indexes\nbased on specific criteria.", + "properties": { + "key": { + "description": "Key is the key of the index.", + "enum": [ + "subscribedURLs", + "receiverPaths" + ], + "type": "string" + }, + "operator": { + "description": "Operator indicates the operation that should be used to evaluate\nwhether the selection requirement is satisfied.\n\nkubebuilder:validation:Enum=Equal;NotEqual;", + "type": "string" + }, + "value": { + "description": "Value can be a static string or an expression that will be evaluated.\n\nkubebuilder:validation:Required", + "type": "string" + } + }, + "required": [ + "key", + "operator", + "value" + ], + "type": "object" + }, + "minItems": 1, + "type": "array" + } + }, + "type": "object" + }, + "kind": { + "description": "Kind is the kind of the target resource.", + "enum": [ + "Warehouse" + ], + "type": "string" + }, + "labelSelector": { + "description": "LabelSelector is a label selector to identify the target resources.\nIf used with IndexSelector and/or Name, the results are the combined (logical AND) of all the criteria.", + "properties": { + "matchExpressions": { + "description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.", + "items": { + "description": "A label selector requirement is a selector that contains values, a key, and an operator that\nrelates the key and values.", + "properties": { + "key": { + "description": "key is the label key that the selector applies to.", + "type": "string" + }, + "operator": { + "description": "operator represents a key's relationship to a set of values.\nValid operators are In, NotIn, Exists and DoesNotExist.", + "type": "string" + }, + "values": { + "description": "values is an array of string values. If the operator is In or NotIn,\nthe values array must be non-empty. If the operator is Exists or DoesNotExist,\nthe values array must be empty. This array is replaced during a strategic\nmerge patch.", + "items": { + "type": "string" + }, + "type": "array", + "x-kubernetes-list-type": "atomic" + } + }, + "required": [ + "key", + "operator" + ], + "type": "object" + }, + "type": "array", + "x-kubernetes-list-type": "atomic" + }, + "matchLabels": { + "additionalProperties": { + "type": "string" + }, + "description": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels\nmap is equivalent to an element of matchExpressions, whose key field is \"key\", the\noperator is \"In\", and the values array contains only \"value\". The requirements are ANDed.", + "type": "object" + } + }, + "type": "object", + "x-kubernetes-map-type": "atomic" + }, + "name": { + "description": "Name is the name of the target resource. If LabelSelector and/or IndexSelectors\nare also specified, the results are the combined (logical AND) of the criteria.", + "type": "string" + } + }, + "required": [ + "kind" + ], + "type": "object" + }, + "minItems": 1, + "type": "array" + } + }, + "required": [ + "action" + ], + "type": "object" + }, + "minItems": 1, + "type": "array" + }, + "secretRef": { + "description": "SecretRef contains a reference to a Secret. For Project-scoped webhook\nreceivers, the referenced Secret must be in the same namespace as the\nProjectConfig.\n\nFor cluster-scoped webhook receivers, the referenced Secret must be in the\ndesignated \"cluster Secrets\" namespace.\n\nThe Secret's data map is expected to contain a `secret` key whose value\ndoes NOT need to be shared directly with the sender. It is used only by\nKargo to create a complex, hard-to-guess URL, which implicitly serves as a\nshared secret.", + "properties": { + "name": { + "default": "", + "description": "Name of the referent.\nThis field is effectively required, but due to backwards compatibility is\nallowed to be empty. Instances of this type with an empty value here are\nalmost certainly wrong.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + } + }, + "type": "object", + "x-kubernetes-map-type": "atomic" + } + }, + "required": [ + "secretRef" + ], + "type": "object" + }, "gitea": { "description": "Gitea contains the configuration for a webhook receiver that is compatible\nwith Gitea payloads.", "properties": {