Composition Function status conditions and claim events.

Signed-off-by: dalton hill <dalton.hill.0@protonmail.com>
This commit is contained in:
dalton hill 2024-06-03 11:36:15 -05:00
parent d85d6cb074
commit 0b75611324
16 changed files with 1800 additions and 237 deletions

View File

@ -150,6 +150,113 @@ func (Severity) EnumDescriptor() ([]byte, []int) {
return file_apiextensions_fn_proto_v1beta1_run_function_proto_rawDescGZIP(), []int{1}
}
// Target of Function results and conditions.
type Target int32
const (
// If the target is unspecified, the result targets the composite resource.
Target_TARGET_UNSPECIFIED Target = 0
// Target the composite resource. Results that target the composite resource
// should include detailed, advanced information.
Target_TARGET_COMPOSITE Target = 1
// Target the composite and the claim. Results that target the composite and
// the claim should include only end-user friendly information.
Target_TARGET_COMPOSITE_AND_CLAIM Target = 2
)
// Enum value maps for Target.
var (
Target_name = map[int32]string{
0: "TARGET_UNSPECIFIED",
1: "TARGET_COMPOSITE",
2: "TARGET_COMPOSITE_AND_CLAIM",
}
Target_value = map[string]int32{
"TARGET_UNSPECIFIED": 0,
"TARGET_COMPOSITE": 1,
"TARGET_COMPOSITE_AND_CLAIM": 2,
}
)
func (x Target) Enum() *Target {
p := new(Target)
*p = x
return p
}
func (x Target) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (Target) Descriptor() protoreflect.EnumDescriptor {
return file_apiextensions_fn_proto_v1beta1_run_function_proto_enumTypes[2].Descriptor()
}
func (Target) Type() protoreflect.EnumType {
return &file_apiextensions_fn_proto_v1beta1_run_function_proto_enumTypes[2]
}
func (x Target) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use Target.Descriptor instead.
func (Target) EnumDescriptor() ([]byte, []int) {
return file_apiextensions_fn_proto_v1beta1_run_function_proto_rawDescGZIP(), []int{2}
}
type Status int32
const (
Status_STATUS_CONDITION_UNSPECIFIED Status = 0
Status_STATUS_CONDITION_UNKNOWN Status = 1
Status_STATUS_CONDITION_TRUE Status = 2
Status_STATUS_CONDITION_FALSE Status = 3
)
// Enum value maps for Status.
var (
Status_name = map[int32]string{
0: "STATUS_CONDITION_UNSPECIFIED",
1: "STATUS_CONDITION_UNKNOWN",
2: "STATUS_CONDITION_TRUE",
3: "STATUS_CONDITION_FALSE",
}
Status_value = map[string]int32{
"STATUS_CONDITION_UNSPECIFIED": 0,
"STATUS_CONDITION_UNKNOWN": 1,
"STATUS_CONDITION_TRUE": 2,
"STATUS_CONDITION_FALSE": 3,
}
)
func (x Status) Enum() *Status {
p := new(Status)
*p = x
return p
}
func (x Status) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (Status) Descriptor() protoreflect.EnumDescriptor {
return file_apiextensions_fn_proto_v1beta1_run_function_proto_enumTypes[3].Descriptor()
}
func (Status) Type() protoreflect.EnumType {
return &file_apiextensions_fn_proto_v1beta1_run_function_proto_enumTypes[3]
}
func (x Status) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use Status.Descriptor instead.
func (Status) EnumDescriptor() ([]byte, []int) {
return file_apiextensions_fn_proto_v1beta1_run_function_proto_rawDescGZIP(), []int{3}
}
// A RunFunctionRequest requests that the Composition Function be run.
type RunFunctionRequest struct {
state protoimpl.MessageState
@ -468,6 +575,9 @@ type RunFunctionResponse struct {
Context *structpb.Struct `protobuf:"bytes,4,opt,name=context,proto3,oneof" json:"context,omitempty"`
// Requirements that must be satisfied for this Function to run successfully.
Requirements *Requirements `protobuf:"bytes,5,opt,name=requirements,proto3" json:"requirements,omitempty"`
// Status conditions to be applied to the composite resource. Conditions may also
// optionally be applied to the composite resource's associated claim.
Conditions []*Condition `protobuf:"bytes,6,rep,name=conditions,proto3" json:"conditions,omitempty"`
}
func (x *RunFunctionResponse) Reset() {
@ -537,6 +647,13 @@ func (x *RunFunctionResponse) GetRequirements() *Requirements {
return nil
}
func (x *RunFunctionResponse) GetConditions() []*Condition {
if x != nil {
return x.Conditions
}
return nil
}
// RequestMeta contains metadata pertaining to a RunFunctionRequest.
type RequestMeta struct {
state protoimpl.MessageState
@ -1017,6 +1134,11 @@ type Result struct {
Severity Severity `protobuf:"varint,1,opt,name=severity,proto3,enum=apiextensions.fn.proto.v1beta1.Severity" json:"severity,omitempty"`
// Human-readable details about the result.
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
// Optional PascalCase, machine-readable reason for this result. If omitted,
// the value will be ComposeResources.
Reason *string `protobuf:"bytes,3,opt,name=reason,proto3,oneof" json:"reason,omitempty"`
// The resources this result targets.
Target *Target `protobuf:"varint,4,opt,name=target,proto3,enum=apiextensions.fn.proto.v1beta1.Target,oneof" json:"target,omitempty"`
}
func (x *Result) Reset() {
@ -1065,6 +1187,113 @@ func (x *Result) GetMessage() string {
return ""
}
func (x *Result) GetReason() string {
if x != nil && x.Reason != nil {
return *x.Reason
}
return ""
}
func (x *Result) GetTarget() Target {
if x != nil && x.Target != nil {
return *x.Target
}
return Target_TARGET_UNSPECIFIED
}
// Status condition to be applied to the composite resource. Condition may also
// optionally be applied to the composite resource's associated claim. For
// detailed information on proper usage of status conditions, please see
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties.
type Condition struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Type of condition in PascalCase.
Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"`
// Status of the condition.
Status Status `protobuf:"varint,2,opt,name=status,proto3,enum=apiextensions.fn.proto.v1beta1.Status" json:"status,omitempty"`
// Reason contains a programmatic identifier indicating the reason for the
// condition's last transition. Producers of specific condition types may
// define expected values and meanings for this field, and whether the values
// are considered a guaranteed API. The value should be a PascalCase string.
// This field may not be empty.
Reason string `protobuf:"bytes,3,opt,name=reason,proto3" json:"reason,omitempty"`
// Message is a human readable message indicating details about the
// transition. This may be an empty string.
Message *string `protobuf:"bytes,4,opt,name=message,proto3,oneof" json:"message,omitempty"`
// The resources this condition targets.
Target *Target `protobuf:"varint,5,opt,name=target,proto3,enum=apiextensions.fn.proto.v1beta1.Target,oneof" json:"target,omitempty"`
}
func (x *Condition) Reset() {
*x = Condition{}
if protoimpl.UnsafeEnabled {
mi := &file_apiextensions_fn_proto_v1beta1_run_function_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Condition) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Condition) ProtoMessage() {}
func (x *Condition) ProtoReflect() protoreflect.Message {
mi := &file_apiextensions_fn_proto_v1beta1_run_function_proto_msgTypes[13]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Condition.ProtoReflect.Descriptor instead.
func (*Condition) Descriptor() ([]byte, []int) {
return file_apiextensions_fn_proto_v1beta1_run_function_proto_rawDescGZIP(), []int{13}
}
func (x *Condition) GetType() string {
if x != nil {
return x.Type
}
return ""
}
func (x *Condition) GetStatus() Status {
if x != nil {
return x.Status
}
return Status_STATUS_CONDITION_UNSPECIFIED
}
func (x *Condition) GetReason() string {
if x != nil {
return x.Reason
}
return ""
}
func (x *Condition) GetMessage() string {
if x != nil && x.Message != nil {
return *x.Message
}
return ""
}
func (x *Condition) GetTarget() Target {
if x != nil && x.Target != nil {
return *x.Target
}
return Target_TARGET_UNSPECIFIED
}
var File_apiextensions_fn_proto_v1beta1_run_function_proto protoreflect.FileDescriptor
var file_apiextensions_fn_proto_v1beta1_run_function_proto_rawDesc = []byte{
@ -1147,7 +1376,7 @@ var file_apiextensions_fn_proto_v1beta1_run_function_proto_rawDesc = []byte{
0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x61,
0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65,
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x22, 0xf0, 0x02,
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x22, 0xbb, 0x03,
0x0a, 0x13, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
@ -1170,120 +1399,161 @@ var file_apiextensions_fn_proto_v1beta1_run_function_proto_rawDesc = []byte{
0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72,
0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x0c, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d,
0x65, 0x6e, 0x74, 0x73, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
0x22, 0x1f, 0x0a, 0x0b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x12,
0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61,
0x67, 0x22, 0xee, 0x01, 0x0a, 0x0c, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e,
0x74, 0x73, 0x12, 0x69, 0x0a, 0x0f, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x72, 0x65, 0x73, 0x6f,
0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x61, 0x70,
0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x71,
0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, 0x78, 0x74, 0x72, 0x61, 0x52,
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x65,
0x78, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, 0x73, 0x0a,
0x13, 0x45, 0x78, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45,
0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x46, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e,
0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76,
0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53,
0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
0x38, 0x01, 0x22, 0xc3, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53,
0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x70, 0x69, 0x5f, 0x76,
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70,
0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x1f, 0x0a, 0x0a,
0x6d, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
0x48, 0x00, 0x52, 0x09, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x50, 0x0a,
0x0c, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x04, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
0x65, 0x6e, 0x74, 0x73, 0x12, 0x49, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f,
0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78,
0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74,
0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42,
0x0a, 0x0a, 0x08, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x1f, 0x0a, 0x0b, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61,
0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0xee, 0x01, 0x0a,
0x0c, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x69, 0x0a,
0x0f, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65,
0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d,
0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, 0x78, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72,
0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x72, 0x61, 0x52,
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, 0x73, 0x0a, 0x13, 0x45, 0x78, 0x74, 0x72,
0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
0x79, 0x12, 0x46, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x30, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73,
0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61,
0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74,
0x6f, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc3, 0x01,
0x0a, 0x10, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74,
0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x70, 0x69, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73,
0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x1f, 0x0a, 0x0a, 0x6d, 0x61, 0x74, 0x63, 0x68,
0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x6d,
0x61, 0x74, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x50, 0x0a, 0x0c, 0x6d, 0x61, 0x74, 0x63,
0x68, 0x5f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b,
0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66,
0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e,
0x4d, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x48, 0x00, 0x52, 0x0b, 0x6d,
0x61, 0x74, 0x63, 0x68, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x42, 0x07, 0x0a, 0x05, 0x6d, 0x61,
0x74, 0x63, 0x68, 0x22, 0x99, 0x01, 0x0a, 0x0b, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x61, 0x62,
0x65, 0x6c, 0x73, 0x12, 0x4f, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62,
0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73,
0x48, 0x00, 0x52, 0x0b, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x42,
0x07, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x22, 0x99, 0x01, 0x0a, 0x0b, 0x4d, 0x61, 0x74,
0x63, 0x68, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x4f, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65,
0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78,
0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61,
0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e,
0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22,
0x5a, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12,
0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61,
0x67, 0x12, 0x30, 0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x03, 0x74, 0x74, 0x6c,
0x88, 0x01, 0x01, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x74, 0x74, 0x6c, 0x22, 0x8b, 0x02, 0x0a, 0x05,
0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x46, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69,
0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78,
0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4c,
0x61, 0x62, 0x65, 0x6c, 0x73, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72,
0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62,
0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
0x3a, 0x02, 0x38, 0x01, 0x22, 0x5a, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x4d, 0x65, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x30, 0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00,
0x52, 0x03, 0x74, 0x74, 0x6c, 0x88, 0x01, 0x01, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x74, 0x74, 0x6c,
0x22, 0x8b, 0x02, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x46, 0x0a, 0x09, 0x63, 0x6f,
0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e,
0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52,
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69,
0x74, 0x65, 0x12, 0x52, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18,
0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e,
0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76,
0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x73,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x72, 0x65, 0x73,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, 0x66, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72,
0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3e, 0x0a, 0x05, 0x76, 0x61,
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x61, 0x70, 0x69, 0x65,
0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75,
0x72, 0x63, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xb2,
0x02, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x08, 0x72,
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x12, 0x6e, 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64,
0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x61,
0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65,
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x63,
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73,
0x12, 0x3b, 0x0a, 0x05, 0x72, 0x65, 0x61, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32,
0x25, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e,
0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31,
0x2e, 0x52, 0x65, 0x61, 0x64, 0x79, 0x52, 0x05, 0x72, 0x65, 0x61, 0x64, 0x79, 0x1a, 0x44, 0x0a,
0x16, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x61, 0x69,
0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c,
0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a,
0x02, 0x38, 0x01, 0x22, 0x68, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x44, 0x0a,
0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32,
0x28, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e,
0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31,
0x2e, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72,
0x69, 0x74, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2a, 0x3f, 0x0a,
0x05, 0x52, 0x65, 0x61, 0x64, 0x79, 0x12, 0x15, 0x0a, 0x11, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f,
0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a,
0x0a, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x54, 0x52, 0x55, 0x45, 0x10, 0x01, 0x12, 0x0f, 0x0a,
0x0b, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x46, 0x41, 0x4c, 0x53, 0x45, 0x10, 0x02, 0x2a, 0x63,
0x0a, 0x08, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x45,
0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49,
0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59,
0x5f, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x45, 0x56, 0x45,
0x52, 0x49, 0x54, 0x59, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x13,
0x0a, 0x0f, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41,
0x4c, 0x10, 0x03, 0x32, 0x91, 0x01, 0x0a, 0x15, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x78, 0x0a,
0x0b, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x2e, 0x61,
0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x75,
0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x33, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73,
0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72,
0x63, 0x65, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x12, 0x52, 0x0a,
0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x34, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73,
0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61,
0x31, 0x2e, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x46, 0x5a, 0x44, 0x67, 0x69, 0x74, 0x68, 0x75,
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x70, 0x6c, 0x61, 0x6e, 0x65,
0x2f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x73,
0x2f, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x66,
0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x73, 0x1a, 0x66, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e,
0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73,
0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31,
0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x05,
0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xb2, 0x02, 0x0a, 0x08, 0x52, 0x65,
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63,
0x74, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x6e, 0x0a, 0x12, 0x63,
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c,
0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74,
0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x61,
0x69, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x3b, 0x0a, 0x05, 0x72,
0x65, 0x61, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x61, 0x70, 0x69,
0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64,
0x79, 0x52, 0x05, 0x72, 0x65, 0x61, 0x64, 0x79, 0x1a, 0x44, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x6e,
0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x45, 0x6e, 0x74,
0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xe0,
0x01, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x44, 0x0a, 0x08, 0x73, 0x65, 0x76,
0x65, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x61, 0x70,
0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x76,
0x65, 0x72, 0x69, 0x74, 0x79, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12,
0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x06, 0x72, 0x65, 0x61,
0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x61,
0x73, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x43, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65,
0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x01,
0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f,
0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65,
0x74, 0x22, 0xf2, 0x01, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12,
0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74,
0x79, 0x70, 0x65, 0x12, 0x3e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62,
0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61,
0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20,
0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x07, 0x6d,
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x07,
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x43, 0x0a, 0x06, 0x74, 0x61,
0x72, 0x67, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x61, 0x70, 0x69,
0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x54, 0x61, 0x72, 0x67,
0x65, 0x74, 0x48, 0x01, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x88, 0x01, 0x01, 0x42,
0x0a, 0x0a, 0x08, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x5f,
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2a, 0x3f, 0x0a, 0x05, 0x52, 0x65, 0x61, 0x64, 0x79, 0x12,
0x15, 0x0a, 0x11, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49,
0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f,
0x54, 0x52, 0x55, 0x45, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f,
0x46, 0x41, 0x4c, 0x53, 0x45, 0x10, 0x02, 0x2a, 0x63, 0x0a, 0x08, 0x53, 0x65, 0x76, 0x65, 0x72,
0x69, 0x74, 0x79, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f,
0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a,
0x0e, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x10,
0x01, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x57, 0x41,
0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x45, 0x56, 0x45, 0x52,
0x49, 0x54, 0x59, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x03, 0x2a, 0x56, 0x0a, 0x06,
0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x12, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54,
0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14,
0x0a, 0x10, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x53, 0x49,
0x54, 0x45, 0x10, 0x01, 0x12, 0x1e, 0x0a, 0x1a, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x43,
0x4f, 0x4d, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x45, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x43, 0x4c, 0x41,
0x49, 0x4d, 0x10, 0x02, 0x2a, 0x7f, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20,
0x0a, 0x1c, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49,
0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00,
0x12, 0x1c, 0x0a, 0x18, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x4f, 0x4e, 0x44, 0x49,
0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x01, 0x12, 0x19,
0x0a, 0x15, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49,
0x4f, 0x4e, 0x5f, 0x54, 0x52, 0x55, 0x45, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x54, 0x41,
0x54, 0x55, 0x53, 0x5f, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x46, 0x41,
0x4c, 0x53, 0x45, 0x10, 0x03, 0x32, 0x91, 0x01, 0x0a, 0x15, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12,
0x78, 0x0a, 0x0b, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x32,
0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66,
0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e,
0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x33, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65,
0x74, 0x61, 0x31, 0x2e, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x46, 0x5a, 0x44, 0x67, 0x69, 0x74,
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x70, 0x6c, 0x61,
0x6e, 0x65, 0x2f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70,
0x69, 0x73, 0x2f, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73,
0x2f, 0x66, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61,
0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@ -1298,71 +1568,78 @@ func file_apiextensions_fn_proto_v1beta1_run_function_proto_rawDescGZIP() []byte
return file_apiextensions_fn_proto_v1beta1_run_function_proto_rawDescData
}
var file_apiextensions_fn_proto_v1beta1_run_function_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_apiextensions_fn_proto_v1beta1_run_function_proto_msgTypes = make([]protoimpl.MessageInfo, 20)
var file_apiextensions_fn_proto_v1beta1_run_function_proto_enumTypes = make([]protoimpl.EnumInfo, 4)
var file_apiextensions_fn_proto_v1beta1_run_function_proto_msgTypes = make([]protoimpl.MessageInfo, 21)
var file_apiextensions_fn_proto_v1beta1_run_function_proto_goTypes = []interface{}{
(Ready)(0), // 0: apiextensions.fn.proto.v1beta1.Ready
(Severity)(0), // 1: apiextensions.fn.proto.v1beta1.Severity
(*RunFunctionRequest)(nil), // 2: apiextensions.fn.proto.v1beta1.RunFunctionRequest
(*Credentials)(nil), // 3: apiextensions.fn.proto.v1beta1.Credentials
(*CredentialData)(nil), // 4: apiextensions.fn.proto.v1beta1.CredentialData
(*Resources)(nil), // 5: apiextensions.fn.proto.v1beta1.Resources
(*RunFunctionResponse)(nil), // 6: apiextensions.fn.proto.v1beta1.RunFunctionResponse
(*RequestMeta)(nil), // 7: apiextensions.fn.proto.v1beta1.RequestMeta
(*Requirements)(nil), // 8: apiextensions.fn.proto.v1beta1.Requirements
(*ResourceSelector)(nil), // 9: apiextensions.fn.proto.v1beta1.ResourceSelector
(*MatchLabels)(nil), // 10: apiextensions.fn.proto.v1beta1.MatchLabels
(*ResponseMeta)(nil), // 11: apiextensions.fn.proto.v1beta1.ResponseMeta
(*State)(nil), // 12: apiextensions.fn.proto.v1beta1.State
(*Resource)(nil), // 13: apiextensions.fn.proto.v1beta1.Resource
(*Result)(nil), // 14: apiextensions.fn.proto.v1beta1.Result
nil, // 15: apiextensions.fn.proto.v1beta1.RunFunctionRequest.ExtraResourcesEntry
nil, // 16: apiextensions.fn.proto.v1beta1.RunFunctionRequest.CredentialsEntry
nil, // 17: apiextensions.fn.proto.v1beta1.CredentialData.DataEntry
nil, // 18: apiextensions.fn.proto.v1beta1.Requirements.ExtraResourcesEntry
nil, // 19: apiextensions.fn.proto.v1beta1.MatchLabels.LabelsEntry
nil, // 20: apiextensions.fn.proto.v1beta1.State.ResourcesEntry
nil, // 21: apiextensions.fn.proto.v1beta1.Resource.ConnectionDetailsEntry
(*structpb.Struct)(nil), // 22: google.protobuf.Struct
(*durationpb.Duration)(nil), // 23: google.protobuf.Duration
(Target)(0), // 2: apiextensions.fn.proto.v1beta1.Target
(Status)(0), // 3: apiextensions.fn.proto.v1beta1.Status
(*RunFunctionRequest)(nil), // 4: apiextensions.fn.proto.v1beta1.RunFunctionRequest
(*Credentials)(nil), // 5: apiextensions.fn.proto.v1beta1.Credentials
(*CredentialData)(nil), // 6: apiextensions.fn.proto.v1beta1.CredentialData
(*Resources)(nil), // 7: apiextensions.fn.proto.v1beta1.Resources
(*RunFunctionResponse)(nil), // 8: apiextensions.fn.proto.v1beta1.RunFunctionResponse
(*RequestMeta)(nil), // 9: apiextensions.fn.proto.v1beta1.RequestMeta
(*Requirements)(nil), // 10: apiextensions.fn.proto.v1beta1.Requirements
(*ResourceSelector)(nil), // 11: apiextensions.fn.proto.v1beta1.ResourceSelector
(*MatchLabels)(nil), // 12: apiextensions.fn.proto.v1beta1.MatchLabels
(*ResponseMeta)(nil), // 13: apiextensions.fn.proto.v1beta1.ResponseMeta
(*State)(nil), // 14: apiextensions.fn.proto.v1beta1.State
(*Resource)(nil), // 15: apiextensions.fn.proto.v1beta1.Resource
(*Result)(nil), // 16: apiextensions.fn.proto.v1beta1.Result
(*Condition)(nil), // 17: apiextensions.fn.proto.v1beta1.Condition
nil, // 18: apiextensions.fn.proto.v1beta1.RunFunctionRequest.ExtraResourcesEntry
nil, // 19: apiextensions.fn.proto.v1beta1.RunFunctionRequest.CredentialsEntry
nil, // 20: apiextensions.fn.proto.v1beta1.CredentialData.DataEntry
nil, // 21: apiextensions.fn.proto.v1beta1.Requirements.ExtraResourcesEntry
nil, // 22: apiextensions.fn.proto.v1beta1.MatchLabels.LabelsEntry
nil, // 23: apiextensions.fn.proto.v1beta1.State.ResourcesEntry
nil, // 24: apiextensions.fn.proto.v1beta1.Resource.ConnectionDetailsEntry
(*structpb.Struct)(nil), // 25: google.protobuf.Struct
(*durationpb.Duration)(nil), // 26: google.protobuf.Duration
}
var file_apiextensions_fn_proto_v1beta1_run_function_proto_depIdxs = []int32{
7, // 0: apiextensions.fn.proto.v1beta1.RunFunctionRequest.meta:type_name -> apiextensions.fn.proto.v1beta1.RequestMeta
12, // 1: apiextensions.fn.proto.v1beta1.RunFunctionRequest.observed:type_name -> apiextensions.fn.proto.v1beta1.State
12, // 2: apiextensions.fn.proto.v1beta1.RunFunctionRequest.desired:type_name -> apiextensions.fn.proto.v1beta1.State
22, // 3: apiextensions.fn.proto.v1beta1.RunFunctionRequest.input:type_name -> google.protobuf.Struct
22, // 4: apiextensions.fn.proto.v1beta1.RunFunctionRequest.context:type_name -> google.protobuf.Struct
15, // 5: apiextensions.fn.proto.v1beta1.RunFunctionRequest.extra_resources:type_name -> apiextensions.fn.proto.v1beta1.RunFunctionRequest.ExtraResourcesEntry
16, // 6: apiextensions.fn.proto.v1beta1.RunFunctionRequest.credentials:type_name -> apiextensions.fn.proto.v1beta1.RunFunctionRequest.CredentialsEntry
4, // 7: apiextensions.fn.proto.v1beta1.Credentials.credential_data:type_name -> apiextensions.fn.proto.v1beta1.CredentialData
17, // 8: apiextensions.fn.proto.v1beta1.CredentialData.data:type_name -> apiextensions.fn.proto.v1beta1.CredentialData.DataEntry
13, // 9: apiextensions.fn.proto.v1beta1.Resources.items:type_name -> apiextensions.fn.proto.v1beta1.Resource
11, // 10: apiextensions.fn.proto.v1beta1.RunFunctionResponse.meta:type_name -> apiextensions.fn.proto.v1beta1.ResponseMeta
12, // 11: apiextensions.fn.proto.v1beta1.RunFunctionResponse.desired:type_name -> apiextensions.fn.proto.v1beta1.State
14, // 12: apiextensions.fn.proto.v1beta1.RunFunctionResponse.results:type_name -> apiextensions.fn.proto.v1beta1.Result
22, // 13: apiextensions.fn.proto.v1beta1.RunFunctionResponse.context:type_name -> google.protobuf.Struct
8, // 14: apiextensions.fn.proto.v1beta1.RunFunctionResponse.requirements:type_name -> apiextensions.fn.proto.v1beta1.Requirements
18, // 15: apiextensions.fn.proto.v1beta1.Requirements.extra_resources:type_name -> apiextensions.fn.proto.v1beta1.Requirements.ExtraResourcesEntry
10, // 16: apiextensions.fn.proto.v1beta1.ResourceSelector.match_labels:type_name -> apiextensions.fn.proto.v1beta1.MatchLabels
19, // 17: apiextensions.fn.proto.v1beta1.MatchLabels.labels:type_name -> apiextensions.fn.proto.v1beta1.MatchLabels.LabelsEntry
23, // 18: apiextensions.fn.proto.v1beta1.ResponseMeta.ttl:type_name -> google.protobuf.Duration
13, // 19: apiextensions.fn.proto.v1beta1.State.composite:type_name -> apiextensions.fn.proto.v1beta1.Resource
20, // 20: apiextensions.fn.proto.v1beta1.State.resources:type_name -> apiextensions.fn.proto.v1beta1.State.ResourcesEntry
22, // 21: apiextensions.fn.proto.v1beta1.Resource.resource:type_name -> google.protobuf.Struct
21, // 22: apiextensions.fn.proto.v1beta1.Resource.connection_details:type_name -> apiextensions.fn.proto.v1beta1.Resource.ConnectionDetailsEntry
0, // 23: apiextensions.fn.proto.v1beta1.Resource.ready:type_name -> apiextensions.fn.proto.v1beta1.Ready
1, // 24: apiextensions.fn.proto.v1beta1.Result.severity:type_name -> apiextensions.fn.proto.v1beta1.Severity
5, // 25: apiextensions.fn.proto.v1beta1.RunFunctionRequest.ExtraResourcesEntry.value:type_name -> apiextensions.fn.proto.v1beta1.Resources
3, // 26: apiextensions.fn.proto.v1beta1.RunFunctionRequest.CredentialsEntry.value:type_name -> apiextensions.fn.proto.v1beta1.Credentials
9, // 27: apiextensions.fn.proto.v1beta1.Requirements.ExtraResourcesEntry.value:type_name -> apiextensions.fn.proto.v1beta1.ResourceSelector
13, // 28: apiextensions.fn.proto.v1beta1.State.ResourcesEntry.value:type_name -> apiextensions.fn.proto.v1beta1.Resource
2, // 29: apiextensions.fn.proto.v1beta1.FunctionRunnerService.RunFunction:input_type -> apiextensions.fn.proto.v1beta1.RunFunctionRequest
6, // 30: apiextensions.fn.proto.v1beta1.FunctionRunnerService.RunFunction:output_type -> apiextensions.fn.proto.v1beta1.RunFunctionResponse
30, // [30:31] is the sub-list for method output_type
29, // [29:30] is the sub-list for method input_type
29, // [29:29] is the sub-list for extension type_name
29, // [29:29] is the sub-list for extension extendee
0, // [0:29] is the sub-list for field type_name
9, // 0: apiextensions.fn.proto.v1beta1.RunFunctionRequest.meta:type_name -> apiextensions.fn.proto.v1beta1.RequestMeta
14, // 1: apiextensions.fn.proto.v1beta1.RunFunctionRequest.observed:type_name -> apiextensions.fn.proto.v1beta1.State
14, // 2: apiextensions.fn.proto.v1beta1.RunFunctionRequest.desired:type_name -> apiextensions.fn.proto.v1beta1.State
25, // 3: apiextensions.fn.proto.v1beta1.RunFunctionRequest.input:type_name -> google.protobuf.Struct
25, // 4: apiextensions.fn.proto.v1beta1.RunFunctionRequest.context:type_name -> google.protobuf.Struct
18, // 5: apiextensions.fn.proto.v1beta1.RunFunctionRequest.extra_resources:type_name -> apiextensions.fn.proto.v1beta1.RunFunctionRequest.ExtraResourcesEntry
19, // 6: apiextensions.fn.proto.v1beta1.RunFunctionRequest.credentials:type_name -> apiextensions.fn.proto.v1beta1.RunFunctionRequest.CredentialsEntry
6, // 7: apiextensions.fn.proto.v1beta1.Credentials.credential_data:type_name -> apiextensions.fn.proto.v1beta1.CredentialData
20, // 8: apiextensions.fn.proto.v1beta1.CredentialData.data:type_name -> apiextensions.fn.proto.v1beta1.CredentialData.DataEntry
15, // 9: apiextensions.fn.proto.v1beta1.Resources.items:type_name -> apiextensions.fn.proto.v1beta1.Resource
13, // 10: apiextensions.fn.proto.v1beta1.RunFunctionResponse.meta:type_name -> apiextensions.fn.proto.v1beta1.ResponseMeta
14, // 11: apiextensions.fn.proto.v1beta1.RunFunctionResponse.desired:type_name -> apiextensions.fn.proto.v1beta1.State
16, // 12: apiextensions.fn.proto.v1beta1.RunFunctionResponse.results:type_name -> apiextensions.fn.proto.v1beta1.Result
25, // 13: apiextensions.fn.proto.v1beta1.RunFunctionResponse.context:type_name -> google.protobuf.Struct
10, // 14: apiextensions.fn.proto.v1beta1.RunFunctionResponse.requirements:type_name -> apiextensions.fn.proto.v1beta1.Requirements
17, // 15: apiextensions.fn.proto.v1beta1.RunFunctionResponse.conditions:type_name -> apiextensions.fn.proto.v1beta1.Condition
21, // 16: apiextensions.fn.proto.v1beta1.Requirements.extra_resources:type_name -> apiextensions.fn.proto.v1beta1.Requirements.ExtraResourcesEntry
12, // 17: apiextensions.fn.proto.v1beta1.ResourceSelector.match_labels:type_name -> apiextensions.fn.proto.v1beta1.MatchLabels
22, // 18: apiextensions.fn.proto.v1beta1.MatchLabels.labels:type_name -> apiextensions.fn.proto.v1beta1.MatchLabels.LabelsEntry
26, // 19: apiextensions.fn.proto.v1beta1.ResponseMeta.ttl:type_name -> google.protobuf.Duration
15, // 20: apiextensions.fn.proto.v1beta1.State.composite:type_name -> apiextensions.fn.proto.v1beta1.Resource
23, // 21: apiextensions.fn.proto.v1beta1.State.resources:type_name -> apiextensions.fn.proto.v1beta1.State.ResourcesEntry
25, // 22: apiextensions.fn.proto.v1beta1.Resource.resource:type_name -> google.protobuf.Struct
24, // 23: apiextensions.fn.proto.v1beta1.Resource.connection_details:type_name -> apiextensions.fn.proto.v1beta1.Resource.ConnectionDetailsEntry
0, // 24: apiextensions.fn.proto.v1beta1.Resource.ready:type_name -> apiextensions.fn.proto.v1beta1.Ready
1, // 25: apiextensions.fn.proto.v1beta1.Result.severity:type_name -> apiextensions.fn.proto.v1beta1.Severity
2, // 26: apiextensions.fn.proto.v1beta1.Result.target:type_name -> apiextensions.fn.proto.v1beta1.Target
3, // 27: apiextensions.fn.proto.v1beta1.Condition.status:type_name -> apiextensions.fn.proto.v1beta1.Status
2, // 28: apiextensions.fn.proto.v1beta1.Condition.target:type_name -> apiextensions.fn.proto.v1beta1.Target
7, // 29: apiextensions.fn.proto.v1beta1.RunFunctionRequest.ExtraResourcesEntry.value:type_name -> apiextensions.fn.proto.v1beta1.Resources
5, // 30: apiextensions.fn.proto.v1beta1.RunFunctionRequest.CredentialsEntry.value:type_name -> apiextensions.fn.proto.v1beta1.Credentials
11, // 31: apiextensions.fn.proto.v1beta1.Requirements.ExtraResourcesEntry.value:type_name -> apiextensions.fn.proto.v1beta1.ResourceSelector
15, // 32: apiextensions.fn.proto.v1beta1.State.ResourcesEntry.value:type_name -> apiextensions.fn.proto.v1beta1.Resource
4, // 33: apiextensions.fn.proto.v1beta1.FunctionRunnerService.RunFunction:input_type -> apiextensions.fn.proto.v1beta1.RunFunctionRequest
8, // 34: apiextensions.fn.proto.v1beta1.FunctionRunnerService.RunFunction:output_type -> apiextensions.fn.proto.v1beta1.RunFunctionResponse
34, // [34:35] is the sub-list for method output_type
33, // [33:34] is the sub-list for method input_type
33, // [33:33] is the sub-list for extension type_name
33, // [33:33] is the sub-list for extension extendee
0, // [0:33] is the sub-list for field type_name
}
func init() { file_apiextensions_fn_proto_v1beta1_run_function_proto_init() }
@ -1527,6 +1804,18 @@ func file_apiextensions_fn_proto_v1beta1_run_function_proto_init() {
return nil
}
}
file_apiextensions_fn_proto_v1beta1_run_function_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Condition); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_apiextensions_fn_proto_v1beta1_run_function_proto_msgTypes[0].OneofWrappers = []interface{}{}
file_apiextensions_fn_proto_v1beta1_run_function_proto_msgTypes[1].OneofWrappers = []interface{}{
@ -1538,13 +1827,15 @@ func file_apiextensions_fn_proto_v1beta1_run_function_proto_init() {
(*ResourceSelector_MatchLabels)(nil),
}
file_apiextensions_fn_proto_v1beta1_run_function_proto_msgTypes[9].OneofWrappers = []interface{}{}
file_apiextensions_fn_proto_v1beta1_run_function_proto_msgTypes[12].OneofWrappers = []interface{}{}
file_apiextensions_fn_proto_v1beta1_run_function_proto_msgTypes[13].OneofWrappers = []interface{}{}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_apiextensions_fn_proto_v1beta1_run_function_proto_rawDesc,
NumEnums: 2,
NumMessages: 20,
NumEnums: 4,
NumMessages: 21,
NumExtensions: 0,
NumServices: 1,
},

View File

@ -121,6 +121,10 @@ message RunFunctionResponse {
// Requirements that must be satisfied for this Function to run successfully.
Requirements requirements = 5;
// Status conditions to be applied to the composite resource. Conditions may also
// optionally be applied to the composite resource's associated claim.
repeated Condition conditions = 6;
}
// RequestMeta contains metadata pertaining to a RunFunctionRequest.
@ -243,6 +247,13 @@ message Result {
// Human-readable details about the result.
string message = 2;
// Optional PascalCase, machine-readable reason for this result. If omitted,
// the value will be ComposeResources.
optional string reason = 3;
// The resources this result targets.
optional Target target = 4;
}
// Severity of Function results.
@ -262,4 +273,54 @@ enum Severity {
// Normal results are emitted as normal events and debug logs associated
// with the composite resource.
SEVERITY_NORMAL = 3;
}
}
// Target of Function results and conditions.
enum Target {
// If the target is unspecified, the result targets the composite resource.
TARGET_UNSPECIFIED = 0;
// Target the composite resource. Results that target the composite resource
// should include detailed, advanced information.
TARGET_COMPOSITE = 1;
// Target the composite and the claim. Results that target the composite and
// the claim should include only end-user friendly information.
TARGET_COMPOSITE_AND_CLAIM = 2;
}
// Status condition to be applied to the composite resource. Condition may also
// optionally be applied to the composite resource's associated claim. For
// detailed information on proper usage of status conditions, please see
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties.
message Condition {
// Type of condition in PascalCase.
string type = 1;
// Status of the condition.
Status status = 2;
// Reason contains a programmatic identifier indicating the reason for the
// condition's last transition. Producers of specific condition types may
// define expected values and meanings for this field, and whether the values
// are considered a guaranteed API. The value should be a PascalCase string.
// This field may not be empty.
string reason = 3;
// Message is a human readable message indicating details about the
// transition. This may be an empty string.
optional string message = 4;
// The resources this condition targets.
optional Target target = 5;
}
enum Status {
STATUS_CONDITION_UNSPECIFIED = 0;
STATUS_CONDITION_UNKNOWN = 1;
STATUS_CONDITION_TRUE = 2;
STATUS_CONDITION_FALSE = 3;
}

View File

@ -526,6 +526,15 @@ func TestConvertToCRDs(t *testing.T) {
},
},
},
"claimConditionTypes": {
Type: "array",
XListType: ptr.To("set"),
Items: &extv1.JSONSchemaPropsOrArray{
Schema: &extv1.JSONSchemaProps{
Type: "string",
},
},
},
"connectionDetails": {
Type: "object",
Properties: map[string]extv1.JSONSchemaProps{
@ -869,6 +878,15 @@ func TestConvertToCRDs(t *testing.T) {
},
},
},
"claimConditionTypes": {
Type: "array",
XListType: ptr.To("set"),
Items: &extv1.JSONSchemaPropsOrArray{
Schema: &extv1.JSONSchemaProps{
Type: "string",
},
},
},
"connectionDetails": {
Type: "object",
Properties: map[string]extv1.JSONSchemaProps{
@ -1113,6 +1131,15 @@ func TestConvertToCRDs(t *testing.T) {
},
},
},
"claimConditionTypes": {
Type: "array",
XListType: ptr.To("set"),
Items: &extv1.JSONSchemaPropsOrArray{
Schema: &extv1.JSONSchemaProps{
Type: "string",
},
},
},
"connectionDetails": {
Type: "object",
Properties: map[string]extv1.JSONSchemaProps{

8
go.mod
View File

@ -9,7 +9,7 @@ require (
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24
github.com/Masterminds/semver v1.5.0
github.com/alecthomas/kong v0.9.0
github.com/crossplane/crossplane-runtime v1.17.0-rc.0.0.20240520203451-fc036618ffd8
github.com/crossplane/crossplane-runtime v1.17.0-rc.0.0.20240628014613-063a0273907b
github.com/docker/docker v25.0.5+incompatible
github.com/docker/go-connections v0.5.0
github.com/emicklei/dot v1.6.2
@ -120,7 +120,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/sso v1.12.10 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.10 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.19.0 // indirect
github.com/aws/smithy-go v1.20.2
github.com/aws/smithy-go v1.20.2 // indirect
github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20230510185313-f5e39e5f34c7 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
@ -134,11 +134,11 @@ require (
github.com/docker/docker-credential-helpers v0.8.2
github.com/docker/go-units v0.5.0 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/evanphx/json-patch v5.9.0+incompatible // indirect
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-logr/zapr v1.3.0 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect

12
go.sum
View File

@ -125,8 +125,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/crossplane/crossplane-runtime v1.17.0-rc.0.0.20240520203451-fc036618ffd8 h1:4OtdWor2ixE1Nk+96//Knf63wRiyKFnxFcJx4iM+WY0=
github.com/crossplane/crossplane-runtime v1.17.0-rc.0.0.20240520203451-fc036618ffd8/go.mod h1:aZ1ODIvtOPFFVZ9oo3qVH/MQHuim24qWg2Tj6n+AIf4=
github.com/crossplane/crossplane-runtime v1.17.0-rc.0.0.20240628014613-063a0273907b h1:XNYG9Px6WsZ8OvfZ/hPDtnglK2jAmmkox1/JUZjXE9I=
github.com/crossplane/crossplane-runtime v1.17.0-rc.0.0.20240628014613-063a0273907b/go.mod h1:saPoKGl3PfzzL8Q6PH+/cIjD0ssrmHW/gmiqstWy+0Q=
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0=
@ -169,8 +169,8 @@ github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U=
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls=
github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg=
github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
@ -195,8 +195,8 @@ github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod
github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys=
github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=

View File

@ -473,6 +473,12 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reco
cm.SetConditions(xpv1.ReconcileSuccess())
// Copy any custom status conditions from the XR to the claim.
for _, cType := range xr.GetClaimConditionTypes() {
c := xr.GetCondition(cType)
cm.SetConditions(c)
}
if !resource.IsConditionTrue(xr.GetCondition(xpv1.TypeReady)) {
record.Event(cm, event.Normal(reasonBind, "Composite resource is not yet ready"))

View File

@ -535,6 +535,93 @@ func TestReconcile(t *testing.T) {
r: reconcile.Result{Requeue: false},
},
},
"ClaimConditions": {
reason: "We should copy custom conditions from the XR if seen in the claimConditions array.",
args: args{
client: &test.MockClient{
MockGet: test.NewMockGetFn(nil, func(obj client.Object) error {
switch o := obj.(type) {
case *claim.Unstructured:
// We won't try to get an XR unless the claim
// references one.
o.SetResourceReference(&corev1.ObjectReference{Name: "cool-composite"})
// The system conditions are already set.
o.SetConditions(xpv1.ReconcileSuccess())
o.SetConditions(xpv1.Available())
// Database was marked as creating in a prior reconciliation.
o.SetConditions(xpv1.Condition{
Type: "DatabaseReady",
Status: corev1.ConditionFalse,
Reason: "Creating",
})
case *composite.Unstructured:
// Pretend the XR exists and is available.
o.SetCreationTimestamp(now)
o.SetClaimReference(&claim.Reference{})
o.SetConditions(xpv1.Available())
o.SetConditions(
// Database has become ready.
xpv1.Condition{
Type: "DatabaseReady",
Status: corev1.ConditionTrue,
Reason: "Available",
},
// Bucket is a new condition.
xpv1.Condition{
Type: "BucketReady",
Status: corev1.ConditionFalse,
Reason: "Creating",
},
// Internal condition should not be copied over as it is not in
// claimConditions.
xpv1.Condition{
Type: "InternalSync",
Status: corev1.ConditionFalse,
Reason: "Syncing",
},
)
// Database and Bucket are claim conditions so they should be
// copied over.
o.SetClaimConditionTypes("DatabaseReady", "BucketReady")
}
return nil
}),
MockStatusUpdate: WantClaim(t, NewClaim(func(cm *claim.Unstructured) {
// Check that we set our status condition.
cm.SetResourceReference(&corev1.ObjectReference{Name: "cool-composite"})
cm.SetConnectionDetailsLastPublishedTime(&now)
cm.SetConditions(xpv1.ReconcileSuccess())
cm.SetConditions(xpv1.Available())
cm.SetConditions(
// Database condition should have been updated to show ready.
xpv1.Condition{
Type: "DatabaseReady",
Status: corev1.ConditionTrue,
Reason: "Available",
},
// Bucket condition should have been created.
xpv1.Condition{
Type: "BucketReady",
Status: corev1.ConditionFalse,
Reason: "Creating",
},
)
})),
},
opts: []ReconcilerOption{
WithClaimFinalizer(resource.FinalizerFns{
AddFinalizerFn: func(_ context.Context, _ resource.Object) error { return nil },
}),
WithCompositeSyncer(CompositeSyncerFn(func(_ context.Context, _ *claim.Unstructured, _ *composite.Unstructured) error { return nil })),
WithConnectionPropagator(ConnectionPropagatorFn(func(_ context.Context, _ resource.LocalConnectionSecretOwner, _ resource.ConnectionSecretOwner) (propagated bool, err error) {
return true, nil
})),
},
},
want: want{
r: reconcile.Result{Requeue: false},
},
},
}
for name, tc := range cases {

View File

@ -34,6 +34,7 @@ import (
"k8s.io/apimachinery/pkg/util/json"
"sigs.k8s.io/controller-runtime/pkg/client"
xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
"github.com/crossplane/crossplane-runtime/pkg/errors"
"github.com/crossplane/crossplane-runtime/pkg/event"
"github.com/crossplane/crossplane-runtime/pkg/meta"
@ -291,7 +292,8 @@ func (c *FunctionComposer) Compose(ctx context.Context, xr *composite.Unstructur
// The Function pipeline starts with empty desired state.
d := &v1beta1.State{}
events := []event.Event{}
events := []TargetedEvent{}
conditions := []TargetedCondition{}
// The Function context starts empty...
fctx := &structpb.Struct{Fields: map[string]*structpb.Value{}}
@ -397,22 +399,58 @@ func (c *FunctionComposer) Compose(ctx context.Context, xr *composite.Unstructur
// We intentionally discard/ignore this after the last Function runs.
fctx = rsp.GetContext()
for _, c := range rsp.GetConditions() {
var status corev1.ConditionStatus
switch c.GetStatus() {
case v1beta1.Status_STATUS_CONDITION_TRUE:
status = corev1.ConditionTrue
case v1beta1.Status_STATUS_CONDITION_FALSE:
status = corev1.ConditionFalse
case v1beta1.Status_STATUS_CONDITION_UNKNOWN, v1beta1.Status_STATUS_CONDITION_UNSPECIFIED:
status = corev1.ConditionUnknown
}
conditions = append(conditions, TargetedCondition{
Condition: xpv1.Condition{
Type: xpv1.ConditionType(c.GetType()),
Status: status,
LastTransitionTime: metav1.Now(),
Reason: xpv1.ConditionReason(c.GetReason()),
Message: c.GetMessage(),
},
Target: convertTarget(c.GetTarget()),
})
}
// Results of fatal severity stop the Composition process. Other results
// are accumulated to be emitted as events by the Reconciler.
for _, rs := range rsp.GetResults() {
reason := event.Reason(rs.GetReason())
if reason == "" {
reason = reasonCompose
}
e := TargetedEvent{Target: convertTarget(rs.GetTarget())}
switch rs.GetSeverity() {
case v1beta1.Severity_SEVERITY_FATAL:
return CompositionResult{}, errors.Errorf(errFmtFatalResult, fn.Step, rs.GetMessage())
return CompositionResult{Events: events, Conditions: conditions}, errors.Errorf(errFmtFatalResult, fn.Step, rs.GetMessage())
case v1beta1.Severity_SEVERITY_WARNING:
events = append(events, event.Warning(reasonCompose, errors.Errorf("Pipeline step %q: %s", fn.Step, rs.GetMessage())))
e.Event = event.Warning(reason, errors.New(rs.GetMessage()))
e.Detail = fmt.Sprintf("Pipeline step %q", fn.Step)
case v1beta1.Severity_SEVERITY_NORMAL:
events = append(events, event.Normal(reasonCompose, fmt.Sprintf("Pipeline step %q: %s", fn.Step, rs.GetMessage())))
e.Event = event.Normal(reason, rs.GetMessage())
e.Detail = fmt.Sprintf("Pipeline step %q", fn.Step)
case v1beta1.Severity_SEVERITY_UNSPECIFIED:
// We could hit this case if a Function was built against a newer
// protobuf than this build of Crossplane, and the new protobuf
// introduced a severity that we don't know about.
events = append(events, event.Warning(reasonCompose, errors.Errorf("Pipeline step %q returned a result of unknown severity (assuming warning): %s", fn.Step, rs.GetMessage())))
e.Event = event.Warning(reason, errors.Errorf("Pipeline step %q returned a result of unknown severity (assuming warning): %s", fn.Step, rs.GetMessage()))
// Explicitly target only the XR, since we're including information
// about an exceptional, unexpected state.
e.Target = CompositionTargetComposite
}
events = append(events, e)
}
}
@ -531,7 +569,10 @@ func (c *FunctionComposer) Compose(ctx context.Context, xr *composite.Unstructur
// We mark the resource as not synced, so that once we get to
// decide the XR's Synced condition, we can set it to false if
// any of the resources didn't sync successfully.
events = append(events, event.Warning(reasonCompose, errors.Wrapf(err, errFmtApplyCD, name)))
events = append(events, TargetedEvent{
Event: event.Warning(reasonCompose, errors.Wrapf(err, errFmtApplyCD, name)),
Target: CompositionTargetComposite,
})
// NOTE(phisco): here we behave differently w.r.t. the native
// p&t composer, as we respect the readiness reported by
// functions, while there we defaulted to also set ready false
@ -572,7 +613,7 @@ func (c *FunctionComposer) Compose(ctx context.Context, xr *composite.Unstructur
return CompositionResult{}, errors.Wrap(err, errApplyXRStatus)
}
return CompositionResult{ConnectionDetails: d.GetComposite().GetConnectionDetails(), Composed: resources, Events: events}, nil
return CompositionResult{ConnectionDetails: d.GetComposite().GetConnectionDetails(), Composed: resources, Events: events, Conditions: conditions}, nil
}
// ComposedFieldOwnerName generates a unique field owner name
@ -935,3 +976,10 @@ func (u *PatchingManagedFieldsUpgrader) Upgrade(ctx context.Context, obj client.
return errors.Wrap(resource.IgnoreNotFound(u.client.Patch(ctx, obj, client.RawPatch(types.JSONPatchType, p))), "cannot clear field managers")
}
}
func convertTarget(t v1beta1.Target) CompositionTarget {
if t == v1beta1.Target_TARGET_COMPOSITE_AND_CLAIM {
return CompositionTargetCompositeAndClaim
}
return CompositionTargetComposite
}

View File

@ -229,14 +229,57 @@ func TestFunctionCompose(t *testing.T) {
},
},
"FatalFunctionResultError": {
reason: "We should return any fatal function results as an error",
reason: "We should return any fatal function results as an error. Any conditions returned by the function should be passed up. Any results returned by the function prior to the fatal result should be passed up.",
params: params{
r: FunctionRunnerFn(func(_ context.Context, _ string, _ *v1beta1.RunFunctionRequest) (rsp *v1beta1.RunFunctionResponse, err error) {
r := &v1beta1.Result{
Severity: v1beta1.Severity_SEVERITY_FATAL,
Message: "oh no",
}
return &v1beta1.RunFunctionResponse{Results: []*v1beta1.Result{r}}, nil
return &v1beta1.RunFunctionResponse{
Results: []*v1beta1.Result{
// This result should be passed up as it was sent before the fatal
// result. The reason should be defaulted. The target should be
// defaulted.
{
Severity: v1beta1.Severity_SEVERITY_NORMAL,
Message: "A result before the fatal result with the default Reason.",
},
// This result should be passed up as it was sent before the fatal
// result. The reason should be kept. The target should be kept.
{
Severity: v1beta1.Severity_SEVERITY_NORMAL,
Reason: ptr.To("SomeReason"),
Message: "A result before the fatal result with a specific Reason.",
Target: v1beta1.Target_TARGET_COMPOSITE_AND_CLAIM.Enum(),
},
// The fatal result
{
Severity: v1beta1.Severity_SEVERITY_FATAL,
Message: "oh no",
},
// This result should not be passed up as it was sent after the
// fatal result.
{
Severity: v1beta1.Severity_SEVERITY_NORMAL,
Message: "a result after the fatal result",
},
},
Conditions: []*v1beta1.Condition{
// A condition returned by the function with only the minimum
// necessary values.
{
Type: "DatabaseReady",
Status: v1beta1.Status_STATUS_CONDITION_FALSE,
Reason: "Creating",
},
// A condition returned by the function with all optional values
// given.
{
Type: "DeploymentReady",
Status: v1beta1.Status_STATUS_CONDITION_TRUE,
Reason: "Available",
Message: ptr.To("The deployment is ready."),
Target: v1beta1.Target_TARGET_COMPOSITE_AND_CLAIM.Enum(),
},
},
}, nil
}),
o: []FunctionComposerOption{
WithCompositeConnectionDetailsFetcher(ConnectionDetailsFetcherFn(func(_ context.Context, _ resource.ConnectionSecretOwner) (managed.ConnectionDetails, error) {
@ -264,6 +307,51 @@ func TestFunctionCompose(t *testing.T) {
},
want: want{
err: errors.Errorf(errFmtFatalResult, "run-cool-function", "oh no"),
res: CompositionResult{
Events: []TargetedEvent{
// The event with minimum values.
{
Event: event.Event{
Type: "Normal",
Reason: "ComposeResources",
Message: "A result before the fatal result with the default Reason.",
},
Detail: "Pipeline step \"run-cool-function\"",
Target: CompositionTargetComposite,
},
// The event that provides all possible values.
{
Event: event.Event{
Type: "Normal",
Reason: "SomeReason",
Message: "A result before the fatal result with a specific Reason.",
},
Detail: "Pipeline step \"run-cool-function\"",
Target: CompositionTargetCompositeAndClaim,
},
},
Conditions: []TargetedCondition{
// The condition with minimum values.
{
Condition: xpv1.Condition{
Type: "DatabaseReady",
Status: "False",
Reason: "Creating",
},
Target: CompositionTargetComposite,
},
// The condition that provides all possible values.
{
Condition: xpv1.Condition{
Type: "DeploymentReady",
Status: "True",
Reason: "Available",
Message: "The deployment is ready.",
},
Target: CompositionTargetCompositeAndClaim,
},
},
},
},
},
"RenderComposedResourceMetadataError": {
@ -620,6 +708,30 @@ func TestFunctionCompose(t *testing.T) {
Severity: v1beta1.Severity_SEVERITY_UNSPECIFIED,
Message: "A result of unspecified severity",
},
{
Severity: v1beta1.Severity_SEVERITY_NORMAL,
Reason: ptr.To("SomeReason"),
Message: "A result with all values explicitly set.",
Target: v1beta1.Target_TARGET_COMPOSITE_AND_CLAIM.Enum(),
},
},
Conditions: []*v1beta1.Condition{
// A condition returned by the function with only the minimum
// necessary values.
{
Type: "DatabaseReady",
Status: v1beta1.Status_STATUS_CONDITION_FALSE,
Reason: "Creating",
},
// A condition returned by the function with all optional values
// given.
{
Type: "DeploymentReady",
Status: v1beta1.Status_STATUS_CONDITION_TRUE,
Reason: "Available",
Message: ptr.To("The deployment is ready."),
Target: v1beta1.Target_TARGET_COMPOSITE_AND_CLAIM.Enum(),
},
},
}
return rsp, nil
@ -692,21 +804,62 @@ func TestFunctionCompose(t *testing.T) {
ConnectionDetails: managed.ConnectionDetails{
"from": []byte("function-pipeline"),
},
Events: []event.Event{
Events: []TargetedEvent{
{
Type: "Normal",
Reason: "ComposeResources",
Message: "Pipeline step \"run-cool-function\": A normal result",
Event: event.Event{
Type: "Normal",
Reason: "ComposeResources",
Message: "A normal result",
},
Detail: "Pipeline step \"run-cool-function\"",
Target: CompositionTargetComposite,
},
{
Type: "Warning",
Reason: "ComposeResources",
Message: "Pipeline step \"run-cool-function\": A warning result",
Event: event.Event{
Type: "Warning",
Reason: "ComposeResources",
Message: "A warning result",
},
Detail: "Pipeline step \"run-cool-function\"",
Target: CompositionTargetComposite,
},
{
Type: "Warning",
Reason: "ComposeResources",
Message: "Pipeline step \"run-cool-function\" returned a result of unknown severity (assuming warning): A result of unspecified severity",
Event: event.Event{
Type: "Warning",
Reason: "ComposeResources",
Message: "Pipeline step \"run-cool-function\" returned a result of unknown severity (assuming warning): A result of unspecified severity",
},
Target: CompositionTargetComposite,
},
{
Event: event.Event{
Type: "Normal",
Reason: "SomeReason",
Message: "A result with all values explicitly set.",
},
Detail: "Pipeline step \"run-cool-function\"",
Target: CompositionTargetCompositeAndClaim,
},
},
Conditions: []TargetedCondition{
// The condition with minimum values.
{
Condition: xpv1.Condition{
Type: "DatabaseReady",
Status: "False",
Reason: "Creating",
},
Target: CompositionTargetComposite,
},
// The condition that provides all possible values.
{
Condition: xpv1.Condition{
Type: "DeploymentReady",
Status: "True",
Reason: "Available",
Message: "The deployment is ready.",
},
Target: CompositionTargetCompositeAndClaim,
},
},
},
@ -785,6 +938,13 @@ func TestFunctionCompose(t *testing.T) {
Severity: v1beta1.Severity_SEVERITY_UNSPECIFIED,
Message: "A result of unspecified severity",
},
{
// If the severity is unknown, the target should be force set
// to target only the XR.
Severity: v1beta1.Severity_SEVERITY_UNSPECIFIED,
Message: "A result of unspecified severity targeting the claim should be forced to only target the XR.",
Target: v1beta1.Target_TARGET_COMPOSITE_AND_CLAIM.Enum(),
},
},
Requirements: requirements,
}
@ -893,21 +1053,42 @@ func TestFunctionCompose(t *testing.T) {
ConnectionDetails: managed.ConnectionDetails{
"from": []byte("function-pipeline"),
},
Events: []event.Event{
Events: []TargetedEvent{
{
Type: "Normal",
Reason: "ComposeResources",
Message: "Pipeline step \"run-cool-function\": A normal result",
Event: event.Event{
Type: "Normal",
Reason: "ComposeResources",
Message: "A normal result",
},
Detail: "Pipeline step \"run-cool-function\"",
Target: CompositionTargetComposite,
},
{
Type: "Warning",
Reason: "ComposeResources",
Message: "Pipeline step \"run-cool-function\": A warning result",
Event: event.Event{
Type: "Warning",
Reason: "ComposeResources",
Message: "A warning result",
},
Detail: "Pipeline step \"run-cool-function\"",
Target: CompositionTargetComposite,
},
{
Type: "Warning",
Reason: "ComposeResources",
Message: "Pipeline step \"run-cool-function\" returned a result of unknown severity (assuming warning): A result of unspecified severity",
Event: event.Event{
Type: "Warning",
Reason: "ComposeResources",
Message: "Pipeline step \"run-cool-function\" returned a result of unknown severity (assuming warning): A result of unspecified severity",
},
Target: CompositionTargetComposite,
},
// If the severity is unknown, the target should be force set
// to target only the XR.
{
Event: event.Event{
Type: "Warning",
Reason: "ComposeResources",
Message: "Pipeline step \"run-cool-function\" returned a result of unknown severity (assuming warning): A result of unspecified severity targeting the claim should be forced to only target the XR.",
},
Target: CompositionTargetComposite,
},
},
},

View File

@ -183,7 +183,7 @@ func (c *PTComposer) Compose(ctx context.Context, xr *composite.Unstructured, re
}
}
events := make([]event.Event, 0)
events := make([]TargetedEvent, 0)
// We optimistically render all composed resources that we are able to with
// the expectation that any that we fail to render will subsequently have
@ -213,17 +213,26 @@ func (c *PTComposer) Compose(ctx context.Context, xr *composite.Unstructured, re
rendered := true
if err := RenderFromCompositeAndEnvironmentPatches(r, xr, req.Environment, ta.Template.Patches); err != nil {
events = append(events, event.Warning(reasonCompose, errors.Wrapf(err, errFmtRenderFromCompositePatches, name)))
events = append(events, TargetedEvent{
Event: event.Warning(reasonCompose, errors.Wrapf(err, errFmtRenderFromCompositePatches, name)),
Target: CompositionTargetComposite,
})
rendered = false
}
if err := RenderComposedResourceMetadata(r, xr, ResourceName(ptr.Deref(ta.Template.Name, ""))); err != nil {
events = append(events, event.Warning(reasonCompose, errors.Wrapf(err, errFmtRenderMetadata, name)))
events = append(events, TargetedEvent{
Event: event.Warning(reasonCompose, errors.Wrapf(err, errFmtRenderMetadata, name)),
Target: CompositionTargetComposite,
})
rendered = false
}
if err := c.composed.GenerateName(ctx, r); err != nil {
events = append(events, event.Warning(reasonCompose, errors.Wrapf(err, errFmtGenerateName, name)))
events = append(events, TargetedEvent{
Event: event.Warning(reasonCompose, errors.Wrapf(err, errFmtGenerateName, name)),
Target: CompositionTargetComposite,
})
rendered = false
}
@ -274,7 +283,10 @@ func (c *PTComposer) Compose(ctx context.Context, xr *composite.Unstructured, re
// run again the composition after some other resource is
// created or updated successfully. So, we emit a warning event
// and move on.
events = append(events, event.Warning(reasonCompose, errors.Wrapf(err, errFmtApplyComposed, ptr.Deref(t.Name, fmt.Sprintf("%d", i+1)))))
events = append(events, TargetedEvent{
Event: event.Warning(reasonCompose, errors.Wrapf(err, errFmtApplyComposed, ptr.Deref(t.Name, fmt.Sprintf("%d", i+1)))),
Target: CompositionTargetComposite,
})
// We unset the cd here so that we don't try to observe it
// later. This will also mean we report it as not ready and not
// synced. Resulting in the XR being reported as not ready nor

View File

@ -467,8 +467,11 @@ func TestPTCompose(t *testing.T) {
},
},
ConnectionDetails: details,
Events: []event.Event{
event.Warning(reasonCompose, errors.Wrapf(errBoom, errFmtGenerateName, "uncool-resource")),
Events: []TargetedEvent{
{
Event: event.Warning(reasonCompose, errors.Wrapf(errBoom, errFmtGenerateName, "uncool-resource")),
Target: CompositionTargetComposite,
},
},
},
},

View File

@ -24,9 +24,11 @@ import (
"strconv"
"time"
corev1 "k8s.io/api/core/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
@ -38,6 +40,7 @@ import (
"github.com/crossplane/crossplane-runtime/pkg/meta"
"github.com/crossplane/crossplane-runtime/pkg/reconciler/managed"
"github.com/crossplane/crossplane-runtime/pkg/resource"
"github.com/crossplane/crossplane-runtime/pkg/resource/unstructured/claim"
"github.com/crossplane/crossplane-runtime/pkg/resource/unstructured/composed"
"github.com/crossplane/crossplane-runtime/pkg/resource/unstructured/composite"
@ -72,6 +75,8 @@ const (
errInvalidResources = "some resources were invalid, check events"
errRenderCD = "cannot render composed resource"
errSyncResources = "cannot sync composed resources"
errGetClaim = "cannot get referenced claim"
errParseClaimRef = "cannot parse claim reference"
reconcilePausedMsg = "Reconciliation (including deletion) is paused via the pause annotation"
)
@ -86,6 +91,11 @@ const (
reasonPaused event.Reason = "ReconciliationPaused"
)
// Condition reasons.
const (
reasonFatalError xpv1.ConditionReason = "FatalError"
)
// ControllerName returns the recommended name for controllers that use this
// package to reconcile a particular kind of composite resource.
func ControllerName(name string) string {
@ -185,7 +195,48 @@ type CompositionRequest struct {
type CompositionResult struct {
Composed []ComposedResource
ConnectionDetails managed.ConnectionDetails
Events []event.Event
Events []TargetedEvent
Conditions []TargetedCondition
}
// A CompositionTarget is the target of a composition event or condition.
type CompositionTarget string
// Composition event and condition targets.
const (
CompositionTargetComposite CompositionTarget = "Composite"
CompositionTargetCompositeAndClaim CompositionTarget = "CompositeAndClaim"
)
// A TargetedEvent represents an event produced by the composition process. It
// can target either the XR only, or both the XR and the claim.
type TargetedEvent struct {
event.Event
Target CompositionTarget
// Detail about the event to be included in the composite resource event but
// not the claim.
Detail string
}
// AsEvent produces the base event.
func (e *TargetedEvent) AsEvent() event.Event {
return event.Event{Type: e.Type, Reason: e.Reason, Message: e.Message, Annotations: e.Annotations}
}
// AsDetailedEvent produces an event with additional detail if available.
func (e *TargetedEvent) AsDetailedEvent() event.Event {
if e.Detail == "" {
return e.AsEvent()
}
msg := fmt.Sprintf("%s: %s", e.Detail, e.Message)
return event.Event{Type: e.Type, Reason: e.Reason, Message: msg, Annotations: e.Annotations}
}
// A TargetedCondition represents a condition produced by the composition
// process. It can target either the XR only, or both the XR and the claim.
type TargetedCondition struct {
xpv1.Condition
Target CompositionTarget
}
// A Composer composes (i.e. creates, updates, or deletes) resources given the
@ -608,6 +659,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reco
if kerrors.IsConflict(err) {
return reconcile.Result{Requeue: true}, nil
}
err = errors.Wrap(err, errCompose)
r.record.Event(xr, event.Warning(reasonCompose, err))
if kerrors.IsInvalid(err) {
@ -621,6 +673,22 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reco
err = errors.Wrap(errors.New(errInvalidResources), errCompose)
}
xr.SetConditions(xpv1.ReconcileError(err))
meta := r.handleCommonCompositionResult(ctx, res, xr)
// We encountered a fatal error. For any custom status conditions that were
// not received due to the fatal error, mark them as unknown.
for _, c := range xr.GetConditions() {
if xpv1.IsSystemConditionType(c.Type) {
continue
}
if !meta.conditionTypesSeen[c.Type] {
c.Status = corev1.ConditionUnknown
c.Reason = reasonFatalError
c.Message = "A fatal error occurred before the status of this condition could be determined."
xr.SetConditions(c)
}
}
return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, xr), errUpdateStatus)
}
@ -654,16 +722,9 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reco
r.record.Event(xr, event.Normal(reasonPublish, "Successfully published connection details"))
}
warnings := 0
for _, e := range res.Events {
if e.Type == event.TypeWarning {
warnings++
}
log.Debug(e.Message)
r.record.Event(xr, e)
}
meta := r.handleCommonCompositionResult(ctx, res, xr)
if warnings == 0 {
if meta.numWarningEvents == 0 {
// We don't consider warnings severe enough to prevent the XR from being
// considered synced (i.e. severe enough to return a ReconcileError) but
// they are severe enough that we probably shouldn't say we successfully
@ -736,3 +797,74 @@ func getComposerResourcesNames(cds []ComposedResource) []string {
}
return names
}
type compositionResultMeta struct {
numWarningEvents int
conditionTypesSeen map[xpv1.ConditionType]bool
}
func (r *Reconciler) handleCommonCompositionResult(ctx context.Context, res CompositionResult, xr *composite.Unstructured) compositionResultMeta {
log := r.log.WithValues(
"uid", xr.GetUID(),
"version", xr.GetResourceVersion(),
"name", xr.GetName(),
)
cm, err := getClaimFromXR(ctx, r.client, xr)
if err != nil {
log.Debug(errGetClaim, "error", err)
}
numWarningEvents := 0
for _, e := range res.Events {
if e.Event.Type == event.TypeWarning {
numWarningEvents++
}
detailedEvent := e.AsDetailedEvent()
log.Debug(detailedEvent.Message)
r.record.Event(xr, detailedEvent)
if e.Target == CompositionTargetCompositeAndClaim && cm != nil {
r.record.Event(cm, e.AsEvent())
}
}
conditionTypesSeen := make(map[xpv1.ConditionType]bool)
for _, c := range res.Conditions {
if xpv1.IsSystemConditionType(c.Condition.Type) {
// Do not let users update system conditions.
continue
}
conditionTypesSeen[c.Condition.Type] = true
xr.SetConditions(c.Condition)
if c.Target == CompositionTargetCompositeAndClaim {
// We can ignore the error as it only occurs if given a system condition.
_ = xr.SetClaimConditionTypes(c.Condition.Type)
}
}
return compositionResultMeta{
numWarningEvents: numWarningEvents,
conditionTypesSeen: conditionTypesSeen,
}
}
func getClaimFromXR(ctx context.Context, c client.Client, xr *composite.Unstructured) (*claim.Unstructured, error) {
if xr.GetClaimReference() == nil {
return nil, nil
}
gv, err := schema.ParseGroupVersion(xr.GetClaimReference().APIVersion)
if err != nil {
return nil, errors.Wrap(err, errParseClaimRef)
}
claimGVK := gv.WithKind(xr.GetClaimReference().Kind)
cm := claim.New(claim.WithGroupVersionKind(claimGVK))
claimNN := types.NamespacedName{Namespace: xr.GetClaimReference().Namespace, Name: xr.GetClaimReference().Name}
if err := c.Get(ctx, claimNN, cm); err != nil {
return nil, errors.Wrap(err, errGetClaim)
}
return cm, nil
}

View File

@ -18,6 +18,7 @@ package composite
import (
"context"
"fmt"
"testing"
"time"
@ -26,6 +27,7 @@ import (
corev1 "k8s.io/api/core/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
@ -36,6 +38,7 @@ import (
"github.com/crossplane/crossplane-runtime/pkg/meta"
"github.com/crossplane/crossplane-runtime/pkg/reconciler/managed"
"github.com/crossplane/crossplane-runtime/pkg/resource"
"github.com/crossplane/crossplane-runtime/pkg/resource/unstructured/claim"
"github.com/crossplane/crossplane-runtime/pkg/resource/unstructured/composed"
"github.com/crossplane/crossplane-runtime/pkg/resource/unstructured/composite"
"github.com/crossplane/crossplane-runtime/pkg/test"
@ -446,7 +449,12 @@ func TestReconcile(t *testing.T) {
})),
WithComposer(ComposerFn(func(_ context.Context, _ *composite.Unstructured, _ CompositionRequest) (CompositionResult, error) {
return CompositionResult{
Events: []event.Event{event.Warning("Warning", errBoom)},
Events: []TargetedEvent{
{
Event: event.Warning("Warning", errBoom),
Target: CompositionTargetComposite,
},
},
}, nil
})),
WithConnectionPublishers(managed.ConnectionPublisherFns{
@ -714,6 +722,588 @@ func TestReconcile(t *testing.T) {
r: reconcile.Result{RequeueAfter: defaultPollInterval},
},
},
"CustomEventsAndConditions": {
reason: "We should emit custom events and set custom conditions that were returned by the composer on both the composite resource and the claim.",
args: args{
client: &test.MockClient{
MockGet: test.NewMockGetFn(nil, func(obj client.Object) error {
if xr, ok := obj.(*composite.Unstructured); ok {
// non-nil claim ref to trigger claim Get()
xr.SetClaimReference(&claim.Reference{})
return nil
}
if cm, ok := obj.(*claim.Unstructured); ok {
claim.New(claim.WithGroupVersionKind(schema.GroupVersionKind{})).DeepCopyInto(cm)
return nil
}
return nil
}),
MockStatusUpdate: WantComposite(t, NewComposite(func(cr resource.Composite) {
cr.SetCompositionReference(&corev1.ObjectReference{})
cr.SetConditions(
xpv1.Condition{
Type: "DatabaseReady",
Status: corev1.ConditionTrue,
Reason: "Available",
Message: "This is a condition for database availability.",
},
xpv1.Condition{
Type: "InternalSync",
Status: corev1.ConditionTrue,
LastTransitionTime: metav1.Time{},
Reason: "SyncSuccess",
Message: "This is a condition representing an internal sync process.",
ObservedGeneration: 0,
},
xpv1.ReconcileSuccess(),
xpv1.Available(),
)
cr.(*composite.Unstructured).SetClaimConditionTypes("DatabaseReady")
cr.SetClaimReference(&claim.Reference{})
})),
},
opts: []ReconcilerOption{
WithRecorder(newTestRecorder(
eventArgs{
Kind: compositeKind,
Event: event.Event{
Type: event.Type(corev1.EventTypeNormal),
Reason: "SelectComposition",
Message: "Successfully selected composition: ",
Annotations: map[string]string{},
},
},
eventArgs{
Kind: compositeKind,
Event: event.Event{
Type: event.TypeNormal,
Reason: "DatabaseAvailable",
// The composite should have the "Pipeline step" prefix.
Message: "Pipeline step \"some-function\": This is an event for database availability.",
Annotations: map[string]string{},
},
},
eventArgs{
Kind: claimKind,
Event: event.Event{
Type: event.TypeNormal,
Reason: "DatabaseAvailable",
// The claim should not have the "Pipeline step" prefix.
Message: "This is an event for database availability.",
Annotations: map[string]string{},
},
},
eventArgs{
Kind: compositeKind,
Event: event.Event{
Type: event.TypeNormal,
Reason: "SyncSuccess",
Message: "Pipeline step \"some-function\": Internal sync was successful.",
Annotations: map[string]string{},
},
},
eventArgs{
Kind: compositeKind,
Event: event.Event{
Type: event.Type(corev1.EventTypeNormal),
Reason: "ComposeResources",
Message: "Successfully composed resources",
Annotations: map[string]string{},
},
},
)),
WithCompositeFinalizer(resource.NewNopFinalizer()),
WithCompositionSelector(CompositionSelectorFn(func(_ context.Context, cr resource.Composite) error {
cr.SetCompositionReference(&corev1.ObjectReference{})
return nil
})),
WithCompositionRevisionFetcher(CompositionRevisionFetcherFn(func(_ context.Context, _ resource.Composite) (*v1.CompositionRevision, error) {
return &v1.CompositionRevision{}, nil
})),
WithCompositionRevisionValidator(CompositionRevisionValidatorFn(func(_ *v1.CompositionRevision) error { return nil })),
WithConfigurator(ConfiguratorFn(func(_ context.Context, _ resource.Composite, _ *v1.CompositionRevision) error {
return nil
})),
WithComposer(ComposerFn(func(_ context.Context, _ *composite.Unstructured, _ CompositionRequest) (CompositionResult, error) {
return CompositionResult{
Composed: []ComposedResource{},
ConnectionDetails: cd,
Events: []TargetedEvent{
{
Event: event.Event{
Type: event.TypeNormal,
Reason: "DatabaseAvailable",
Message: "This is an event for database availability.",
Annotations: map[string]string{},
},
Detail: "Pipeline step \"some-function\"",
Target: CompositionTargetCompositeAndClaim,
},
{
Event: event.Event{
Type: event.TypeNormal,
Reason: "SyncSuccess",
Message: "Internal sync was successful.",
Annotations: map[string]string{},
},
Detail: "Pipeline step \"some-function\"",
Target: CompositionTargetComposite,
},
},
Conditions: []TargetedCondition{
{
Condition: xpv1.Condition{
Type: "DatabaseReady",
Status: corev1.ConditionTrue,
Reason: "Available",
Message: "This is a condition for database availability.",
},
Target: CompositionTargetCompositeAndClaim,
},
{
Condition: xpv1.Condition{
Type: "InternalSync",
Status: corev1.ConditionTrue,
LastTransitionTime: metav1.Time{},
Reason: "SyncSuccess",
Message: "This is a condition representing an internal sync process.",
ObservedGeneration: 0,
},
Target: CompositionTargetComposite,
},
},
}, nil
})),
},
},
want: want{
r: reconcile.Result{RequeueAfter: defaultPollInterval},
},
},
"CustomEventsAndConditionFatal": {
reason: "In the case of a fatal result from the composer, we should set all custom conditions that were seen. If any custom conditions were not seen, they should be marked as Unknown. The error message should be emitted as an event to the composite but not the claim.",
args: args{
client: &test.MockClient{
MockGet: test.NewMockGetFn(nil, func(obj client.Object) error {
if xr, ok := obj.(*composite.Unstructured); ok {
// non-nil claim ref to trigger claim Get()
xr.SetClaimReference(&claim.Reference{})
xr.SetConditions(xpv1.Condition{
Type: "DatabaseReady",
Status: corev1.ConditionTrue,
Reason: "Available",
Message: "This is a condition for database availability.",
})
xr.SetClaimConditionTypes("DatabaseReady")
return nil
}
if cm, ok := obj.(*claim.Unstructured); ok {
claim.New(claim.WithGroupVersionKind(schema.GroupVersionKind{})).DeepCopyInto(cm)
return nil
}
return nil
}),
MockStatusUpdate: WantComposite(t, NewComposite(func(cr resource.Composite) {
cr.SetCompositionReference(&corev1.ObjectReference{})
cr.SetConditions(
xpv1.Condition{
Type: "DatabaseReady",
Status: corev1.ConditionUnknown,
Reason: "FatalError",
Message: "A fatal error occurred before the status of this condition could be determined.",
},
xpv1.ReconcileError(fmt.Errorf("cannot compose resources: %w", errBoom)),
xpv1.Condition{
Type: "InternalSync",
Status: corev1.ConditionTrue,
LastTransitionTime: metav1.Time{},
Reason: "SyncSuccess",
Message: "This is a condition representing an internal sync process.",
ObservedGeneration: 0,
},
xpv1.Condition{
Type: "BucketReady",
Status: corev1.ConditionTrue,
LastTransitionTime: metav1.Time{},
Reason: "Available",
Message: "This is a condition for bucket availability.",
ObservedGeneration: 0,
},
)
cr.(*composite.Unstructured).SetClaimConditionTypes(
"DatabaseReady",
"BucketReady",
)
cr.SetClaimReference(&claim.Reference{})
})),
},
opts: []ReconcilerOption{
WithRecorder(newTestRecorder(
eventArgs{
Kind: compositeKind,
Event: event.Event{
Type: event.Type(corev1.EventTypeNormal),
Reason: "SelectComposition",
Message: "Successfully selected composition: ",
Annotations: map[string]string{},
},
},
eventArgs{
Kind: compositeKind,
Event: event.Warning("ComposeResources", fmt.Errorf("cannot compose resources: %w", errBoom)),
},
eventArgs{
Kind: compositeKind,
Event: event.Event{
Type: event.TypeNormal,
Reason: "DatabaseAvailable",
Message: "Pipeline step \"some-function\": This is an event for database availability.",
},
},
eventArgs{
Kind: claimKind,
Event: event.Event{
Type: event.TypeNormal,
Reason: "DatabaseAvailable",
// The claim should not have the "Pipeline step" prefix.
Message: "This is an event for database availability.",
},
},
eventArgs{
Kind: compositeKind,
Event: event.Event{
Type: event.TypeNormal,
Reason: "SyncSuccess",
// The composite should have the "Pipeline step" prefix.
Message: "Pipeline step \"some-function\": Internal sync was successful.",
Annotations: map[string]string{},
},
},
eventArgs{
Kind: compositeKind,
Event: event.Event{
Type: event.TypeNormal,
Reason: "EventNoDetail",
// The composite should not have the prefix as it had an empty
// detail.
Message: "This event should not contain a detail prefix.",
Annotations: map[string]string{},
},
},
)),
WithCompositeFinalizer(resource.NewNopFinalizer()),
WithCompositionSelector(CompositionSelectorFn(func(_ context.Context, cr resource.Composite) error {
cr.SetCompositionReference(&corev1.ObjectReference{})
return nil
})),
WithCompositionRevisionFetcher(CompositionRevisionFetcherFn(func(_ context.Context, _ resource.Composite) (*v1.CompositionRevision, error) {
return &v1.CompositionRevision{}, nil
})),
WithCompositionRevisionValidator(CompositionRevisionValidatorFn(func(_ *v1.CompositionRevision) error { return nil })),
WithConfigurator(ConfiguratorFn(func(_ context.Context, _ resource.Composite, _ *v1.CompositionRevision) error {
return nil
})),
WithComposer(ComposerFn(func(_ context.Context, _ *composite.Unstructured, _ CompositionRequest) (CompositionResult, error) {
return CompositionResult{
Composed: []ComposedResource{},
ConnectionDetails: cd,
Events: []TargetedEvent{
{
Event: event.Event{
Type: event.TypeNormal,
Reason: "DatabaseAvailable",
Message: "This is an event for database availability.",
},
Detail: "Pipeline step \"some-function\"",
Target: CompositionTargetCompositeAndClaim,
},
{
Event: event.Event{
Type: event.TypeNormal,
Reason: "SyncSuccess",
Message: "Internal sync was successful.",
Annotations: map[string]string{},
},
Detail: "Pipeline step \"some-function\"",
Target: CompositionTargetComposite,
},
{
Event: event.Event{
Type: event.TypeNormal,
Reason: "EventNoDetail",
Message: "This event should not contain a detail prefix.",
Annotations: map[string]string{},
},
Target: CompositionTargetComposite,
},
},
Conditions: []TargetedCondition{
{
Condition: xpv1.Condition{
Type: "InternalSync",
Status: corev1.ConditionTrue,
LastTransitionTime: metav1.Time{},
Reason: "SyncSuccess",
Message: "This is a condition representing an internal sync process.",
ObservedGeneration: 0,
},
Target: CompositionTargetComposite,
},
{
Condition: xpv1.Condition{
Type: "BucketReady",
Status: corev1.ConditionTrue,
LastTransitionTime: metav1.Time{},
Reason: "Available",
Message: "This is a condition for bucket availability.",
ObservedGeneration: 0,
},
Target: CompositionTargetCompositeAndClaim,
},
},
}, errBoom
})),
},
},
want: want{
r: reconcile.Result{Requeue: true},
},
},
"CustomConditionUpdate": {
reason: "Custom conditions should be updated if they already exist. Additionally, if a condition already exists in the status but was not included in the response, it should remain in the status.",
args: args{
client: &test.MockClient{
MockGet: test.NewMockGetFn(nil, func(obj client.Object) error {
if xr, ok := obj.(*composite.Unstructured); ok {
// non-nil claim ref to trigger claim Get()
xr.SetClaimReference(&claim.Reference{})
// The database condition already exists on the XR.
xr.SetConditions(xpv1.Condition{
Type: "DatabaseReady",
Status: corev1.ConditionTrue,
Reason: "Available",
Message: "This is a condition for database availability.",
})
// The bucket began in a non-ready state.
xr.SetConditions(xpv1.Condition{
Type: "BucketReady",
Status: corev1.ConditionFalse,
Reason: "Creating",
Message: "Waiting for bucket to be created.",
})
xr.SetClaimConditionTypes("DatabaseReady", "BucketReady")
return nil
}
if cm, ok := obj.(*claim.Unstructured); ok {
claim.New(claim.WithGroupVersionKind(schema.GroupVersionKind{})).DeepCopyInto(cm)
return nil
}
return nil
}),
MockStatusUpdate: WantComposite(t, NewComposite(func(cr resource.Composite) {
cr.SetCompositionReference(&corev1.ObjectReference{})
cr.SetConditions(
// The database condition should exist even though it was not seen
// during this reconcile.
xpv1.Condition{
Type: "DatabaseReady",
Status: corev1.ConditionTrue,
Reason: "Available",
Message: "This is a condition for database availability.",
},
// The bucket condition should be updated to reflect the latest
// condition which is available.
xpv1.Condition{
Type: "BucketReady",
Status: corev1.ConditionTrue,
LastTransitionTime: metav1.Time{},
Reason: "Available",
Message: "This is a condition for bucket availability.",
ObservedGeneration: 0,
},
xpv1.Condition{
Type: "InternalSync",
Status: corev1.ConditionTrue,
LastTransitionTime: metav1.Time{},
Reason: "SyncSuccess",
Message: "This is a condition representing an internal sync process.",
ObservedGeneration: 0,
},
xpv1.ReconcileSuccess(),
xpv1.Available(),
)
cr.(*composite.Unstructured).SetClaimConditionTypes(
// The database claim condition should exist even though it was
// not seen during this reconcile.
"DatabaseReady",
"BucketReady",
)
cr.SetClaimReference(&claim.Reference{})
})),
},
opts: []ReconcilerOption{
WithRecorder(newTestRecorder(
eventArgs{
Kind: compositeKind,
Event: event.Event{
Type: event.Type(corev1.EventTypeNormal),
Reason: "SelectComposition",
Message: "Successfully selected composition: ",
Annotations: map[string]string{},
},
},
eventArgs{
Kind: compositeKind,
Event: event.Event{
Type: event.Type(corev1.EventTypeNormal),
Reason: "ComposeResources",
Message: "Successfully composed resources",
Annotations: map[string]string{},
},
},
)),
WithCompositeFinalizer(resource.NewNopFinalizer()),
WithCompositionSelector(CompositionSelectorFn(func(_ context.Context, cr resource.Composite) error {
cr.SetCompositionReference(&corev1.ObjectReference{})
return nil
})),
WithCompositionRevisionFetcher(CompositionRevisionFetcherFn(func(_ context.Context, _ resource.Composite) (*v1.CompositionRevision, error) {
return &v1.CompositionRevision{}, nil
})),
WithCompositionRevisionValidator(CompositionRevisionValidatorFn(func(_ *v1.CompositionRevision) error { return nil })),
WithConfigurator(ConfiguratorFn(func(_ context.Context, _ resource.Composite, _ *v1.CompositionRevision) error {
return nil
})),
WithComposer(ComposerFn(func(_ context.Context, _ *composite.Unstructured, _ CompositionRequest) (CompositionResult, error) {
return CompositionResult{
Composed: []ComposedResource{},
ConnectionDetails: cd,
Events: []TargetedEvent{},
Conditions: []TargetedCondition{
// The database condition is not added to the XR again.
{
Condition: xpv1.Condition{
Type: "InternalSync",
Status: corev1.ConditionTrue,
LastTransitionTime: metav1.Time{},
Reason: "SyncSuccess",
Message: "This is a condition representing an internal sync process.",
ObservedGeneration: 0,
},
Target: CompositionTargetComposite,
},
// The bucket is now ready.
{
Condition: xpv1.Condition{
Type: "BucketReady",
Status: corev1.ConditionTrue,
LastTransitionTime: metav1.Time{},
Reason: "Available",
Message: "This is a condition for bucket availability.",
ObservedGeneration: 0,
},
Target: CompositionTargetCompositeAndClaim,
},
},
}, nil
})),
},
},
want: want{
r: reconcile.Result{RequeueAfter: defaultPollInterval},
},
},
"CustomEventsFailToGetClaim": {
reason: "We should emit custom events that were returned by the composer. If we cannot get the claim, we should just emit events for the composite and continue as normal.",
args: args{
client: &test.MockClient{
MockGet: test.NewMockGetFn(nil, func(obj client.Object) error {
if xr, ok := obj.(*composite.Unstructured); ok {
// non-nil claim ref to trigger claim Get()
xr.SetClaimReference(&claim.Reference{})
return nil
}
if _, ok := obj.(*claim.Unstructured); ok {
// something went wrong when getting the claim
return errBoom
}
return nil
}),
MockStatusUpdate: WantComposite(t, NewComposite(func(cr resource.Composite) {
cr.SetCompositionReference(&corev1.ObjectReference{})
cr.SetConditions(xpv1.ReconcileSuccess(), xpv1.Available())
cr.SetClaimReference(&claim.Reference{})
})),
},
opts: []ReconcilerOption{
WithRecorder(newTestRecorder(
eventArgs{
Kind: compositeKind,
Event: event.Event{
Type: event.Type(corev1.EventTypeNormal),
Reason: "SelectComposition",
Message: "Successfully selected composition: ",
Annotations: map[string]string{},
},
},
eventArgs{
Kind: compositeKind,
Event: event.Event{
Type: event.TypeNormal,
Reason: "DatabaseAvailable",
Message: "Pipeline step \"some-function\": This is an event for database availability.",
Annotations: map[string]string{},
},
},
eventArgs{
Kind: compositeKind,
Event: event.Event{
Type: event.Type(corev1.EventTypeNormal),
Reason: "ComposeResources",
Message: "Successfully composed resources",
Annotations: map[string]string{},
},
},
)),
WithCompositeFinalizer(resource.NewNopFinalizer()),
WithCompositionSelector(CompositionSelectorFn(func(_ context.Context, cr resource.Composite) error {
cr.SetCompositionReference(&corev1.ObjectReference{})
return nil
})),
WithCompositionRevisionFetcher(CompositionRevisionFetcherFn(func(_ context.Context, _ resource.Composite) (*v1.CompositionRevision, error) {
return &v1.CompositionRevision{}, nil
})),
WithCompositionRevisionValidator(CompositionRevisionValidatorFn(func(_ *v1.CompositionRevision) error { return nil })),
WithConfigurator(ConfiguratorFn(func(_ context.Context, _ resource.Composite, _ *v1.CompositionRevision) error {
return nil
})),
WithComposer(ComposerFn(func(_ context.Context, _ *composite.Unstructured, _ CompositionRequest) (CompositionResult, error) {
return CompositionResult{
Composed: []ComposedResource{},
ConnectionDetails: cd,
Events: []TargetedEvent{
{
Event: event.Event{
Type: event.TypeNormal,
Reason: "DatabaseAvailable",
Message: "This is an event for database availability.",
Annotations: map[string]string{},
},
Detail: "Pipeline step \"some-function\"",
Target: CompositionTargetCompositeAndClaim,
},
},
}, nil
})),
},
},
want: want{
r: reconcile.Result{RequeueAfter: defaultPollInterval},
},
},
}
for name, tc := range cases {
@ -727,6 +1317,12 @@ func TestReconcile(t *testing.T) {
if diff := cmp.Diff(tc.want.r, got, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nr.Reconcile(...): -want, +got:\n%s", tc.reason, diff)
}
if tr, ok := r.record.(*testRecorder); ok {
if diff := cmp.Diff(tr.Want, tr.Got, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nr.Reconcile(...): -want events, +got events:\n%s", tc.reason, diff)
}
}
})
}
}
@ -830,3 +1426,41 @@ func TestFilterToXRPatches(t *testing.T) {
})
}
}
// Test types.
const (
compositeKind = "Composite"
claimKind = "Claim"
)
// testRecorder allows asserting event creation.
type testRecorder struct {
Want []eventArgs
Got []eventArgs
}
type eventArgs struct {
Kind string
Event event.Event
}
func (r *testRecorder) Event(obj runtime.Object, e event.Event) {
var kind string
switch obj.(type) {
case *composite.Unstructured:
kind = compositeKind
case *claim.Unstructured:
kind = claimKind
}
r.Got = append(r.Got, eventArgs{Kind: kind, Event: e})
}
func (r *testRecorder) WithAnnotations(_ ...string) event.Recorder {
return r
}
func newTestRecorder(expected ...eventArgs) *testRecorder {
return &testRecorder{
Want: expected,
}
}

View File

@ -20,7 +20,6 @@ import (
"context"
"testing"
"github.com/aws/smithy-go/ptr"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
admv1 "k8s.io/api/admissionregistration/v1"
@ -32,6 +31,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client"
xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
@ -697,7 +697,7 @@ func TestAPIEstablisherReleaseObjects(t *testing.T) {
for _, ref := range o.GetOwnerReferences() {
if ref.Kind == "ProviderRevision" && ref.UID == "some-unique-uid-2312" {
found = true
if ptr.ToBool(ref.Controller) {
if ptr.Deref(ref.Controller, false) {
t.Errorf("expected controller to be false, got %t", *ref.Controller)
}
}

View File

@ -466,6 +466,15 @@ func TestForCompositeResource(t *testing.T) {
},
},
},
"claimConditionTypes": {
Type: "array",
XListType: ptr.To("set"),
Items: &extv1.JSONSchemaPropsOrArray{
Schema: &extv1.JSONSchemaProps{
Type: "string",
},
},
},
"connectionDetails": {
Type: "object",
Properties: map[string]extv1.JSONSchemaProps{
@ -783,6 +792,15 @@ func TestForCompositeResource(t *testing.T) {
},
},
},
"claimConditionTypes": {
Type: "array",
XListType: ptr.To("set"),
Items: &extv1.JSONSchemaPropsOrArray{
Schema: &extv1.JSONSchemaProps{
Type: "string",
},
},
},
"connectionDetails": {
Type: "object",
Properties: map[string]extv1.JSONSchemaProps{
@ -1050,6 +1068,15 @@ func TestForCompositeResource(t *testing.T) {
},
},
},
"claimConditionTypes": {
Type: "array",
XListType: ptr.To("set"),
Items: &extv1.JSONSchemaPropsOrArray{
Schema: &extv1.JSONSchemaProps{
Type: "string",
},
},
},
"connectionDetails": {
Type: "object",
Properties: map[string]extv1.JSONSchemaProps{
@ -1333,6 +1360,15 @@ func TestForCompositeResource(t *testing.T) {
},
},
},
"claimConditionTypes": {
Type: "array",
XListType: ptr.To("set"),
Items: &extv1.JSONSchemaPropsOrArray{
Schema: &extv1.JSONSchemaProps{
Type: "string",
},
},
},
"connectionDetails": {
Type: "object",
Properties: map[string]extv1.JSONSchemaProps{
@ -1626,6 +1662,15 @@ func TestForCompositeResource(t *testing.T) {
},
},
},
"claimConditionTypes": {
Type: "array",
XListType: ptr.To("set"),
Items: &extv1.JSONSchemaPropsOrArray{
Schema: &extv1.JSONSchemaProps{
Type: "string",
},
},
},
"connectionDetails": {
Type: "object",
Properties: map[string]extv1.JSONSchemaProps{
@ -2119,6 +2164,15 @@ func TestForCompositeResourceClaim(t *testing.T) {
},
},
},
"claimConditionTypes": {
Type: "array",
XListType: ptr.To("set"),
Items: &extv1.JSONSchemaPropsOrArray{
Schema: &extv1.JSONSchemaProps{
Type: "string",
},
},
},
"connectionDetails": {
Type: "object",
Properties: map[string]extv1.JSONSchemaProps{
@ -2405,6 +2459,15 @@ func TestForCompositeResourceClaim(t *testing.T) {
},
},
},
"claimConditionTypes": {
Type: "array",
XListType: ptr.To("set"),
Items: &extv1.JSONSchemaPropsOrArray{
Schema: &extv1.JSONSchemaProps{
Type: "string",
},
},
},
"connectionDetails": {
Type: "object",
Properties: map[string]extv1.JSONSchemaProps{
@ -2705,6 +2768,15 @@ func TestForCompositeResourceClaimEmptyXrd(t *testing.T) {
},
},
},
"claimConditionTypes": {
Type: "array",
XListType: ptr.To("set"),
Items: &extv1.JSONSchemaPropsOrArray{
Schema: &extv1.JSONSchemaProps{
Type: "string",
},
},
},
"connectionDetails": {
Type: "object",
Properties: map[string]extv1.JSONSchemaProps{

View File

@ -356,6 +356,15 @@ func CompositeResourceStatusProps() map[string]extv1.JSONSchemaProps {
"lastPublishedTime": {Type: "string", Format: "date-time"},
},
},
"claimConditionTypes": {
Type: "array",
XListType: ptr.To("set"),
Items: &extv1.JSONSchemaPropsOrArray{
Schema: &extv1.JSONSchemaProps{
Type: "string",
},
},
},
}
}