diff --git a/pb/c1/config/v1/config.pb.go b/pb/c1/config/v1/config.pb.go index 14ec079e8..06945eed8 100644 --- a/pb/c1/config/v1/config.pb.go +++ b/pb/c1/config/v1/config.pb.go @@ -562,6 +562,10 @@ type Field struct { // *Field_BoolField // *Field_StringSliceField // *Field_StringMapField + // *Field_ResourceIdField + // *Field_ResourceIdSliceField + // *Field_ResourceField + // *Field_ResourceSliceField Field isField_Field `protobuf_oneof:"field"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -693,6 +697,42 @@ func (x *Field) GetStringMapField() *StringMapField { return nil } +func (x *Field) GetResourceIdField() *ResourceIdField { + if x != nil { + if x, ok := x.Field.(*Field_ResourceIdField); ok { + return x.ResourceIdField + } + } + return nil +} + +func (x *Field) GetResourceIdSliceField() *ResourceIdSliceField { + if x != nil { + if x, ok := x.Field.(*Field_ResourceIdSliceField); ok { + return x.ResourceIdSliceField + } + } + return nil +} + +func (x *Field) GetResourceField() *ResourceField { + if x != nil { + if x, ok := x.Field.(*Field_ResourceField); ok { + return x.ResourceField + } + } + return nil +} + +func (x *Field) GetResourceSliceField() *ResourceSliceField { + if x != nil { + if x, ok := x.Field.(*Field_ResourceSliceField); ok { + return x.ResourceSliceField + } + } + return nil +} + func (x *Field) SetName(v string) { x.Name = v } @@ -761,6 +801,38 @@ func (x *Field) SetStringMapField(v *StringMapField) { x.Field = &Field_StringMapField{v} } +func (x *Field) SetResourceIdField(v *ResourceIdField) { + if v == nil { + x.Field = nil + return + } + x.Field = &Field_ResourceIdField{v} +} + +func (x *Field) SetResourceIdSliceField(v *ResourceIdSliceField) { + if v == nil { + x.Field = nil + return + } + x.Field = &Field_ResourceIdSliceField{v} +} + +func (x *Field) SetResourceField(v *ResourceField) { + if v == nil { + x.Field = nil + return + } + x.Field = &Field_ResourceField{v} +} + +func (x *Field) SetResourceSliceField(v *ResourceSliceField) { + if v == nil { + x.Field = nil + return + } + x.Field = &Field_ResourceSliceField{v} +} + func (x *Field) HasField() bool { if x == nil { return false @@ -808,6 +880,38 @@ func (x *Field) HasStringMapField() bool { return ok } +func (x *Field) HasResourceIdField() bool { + if x == nil { + return false + } + _, ok := x.Field.(*Field_ResourceIdField) + return ok +} + +func (x *Field) HasResourceIdSliceField() bool { + if x == nil { + return false + } + _, ok := x.Field.(*Field_ResourceIdSliceField) + return ok +} + +func (x *Field) HasResourceField() bool { + if x == nil { + return false + } + _, ok := x.Field.(*Field_ResourceField) + return ok +} + +func (x *Field) HasResourceSliceField() bool { + if x == nil { + return false + } + _, ok := x.Field.(*Field_ResourceSliceField) + return ok +} + func (x *Field) ClearField() { x.Field = nil } @@ -842,12 +946,40 @@ func (x *Field) ClearStringMapField() { } } +func (x *Field) ClearResourceIdField() { + if _, ok := x.Field.(*Field_ResourceIdField); ok { + x.Field = nil + } +} + +func (x *Field) ClearResourceIdSliceField() { + if _, ok := x.Field.(*Field_ResourceIdSliceField); ok { + x.Field = nil + } +} + +func (x *Field) ClearResourceField() { + if _, ok := x.Field.(*Field_ResourceField); ok { + x.Field = nil + } +} + +func (x *Field) ClearResourceSliceField() { + if _, ok := x.Field.(*Field_ResourceSliceField); ok { + x.Field = nil + } +} + const Field_Field_not_set_case case_Field_Field = 0 const Field_StringField_case case_Field_Field = 100 const Field_IntField_case case_Field_Field = 101 const Field_BoolField_case case_Field_Field = 102 const Field_StringSliceField_case case_Field_Field = 103 const Field_StringMapField_case case_Field_Field = 104 +const Field_ResourceIdField_case case_Field_Field = 105 +const Field_ResourceIdSliceField_case case_Field_Field = 106 +const Field_ResourceField_case case_Field_Field = 107 +const Field_ResourceSliceField_case case_Field_Field = 108 func (x *Field) WhichField() case_Field_Field { if x == nil { @@ -864,6 +996,14 @@ func (x *Field) WhichField() case_Field_Field { return Field_StringSliceField_case case *Field_StringMapField: return Field_StringMapField_case + case *Field_ResourceIdField: + return Field_ResourceIdField_case + case *Field_ResourceIdSliceField: + return Field_ResourceIdSliceField_case + case *Field_ResourceField: + return Field_ResourceField_case + case *Field_ResourceSliceField: + return Field_ResourceSliceField_case default: return Field_Field_not_set_case } @@ -880,11 +1020,16 @@ type Field_builder struct { IsOps bool IsSecret bool // Fields of oneof Field: - StringField *StringField - IntField *IntField - BoolField *BoolField - StringSliceField *StringSliceField - StringMapField *StringMapField + StringField *StringField + IntField *IntField + BoolField *BoolField + StringSliceField *StringSliceField + StringMapField *StringMapField + ResourceIdField *ResourceIdField + ResourceIdSliceField *ResourceIdSliceField + // These are meant to serve as return types for actions. + ResourceField *ResourceField + ResourceSliceField *ResourceSliceField // -- end of Field } @@ -914,6 +1059,18 @@ func (b0 Field_builder) Build() *Field { if b.StringMapField != nil { x.Field = &Field_StringMapField{b.StringMapField} } + if b.ResourceIdField != nil { + x.Field = &Field_ResourceIdField{b.ResourceIdField} + } + if b.ResourceIdSliceField != nil { + x.Field = &Field_ResourceIdSliceField{b.ResourceIdSliceField} + } + if b.ResourceField != nil { + x.Field = &Field_ResourceField{b.ResourceField} + } + if b.ResourceSliceField != nil { + x.Field = &Field_ResourceSliceField{b.ResourceSliceField} + } return m0 } @@ -951,6 +1108,23 @@ type Field_StringMapField struct { StringMapField *StringMapField `protobuf:"bytes,104,opt,name=string_map_field,json=stringMapField,proto3,oneof"` } +type Field_ResourceIdField struct { + ResourceIdField *ResourceIdField `protobuf:"bytes,105,opt,name=resource_id_field,json=resourceIdField,proto3,oneof"` +} + +type Field_ResourceIdSliceField struct { + ResourceIdSliceField *ResourceIdSliceField `protobuf:"bytes,106,opt,name=resource_id_slice_field,json=resourceIdSliceField,proto3,oneof"` +} + +type Field_ResourceField struct { + // These are meant to serve as return types for actions. + ResourceField *ResourceField `protobuf:"bytes,107,opt,name=resource_field,json=resourceField,proto3,oneof"` +} + +type Field_ResourceSliceField struct { + ResourceSliceField *ResourceSliceField `protobuf:"bytes,108,opt,name=resource_slice_field,json=resourceSliceField,proto3,oneof"` +} + func (*Field_StringField) isField_Field() {} func (*Field_IntField) isField_Field() {} @@ -961,6 +1135,522 @@ func (*Field_StringSliceField) isField_Field() {} func (*Field_StringMapField) isField_Field() {} +func (*Field_ResourceIdField) isField_Field() {} + +func (*Field_ResourceIdSliceField) isField_Field() {} + +func (*Field_ResourceField) isField_Field() {} + +func (*Field_ResourceSliceField) isField_Field() {} + +// These are partially duplicate with the Resource proto in the connector package. +// This is to avoid import cycles +type Resource struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + ResourceId *ResourceId `protobuf:"bytes,1,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + ParentResourceId *ResourceId `protobuf:"bytes,2,opt,name=parent_resource_id,json=parentResourceId,proto3" json:"parent_resource_id,omitempty"` + DisplayName string `protobuf:"bytes,3,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` + Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty"` + Annotations []*anypb.Any `protobuf:"bytes,5,rep,name=annotations,proto3" json:"annotations,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Resource) Reset() { + *x = Resource{} + mi := &file_c1_config_v1_config_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Resource) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Resource) ProtoMessage() {} + +func (x *Resource) ProtoReflect() protoreflect.Message { + mi := &file_c1_config_v1_config_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Resource) GetResourceId() *ResourceId { + if x != nil { + return x.ResourceId + } + return nil +} + +func (x *Resource) GetParentResourceId() *ResourceId { + if x != nil { + return x.ParentResourceId + } + return nil +} + +func (x *Resource) GetDisplayName() string { + if x != nil { + return x.DisplayName + } + return "" +} + +func (x *Resource) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *Resource) GetAnnotations() []*anypb.Any { + if x != nil { + return x.Annotations + } + return nil +} + +func (x *Resource) SetResourceId(v *ResourceId) { + x.ResourceId = v +} + +func (x *Resource) SetParentResourceId(v *ResourceId) { + x.ParentResourceId = v +} + +func (x *Resource) SetDisplayName(v string) { + x.DisplayName = v +} + +func (x *Resource) SetDescription(v string) { + x.Description = v +} + +func (x *Resource) SetAnnotations(v []*anypb.Any) { + x.Annotations = v +} + +func (x *Resource) HasResourceId() bool { + if x == nil { + return false + } + return x.ResourceId != nil +} + +func (x *Resource) HasParentResourceId() bool { + if x == nil { + return false + } + return x.ParentResourceId != nil +} + +func (x *Resource) ClearResourceId() { + x.ResourceId = nil +} + +func (x *Resource) ClearParentResourceId() { + x.ParentResourceId = nil +} + +type Resource_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + ResourceId *ResourceId + ParentResourceId *ResourceId + DisplayName string + Description string + Annotations []*anypb.Any +} + +func (b0 Resource_builder) Build() *Resource { + m0 := &Resource{} + b, x := &b0, m0 + _, _ = b, x + x.ResourceId = b.ResourceId + x.ParentResourceId = b.ParentResourceId + x.DisplayName = b.DisplayName + x.Description = b.Description + x.Annotations = b.Annotations + return m0 +} + +type ResourceId struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + ResourceTypeId string `protobuf:"bytes,1,opt,name=resource_type_id,json=resourceTypeId,proto3" json:"resource_type_id,omitempty"` + ResourceId string `protobuf:"bytes,2,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResourceId) Reset() { + *x = ResourceId{} + mi := &file_c1_config_v1_config_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResourceId) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResourceId) ProtoMessage() {} + +func (x *ResourceId) ProtoReflect() protoreflect.Message { + mi := &file_c1_config_v1_config_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *ResourceId) GetResourceTypeId() string { + if x != nil { + return x.ResourceTypeId + } + return "" +} + +func (x *ResourceId) GetResourceId() string { + if x != nil { + return x.ResourceId + } + return "" +} + +func (x *ResourceId) SetResourceTypeId(v string) { + x.ResourceTypeId = v +} + +func (x *ResourceId) SetResourceId(v string) { + x.ResourceId = v +} + +type ResourceId_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + ResourceTypeId string + ResourceId string +} + +func (b0 ResourceId_builder) Build() *ResourceId { + m0 := &ResourceId{} + b, x := &b0, m0 + _, _ = b, x + x.ResourceTypeId = b.ResourceTypeId + x.ResourceId = b.ResourceId + return m0 +} + +type ResourceField struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + DefaultValue *Resource `protobuf:"bytes,1,opt,name=default_value,json=defaultValue,proto3" json:"default_value,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResourceField) Reset() { + *x = ResourceField{} + mi := &file_c1_config_v1_config_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResourceField) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResourceField) ProtoMessage() {} + +func (x *ResourceField) ProtoReflect() protoreflect.Message { + mi := &file_c1_config_v1_config_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *ResourceField) GetDefaultValue() *Resource { + if x != nil { + return x.DefaultValue + } + return nil +} + +func (x *ResourceField) SetDefaultValue(v *Resource) { + x.DefaultValue = v +} + +func (x *ResourceField) HasDefaultValue() bool { + if x == nil { + return false + } + return x.DefaultValue != nil +} + +func (x *ResourceField) ClearDefaultValue() { + x.DefaultValue = nil +} + +type ResourceField_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + DefaultValue *Resource +} + +func (b0 ResourceField_builder) Build() *ResourceField { + m0 := &ResourceField{} + b, x := &b0, m0 + _, _ = b, x + x.DefaultValue = b.DefaultValue + return m0 +} + +type ResourceSliceField struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + DefaultValue []*Resource `protobuf:"bytes,1,rep,name=default_value,json=defaultValue,proto3" json:"default_value,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResourceSliceField) Reset() { + *x = ResourceSliceField{} + mi := &file_c1_config_v1_config_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResourceSliceField) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResourceSliceField) ProtoMessage() {} + +func (x *ResourceSliceField) ProtoReflect() protoreflect.Message { + mi := &file_c1_config_v1_config_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *ResourceSliceField) GetDefaultValue() []*Resource { + if x != nil { + return x.DefaultValue + } + return nil +} + +func (x *ResourceSliceField) SetDefaultValue(v []*Resource) { + x.DefaultValue = v +} + +type ResourceSliceField_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + DefaultValue []*Resource +} + +func (b0 ResourceSliceField_builder) Build() *ResourceSliceField { + m0 := &ResourceSliceField{} + b, x := &b0, m0 + _, _ = b, x + x.DefaultValue = b.DefaultValue + return m0 +} + +type ResourceIdField struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + DefaultValue *ResourceId `protobuf:"bytes,1,opt,name=default_value,json=defaultValue,proto3" json:"default_value,omitempty"` + Rules *ResourceIDRules `protobuf:"bytes,3,opt,name=rules,proto3,oneof" json:"rules,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResourceIdField) Reset() { + *x = ResourceIdField{} + mi := &file_c1_config_v1_config_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResourceIdField) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResourceIdField) ProtoMessage() {} + +func (x *ResourceIdField) ProtoReflect() protoreflect.Message { + mi := &file_c1_config_v1_config_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *ResourceIdField) GetDefaultValue() *ResourceId { + if x != nil { + return x.DefaultValue + } + return nil +} + +func (x *ResourceIdField) GetRules() *ResourceIDRules { + if x != nil { + return x.Rules + } + return nil +} + +func (x *ResourceIdField) SetDefaultValue(v *ResourceId) { + x.DefaultValue = v +} + +func (x *ResourceIdField) SetRules(v *ResourceIDRules) { + x.Rules = v +} + +func (x *ResourceIdField) HasDefaultValue() bool { + if x == nil { + return false + } + return x.DefaultValue != nil +} + +func (x *ResourceIdField) HasRules() bool { + if x == nil { + return false + } + return x.Rules != nil +} + +func (x *ResourceIdField) ClearDefaultValue() { + x.DefaultValue = nil +} + +func (x *ResourceIdField) ClearRules() { + x.Rules = nil +} + +type ResourceIdField_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + DefaultValue *ResourceId + Rules *ResourceIDRules +} + +func (b0 ResourceIdField_builder) Build() *ResourceIdField { + m0 := &ResourceIdField{} + b, x := &b0, m0 + _, _ = b, x + x.DefaultValue = b.DefaultValue + x.Rules = b.Rules + return m0 +} + +type ResourceIdSliceField struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + DefaultValue []*ResourceIdField `protobuf:"bytes,1,rep,name=default_value,json=defaultValue,proto3" json:"default_value,omitempty"` + Rules *RepeatedResourceIdRules `protobuf:"bytes,2,opt,name=rules,proto3,oneof" json:"rules,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResourceIdSliceField) Reset() { + *x = ResourceIdSliceField{} + mi := &file_c1_config_v1_config_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResourceIdSliceField) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResourceIdSliceField) ProtoMessage() {} + +func (x *ResourceIdSliceField) ProtoReflect() protoreflect.Message { + mi := &file_c1_config_v1_config_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *ResourceIdSliceField) GetDefaultValue() []*ResourceIdField { + if x != nil { + return x.DefaultValue + } + return nil +} + +func (x *ResourceIdSliceField) GetRules() *RepeatedResourceIdRules { + if x != nil { + return x.Rules + } + return nil +} + +func (x *ResourceIdSliceField) SetDefaultValue(v []*ResourceIdField) { + x.DefaultValue = v +} + +func (x *ResourceIdSliceField) SetRules(v *RepeatedResourceIdRules) { + x.Rules = v +} + +func (x *ResourceIdSliceField) HasRules() bool { + if x == nil { + return false + } + return x.Rules != nil +} + +func (x *ResourceIdSliceField) ClearRules() { + x.Rules = nil +} + +type ResourceIdSliceField_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + DefaultValue []*ResourceIdField + Rules *RepeatedResourceIdRules +} + +func (b0 ResourceIdSliceField_builder) Build() *ResourceIdSliceField { + m0 := &ResourceIdSliceField{} + b, x := &b0, m0 + _, _ = b, x + x.DefaultValue = b.DefaultValue + x.Rules = b.Rules + return m0 +} + type IntField struct { state protoimpl.MessageState `protogen:"hybrid.v1"` // rules @@ -972,7 +1662,7 @@ type IntField struct { func (x *IntField) Reset() { *x = IntField{} - mi := &file_c1_config_v1_config_proto_msgTypes[4] + mi := &file_c1_config_v1_config_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -984,7 +1674,7 @@ func (x *IntField) String() string { func (*IntField) ProtoMessage() {} func (x *IntField) ProtoReflect() protoreflect.Message { - mi := &file_c1_config_v1_config_proto_msgTypes[4] + mi := &file_c1_config_v1_config_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1055,7 +1745,7 @@ type BoolField struct { func (x *BoolField) Reset() { *x = BoolField{} - mi := &file_c1_config_v1_config_proto_msgTypes[5] + mi := &file_c1_config_v1_config_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1067,7 +1757,7 @@ func (x *BoolField) String() string { func (*BoolField) ProtoMessage() {} func (x *BoolField) ProtoReflect() protoreflect.Message { - mi := &file_c1_config_v1_config_proto_msgTypes[5] + mi := &file_c1_config_v1_config_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1137,7 +1827,7 @@ type StringSliceField struct { func (x *StringSliceField) Reset() { *x = StringSliceField{} - mi := &file_c1_config_v1_config_proto_msgTypes[6] + mi := &file_c1_config_v1_config_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1149,7 +1839,7 @@ func (x *StringSliceField) String() string { func (*StringSliceField) ProtoMessage() {} func (x *StringSliceField) ProtoReflect() protoreflect.Message { - mi := &file_c1_config_v1_config_proto_msgTypes[6] + mi := &file_c1_config_v1_config_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1219,7 +1909,7 @@ type StringMapField struct { func (x *StringMapField) Reset() { *x = StringMapField{} - mi := &file_c1_config_v1_config_proto_msgTypes[7] + mi := &file_c1_config_v1_config_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1231,7 +1921,7 @@ func (x *StringMapField) String() string { func (*StringMapField) ProtoMessage() {} func (x *StringMapField) ProtoReflect() protoreflect.Message { - mi := &file_c1_config_v1_config_proto_msgTypes[7] + mi := &file_c1_config_v1_config_proto_msgTypes[13] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1302,7 +1992,7 @@ type StringFieldOption struct { func (x *StringFieldOption) Reset() { *x = StringFieldOption{} - mi := &file_c1_config_v1_config_proto_msgTypes[8] + mi := &file_c1_config_v1_config_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1314,7 +2004,7 @@ func (x *StringFieldOption) String() string { func (*StringFieldOption) ProtoMessage() {} func (x *StringFieldOption) ProtoReflect() protoreflect.Message { - mi := &file_c1_config_v1_config_proto_msgTypes[8] + mi := &file_c1_config_v1_config_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1390,7 +2080,7 @@ type StringField struct { func (x *StringField) Reset() { *x = StringField{} - mi := &file_c1_config_v1_config_proto_msgTypes[9] + mi := &file_c1_config_v1_config_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1402,7 +2092,7 @@ func (x *StringField) String() string { func (*StringField) ProtoMessage() {} func (x *StringField) ProtoReflect() protoreflect.Message { - mi := &file_c1_config_v1_config_proto_msgTypes[9] + mi := &file_c1_config_v1_config_proto_msgTypes[15] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1535,7 +2225,7 @@ const file_c1_config_v1_config_proto_rawDesc = "" + "\fdisplay_name\x18\x02 \x01(\tR\vdisplayName\x12\x1b\n" + "\thelp_text\x18\x03 \x01(\tR\bhelpText\x12\x16\n" + "\x06fields\x18\x04 \x03(\tR\x06fields\x12\x18\n" + - "\adefault\x18\x05 \x01(\bR\adefault\"\xab\x04\n" + + "\adefault\x18\x05 \x01(\bR\adefault\"\xf1\x06\n" + "\x05Field\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\x12!\n" + "\fdisplay_name\x18\x02 \x01(\tR\vdisplayName\x12 \n" + @@ -1550,8 +2240,36 @@ const file_c1_config_v1_config_proto_rawDesc = "" + "\n" + "bool_field\x18f \x01(\v2\x17.c1.config.v1.BoolFieldH\x00R\tboolField\x12N\n" + "\x12string_slice_field\x18g \x01(\v2\x1e.c1.config.v1.StringSliceFieldH\x00R\x10stringSliceField\x12H\n" + - "\x10string_map_field\x18h \x01(\v2\x1c.c1.config.v1.StringMapFieldH\x00R\x0estringMapFieldB\a\n" + - "\x05field\"n\n" + + "\x10string_map_field\x18h \x01(\v2\x1c.c1.config.v1.StringMapFieldH\x00R\x0estringMapField\x12K\n" + + "\x11resource_id_field\x18i \x01(\v2\x1d.c1.config.v1.ResourceIdFieldH\x00R\x0fresourceIdField\x12[\n" + + "\x17resource_id_slice_field\x18j \x01(\v2\".c1.config.v1.ResourceIdSliceFieldH\x00R\x14resourceIdSliceField\x12D\n" + + "\x0eresource_field\x18k \x01(\v2\x1b.c1.config.v1.ResourceFieldH\x00R\rresourceField\x12T\n" + + "\x14resource_slice_field\x18l \x01(\v2 .c1.config.v1.ResourceSliceFieldH\x00R\x12resourceSliceFieldB\a\n" + + "\x05field\"\x8a\x02\n" + + "\bResource\x129\n" + + "\vresource_id\x18\x01 \x01(\v2\x18.c1.config.v1.ResourceIdR\n" + + "resourceId\x12F\n" + + "\x12parent_resource_id\x18\x02 \x01(\v2\x18.c1.config.v1.ResourceIdR\x10parentResourceId\x12!\n" + + "\fdisplay_name\x18\x03 \x01(\tR\vdisplayName\x12 \n" + + "\vdescription\x18\x04 \x01(\tR\vdescription\x126\n" + + "\vannotations\x18\x05 \x03(\v2\x14.google.protobuf.AnyR\vannotations\"W\n" + + "\n" + + "ResourceId\x12(\n" + + "\x10resource_type_id\x18\x01 \x01(\tR\x0eresourceTypeId\x12\x1f\n" + + "\vresource_id\x18\x02 \x01(\tR\n" + + "resourceId\"L\n" + + "\rResourceField\x12;\n" + + "\rdefault_value\x18\x01 \x01(\v2\x16.c1.config.v1.ResourceR\fdefaultValue\"Q\n" + + "\x12ResourceSliceField\x12;\n" + + "\rdefault_value\x18\x01 \x03(\v2\x16.c1.config.v1.ResourceR\fdefaultValue\"\x94\x01\n" + + "\x0fResourceIdField\x12=\n" + + "\rdefault_value\x18\x01 \x01(\v2\x18.c1.config.v1.ResourceIdR\fdefaultValue\x128\n" + + "\x05rules\x18\x03 \x01(\v2\x1d.c1.config.v1.ResourceIDRulesH\x00R\x05rules\x88\x01\x01B\b\n" + + "\x06_rules\"\xa6\x01\n" + + "\x14ResourceIdSliceField\x12B\n" + + "\rdefault_value\x18\x01 \x03(\v2\x1d.c1.config.v1.ResourceIdFieldR\fdefaultValue\x12@\n" + + "\x05rules\x18\x02 \x01(\v2%.c1.config.v1.RepeatedResourceIdRulesH\x00R\x05rules\x88\x01\x01B\b\n" + + "\x06_rules\"n\n" + "\bIntField\x12#\n" + "\rdefault_value\x18\x01 \x01(\x03R\fdefaultValue\x123\n" + "\x05rules\x18\x02 \x01(\v2\x18.c1.config.v1.Int64RulesH\x00R\x05rules\x88\x01\x01B\b\n" + @@ -1596,52 +2314,73 @@ const file_c1_config_v1_config_proto_rawDesc = "" + "\x1dSTRING_FIELD_TYPE_FILE_UPLOAD\x10\x04B3Z1github.com/conductorone/baton-sdk/pb/c1/config/v1b\x06proto3" var file_c1_config_v1_config_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_c1_config_v1_config_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_c1_config_v1_config_proto_msgTypes = make([]protoimpl.MessageInfo, 17) var file_c1_config_v1_config_proto_goTypes = []any{ - (ConstraintKind)(0), // 0: c1.config.v1.ConstraintKind - (StringFieldType)(0), // 1: c1.config.v1.StringFieldType - (*Configuration)(nil), // 2: c1.config.v1.Configuration - (*Constraint)(nil), // 3: c1.config.v1.Constraint - (*FieldGroup)(nil), // 4: c1.config.v1.FieldGroup - (*Field)(nil), // 5: c1.config.v1.Field - (*IntField)(nil), // 6: c1.config.v1.IntField - (*BoolField)(nil), // 7: c1.config.v1.BoolField - (*StringSliceField)(nil), // 8: c1.config.v1.StringSliceField - (*StringMapField)(nil), // 9: c1.config.v1.StringMapField - (*StringFieldOption)(nil), // 10: c1.config.v1.StringFieldOption - (*StringField)(nil), // 11: c1.config.v1.StringField - nil, // 12: c1.config.v1.StringMapField.DefaultValueEntry - (*Int64Rules)(nil), // 13: c1.config.v1.Int64Rules - (*BoolRules)(nil), // 14: c1.config.v1.BoolRules - (*RepeatedStringRules)(nil), // 15: c1.config.v1.RepeatedStringRules - (*StringMapRules)(nil), // 16: c1.config.v1.StringMapRules - (*StringRules)(nil), // 17: c1.config.v1.StringRules - (*anypb.Any)(nil), // 18: google.protobuf.Any + (ConstraintKind)(0), // 0: c1.config.v1.ConstraintKind + (StringFieldType)(0), // 1: c1.config.v1.StringFieldType + (*Configuration)(nil), // 2: c1.config.v1.Configuration + (*Constraint)(nil), // 3: c1.config.v1.Constraint + (*FieldGroup)(nil), // 4: c1.config.v1.FieldGroup + (*Field)(nil), // 5: c1.config.v1.Field + (*Resource)(nil), // 6: c1.config.v1.Resource + (*ResourceId)(nil), // 7: c1.config.v1.ResourceId + (*ResourceField)(nil), // 8: c1.config.v1.ResourceField + (*ResourceSliceField)(nil), // 9: c1.config.v1.ResourceSliceField + (*ResourceIdField)(nil), // 10: c1.config.v1.ResourceIdField + (*ResourceIdSliceField)(nil), // 11: c1.config.v1.ResourceIdSliceField + (*IntField)(nil), // 12: c1.config.v1.IntField + (*BoolField)(nil), // 13: c1.config.v1.BoolField + (*StringSliceField)(nil), // 14: c1.config.v1.StringSliceField + (*StringMapField)(nil), // 15: c1.config.v1.StringMapField + (*StringFieldOption)(nil), // 16: c1.config.v1.StringFieldOption + (*StringField)(nil), // 17: c1.config.v1.StringField + nil, // 18: c1.config.v1.StringMapField.DefaultValueEntry + (*anypb.Any)(nil), // 19: google.protobuf.Any + (*ResourceIDRules)(nil), // 20: c1.config.v1.ResourceIDRules + (*RepeatedResourceIdRules)(nil), // 21: c1.config.v1.RepeatedResourceIdRules + (*Int64Rules)(nil), // 22: c1.config.v1.Int64Rules + (*BoolRules)(nil), // 23: c1.config.v1.BoolRules + (*RepeatedStringRules)(nil), // 24: c1.config.v1.RepeatedStringRules + (*StringMapRules)(nil), // 25: c1.config.v1.StringMapRules + (*StringRules)(nil), // 26: c1.config.v1.StringRules } var file_c1_config_v1_config_proto_depIdxs = []int32{ 5, // 0: c1.config.v1.Configuration.fields:type_name -> c1.config.v1.Field 3, // 1: c1.config.v1.Configuration.constraints:type_name -> c1.config.v1.Constraint 4, // 2: c1.config.v1.Configuration.field_groups:type_name -> c1.config.v1.FieldGroup 0, // 3: c1.config.v1.Constraint.kind:type_name -> c1.config.v1.ConstraintKind - 11, // 4: c1.config.v1.Field.string_field:type_name -> c1.config.v1.StringField - 6, // 5: c1.config.v1.Field.int_field:type_name -> c1.config.v1.IntField - 7, // 6: c1.config.v1.Field.bool_field:type_name -> c1.config.v1.BoolField - 8, // 7: c1.config.v1.Field.string_slice_field:type_name -> c1.config.v1.StringSliceField - 9, // 8: c1.config.v1.Field.string_map_field:type_name -> c1.config.v1.StringMapField - 13, // 9: c1.config.v1.IntField.rules:type_name -> c1.config.v1.Int64Rules - 14, // 10: c1.config.v1.BoolField.rules:type_name -> c1.config.v1.BoolRules - 15, // 11: c1.config.v1.StringSliceField.rules:type_name -> c1.config.v1.RepeatedStringRules - 12, // 12: c1.config.v1.StringMapField.default_value:type_name -> c1.config.v1.StringMapField.DefaultValueEntry - 16, // 13: c1.config.v1.StringMapField.rules:type_name -> c1.config.v1.StringMapRules - 17, // 14: c1.config.v1.StringField.rules:type_name -> c1.config.v1.StringRules - 1, // 15: c1.config.v1.StringField.type:type_name -> c1.config.v1.StringFieldType - 10, // 16: c1.config.v1.StringField.options:type_name -> c1.config.v1.StringFieldOption - 18, // 17: c1.config.v1.StringMapField.DefaultValueEntry.value:type_name -> google.protobuf.Any - 18, // [18:18] is the sub-list for method output_type - 18, // [18:18] is the sub-list for method input_type - 18, // [18:18] is the sub-list for extension type_name - 18, // [18:18] is the sub-list for extension extendee - 0, // [0:18] is the sub-list for field type_name + 17, // 4: c1.config.v1.Field.string_field:type_name -> c1.config.v1.StringField + 12, // 5: c1.config.v1.Field.int_field:type_name -> c1.config.v1.IntField + 13, // 6: c1.config.v1.Field.bool_field:type_name -> c1.config.v1.BoolField + 14, // 7: c1.config.v1.Field.string_slice_field:type_name -> c1.config.v1.StringSliceField + 15, // 8: c1.config.v1.Field.string_map_field:type_name -> c1.config.v1.StringMapField + 10, // 9: c1.config.v1.Field.resource_id_field:type_name -> c1.config.v1.ResourceIdField + 11, // 10: c1.config.v1.Field.resource_id_slice_field:type_name -> c1.config.v1.ResourceIdSliceField + 8, // 11: c1.config.v1.Field.resource_field:type_name -> c1.config.v1.ResourceField + 9, // 12: c1.config.v1.Field.resource_slice_field:type_name -> c1.config.v1.ResourceSliceField + 7, // 13: c1.config.v1.Resource.resource_id:type_name -> c1.config.v1.ResourceId + 7, // 14: c1.config.v1.Resource.parent_resource_id:type_name -> c1.config.v1.ResourceId + 19, // 15: c1.config.v1.Resource.annotations:type_name -> google.protobuf.Any + 6, // 16: c1.config.v1.ResourceField.default_value:type_name -> c1.config.v1.Resource + 6, // 17: c1.config.v1.ResourceSliceField.default_value:type_name -> c1.config.v1.Resource + 7, // 18: c1.config.v1.ResourceIdField.default_value:type_name -> c1.config.v1.ResourceId + 20, // 19: c1.config.v1.ResourceIdField.rules:type_name -> c1.config.v1.ResourceIDRules + 10, // 20: c1.config.v1.ResourceIdSliceField.default_value:type_name -> c1.config.v1.ResourceIdField + 21, // 21: c1.config.v1.ResourceIdSliceField.rules:type_name -> c1.config.v1.RepeatedResourceIdRules + 22, // 22: c1.config.v1.IntField.rules:type_name -> c1.config.v1.Int64Rules + 23, // 23: c1.config.v1.BoolField.rules:type_name -> c1.config.v1.BoolRules + 24, // 24: c1.config.v1.StringSliceField.rules:type_name -> c1.config.v1.RepeatedStringRules + 18, // 25: c1.config.v1.StringMapField.default_value:type_name -> c1.config.v1.StringMapField.DefaultValueEntry + 25, // 26: c1.config.v1.StringMapField.rules:type_name -> c1.config.v1.StringMapRules + 26, // 27: c1.config.v1.StringField.rules:type_name -> c1.config.v1.StringRules + 1, // 28: c1.config.v1.StringField.type:type_name -> c1.config.v1.StringFieldType + 16, // 29: c1.config.v1.StringField.options:type_name -> c1.config.v1.StringFieldOption + 19, // 30: c1.config.v1.StringMapField.DefaultValueEntry.value:type_name -> google.protobuf.Any + 31, // [31:31] is the sub-list for method output_type + 31, // [31:31] is the sub-list for method input_type + 31, // [31:31] is the sub-list for extension type_name + 31, // [31:31] is the sub-list for extension extendee + 0, // [0:31] is the sub-list for field type_name } func init() { file_c1_config_v1_config_proto_init() } @@ -1656,19 +2395,25 @@ func file_c1_config_v1_config_proto_init() { (*Field_BoolField)(nil), (*Field_StringSliceField)(nil), (*Field_StringMapField)(nil), + (*Field_ResourceIdField)(nil), + (*Field_ResourceIdSliceField)(nil), + (*Field_ResourceField)(nil), + (*Field_ResourceSliceField)(nil), } - file_c1_config_v1_config_proto_msgTypes[4].OneofWrappers = []any{} - file_c1_config_v1_config_proto_msgTypes[5].OneofWrappers = []any{} - file_c1_config_v1_config_proto_msgTypes[6].OneofWrappers = []any{} - file_c1_config_v1_config_proto_msgTypes[7].OneofWrappers = []any{} + file_c1_config_v1_config_proto_msgTypes[8].OneofWrappers = []any{} file_c1_config_v1_config_proto_msgTypes[9].OneofWrappers = []any{} + file_c1_config_v1_config_proto_msgTypes[10].OneofWrappers = []any{} + file_c1_config_v1_config_proto_msgTypes[11].OneofWrappers = []any{} + file_c1_config_v1_config_proto_msgTypes[12].OneofWrappers = []any{} + file_c1_config_v1_config_proto_msgTypes[13].OneofWrappers = []any{} + file_c1_config_v1_config_proto_msgTypes[15].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_c1_config_v1_config_proto_rawDesc), len(file_c1_config_v1_config_proto_rawDesc)), NumEnums: 2, - NumMessages: 11, + NumMessages: 17, NumExtensions: 0, NumServices: 0, }, diff --git a/pb/c1/config/v1/config.pb.validate.go b/pb/c1/config/v1/config.pb.validate.go index ff0ca67d6..c58e2bd2c 100644 --- a/pb/c1/config/v1/config.pb.validate.go +++ b/pb/c1/config/v1/config.pb.validate.go @@ -706,6 +706,170 @@ func (m *Field) validate(all bool) error { } } + case *Field_ResourceIdField: + if v == nil { + err := FieldValidationError{ + field: "Field", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetResourceIdField()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, FieldValidationError{ + field: "ResourceIdField", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, FieldValidationError{ + field: "ResourceIdField", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetResourceIdField()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return FieldValidationError{ + field: "ResourceIdField", + reason: "embedded message failed validation", + cause: err, + } + } + } + + case *Field_ResourceIdSliceField: + if v == nil { + err := FieldValidationError{ + field: "Field", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetResourceIdSliceField()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, FieldValidationError{ + field: "ResourceIdSliceField", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, FieldValidationError{ + field: "ResourceIdSliceField", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetResourceIdSliceField()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return FieldValidationError{ + field: "ResourceIdSliceField", + reason: "embedded message failed validation", + cause: err, + } + } + } + + case *Field_ResourceField: + if v == nil { + err := FieldValidationError{ + field: "Field", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetResourceField()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, FieldValidationError{ + field: "ResourceField", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, FieldValidationError{ + field: "ResourceField", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetResourceField()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return FieldValidationError{ + field: "ResourceField", + reason: "embedded message failed validation", + cause: err, + } + } + } + + case *Field_ResourceSliceField: + if v == nil { + err := FieldValidationError{ + field: "Field", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetResourceSliceField()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, FieldValidationError{ + field: "ResourceSliceField", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, FieldValidationError{ + field: "ResourceSliceField", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetResourceSliceField()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return FieldValidationError{ + field: "ResourceSliceField", + reason: "embedded message failed validation", + cause: err, + } + } + } + default: _ = v // ensures v is used } @@ -787,6 +951,900 @@ var _ interface { ErrorName() string } = FieldValidationError{} +// Validate checks the field values on Resource with the rules defined in the +// proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *Resource) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on Resource with the rules defined in +// the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in ResourceMultiError, or nil +// if none found. +func (m *Resource) ValidateAll() error { + return m.validate(true) +} + +func (m *Resource) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if all { + switch v := interface{}(m.GetResourceId()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ResourceValidationError{ + field: "ResourceId", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ResourceValidationError{ + field: "ResourceId", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetResourceId()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ResourceValidationError{ + field: "ResourceId", + reason: "embedded message failed validation", + cause: err, + } + } + } + + if all { + switch v := interface{}(m.GetParentResourceId()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ResourceValidationError{ + field: "ParentResourceId", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ResourceValidationError{ + field: "ParentResourceId", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetParentResourceId()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ResourceValidationError{ + field: "ParentResourceId", + reason: "embedded message failed validation", + cause: err, + } + } + } + + // no validation rules for DisplayName + + // no validation rules for Description + + for idx, item := range m.GetAnnotations() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ResourceValidationError{ + field: fmt.Sprintf("Annotations[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ResourceValidationError{ + field: fmt.Sprintf("Annotations[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ResourceValidationError{ + field: fmt.Sprintf("Annotations[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if len(errors) > 0 { + return ResourceMultiError(errors) + } + + return nil +} + +// ResourceMultiError is an error wrapping multiple validation errors returned +// by Resource.ValidateAll() if the designated constraints aren't met. +type ResourceMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ResourceMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ResourceMultiError) AllErrors() []error { return m } + +// ResourceValidationError is the validation error returned by +// Resource.Validate if the designated constraints aren't met. +type ResourceValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ResourceValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ResourceValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ResourceValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ResourceValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ResourceValidationError) ErrorName() string { return "ResourceValidationError" } + +// Error satisfies the builtin error interface +func (e ResourceValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sResource.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ResourceValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ResourceValidationError{} + +// Validate checks the field values on ResourceId with the rules defined in the +// proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *ResourceId) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ResourceId with the rules defined in +// the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in ResourceIdMultiError, or +// nil if none found. +func (m *ResourceId) ValidateAll() error { + return m.validate(true) +} + +func (m *ResourceId) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for ResourceTypeId + + // no validation rules for ResourceId + + if len(errors) > 0 { + return ResourceIdMultiError(errors) + } + + return nil +} + +// ResourceIdMultiError is an error wrapping multiple validation errors +// returned by ResourceId.ValidateAll() if the designated constraints aren't met. +type ResourceIdMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ResourceIdMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ResourceIdMultiError) AllErrors() []error { return m } + +// ResourceIdValidationError is the validation error returned by +// ResourceId.Validate if the designated constraints aren't met. +type ResourceIdValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ResourceIdValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ResourceIdValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ResourceIdValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ResourceIdValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ResourceIdValidationError) ErrorName() string { return "ResourceIdValidationError" } + +// Error satisfies the builtin error interface +func (e ResourceIdValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sResourceId.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ResourceIdValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ResourceIdValidationError{} + +// Validate checks the field values on ResourceField with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *ResourceField) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ResourceField with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in ResourceFieldMultiError, or +// nil if none found. +func (m *ResourceField) ValidateAll() error { + return m.validate(true) +} + +func (m *ResourceField) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if all { + switch v := interface{}(m.GetDefaultValue()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ResourceFieldValidationError{ + field: "DefaultValue", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ResourceFieldValidationError{ + field: "DefaultValue", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetDefaultValue()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ResourceFieldValidationError{ + field: "DefaultValue", + reason: "embedded message failed validation", + cause: err, + } + } + } + + if len(errors) > 0 { + return ResourceFieldMultiError(errors) + } + + return nil +} + +// ResourceFieldMultiError is an error wrapping multiple validation errors +// returned by ResourceField.ValidateAll() if the designated constraints +// aren't met. +type ResourceFieldMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ResourceFieldMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ResourceFieldMultiError) AllErrors() []error { return m } + +// ResourceFieldValidationError is the validation error returned by +// ResourceField.Validate if the designated constraints aren't met. +type ResourceFieldValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ResourceFieldValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ResourceFieldValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ResourceFieldValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ResourceFieldValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ResourceFieldValidationError) ErrorName() string { return "ResourceFieldValidationError" } + +// Error satisfies the builtin error interface +func (e ResourceFieldValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sResourceField.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ResourceFieldValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ResourceFieldValidationError{} + +// Validate checks the field values on ResourceSliceField with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *ResourceSliceField) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ResourceSliceField with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// ResourceSliceFieldMultiError, or nil if none found. +func (m *ResourceSliceField) ValidateAll() error { + return m.validate(true) +} + +func (m *ResourceSliceField) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + for idx, item := range m.GetDefaultValue() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ResourceSliceFieldValidationError{ + field: fmt.Sprintf("DefaultValue[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ResourceSliceFieldValidationError{ + field: fmt.Sprintf("DefaultValue[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ResourceSliceFieldValidationError{ + field: fmt.Sprintf("DefaultValue[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if len(errors) > 0 { + return ResourceSliceFieldMultiError(errors) + } + + return nil +} + +// ResourceSliceFieldMultiError is an error wrapping multiple validation errors +// returned by ResourceSliceField.ValidateAll() if the designated constraints +// aren't met. +type ResourceSliceFieldMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ResourceSliceFieldMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ResourceSliceFieldMultiError) AllErrors() []error { return m } + +// ResourceSliceFieldValidationError is the validation error returned by +// ResourceSliceField.Validate if the designated constraints aren't met. +type ResourceSliceFieldValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ResourceSliceFieldValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ResourceSliceFieldValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ResourceSliceFieldValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ResourceSliceFieldValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ResourceSliceFieldValidationError) ErrorName() string { + return "ResourceSliceFieldValidationError" +} + +// Error satisfies the builtin error interface +func (e ResourceSliceFieldValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sResourceSliceField.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ResourceSliceFieldValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ResourceSliceFieldValidationError{} + +// Validate checks the field values on ResourceIdField with the rules defined +// in the proto definition for this message. If any rules are violated, the +// first error encountered is returned, or nil if there are no violations. +func (m *ResourceIdField) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ResourceIdField with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// ResourceIdFieldMultiError, or nil if none found. +func (m *ResourceIdField) ValidateAll() error { + return m.validate(true) +} + +func (m *ResourceIdField) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if all { + switch v := interface{}(m.GetDefaultValue()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ResourceIdFieldValidationError{ + field: "DefaultValue", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ResourceIdFieldValidationError{ + field: "DefaultValue", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetDefaultValue()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ResourceIdFieldValidationError{ + field: "DefaultValue", + reason: "embedded message failed validation", + cause: err, + } + } + } + + if m.Rules != nil { + + if all { + switch v := interface{}(m.GetRules()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ResourceIdFieldValidationError{ + field: "Rules", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ResourceIdFieldValidationError{ + field: "Rules", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetRules()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ResourceIdFieldValidationError{ + field: "Rules", + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if len(errors) > 0 { + return ResourceIdFieldMultiError(errors) + } + + return nil +} + +// ResourceIdFieldMultiError is an error wrapping multiple validation errors +// returned by ResourceIdField.ValidateAll() if the designated constraints +// aren't met. +type ResourceIdFieldMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ResourceIdFieldMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ResourceIdFieldMultiError) AllErrors() []error { return m } + +// ResourceIdFieldValidationError is the validation error returned by +// ResourceIdField.Validate if the designated constraints aren't met. +type ResourceIdFieldValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ResourceIdFieldValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ResourceIdFieldValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ResourceIdFieldValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ResourceIdFieldValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ResourceIdFieldValidationError) ErrorName() string { return "ResourceIdFieldValidationError" } + +// Error satisfies the builtin error interface +func (e ResourceIdFieldValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sResourceIdField.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ResourceIdFieldValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ResourceIdFieldValidationError{} + +// Validate checks the field values on ResourceIdSliceField with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *ResourceIdSliceField) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ResourceIdSliceField with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// ResourceIdSliceFieldMultiError, or nil if none found. +func (m *ResourceIdSliceField) ValidateAll() error { + return m.validate(true) +} + +func (m *ResourceIdSliceField) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + for idx, item := range m.GetDefaultValue() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ResourceIdSliceFieldValidationError{ + field: fmt.Sprintf("DefaultValue[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ResourceIdSliceFieldValidationError{ + field: fmt.Sprintf("DefaultValue[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ResourceIdSliceFieldValidationError{ + field: fmt.Sprintf("DefaultValue[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if m.Rules != nil { + + if all { + switch v := interface{}(m.GetRules()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ResourceIdSliceFieldValidationError{ + field: "Rules", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ResourceIdSliceFieldValidationError{ + field: "Rules", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetRules()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ResourceIdSliceFieldValidationError{ + field: "Rules", + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if len(errors) > 0 { + return ResourceIdSliceFieldMultiError(errors) + } + + return nil +} + +// ResourceIdSliceFieldMultiError is an error wrapping multiple validation +// errors returned by ResourceIdSliceField.ValidateAll() if the designated +// constraints aren't met. +type ResourceIdSliceFieldMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ResourceIdSliceFieldMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ResourceIdSliceFieldMultiError) AllErrors() []error { return m } + +// ResourceIdSliceFieldValidationError is the validation error returned by +// ResourceIdSliceField.Validate if the designated constraints aren't met. +type ResourceIdSliceFieldValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ResourceIdSliceFieldValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ResourceIdSliceFieldValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ResourceIdSliceFieldValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ResourceIdSliceFieldValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ResourceIdSliceFieldValidationError) ErrorName() string { + return "ResourceIdSliceFieldValidationError" +} + +// Error satisfies the builtin error interface +func (e ResourceIdSliceFieldValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sResourceIdSliceField.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ResourceIdSliceFieldValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ResourceIdSliceFieldValidationError{} + // Validate checks the field values on IntField with the rules defined in the // proto definition for this message. If any rules are violated, the first // error encountered is returned, or nil if there are no violations. diff --git a/pb/c1/config/v1/config_protoopaque.pb.go b/pb/c1/config/v1/config_protoopaque.pb.go index 5dd83dbfe..5cc36692d 100644 --- a/pb/c1/config/v1/config_protoopaque.pb.go +++ b/pb/c1/config/v1/config_protoopaque.pb.go @@ -685,6 +685,42 @@ func (x *Field) GetStringMapField() *StringMapField { return nil } +func (x *Field) GetResourceIdField() *ResourceIdField { + if x != nil { + if x, ok := x.xxx_hidden_Field.(*field_ResourceIdField); ok { + return x.ResourceIdField + } + } + return nil +} + +func (x *Field) GetResourceIdSliceField() *ResourceIdSliceField { + if x != nil { + if x, ok := x.xxx_hidden_Field.(*field_ResourceIdSliceField); ok { + return x.ResourceIdSliceField + } + } + return nil +} + +func (x *Field) GetResourceField() *ResourceField { + if x != nil { + if x, ok := x.xxx_hidden_Field.(*field_ResourceField); ok { + return x.ResourceField + } + } + return nil +} + +func (x *Field) GetResourceSliceField() *ResourceSliceField { + if x != nil { + if x, ok := x.xxx_hidden_Field.(*field_ResourceSliceField); ok { + return x.ResourceSliceField + } + } + return nil +} + func (x *Field) SetName(v string) { x.xxx_hidden_Name = v } @@ -753,6 +789,38 @@ func (x *Field) SetStringMapField(v *StringMapField) { x.xxx_hidden_Field = &field_StringMapField{v} } +func (x *Field) SetResourceIdField(v *ResourceIdField) { + if v == nil { + x.xxx_hidden_Field = nil + return + } + x.xxx_hidden_Field = &field_ResourceIdField{v} +} + +func (x *Field) SetResourceIdSliceField(v *ResourceIdSliceField) { + if v == nil { + x.xxx_hidden_Field = nil + return + } + x.xxx_hidden_Field = &field_ResourceIdSliceField{v} +} + +func (x *Field) SetResourceField(v *ResourceField) { + if v == nil { + x.xxx_hidden_Field = nil + return + } + x.xxx_hidden_Field = &field_ResourceField{v} +} + +func (x *Field) SetResourceSliceField(v *ResourceSliceField) { + if v == nil { + x.xxx_hidden_Field = nil + return + } + x.xxx_hidden_Field = &field_ResourceSliceField{v} +} + func (x *Field) HasField() bool { if x == nil { return false @@ -800,6 +868,38 @@ func (x *Field) HasStringMapField() bool { return ok } +func (x *Field) HasResourceIdField() bool { + if x == nil { + return false + } + _, ok := x.xxx_hidden_Field.(*field_ResourceIdField) + return ok +} + +func (x *Field) HasResourceIdSliceField() bool { + if x == nil { + return false + } + _, ok := x.xxx_hidden_Field.(*field_ResourceIdSliceField) + return ok +} + +func (x *Field) HasResourceField() bool { + if x == nil { + return false + } + _, ok := x.xxx_hidden_Field.(*field_ResourceField) + return ok +} + +func (x *Field) HasResourceSliceField() bool { + if x == nil { + return false + } + _, ok := x.xxx_hidden_Field.(*field_ResourceSliceField) + return ok +} + func (x *Field) ClearField() { x.xxx_hidden_Field = nil } @@ -834,12 +934,40 @@ func (x *Field) ClearStringMapField() { } } +func (x *Field) ClearResourceIdField() { + if _, ok := x.xxx_hidden_Field.(*field_ResourceIdField); ok { + x.xxx_hidden_Field = nil + } +} + +func (x *Field) ClearResourceIdSliceField() { + if _, ok := x.xxx_hidden_Field.(*field_ResourceIdSliceField); ok { + x.xxx_hidden_Field = nil + } +} + +func (x *Field) ClearResourceField() { + if _, ok := x.xxx_hidden_Field.(*field_ResourceField); ok { + x.xxx_hidden_Field = nil + } +} + +func (x *Field) ClearResourceSliceField() { + if _, ok := x.xxx_hidden_Field.(*field_ResourceSliceField); ok { + x.xxx_hidden_Field = nil + } +} + const Field_Field_not_set_case case_Field_Field = 0 const Field_StringField_case case_Field_Field = 100 const Field_IntField_case case_Field_Field = 101 const Field_BoolField_case case_Field_Field = 102 const Field_StringSliceField_case case_Field_Field = 103 const Field_StringMapField_case case_Field_Field = 104 +const Field_ResourceIdField_case case_Field_Field = 105 +const Field_ResourceIdSliceField_case case_Field_Field = 106 +const Field_ResourceField_case case_Field_Field = 107 +const Field_ResourceSliceField_case case_Field_Field = 108 func (x *Field) WhichField() case_Field_Field { if x == nil { @@ -856,6 +984,14 @@ func (x *Field) WhichField() case_Field_Field { return Field_StringSliceField_case case *field_StringMapField: return Field_StringMapField_case + case *field_ResourceIdField: + return Field_ResourceIdField_case + case *field_ResourceIdSliceField: + return Field_ResourceIdSliceField_case + case *field_ResourceField: + return Field_ResourceField_case + case *field_ResourceSliceField: + return Field_ResourceSliceField_case default: return Field_Field_not_set_case } @@ -872,11 +1008,16 @@ type Field_builder struct { IsOps bool IsSecret bool // Fields of oneof xxx_hidden_Field: - StringField *StringField - IntField *IntField - BoolField *BoolField - StringSliceField *StringSliceField - StringMapField *StringMapField + StringField *StringField + IntField *IntField + BoolField *BoolField + StringSliceField *StringSliceField + StringMapField *StringMapField + ResourceIdField *ResourceIdField + ResourceIdSliceField *ResourceIdSliceField + // These are meant to serve as return types for actions. + ResourceField *ResourceField + ResourceSliceField *ResourceSliceField // -- end of xxx_hidden_Field } @@ -906,6 +1047,18 @@ func (b0 Field_builder) Build() *Field { if b.StringMapField != nil { x.xxx_hidden_Field = &field_StringMapField{b.StringMapField} } + if b.ResourceIdField != nil { + x.xxx_hidden_Field = &field_ResourceIdField{b.ResourceIdField} + } + if b.ResourceIdSliceField != nil { + x.xxx_hidden_Field = &field_ResourceIdSliceField{b.ResourceIdSliceField} + } + if b.ResourceField != nil { + x.xxx_hidden_Field = &field_ResourceField{b.ResourceField} + } + if b.ResourceSliceField != nil { + x.xxx_hidden_Field = &field_ResourceSliceField{b.ResourceSliceField} + } return m0 } @@ -943,6 +1096,23 @@ type field_StringMapField struct { StringMapField *StringMapField `protobuf:"bytes,104,opt,name=string_map_field,json=stringMapField,proto3,oneof"` } +type field_ResourceIdField struct { + ResourceIdField *ResourceIdField `protobuf:"bytes,105,opt,name=resource_id_field,json=resourceIdField,proto3,oneof"` +} + +type field_ResourceIdSliceField struct { + ResourceIdSliceField *ResourceIdSliceField `protobuf:"bytes,106,opt,name=resource_id_slice_field,json=resourceIdSliceField,proto3,oneof"` +} + +type field_ResourceField struct { + // These are meant to serve as return types for actions. + ResourceField *ResourceField `protobuf:"bytes,107,opt,name=resource_field,json=resourceField,proto3,oneof"` +} + +type field_ResourceSliceField struct { + ResourceSliceField *ResourceSliceField `protobuf:"bytes,108,opt,name=resource_slice_field,json=resourceSliceField,proto3,oneof"` +} + func (*field_StringField) isField_Field() {} func (*field_IntField) isField_Field() {} @@ -953,6 +1123,528 @@ func (*field_StringSliceField) isField_Field() {} func (*field_StringMapField) isField_Field() {} +func (*field_ResourceIdField) isField_Field() {} + +func (*field_ResourceIdSliceField) isField_Field() {} + +func (*field_ResourceField) isField_Field() {} + +func (*field_ResourceSliceField) isField_Field() {} + +// These are partially duplicate with the Resource proto in the connector package. +// This is to avoid import cycles +type Resource struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_ResourceId *ResourceId `protobuf:"bytes,1,opt,name=resource_id,json=resourceId,proto3"` + xxx_hidden_ParentResourceId *ResourceId `protobuf:"bytes,2,opt,name=parent_resource_id,json=parentResourceId,proto3"` + xxx_hidden_DisplayName string `protobuf:"bytes,3,opt,name=display_name,json=displayName,proto3"` + xxx_hidden_Description string `protobuf:"bytes,4,opt,name=description,proto3"` + xxx_hidden_Annotations *[]*anypb.Any `protobuf:"bytes,5,rep,name=annotations,proto3"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Resource) Reset() { + *x = Resource{} + mi := &file_c1_config_v1_config_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Resource) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Resource) ProtoMessage() {} + +func (x *Resource) ProtoReflect() protoreflect.Message { + mi := &file_c1_config_v1_config_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Resource) GetResourceId() *ResourceId { + if x != nil { + return x.xxx_hidden_ResourceId + } + return nil +} + +func (x *Resource) GetParentResourceId() *ResourceId { + if x != nil { + return x.xxx_hidden_ParentResourceId + } + return nil +} + +func (x *Resource) GetDisplayName() string { + if x != nil { + return x.xxx_hidden_DisplayName + } + return "" +} + +func (x *Resource) GetDescription() string { + if x != nil { + return x.xxx_hidden_Description + } + return "" +} + +func (x *Resource) GetAnnotations() []*anypb.Any { + if x != nil { + if x.xxx_hidden_Annotations != nil { + return *x.xxx_hidden_Annotations + } + } + return nil +} + +func (x *Resource) SetResourceId(v *ResourceId) { + x.xxx_hidden_ResourceId = v +} + +func (x *Resource) SetParentResourceId(v *ResourceId) { + x.xxx_hidden_ParentResourceId = v +} + +func (x *Resource) SetDisplayName(v string) { + x.xxx_hidden_DisplayName = v +} + +func (x *Resource) SetDescription(v string) { + x.xxx_hidden_Description = v +} + +func (x *Resource) SetAnnotations(v []*anypb.Any) { + x.xxx_hidden_Annotations = &v +} + +func (x *Resource) HasResourceId() bool { + if x == nil { + return false + } + return x.xxx_hidden_ResourceId != nil +} + +func (x *Resource) HasParentResourceId() bool { + if x == nil { + return false + } + return x.xxx_hidden_ParentResourceId != nil +} + +func (x *Resource) ClearResourceId() { + x.xxx_hidden_ResourceId = nil +} + +func (x *Resource) ClearParentResourceId() { + x.xxx_hidden_ParentResourceId = nil +} + +type Resource_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + ResourceId *ResourceId + ParentResourceId *ResourceId + DisplayName string + Description string + Annotations []*anypb.Any +} + +func (b0 Resource_builder) Build() *Resource { + m0 := &Resource{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_ResourceId = b.ResourceId + x.xxx_hidden_ParentResourceId = b.ParentResourceId + x.xxx_hidden_DisplayName = b.DisplayName + x.xxx_hidden_Description = b.Description + x.xxx_hidden_Annotations = &b.Annotations + return m0 +} + +type ResourceId struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_ResourceTypeId string `protobuf:"bytes,1,opt,name=resource_type_id,json=resourceTypeId,proto3"` + xxx_hidden_ResourceId string `protobuf:"bytes,2,opt,name=resource_id,json=resourceId,proto3"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResourceId) Reset() { + *x = ResourceId{} + mi := &file_c1_config_v1_config_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResourceId) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResourceId) ProtoMessage() {} + +func (x *ResourceId) ProtoReflect() protoreflect.Message { + mi := &file_c1_config_v1_config_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *ResourceId) GetResourceTypeId() string { + if x != nil { + return x.xxx_hidden_ResourceTypeId + } + return "" +} + +func (x *ResourceId) GetResourceId() string { + if x != nil { + return x.xxx_hidden_ResourceId + } + return "" +} + +func (x *ResourceId) SetResourceTypeId(v string) { + x.xxx_hidden_ResourceTypeId = v +} + +func (x *ResourceId) SetResourceId(v string) { + x.xxx_hidden_ResourceId = v +} + +type ResourceId_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + ResourceTypeId string + ResourceId string +} + +func (b0 ResourceId_builder) Build() *ResourceId { + m0 := &ResourceId{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_ResourceTypeId = b.ResourceTypeId + x.xxx_hidden_ResourceId = b.ResourceId + return m0 +} + +type ResourceField struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_DefaultValue *Resource `protobuf:"bytes,1,opt,name=default_value,json=defaultValue,proto3"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResourceField) Reset() { + *x = ResourceField{} + mi := &file_c1_config_v1_config_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResourceField) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResourceField) ProtoMessage() {} + +func (x *ResourceField) ProtoReflect() protoreflect.Message { + mi := &file_c1_config_v1_config_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *ResourceField) GetDefaultValue() *Resource { + if x != nil { + return x.xxx_hidden_DefaultValue + } + return nil +} + +func (x *ResourceField) SetDefaultValue(v *Resource) { + x.xxx_hidden_DefaultValue = v +} + +func (x *ResourceField) HasDefaultValue() bool { + if x == nil { + return false + } + return x.xxx_hidden_DefaultValue != nil +} + +func (x *ResourceField) ClearDefaultValue() { + x.xxx_hidden_DefaultValue = nil +} + +type ResourceField_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + DefaultValue *Resource +} + +func (b0 ResourceField_builder) Build() *ResourceField { + m0 := &ResourceField{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_DefaultValue = b.DefaultValue + return m0 +} + +type ResourceSliceField struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_DefaultValue *[]*Resource `protobuf:"bytes,1,rep,name=default_value,json=defaultValue,proto3"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResourceSliceField) Reset() { + *x = ResourceSliceField{} + mi := &file_c1_config_v1_config_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResourceSliceField) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResourceSliceField) ProtoMessage() {} + +func (x *ResourceSliceField) ProtoReflect() protoreflect.Message { + mi := &file_c1_config_v1_config_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *ResourceSliceField) GetDefaultValue() []*Resource { + if x != nil { + if x.xxx_hidden_DefaultValue != nil { + return *x.xxx_hidden_DefaultValue + } + } + return nil +} + +func (x *ResourceSliceField) SetDefaultValue(v []*Resource) { + x.xxx_hidden_DefaultValue = &v +} + +type ResourceSliceField_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + DefaultValue []*Resource +} + +func (b0 ResourceSliceField_builder) Build() *ResourceSliceField { + m0 := &ResourceSliceField{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_DefaultValue = &b.DefaultValue + return m0 +} + +type ResourceIdField struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_DefaultValue *ResourceId `protobuf:"bytes,1,opt,name=default_value,json=defaultValue,proto3"` + xxx_hidden_Rules *ResourceIDRules `protobuf:"bytes,3,opt,name=rules,proto3,oneof"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResourceIdField) Reset() { + *x = ResourceIdField{} + mi := &file_c1_config_v1_config_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResourceIdField) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResourceIdField) ProtoMessage() {} + +func (x *ResourceIdField) ProtoReflect() protoreflect.Message { + mi := &file_c1_config_v1_config_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *ResourceIdField) GetDefaultValue() *ResourceId { + if x != nil { + return x.xxx_hidden_DefaultValue + } + return nil +} + +func (x *ResourceIdField) GetRules() *ResourceIDRules { + if x != nil { + return x.xxx_hidden_Rules + } + return nil +} + +func (x *ResourceIdField) SetDefaultValue(v *ResourceId) { + x.xxx_hidden_DefaultValue = v +} + +func (x *ResourceIdField) SetRules(v *ResourceIDRules) { + x.xxx_hidden_Rules = v +} + +func (x *ResourceIdField) HasDefaultValue() bool { + if x == nil { + return false + } + return x.xxx_hidden_DefaultValue != nil +} + +func (x *ResourceIdField) HasRules() bool { + if x == nil { + return false + } + return x.xxx_hidden_Rules != nil +} + +func (x *ResourceIdField) ClearDefaultValue() { + x.xxx_hidden_DefaultValue = nil +} + +func (x *ResourceIdField) ClearRules() { + x.xxx_hidden_Rules = nil +} + +type ResourceIdField_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + DefaultValue *ResourceId + Rules *ResourceIDRules +} + +func (b0 ResourceIdField_builder) Build() *ResourceIdField { + m0 := &ResourceIdField{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_DefaultValue = b.DefaultValue + x.xxx_hidden_Rules = b.Rules + return m0 +} + +type ResourceIdSliceField struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_DefaultValue *[]*ResourceIdField `protobuf:"bytes,1,rep,name=default_value,json=defaultValue,proto3"` + xxx_hidden_Rules *RepeatedResourceIdRules `protobuf:"bytes,2,opt,name=rules,proto3,oneof"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResourceIdSliceField) Reset() { + *x = ResourceIdSliceField{} + mi := &file_c1_config_v1_config_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResourceIdSliceField) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResourceIdSliceField) ProtoMessage() {} + +func (x *ResourceIdSliceField) ProtoReflect() protoreflect.Message { + mi := &file_c1_config_v1_config_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *ResourceIdSliceField) GetDefaultValue() []*ResourceIdField { + if x != nil { + if x.xxx_hidden_DefaultValue != nil { + return *x.xxx_hidden_DefaultValue + } + } + return nil +} + +func (x *ResourceIdSliceField) GetRules() *RepeatedResourceIdRules { + if x != nil { + return x.xxx_hidden_Rules + } + return nil +} + +func (x *ResourceIdSliceField) SetDefaultValue(v []*ResourceIdField) { + x.xxx_hidden_DefaultValue = &v +} + +func (x *ResourceIdSliceField) SetRules(v *RepeatedResourceIdRules) { + x.xxx_hidden_Rules = v +} + +func (x *ResourceIdSliceField) HasRules() bool { + if x == nil { + return false + } + return x.xxx_hidden_Rules != nil +} + +func (x *ResourceIdSliceField) ClearRules() { + x.xxx_hidden_Rules = nil +} + +type ResourceIdSliceField_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + DefaultValue []*ResourceIdField + Rules *RepeatedResourceIdRules +} + +func (b0 ResourceIdSliceField_builder) Build() *ResourceIdSliceField { + m0 := &ResourceIdSliceField{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_DefaultValue = &b.DefaultValue + x.xxx_hidden_Rules = b.Rules + return m0 +} + type IntField struct { state protoimpl.MessageState `protogen:"opaque.v1"` xxx_hidden_DefaultValue int64 `protobuf:"varint,1,opt,name=default_value,json=defaultValue,proto3"` @@ -963,7 +1655,7 @@ type IntField struct { func (x *IntField) Reset() { *x = IntField{} - mi := &file_c1_config_v1_config_proto_msgTypes[4] + mi := &file_c1_config_v1_config_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -975,7 +1667,7 @@ func (x *IntField) String() string { func (*IntField) ProtoMessage() {} func (x *IntField) ProtoReflect() protoreflect.Message { - mi := &file_c1_config_v1_config_proto_msgTypes[4] + mi := &file_c1_config_v1_config_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1046,7 +1738,7 @@ type BoolField struct { func (x *BoolField) Reset() { *x = BoolField{} - mi := &file_c1_config_v1_config_proto_msgTypes[5] + mi := &file_c1_config_v1_config_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1058,7 +1750,7 @@ func (x *BoolField) String() string { func (*BoolField) ProtoMessage() {} func (x *BoolField) ProtoReflect() protoreflect.Message { - mi := &file_c1_config_v1_config_proto_msgTypes[5] + mi := &file_c1_config_v1_config_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1128,7 +1820,7 @@ type StringSliceField struct { func (x *StringSliceField) Reset() { *x = StringSliceField{} - mi := &file_c1_config_v1_config_proto_msgTypes[6] + mi := &file_c1_config_v1_config_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1140,7 +1832,7 @@ func (x *StringSliceField) String() string { func (*StringSliceField) ProtoMessage() {} func (x *StringSliceField) ProtoReflect() protoreflect.Message { - mi := &file_c1_config_v1_config_proto_msgTypes[6] + mi := &file_c1_config_v1_config_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1210,7 +1902,7 @@ type StringMapField struct { func (x *StringMapField) Reset() { *x = StringMapField{} - mi := &file_c1_config_v1_config_proto_msgTypes[7] + mi := &file_c1_config_v1_config_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1222,7 +1914,7 @@ func (x *StringMapField) String() string { func (*StringMapField) ProtoMessage() {} func (x *StringMapField) ProtoReflect() protoreflect.Message { - mi := &file_c1_config_v1_config_proto_msgTypes[7] + mi := &file_c1_config_v1_config_proto_msgTypes[13] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1293,7 +1985,7 @@ type StringFieldOption struct { func (x *StringFieldOption) Reset() { *x = StringFieldOption{} - mi := &file_c1_config_v1_config_proto_msgTypes[8] + mi := &file_c1_config_v1_config_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1305,7 +1997,7 @@ func (x *StringFieldOption) String() string { func (*StringFieldOption) ProtoMessage() {} func (x *StringFieldOption) ProtoReflect() protoreflect.Message { - mi := &file_c1_config_v1_config_proto_msgTypes[8] + mi := &file_c1_config_v1_config_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1380,7 +2072,7 @@ type StringField struct { func (x *StringField) Reset() { *x = StringField{} - mi := &file_c1_config_v1_config_proto_msgTypes[9] + mi := &file_c1_config_v1_config_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1392,7 +2084,7 @@ func (x *StringField) String() string { func (*StringField) ProtoMessage() {} func (x *StringField) ProtoReflect() protoreflect.Message { - mi := &file_c1_config_v1_config_proto_msgTypes[9] + mi := &file_c1_config_v1_config_proto_msgTypes[15] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1527,7 +2219,7 @@ const file_c1_config_v1_config_proto_rawDesc = "" + "\fdisplay_name\x18\x02 \x01(\tR\vdisplayName\x12\x1b\n" + "\thelp_text\x18\x03 \x01(\tR\bhelpText\x12\x16\n" + "\x06fields\x18\x04 \x03(\tR\x06fields\x12\x18\n" + - "\adefault\x18\x05 \x01(\bR\adefault\"\xab\x04\n" + + "\adefault\x18\x05 \x01(\bR\adefault\"\xf1\x06\n" + "\x05Field\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\x12!\n" + "\fdisplay_name\x18\x02 \x01(\tR\vdisplayName\x12 \n" + @@ -1542,8 +2234,36 @@ const file_c1_config_v1_config_proto_rawDesc = "" + "\n" + "bool_field\x18f \x01(\v2\x17.c1.config.v1.BoolFieldH\x00R\tboolField\x12N\n" + "\x12string_slice_field\x18g \x01(\v2\x1e.c1.config.v1.StringSliceFieldH\x00R\x10stringSliceField\x12H\n" + - "\x10string_map_field\x18h \x01(\v2\x1c.c1.config.v1.StringMapFieldH\x00R\x0estringMapFieldB\a\n" + - "\x05field\"n\n" + + "\x10string_map_field\x18h \x01(\v2\x1c.c1.config.v1.StringMapFieldH\x00R\x0estringMapField\x12K\n" + + "\x11resource_id_field\x18i \x01(\v2\x1d.c1.config.v1.ResourceIdFieldH\x00R\x0fresourceIdField\x12[\n" + + "\x17resource_id_slice_field\x18j \x01(\v2\".c1.config.v1.ResourceIdSliceFieldH\x00R\x14resourceIdSliceField\x12D\n" + + "\x0eresource_field\x18k \x01(\v2\x1b.c1.config.v1.ResourceFieldH\x00R\rresourceField\x12T\n" + + "\x14resource_slice_field\x18l \x01(\v2 .c1.config.v1.ResourceSliceFieldH\x00R\x12resourceSliceFieldB\a\n" + + "\x05field\"\x8a\x02\n" + + "\bResource\x129\n" + + "\vresource_id\x18\x01 \x01(\v2\x18.c1.config.v1.ResourceIdR\n" + + "resourceId\x12F\n" + + "\x12parent_resource_id\x18\x02 \x01(\v2\x18.c1.config.v1.ResourceIdR\x10parentResourceId\x12!\n" + + "\fdisplay_name\x18\x03 \x01(\tR\vdisplayName\x12 \n" + + "\vdescription\x18\x04 \x01(\tR\vdescription\x126\n" + + "\vannotations\x18\x05 \x03(\v2\x14.google.protobuf.AnyR\vannotations\"W\n" + + "\n" + + "ResourceId\x12(\n" + + "\x10resource_type_id\x18\x01 \x01(\tR\x0eresourceTypeId\x12\x1f\n" + + "\vresource_id\x18\x02 \x01(\tR\n" + + "resourceId\"L\n" + + "\rResourceField\x12;\n" + + "\rdefault_value\x18\x01 \x01(\v2\x16.c1.config.v1.ResourceR\fdefaultValue\"Q\n" + + "\x12ResourceSliceField\x12;\n" + + "\rdefault_value\x18\x01 \x03(\v2\x16.c1.config.v1.ResourceR\fdefaultValue\"\x94\x01\n" + + "\x0fResourceIdField\x12=\n" + + "\rdefault_value\x18\x01 \x01(\v2\x18.c1.config.v1.ResourceIdR\fdefaultValue\x128\n" + + "\x05rules\x18\x03 \x01(\v2\x1d.c1.config.v1.ResourceIDRulesH\x00R\x05rules\x88\x01\x01B\b\n" + + "\x06_rules\"\xa6\x01\n" + + "\x14ResourceIdSliceField\x12B\n" + + "\rdefault_value\x18\x01 \x03(\v2\x1d.c1.config.v1.ResourceIdFieldR\fdefaultValue\x12@\n" + + "\x05rules\x18\x02 \x01(\v2%.c1.config.v1.RepeatedResourceIdRulesH\x00R\x05rules\x88\x01\x01B\b\n" + + "\x06_rules\"n\n" + "\bIntField\x12#\n" + "\rdefault_value\x18\x01 \x01(\x03R\fdefaultValue\x123\n" + "\x05rules\x18\x02 \x01(\v2\x18.c1.config.v1.Int64RulesH\x00R\x05rules\x88\x01\x01B\b\n" + @@ -1588,52 +2308,73 @@ const file_c1_config_v1_config_proto_rawDesc = "" + "\x1dSTRING_FIELD_TYPE_FILE_UPLOAD\x10\x04B3Z1github.com/conductorone/baton-sdk/pb/c1/config/v1b\x06proto3" var file_c1_config_v1_config_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_c1_config_v1_config_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_c1_config_v1_config_proto_msgTypes = make([]protoimpl.MessageInfo, 17) var file_c1_config_v1_config_proto_goTypes = []any{ - (ConstraintKind)(0), // 0: c1.config.v1.ConstraintKind - (StringFieldType)(0), // 1: c1.config.v1.StringFieldType - (*Configuration)(nil), // 2: c1.config.v1.Configuration - (*Constraint)(nil), // 3: c1.config.v1.Constraint - (*FieldGroup)(nil), // 4: c1.config.v1.FieldGroup - (*Field)(nil), // 5: c1.config.v1.Field - (*IntField)(nil), // 6: c1.config.v1.IntField - (*BoolField)(nil), // 7: c1.config.v1.BoolField - (*StringSliceField)(nil), // 8: c1.config.v1.StringSliceField - (*StringMapField)(nil), // 9: c1.config.v1.StringMapField - (*StringFieldOption)(nil), // 10: c1.config.v1.StringFieldOption - (*StringField)(nil), // 11: c1.config.v1.StringField - nil, // 12: c1.config.v1.StringMapField.DefaultValueEntry - (*Int64Rules)(nil), // 13: c1.config.v1.Int64Rules - (*BoolRules)(nil), // 14: c1.config.v1.BoolRules - (*RepeatedStringRules)(nil), // 15: c1.config.v1.RepeatedStringRules - (*StringMapRules)(nil), // 16: c1.config.v1.StringMapRules - (*StringRules)(nil), // 17: c1.config.v1.StringRules - (*anypb.Any)(nil), // 18: google.protobuf.Any + (ConstraintKind)(0), // 0: c1.config.v1.ConstraintKind + (StringFieldType)(0), // 1: c1.config.v1.StringFieldType + (*Configuration)(nil), // 2: c1.config.v1.Configuration + (*Constraint)(nil), // 3: c1.config.v1.Constraint + (*FieldGroup)(nil), // 4: c1.config.v1.FieldGroup + (*Field)(nil), // 5: c1.config.v1.Field + (*Resource)(nil), // 6: c1.config.v1.Resource + (*ResourceId)(nil), // 7: c1.config.v1.ResourceId + (*ResourceField)(nil), // 8: c1.config.v1.ResourceField + (*ResourceSliceField)(nil), // 9: c1.config.v1.ResourceSliceField + (*ResourceIdField)(nil), // 10: c1.config.v1.ResourceIdField + (*ResourceIdSliceField)(nil), // 11: c1.config.v1.ResourceIdSliceField + (*IntField)(nil), // 12: c1.config.v1.IntField + (*BoolField)(nil), // 13: c1.config.v1.BoolField + (*StringSliceField)(nil), // 14: c1.config.v1.StringSliceField + (*StringMapField)(nil), // 15: c1.config.v1.StringMapField + (*StringFieldOption)(nil), // 16: c1.config.v1.StringFieldOption + (*StringField)(nil), // 17: c1.config.v1.StringField + nil, // 18: c1.config.v1.StringMapField.DefaultValueEntry + (*anypb.Any)(nil), // 19: google.protobuf.Any + (*ResourceIDRules)(nil), // 20: c1.config.v1.ResourceIDRules + (*RepeatedResourceIdRules)(nil), // 21: c1.config.v1.RepeatedResourceIdRules + (*Int64Rules)(nil), // 22: c1.config.v1.Int64Rules + (*BoolRules)(nil), // 23: c1.config.v1.BoolRules + (*RepeatedStringRules)(nil), // 24: c1.config.v1.RepeatedStringRules + (*StringMapRules)(nil), // 25: c1.config.v1.StringMapRules + (*StringRules)(nil), // 26: c1.config.v1.StringRules } var file_c1_config_v1_config_proto_depIdxs = []int32{ 5, // 0: c1.config.v1.Configuration.fields:type_name -> c1.config.v1.Field 3, // 1: c1.config.v1.Configuration.constraints:type_name -> c1.config.v1.Constraint 4, // 2: c1.config.v1.Configuration.field_groups:type_name -> c1.config.v1.FieldGroup 0, // 3: c1.config.v1.Constraint.kind:type_name -> c1.config.v1.ConstraintKind - 11, // 4: c1.config.v1.Field.string_field:type_name -> c1.config.v1.StringField - 6, // 5: c1.config.v1.Field.int_field:type_name -> c1.config.v1.IntField - 7, // 6: c1.config.v1.Field.bool_field:type_name -> c1.config.v1.BoolField - 8, // 7: c1.config.v1.Field.string_slice_field:type_name -> c1.config.v1.StringSliceField - 9, // 8: c1.config.v1.Field.string_map_field:type_name -> c1.config.v1.StringMapField - 13, // 9: c1.config.v1.IntField.rules:type_name -> c1.config.v1.Int64Rules - 14, // 10: c1.config.v1.BoolField.rules:type_name -> c1.config.v1.BoolRules - 15, // 11: c1.config.v1.StringSliceField.rules:type_name -> c1.config.v1.RepeatedStringRules - 12, // 12: c1.config.v1.StringMapField.default_value:type_name -> c1.config.v1.StringMapField.DefaultValueEntry - 16, // 13: c1.config.v1.StringMapField.rules:type_name -> c1.config.v1.StringMapRules - 17, // 14: c1.config.v1.StringField.rules:type_name -> c1.config.v1.StringRules - 1, // 15: c1.config.v1.StringField.type:type_name -> c1.config.v1.StringFieldType - 10, // 16: c1.config.v1.StringField.options:type_name -> c1.config.v1.StringFieldOption - 18, // 17: c1.config.v1.StringMapField.DefaultValueEntry.value:type_name -> google.protobuf.Any - 18, // [18:18] is the sub-list for method output_type - 18, // [18:18] is the sub-list for method input_type - 18, // [18:18] is the sub-list for extension type_name - 18, // [18:18] is the sub-list for extension extendee - 0, // [0:18] is the sub-list for field type_name + 17, // 4: c1.config.v1.Field.string_field:type_name -> c1.config.v1.StringField + 12, // 5: c1.config.v1.Field.int_field:type_name -> c1.config.v1.IntField + 13, // 6: c1.config.v1.Field.bool_field:type_name -> c1.config.v1.BoolField + 14, // 7: c1.config.v1.Field.string_slice_field:type_name -> c1.config.v1.StringSliceField + 15, // 8: c1.config.v1.Field.string_map_field:type_name -> c1.config.v1.StringMapField + 10, // 9: c1.config.v1.Field.resource_id_field:type_name -> c1.config.v1.ResourceIdField + 11, // 10: c1.config.v1.Field.resource_id_slice_field:type_name -> c1.config.v1.ResourceIdSliceField + 8, // 11: c1.config.v1.Field.resource_field:type_name -> c1.config.v1.ResourceField + 9, // 12: c1.config.v1.Field.resource_slice_field:type_name -> c1.config.v1.ResourceSliceField + 7, // 13: c1.config.v1.Resource.resource_id:type_name -> c1.config.v1.ResourceId + 7, // 14: c1.config.v1.Resource.parent_resource_id:type_name -> c1.config.v1.ResourceId + 19, // 15: c1.config.v1.Resource.annotations:type_name -> google.protobuf.Any + 6, // 16: c1.config.v1.ResourceField.default_value:type_name -> c1.config.v1.Resource + 6, // 17: c1.config.v1.ResourceSliceField.default_value:type_name -> c1.config.v1.Resource + 7, // 18: c1.config.v1.ResourceIdField.default_value:type_name -> c1.config.v1.ResourceId + 20, // 19: c1.config.v1.ResourceIdField.rules:type_name -> c1.config.v1.ResourceIDRules + 10, // 20: c1.config.v1.ResourceIdSliceField.default_value:type_name -> c1.config.v1.ResourceIdField + 21, // 21: c1.config.v1.ResourceIdSliceField.rules:type_name -> c1.config.v1.RepeatedResourceIdRules + 22, // 22: c1.config.v1.IntField.rules:type_name -> c1.config.v1.Int64Rules + 23, // 23: c1.config.v1.BoolField.rules:type_name -> c1.config.v1.BoolRules + 24, // 24: c1.config.v1.StringSliceField.rules:type_name -> c1.config.v1.RepeatedStringRules + 18, // 25: c1.config.v1.StringMapField.default_value:type_name -> c1.config.v1.StringMapField.DefaultValueEntry + 25, // 26: c1.config.v1.StringMapField.rules:type_name -> c1.config.v1.StringMapRules + 26, // 27: c1.config.v1.StringField.rules:type_name -> c1.config.v1.StringRules + 1, // 28: c1.config.v1.StringField.type:type_name -> c1.config.v1.StringFieldType + 16, // 29: c1.config.v1.StringField.options:type_name -> c1.config.v1.StringFieldOption + 19, // 30: c1.config.v1.StringMapField.DefaultValueEntry.value:type_name -> google.protobuf.Any + 31, // [31:31] is the sub-list for method output_type + 31, // [31:31] is the sub-list for method input_type + 31, // [31:31] is the sub-list for extension type_name + 31, // [31:31] is the sub-list for extension extendee + 0, // [0:31] is the sub-list for field type_name } func init() { file_c1_config_v1_config_proto_init() } @@ -1648,19 +2389,25 @@ func file_c1_config_v1_config_proto_init() { (*field_BoolField)(nil), (*field_StringSliceField)(nil), (*field_StringMapField)(nil), + (*field_ResourceIdField)(nil), + (*field_ResourceIdSliceField)(nil), + (*field_ResourceField)(nil), + (*field_ResourceSliceField)(nil), } - file_c1_config_v1_config_proto_msgTypes[4].OneofWrappers = []any{} - file_c1_config_v1_config_proto_msgTypes[5].OneofWrappers = []any{} - file_c1_config_v1_config_proto_msgTypes[6].OneofWrappers = []any{} - file_c1_config_v1_config_proto_msgTypes[7].OneofWrappers = []any{} + file_c1_config_v1_config_proto_msgTypes[8].OneofWrappers = []any{} file_c1_config_v1_config_proto_msgTypes[9].OneofWrappers = []any{} + file_c1_config_v1_config_proto_msgTypes[10].OneofWrappers = []any{} + file_c1_config_v1_config_proto_msgTypes[11].OneofWrappers = []any{} + file_c1_config_v1_config_proto_msgTypes[12].OneofWrappers = []any{} + file_c1_config_v1_config_proto_msgTypes[13].OneofWrappers = []any{} + file_c1_config_v1_config_proto_msgTypes[15].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_c1_config_v1_config_proto_rawDesc), len(file_c1_config_v1_config_proto_rawDesc)), NumEnums: 2, - NumMessages: 11, + NumMessages: 17, NumExtensions: 0, NumServices: 0, }, diff --git a/pb/c1/config/v1/rules.pb.go b/pb/c1/config/v1/rules.pb.go index 616e289a4..110733848 100644 --- a/pb/c1/config/v1/rules.pb.go +++ b/pb/c1/config/v1/rules.pb.go @@ -1427,6 +1427,120 @@ func (b0 StringMapRules_builder) Build() *StringMapRules { return m0 } +type ResourceIDRules struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + AllowedResourceTypeIds []string `protobuf:"bytes,1,rep,name=allowed_resource_type_ids,json=allowedResourceTypeIds,proto3" json:"allowed_resource_type_ids,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResourceIDRules) Reset() { + *x = ResourceIDRules{} + mi := &file_c1_config_v1_rules_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResourceIDRules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResourceIDRules) ProtoMessage() {} + +func (x *ResourceIDRules) ProtoReflect() protoreflect.Message { + mi := &file_c1_config_v1_rules_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *ResourceIDRules) GetAllowedResourceTypeIds() []string { + if x != nil { + return x.AllowedResourceTypeIds + } + return nil +} + +func (x *ResourceIDRules) SetAllowedResourceTypeIds(v []string) { + x.AllowedResourceTypeIds = v +} + +type ResourceIDRules_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + AllowedResourceTypeIds []string +} + +func (b0 ResourceIDRules_builder) Build() *ResourceIDRules { + m0 := &ResourceIDRules{} + b, x := &b0, m0 + _, _ = b, x + x.AllowedResourceTypeIds = b.AllowedResourceTypeIds + return m0 +} + +type RepeatedResourceIdRules struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + AllowedResourceTypeIds []string `protobuf:"bytes,1,rep,name=allowed_resource_type_ids,json=allowedResourceTypeIds,proto3" json:"allowed_resource_type_ids,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RepeatedResourceIdRules) Reset() { + *x = RepeatedResourceIdRules{} + mi := &file_c1_config_v1_rules_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RepeatedResourceIdRules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RepeatedResourceIdRules) ProtoMessage() {} + +func (x *RepeatedResourceIdRules) ProtoReflect() protoreflect.Message { + mi := &file_c1_config_v1_rules_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *RepeatedResourceIdRules) GetAllowedResourceTypeIds() []string { + if x != nil { + return x.AllowedResourceTypeIds + } + return nil +} + +func (x *RepeatedResourceIdRules) SetAllowedResourceTypeIds(v []string) { + x.AllowedResourceTypeIds = v +} + +type RepeatedResourceIdRules_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + AllowedResourceTypeIds []string +} + +func (b0 RepeatedResourceIdRules_builder) Build() *RepeatedResourceIdRules { + m0 := &RepeatedResourceIdRules{} + b, x := &b0, m0 + _, _ = b, x + x.AllowedResourceTypeIds = b.AllowedResourceTypeIds + return m0 +} + var File_c1_config_v1_rules_proto protoreflect.FileDescriptor const file_c1_config_v1_rules_proto_rawDesc = "" + @@ -1514,7 +1628,11 @@ const file_c1_config_v1_rules_proto_rawDesc = "" + "\x0eStringMapRules\x12%\n" + "\x0evalidate_empty\x18\x01 \x01(\bR\rvalidateEmpty\x12\x1f\n" + "\vis_required\x18\x02 \x01(\bR\n" + - "isRequired*\x99\x02\n" + + "isRequired\"L\n" + + "\x0fResourceIDRules\x129\n" + + "\x19allowed_resource_type_ids\x18\x01 \x03(\tR\x16allowedResourceTypeIds\"T\n" + + "\x17RepeatedResourceIdRules\x129\n" + + "\x19allowed_resource_type_ids\x18\x01 \x03(\tR\x16allowedResourceTypeIds*\x99\x02\n" + "\x0fWellKnownString\x12!\n" + "\x1dWELL_KNOWN_STRING_UNSPECIFIED\x10\x00\x12\x1b\n" + "\x17WELL_KNOWN_STRING_EMAIL\x10\x01\x12\x1e\n" + @@ -1527,15 +1645,17 @@ const file_c1_config_v1_rules_proto_rawDesc = "" + "\x16WELL_KNOWN_STRING_UUID\x10\bB3Z1github.com/conductorone/baton-sdk/pb/c1/config/v1b\x06proto3" var file_c1_config_v1_rules_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_c1_config_v1_rules_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_c1_config_v1_rules_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_c1_config_v1_rules_proto_goTypes = []any{ - (WellKnownString)(0), // 0: c1.config.v1.WellKnownString - (*Int64Rules)(nil), // 1: c1.config.v1.Int64Rules - (*BoolRules)(nil), // 2: c1.config.v1.BoolRules - (*RepeatedRules)(nil), // 3: c1.config.v1.RepeatedRules - (*RepeatedStringRules)(nil), // 4: c1.config.v1.RepeatedStringRules - (*StringRules)(nil), // 5: c1.config.v1.StringRules - (*StringMapRules)(nil), // 6: c1.config.v1.StringMapRules + (WellKnownString)(0), // 0: c1.config.v1.WellKnownString + (*Int64Rules)(nil), // 1: c1.config.v1.Int64Rules + (*BoolRules)(nil), // 2: c1.config.v1.BoolRules + (*RepeatedRules)(nil), // 3: c1.config.v1.RepeatedRules + (*RepeatedStringRules)(nil), // 4: c1.config.v1.RepeatedStringRules + (*StringRules)(nil), // 5: c1.config.v1.StringRules + (*StringMapRules)(nil), // 6: c1.config.v1.StringMapRules + (*ResourceIDRules)(nil), // 7: c1.config.v1.ResourceIDRules + (*RepeatedResourceIdRules)(nil), // 8: c1.config.v1.RepeatedResourceIdRules } var file_c1_config_v1_rules_proto_depIdxs = []int32{ 1, // 0: c1.config.v1.RepeatedRules.int64:type_name -> c1.config.v1.Int64Rules @@ -1570,7 +1690,7 @@ func file_c1_config_v1_rules_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_c1_config_v1_rules_proto_rawDesc), len(file_c1_config_v1_rules_proto_rawDesc)), NumEnums: 1, - NumMessages: 6, + NumMessages: 8, NumExtensions: 0, NumServices: 0, }, diff --git a/pb/c1/config/v1/rules.pb.validate.go b/pb/c1/config/v1/rules.pb.validate.go index a2c8ff0dc..f5f49e9e9 100644 --- a/pb/c1/config/v1/rules.pb.validate.go +++ b/pb/c1/config/v1/rules.pb.validate.go @@ -892,3 +892,205 @@ var _ interface { Cause() error ErrorName() string } = StringMapRulesValidationError{} + +// Validate checks the field values on ResourceIDRules with the rules defined +// in the proto definition for this message. If any rules are violated, the +// first error encountered is returned, or nil if there are no violations. +func (m *ResourceIDRules) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ResourceIDRules with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// ResourceIDRulesMultiError, or nil if none found. +func (m *ResourceIDRules) ValidateAll() error { + return m.validate(true) +} + +func (m *ResourceIDRules) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if len(errors) > 0 { + return ResourceIDRulesMultiError(errors) + } + + return nil +} + +// ResourceIDRulesMultiError is an error wrapping multiple validation errors +// returned by ResourceIDRules.ValidateAll() if the designated constraints +// aren't met. +type ResourceIDRulesMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ResourceIDRulesMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ResourceIDRulesMultiError) AllErrors() []error { return m } + +// ResourceIDRulesValidationError is the validation error returned by +// ResourceIDRules.Validate if the designated constraints aren't met. +type ResourceIDRulesValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ResourceIDRulesValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ResourceIDRulesValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ResourceIDRulesValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ResourceIDRulesValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ResourceIDRulesValidationError) ErrorName() string { return "ResourceIDRulesValidationError" } + +// Error satisfies the builtin error interface +func (e ResourceIDRulesValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sResourceIDRules.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ResourceIDRulesValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ResourceIDRulesValidationError{} + +// Validate checks the field values on RepeatedResourceIdRules with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *RepeatedResourceIdRules) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on RepeatedResourceIdRules with the +// rules defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// RepeatedResourceIdRulesMultiError, or nil if none found. +func (m *RepeatedResourceIdRules) ValidateAll() error { + return m.validate(true) +} + +func (m *RepeatedResourceIdRules) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if len(errors) > 0 { + return RepeatedResourceIdRulesMultiError(errors) + } + + return nil +} + +// RepeatedResourceIdRulesMultiError is an error wrapping multiple validation +// errors returned by RepeatedResourceIdRules.ValidateAll() if the designated +// constraints aren't met. +type RepeatedResourceIdRulesMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m RepeatedResourceIdRulesMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m RepeatedResourceIdRulesMultiError) AllErrors() []error { return m } + +// RepeatedResourceIdRulesValidationError is the validation error returned by +// RepeatedResourceIdRules.Validate if the designated constraints aren't met. +type RepeatedResourceIdRulesValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e RepeatedResourceIdRulesValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e RepeatedResourceIdRulesValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e RepeatedResourceIdRulesValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e RepeatedResourceIdRulesValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e RepeatedResourceIdRulesValidationError) ErrorName() string { + return "RepeatedResourceIdRulesValidationError" +} + +// Error satisfies the builtin error interface +func (e RepeatedResourceIdRulesValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRepeatedResourceIdRules.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = RepeatedResourceIdRulesValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = RepeatedResourceIdRulesValidationError{} diff --git a/pb/c1/config/v1/rules_protoopaque.pb.go b/pb/c1/config/v1/rules_protoopaque.pb.go index 048da3ed4..87964c85b 100644 --- a/pb/c1/config/v1/rules_protoopaque.pb.go +++ b/pb/c1/config/v1/rules_protoopaque.pb.go @@ -1464,6 +1464,120 @@ func (b0 StringMapRules_builder) Build() *StringMapRules { return m0 } +type ResourceIDRules struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_AllowedResourceTypeIds []string `protobuf:"bytes,1,rep,name=allowed_resource_type_ids,json=allowedResourceTypeIds,proto3"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResourceIDRules) Reset() { + *x = ResourceIDRules{} + mi := &file_c1_config_v1_rules_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResourceIDRules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResourceIDRules) ProtoMessage() {} + +func (x *ResourceIDRules) ProtoReflect() protoreflect.Message { + mi := &file_c1_config_v1_rules_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *ResourceIDRules) GetAllowedResourceTypeIds() []string { + if x != nil { + return x.xxx_hidden_AllowedResourceTypeIds + } + return nil +} + +func (x *ResourceIDRules) SetAllowedResourceTypeIds(v []string) { + x.xxx_hidden_AllowedResourceTypeIds = v +} + +type ResourceIDRules_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + AllowedResourceTypeIds []string +} + +func (b0 ResourceIDRules_builder) Build() *ResourceIDRules { + m0 := &ResourceIDRules{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_AllowedResourceTypeIds = b.AllowedResourceTypeIds + return m0 +} + +type RepeatedResourceIdRules struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_AllowedResourceTypeIds []string `protobuf:"bytes,1,rep,name=allowed_resource_type_ids,json=allowedResourceTypeIds,proto3"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RepeatedResourceIdRules) Reset() { + *x = RepeatedResourceIdRules{} + mi := &file_c1_config_v1_rules_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RepeatedResourceIdRules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RepeatedResourceIdRules) ProtoMessage() {} + +func (x *RepeatedResourceIdRules) ProtoReflect() protoreflect.Message { + mi := &file_c1_config_v1_rules_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *RepeatedResourceIdRules) GetAllowedResourceTypeIds() []string { + if x != nil { + return x.xxx_hidden_AllowedResourceTypeIds + } + return nil +} + +func (x *RepeatedResourceIdRules) SetAllowedResourceTypeIds(v []string) { + x.xxx_hidden_AllowedResourceTypeIds = v +} + +type RepeatedResourceIdRules_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + AllowedResourceTypeIds []string +} + +func (b0 RepeatedResourceIdRules_builder) Build() *RepeatedResourceIdRules { + m0 := &RepeatedResourceIdRules{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_AllowedResourceTypeIds = b.AllowedResourceTypeIds + return m0 +} + var File_c1_config_v1_rules_proto protoreflect.FileDescriptor const file_c1_config_v1_rules_proto_rawDesc = "" + @@ -1551,7 +1665,11 @@ const file_c1_config_v1_rules_proto_rawDesc = "" + "\x0eStringMapRules\x12%\n" + "\x0evalidate_empty\x18\x01 \x01(\bR\rvalidateEmpty\x12\x1f\n" + "\vis_required\x18\x02 \x01(\bR\n" + - "isRequired*\x99\x02\n" + + "isRequired\"L\n" + + "\x0fResourceIDRules\x129\n" + + "\x19allowed_resource_type_ids\x18\x01 \x03(\tR\x16allowedResourceTypeIds\"T\n" + + "\x17RepeatedResourceIdRules\x129\n" + + "\x19allowed_resource_type_ids\x18\x01 \x03(\tR\x16allowedResourceTypeIds*\x99\x02\n" + "\x0fWellKnownString\x12!\n" + "\x1dWELL_KNOWN_STRING_UNSPECIFIED\x10\x00\x12\x1b\n" + "\x17WELL_KNOWN_STRING_EMAIL\x10\x01\x12\x1e\n" + @@ -1564,15 +1682,17 @@ const file_c1_config_v1_rules_proto_rawDesc = "" + "\x16WELL_KNOWN_STRING_UUID\x10\bB3Z1github.com/conductorone/baton-sdk/pb/c1/config/v1b\x06proto3" var file_c1_config_v1_rules_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_c1_config_v1_rules_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_c1_config_v1_rules_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_c1_config_v1_rules_proto_goTypes = []any{ - (WellKnownString)(0), // 0: c1.config.v1.WellKnownString - (*Int64Rules)(nil), // 1: c1.config.v1.Int64Rules - (*BoolRules)(nil), // 2: c1.config.v1.BoolRules - (*RepeatedRules)(nil), // 3: c1.config.v1.RepeatedRules - (*RepeatedStringRules)(nil), // 4: c1.config.v1.RepeatedStringRules - (*StringRules)(nil), // 5: c1.config.v1.StringRules - (*StringMapRules)(nil), // 6: c1.config.v1.StringMapRules + (WellKnownString)(0), // 0: c1.config.v1.WellKnownString + (*Int64Rules)(nil), // 1: c1.config.v1.Int64Rules + (*BoolRules)(nil), // 2: c1.config.v1.BoolRules + (*RepeatedRules)(nil), // 3: c1.config.v1.RepeatedRules + (*RepeatedStringRules)(nil), // 4: c1.config.v1.RepeatedStringRules + (*StringRules)(nil), // 5: c1.config.v1.StringRules + (*StringMapRules)(nil), // 6: c1.config.v1.StringMapRules + (*ResourceIDRules)(nil), // 7: c1.config.v1.ResourceIDRules + (*RepeatedResourceIdRules)(nil), // 8: c1.config.v1.RepeatedResourceIdRules } var file_c1_config_v1_rules_proto_depIdxs = []int32{ 1, // 0: c1.config.v1.RepeatedRules.int64:type_name -> c1.config.v1.Int64Rules @@ -1607,7 +1727,7 @@ func file_c1_config_v1_rules_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_c1_config_v1_rules_proto_rawDesc), len(file_c1_config_v1_rules_proto_rawDesc)), NumEnums: 1, - NumMessages: 6, + NumMessages: 8, NumExtensions: 0, NumServices: 0, }, diff --git a/pb/c1/connector/v2/action.pb.go b/pb/c1/connector/v2/action.pb.go index 1b79424b8..d8fbaf708 100644 --- a/pb/c1/connector/v2/action.pb.go +++ b/pb/c1/connector/v2/action.pb.go @@ -88,6 +88,11 @@ const ( ActionType_ACTION_TYPE_ACCOUNT_UPDATE_PROFILE ActionType = 3 ActionType_ACTION_TYPE_ACCOUNT_DISABLE ActionType = 4 ActionType_ACTION_TYPE_ACCOUNT_ENABLE ActionType = 5 + // Generic resource actions + ActionType_ACTION_TYPE_RESOURCE_CREATE ActionType = 6 + ActionType_ACTION_TYPE_RESOURCE_DELETE ActionType = 7 + ActionType_ACTION_TYPE_RESOURCE_ENABLE ActionType = 8 + ActionType_ACTION_TYPE_RESOURCE_DISABLE ActionType = 9 ) // Enum value maps for ActionType. @@ -99,6 +104,10 @@ var ( 3: "ACTION_TYPE_ACCOUNT_UPDATE_PROFILE", 4: "ACTION_TYPE_ACCOUNT_DISABLE", 5: "ACTION_TYPE_ACCOUNT_ENABLE", + 6: "ACTION_TYPE_RESOURCE_CREATE", + 7: "ACTION_TYPE_RESOURCE_DELETE", + 8: "ACTION_TYPE_RESOURCE_ENABLE", + 9: "ACTION_TYPE_RESOURCE_DISABLE", } ActionType_value = map[string]int32{ "ACTION_TYPE_UNSPECIFIED": 0, @@ -107,6 +116,10 @@ var ( "ACTION_TYPE_ACCOUNT_UPDATE_PROFILE": 3, "ACTION_TYPE_ACCOUNT_DISABLE": 4, "ACTION_TYPE_ACCOUNT_ENABLE": 5, + "ACTION_TYPE_RESOURCE_CREATE": 6, + "ACTION_TYPE_RESOURCE_DELETE": 7, + "ACTION_TYPE_RESOURCE_ENABLE": 8, + "ACTION_TYPE_RESOURCE_DISABLE": 9, } ) @@ -133,15 +146,16 @@ func (x ActionType) Number() protoreflect.EnumNumber { } type BatonActionSchema struct { - state protoimpl.MessageState `protogen:"hybrid.v1"` - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Arguments []*v1.Field `protobuf:"bytes,2,rep,name=arguments,proto3" json:"arguments,omitempty"` - Constraints []*v1.Constraint `protobuf:"bytes,3,rep,name=constraints,proto3" json:"constraints,omitempty"` - ReturnTypes []*v1.Field `protobuf:"bytes,4,rep,name=return_types,json=returnTypes,proto3" json:"return_types,omitempty"` - DisplayName string `protobuf:"bytes,5,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` - Description string `protobuf:"bytes,6,opt,name=description,proto3" json:"description,omitempty"` - ActionType []ActionType `protobuf:"varint,7,rep,packed,name=action_type,json=actionType,proto3,enum=c1.connector.v2.ActionType" json:"action_type,omitempty"` - ResourceTypeId string `protobuf:"bytes,8,opt,name=resource_type_id,json=resourceTypeId,proto3" json:"resource_type_id,omitempty"` + state protoimpl.MessageState `protogen:"hybrid.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Arguments []*v1.Field `protobuf:"bytes,2,rep,name=arguments,proto3" json:"arguments,omitempty"` + Constraints []*v1.Constraint `protobuf:"bytes,3,rep,name=constraints,proto3" json:"constraints,omitempty"` + ReturnTypes []*v1.Field `protobuf:"bytes,4,rep,name=return_types,json=returnTypes,proto3" json:"return_types,omitempty"` + DisplayName string `protobuf:"bytes,5,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` + Description string `protobuf:"bytes,6,opt,name=description,proto3" json:"description,omitempty"` + ActionType []ActionType `protobuf:"varint,7,rep,packed,name=action_type,json=actionType,proto3,enum=c1.connector.v2.ActionType" json:"action_type,omitempty"` + // Optional: if set, this action is scoped to a specific resource type + ResourceTypeId string `protobuf:"bytes,8,opt,name=resource_type_id,json=resourceTypeId,proto3" json:"resource_type_id,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -262,13 +276,14 @@ func (x *BatonActionSchema) SetResourceTypeId(v string) { type BatonActionSchema_builder struct { _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. - Name string - Arguments []*v1.Field - Constraints []*v1.Constraint - ReturnTypes []*v1.Field - DisplayName string - Description string - ActionType []ActionType + Name string + Arguments []*v1.Field + Constraints []*v1.Constraint + ReturnTypes []*v1.Field + DisplayName string + Description string + ActionType []ActionType + // Optional: if set, this action is scoped to a specific resource type ResourceTypeId string } @@ -288,12 +303,14 @@ func (b0 BatonActionSchema_builder) Build() *BatonActionSchema { } type InvokeActionRequest struct { - state protoimpl.MessageState `protogen:"hybrid.v1"` - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Args *structpb.Struct `protobuf:"bytes,2,opt,name=args,proto3" json:"args,omitempty"` - Annotations []*anypb.Any `protobuf:"bytes,3,rep,name=annotations,proto3" json:"annotations,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"hybrid.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Args *structpb.Struct `protobuf:"bytes,2,opt,name=args,proto3" json:"args,omitempty"` + Annotations []*anypb.Any `protobuf:"bytes,3,rep,name=annotations,proto3" json:"annotations,omitempty"` + // Optional: if set, invokes a resource-scoped action + ResourceTypeId string `protobuf:"bytes,4,opt,name=resource_type_id,json=resourceTypeId,proto3" json:"resource_type_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *InvokeActionRequest) Reset() { @@ -342,6 +359,13 @@ func (x *InvokeActionRequest) GetAnnotations() []*anypb.Any { return nil } +func (x *InvokeActionRequest) GetResourceTypeId() string { + if x != nil { + return x.ResourceTypeId + } + return "" +} + func (x *InvokeActionRequest) SetName(v string) { x.Name = v } @@ -354,6 +378,10 @@ func (x *InvokeActionRequest) SetAnnotations(v []*anypb.Any) { x.Annotations = v } +func (x *InvokeActionRequest) SetResourceTypeId(v string) { + x.ResourceTypeId = v +} + func (x *InvokeActionRequest) HasArgs() bool { if x == nil { return false @@ -371,6 +399,8 @@ type InvokeActionRequest_builder struct { Name string Args *structpb.Struct Annotations []*anypb.Any + // Optional: if set, invokes a resource-scoped action + ResourceTypeId string } func (b0 InvokeActionRequest_builder) Build() *InvokeActionRequest { @@ -380,6 +410,7 @@ func (b0 InvokeActionRequest_builder) Build() *InvokeActionRequest { x.Name = b.Name x.Args = b.Args x.Annotations = b.Annotations + x.ResourceTypeId = b.ResourceTypeId return m0 } @@ -874,10 +905,12 @@ func (b0 GetActionSchemaResponse_builder) Build() *GetActionSchemaResponse { } type ListActionSchemasRequest struct { - state protoimpl.MessageState `protogen:"hybrid.v1"` - Annotations []*anypb.Any `protobuf:"bytes,1,rep,name=annotations,proto3" json:"annotations,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"hybrid.v1"` + Annotations []*anypb.Any `protobuf:"bytes,1,rep,name=annotations,proto3" json:"annotations,omitempty"` + // Optional: filter to only return actions for a specific resource type + ResourceTypeId string `protobuf:"bytes,2,opt,name=resource_type_id,json=resourceTypeId,proto3" json:"resource_type_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ListActionSchemasRequest) Reset() { @@ -912,14 +945,27 @@ func (x *ListActionSchemasRequest) GetAnnotations() []*anypb.Any { return nil } +func (x *ListActionSchemasRequest) GetResourceTypeId() string { + if x != nil { + return x.ResourceTypeId + } + return "" +} + func (x *ListActionSchemasRequest) SetAnnotations(v []*anypb.Any) { x.Annotations = v } +func (x *ListActionSchemasRequest) SetResourceTypeId(v string) { + x.ResourceTypeId = v +} + type ListActionSchemasRequest_builder struct { _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. Annotations []*anypb.Any + // Optional: filter to only return actions for a specific resource type + ResourceTypeId string } func (b0 ListActionSchemasRequest_builder) Build() *ListActionSchemasRequest { @@ -927,6 +973,7 @@ func (b0 ListActionSchemasRequest_builder) Build() *ListActionSchemasRequest { b, x := &b0, m0 _, _ = b, x x.Annotations = b.Annotations + x.ResourceTypeId = b.ResourceTypeId return m0 } @@ -1015,11 +1062,12 @@ const file_c1_connector_v2_action_proto_rawDesc = "" + "\vdescription\x18\x06 \x01(\tR\vdescription\x12<\n" + "\vaction_type\x18\a \x03(\x0e2\x1b.c1.connector.v2.ActionTypeR\n" + "actionType\x12(\n" + - "\x10resource_type_id\x18\b \x01(\tR\x0eresourceTypeId\"\x8e\x01\n" + + "\x10resource_type_id\x18\b \x01(\tR\x0eresourceTypeId\"\xb8\x01\n" + "\x13InvokeActionRequest\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\x12+\n" + "\x04args\x18\x02 \x01(\v2\x17.google.protobuf.StructR\x04args\x126\n" + - "\vannotations\x18\x03 \x03(\v2\x14.google.protobuf.AnyR\vannotations\"\xe3\x01\n" + + "\vannotations\x18\x03 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x12(\n" + + "\x10resource_type_id\x18\x04 \x01(\tR\x0eresourceTypeId\"\xe3\x01\n" + "\x14InvokeActionResponse\x12\x0e\n" + "\x02id\x18\x01 \x01(\tR\x02id\x12:\n" + "\x06status\x18\x02 \x01(\x0e2\".c1.connector.v2.BatonActionStatusR\x06status\x126\n" + @@ -1041,9 +1089,10 @@ const file_c1_connector_v2_action_proto_rawDesc = "" + "\vannotations\x18\x02 \x03(\v2\x14.google.protobuf.AnyR\vannotations\"\x8d\x01\n" + "\x17GetActionSchemaResponse\x12:\n" + "\x06schema\x18\x01 \x01(\v2\".c1.connector.v2.BatonActionSchemaR\x06schema\x126\n" + - "\vannotations\x18\x02 \x03(\v2\x14.google.protobuf.AnyR\vannotations\"R\n" + + "\vannotations\x18\x02 \x03(\v2\x14.google.protobuf.AnyR\vannotations\"|\n" + "\x18ListActionSchemasRequest\x126\n" + - "\vannotations\x18\x01 \x03(\v2\x14.google.protobuf.AnyR\vannotations\"\x91\x01\n" + + "\vannotations\x18\x01 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x12(\n" + + "\x10resource_type_id\x18\x02 \x01(\tR\x0eresourceTypeId\"\x91\x01\n" + "\x19ListActionSchemasResponse\x12<\n" + "\aschemas\x18\x01 \x03(\v2\".c1.connector.v2.BatonActionSchemaR\aschemas\x126\n" + "\vannotations\x18\x02 \x03(\v2\x14.google.protobuf.AnyR\vannotations*\xdd\x01\n" + @@ -1053,7 +1102,7 @@ const file_c1_connector_v2_action_proto_rawDesc = "" + "\x1bBATON_ACTION_STATUS_PENDING\x10\x02\x12\x1f\n" + "\x1bBATON_ACTION_STATUS_RUNNING\x10\x03\x12 \n" + "\x1cBATON_ACTION_STATUS_COMPLETE\x10\x04\x12\x1e\n" + - "\x1aBATON_ACTION_STATUS_FAILED\x10\x05*\xc4\x01\n" + + "\x1aBATON_ACTION_STATUS_FAILED\x10\x05*\xc9\x02\n" + "\n" + "ActionType\x12\x1b\n" + "\x17ACTION_TYPE_UNSPECIFIED\x10\x00\x12\x17\n" + @@ -1061,7 +1110,11 @@ const file_c1_connector_v2_action_proto_rawDesc = "" + "\x13ACTION_TYPE_ACCOUNT\x10\x02\x12&\n" + "\"ACTION_TYPE_ACCOUNT_UPDATE_PROFILE\x10\x03\x12\x1f\n" + "\x1bACTION_TYPE_ACCOUNT_DISABLE\x10\x04\x12\x1e\n" + - "\x1aACTION_TYPE_ACCOUNT_ENABLE\x10\x052\xa4\x03\n" + + "\x1aACTION_TYPE_ACCOUNT_ENABLE\x10\x05\x12\x1f\n" + + "\x1bACTION_TYPE_RESOURCE_CREATE\x10\x06\x12\x1f\n" + + "\x1bACTION_TYPE_RESOURCE_DELETE\x10\a\x12\x1f\n" + + "\x1bACTION_TYPE_RESOURCE_ENABLE\x10\b\x12 \n" + + "\x1cACTION_TYPE_RESOURCE_DISABLE\x10\t2\xa4\x03\n" + "\rActionService\x12[\n" + "\fInvokeAction\x12$.c1.connector.v2.InvokeActionRequest\x1a%.c1.connector.v2.InvokeActionResponse\x12d\n" + "\x0fGetActionStatus\x12'.c1.connector.v2.GetActionStatusRequest\x1a(.c1.connector.v2.GetActionStatusResponse\x12d\n" + diff --git a/pb/c1/connector/v2/action.pb.validate.go b/pb/c1/connector/v2/action.pb.validate.go index c8eb3b53a..40566def8 100644 --- a/pb/c1/connector/v2/action.pb.validate.go +++ b/pb/c1/connector/v2/action.pb.validate.go @@ -334,6 +334,8 @@ func (m *InvokeActionRequest) validate(all bool) error { } + // no validation rules for ResourceTypeId + if len(errors) > 0 { return InvokeActionRequestMultiError(errors) } @@ -1255,6 +1257,8 @@ func (m *ListActionSchemasRequest) validate(all bool) error { } + // no validation rules for ResourceTypeId + if len(errors) > 0 { return ListActionSchemasRequestMultiError(errors) } diff --git a/pb/c1/connector/v2/action_protoopaque.pb.go b/pb/c1/connector/v2/action_protoopaque.pb.go index 5fcd7ab59..44664477d 100644 --- a/pb/c1/connector/v2/action_protoopaque.pb.go +++ b/pb/c1/connector/v2/action_protoopaque.pb.go @@ -88,6 +88,11 @@ const ( ActionType_ACTION_TYPE_ACCOUNT_UPDATE_PROFILE ActionType = 3 ActionType_ACTION_TYPE_ACCOUNT_DISABLE ActionType = 4 ActionType_ACTION_TYPE_ACCOUNT_ENABLE ActionType = 5 + // Generic resource actions + ActionType_ACTION_TYPE_RESOURCE_CREATE ActionType = 6 + ActionType_ACTION_TYPE_RESOURCE_DELETE ActionType = 7 + ActionType_ACTION_TYPE_RESOURCE_ENABLE ActionType = 8 + ActionType_ACTION_TYPE_RESOURCE_DISABLE ActionType = 9 ) // Enum value maps for ActionType. @@ -99,6 +104,10 @@ var ( 3: "ACTION_TYPE_ACCOUNT_UPDATE_PROFILE", 4: "ACTION_TYPE_ACCOUNT_DISABLE", 5: "ACTION_TYPE_ACCOUNT_ENABLE", + 6: "ACTION_TYPE_RESOURCE_CREATE", + 7: "ACTION_TYPE_RESOURCE_DELETE", + 8: "ACTION_TYPE_RESOURCE_ENABLE", + 9: "ACTION_TYPE_RESOURCE_DISABLE", } ActionType_value = map[string]int32{ "ACTION_TYPE_UNSPECIFIED": 0, @@ -107,6 +116,10 @@ var ( "ACTION_TYPE_ACCOUNT_UPDATE_PROFILE": 3, "ACTION_TYPE_ACCOUNT_DISABLE": 4, "ACTION_TYPE_ACCOUNT_ENABLE": 5, + "ACTION_TYPE_RESOURCE_CREATE": 6, + "ACTION_TYPE_RESOURCE_DELETE": 7, + "ACTION_TYPE_RESOURCE_ENABLE": 8, + "ACTION_TYPE_RESOURCE_DISABLE": 9, } ) @@ -268,13 +281,14 @@ func (x *BatonActionSchema) SetResourceTypeId(v string) { type BatonActionSchema_builder struct { _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. - Name string - Arguments []*v1.Field - Constraints []*v1.Constraint - ReturnTypes []*v1.Field - DisplayName string - Description string - ActionType []ActionType + Name string + Arguments []*v1.Field + Constraints []*v1.Constraint + ReturnTypes []*v1.Field + DisplayName string + Description string + ActionType []ActionType + // Optional: if set, this action is scoped to a specific resource type ResourceTypeId string } @@ -294,12 +308,13 @@ func (b0 BatonActionSchema_builder) Build() *BatonActionSchema { } type InvokeActionRequest struct { - state protoimpl.MessageState `protogen:"opaque.v1"` - xxx_hidden_Name string `protobuf:"bytes,1,opt,name=name,proto3"` - xxx_hidden_Args *structpb.Struct `protobuf:"bytes,2,opt,name=args,proto3"` - xxx_hidden_Annotations *[]*anypb.Any `protobuf:"bytes,3,rep,name=annotations,proto3"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Name string `protobuf:"bytes,1,opt,name=name,proto3"` + xxx_hidden_Args *structpb.Struct `protobuf:"bytes,2,opt,name=args,proto3"` + xxx_hidden_Annotations *[]*anypb.Any `protobuf:"bytes,3,rep,name=annotations,proto3"` + xxx_hidden_ResourceTypeId string `protobuf:"bytes,4,opt,name=resource_type_id,json=resourceTypeId,proto3"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *InvokeActionRequest) Reset() { @@ -350,6 +365,13 @@ func (x *InvokeActionRequest) GetAnnotations() []*anypb.Any { return nil } +func (x *InvokeActionRequest) GetResourceTypeId() string { + if x != nil { + return x.xxx_hidden_ResourceTypeId + } + return "" +} + func (x *InvokeActionRequest) SetName(v string) { x.xxx_hidden_Name = v } @@ -362,6 +384,10 @@ func (x *InvokeActionRequest) SetAnnotations(v []*anypb.Any) { x.xxx_hidden_Annotations = &v } +func (x *InvokeActionRequest) SetResourceTypeId(v string) { + x.xxx_hidden_ResourceTypeId = v +} + func (x *InvokeActionRequest) HasArgs() bool { if x == nil { return false @@ -379,6 +405,8 @@ type InvokeActionRequest_builder struct { Name string Args *structpb.Struct Annotations []*anypb.Any + // Optional: if set, invokes a resource-scoped action + ResourceTypeId string } func (b0 InvokeActionRequest_builder) Build() *InvokeActionRequest { @@ -388,6 +416,7 @@ func (b0 InvokeActionRequest_builder) Build() *InvokeActionRequest { x.xxx_hidden_Name = b.Name x.xxx_hidden_Args = b.Args x.xxx_hidden_Annotations = &b.Annotations + x.xxx_hidden_ResourceTypeId = b.ResourceTypeId return m0 } @@ -891,10 +920,11 @@ func (b0 GetActionSchemaResponse_builder) Build() *GetActionSchemaResponse { } type ListActionSchemasRequest struct { - state protoimpl.MessageState `protogen:"opaque.v1"` - xxx_hidden_Annotations *[]*anypb.Any `protobuf:"bytes,1,rep,name=annotations,proto3"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Annotations *[]*anypb.Any `protobuf:"bytes,1,rep,name=annotations,proto3"` + xxx_hidden_ResourceTypeId string `protobuf:"bytes,2,opt,name=resource_type_id,json=resourceTypeId,proto3"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ListActionSchemasRequest) Reset() { @@ -931,14 +961,27 @@ func (x *ListActionSchemasRequest) GetAnnotations() []*anypb.Any { return nil } +func (x *ListActionSchemasRequest) GetResourceTypeId() string { + if x != nil { + return x.xxx_hidden_ResourceTypeId + } + return "" +} + func (x *ListActionSchemasRequest) SetAnnotations(v []*anypb.Any) { x.xxx_hidden_Annotations = &v } +func (x *ListActionSchemasRequest) SetResourceTypeId(v string) { + x.xxx_hidden_ResourceTypeId = v +} + type ListActionSchemasRequest_builder struct { _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. Annotations []*anypb.Any + // Optional: filter to only return actions for a specific resource type + ResourceTypeId string } func (b0 ListActionSchemasRequest_builder) Build() *ListActionSchemasRequest { @@ -946,6 +989,7 @@ func (b0 ListActionSchemasRequest_builder) Build() *ListActionSchemasRequest { b, x := &b0, m0 _, _ = b, x x.xxx_hidden_Annotations = &b.Annotations + x.xxx_hidden_ResourceTypeId = b.ResourceTypeId return m0 } @@ -1038,11 +1082,12 @@ const file_c1_connector_v2_action_proto_rawDesc = "" + "\vdescription\x18\x06 \x01(\tR\vdescription\x12<\n" + "\vaction_type\x18\a \x03(\x0e2\x1b.c1.connector.v2.ActionTypeR\n" + "actionType\x12(\n" + - "\x10resource_type_id\x18\b \x01(\tR\x0eresourceTypeId\"\x8e\x01\n" + + "\x10resource_type_id\x18\b \x01(\tR\x0eresourceTypeId\"\xb8\x01\n" + "\x13InvokeActionRequest\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\x12+\n" + "\x04args\x18\x02 \x01(\v2\x17.google.protobuf.StructR\x04args\x126\n" + - "\vannotations\x18\x03 \x03(\v2\x14.google.protobuf.AnyR\vannotations\"\xe3\x01\n" + + "\vannotations\x18\x03 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x12(\n" + + "\x10resource_type_id\x18\x04 \x01(\tR\x0eresourceTypeId\"\xe3\x01\n" + "\x14InvokeActionResponse\x12\x0e\n" + "\x02id\x18\x01 \x01(\tR\x02id\x12:\n" + "\x06status\x18\x02 \x01(\x0e2\".c1.connector.v2.BatonActionStatusR\x06status\x126\n" + @@ -1064,9 +1109,10 @@ const file_c1_connector_v2_action_proto_rawDesc = "" + "\vannotations\x18\x02 \x03(\v2\x14.google.protobuf.AnyR\vannotations\"\x8d\x01\n" + "\x17GetActionSchemaResponse\x12:\n" + "\x06schema\x18\x01 \x01(\v2\".c1.connector.v2.BatonActionSchemaR\x06schema\x126\n" + - "\vannotations\x18\x02 \x03(\v2\x14.google.protobuf.AnyR\vannotations\"R\n" + + "\vannotations\x18\x02 \x03(\v2\x14.google.protobuf.AnyR\vannotations\"|\n" + "\x18ListActionSchemasRequest\x126\n" + - "\vannotations\x18\x01 \x03(\v2\x14.google.protobuf.AnyR\vannotations\"\x91\x01\n" + + "\vannotations\x18\x01 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x12(\n" + + "\x10resource_type_id\x18\x02 \x01(\tR\x0eresourceTypeId\"\x91\x01\n" + "\x19ListActionSchemasResponse\x12<\n" + "\aschemas\x18\x01 \x03(\v2\".c1.connector.v2.BatonActionSchemaR\aschemas\x126\n" + "\vannotations\x18\x02 \x03(\v2\x14.google.protobuf.AnyR\vannotations*\xdd\x01\n" + @@ -1076,7 +1122,7 @@ const file_c1_connector_v2_action_proto_rawDesc = "" + "\x1bBATON_ACTION_STATUS_PENDING\x10\x02\x12\x1f\n" + "\x1bBATON_ACTION_STATUS_RUNNING\x10\x03\x12 \n" + "\x1cBATON_ACTION_STATUS_COMPLETE\x10\x04\x12\x1e\n" + - "\x1aBATON_ACTION_STATUS_FAILED\x10\x05*\xc4\x01\n" + + "\x1aBATON_ACTION_STATUS_FAILED\x10\x05*\xc9\x02\n" + "\n" + "ActionType\x12\x1b\n" + "\x17ACTION_TYPE_UNSPECIFIED\x10\x00\x12\x17\n" + @@ -1084,7 +1130,11 @@ const file_c1_connector_v2_action_proto_rawDesc = "" + "\x13ACTION_TYPE_ACCOUNT\x10\x02\x12&\n" + "\"ACTION_TYPE_ACCOUNT_UPDATE_PROFILE\x10\x03\x12\x1f\n" + "\x1bACTION_TYPE_ACCOUNT_DISABLE\x10\x04\x12\x1e\n" + - "\x1aACTION_TYPE_ACCOUNT_ENABLE\x10\x052\xa4\x03\n" + + "\x1aACTION_TYPE_ACCOUNT_ENABLE\x10\x05\x12\x1f\n" + + "\x1bACTION_TYPE_RESOURCE_CREATE\x10\x06\x12\x1f\n" + + "\x1bACTION_TYPE_RESOURCE_DELETE\x10\a\x12\x1f\n" + + "\x1bACTION_TYPE_RESOURCE_ENABLE\x10\b\x12 \n" + + "\x1cACTION_TYPE_RESOURCE_DISABLE\x10\t2\xa4\x03\n" + "\rActionService\x12[\n" + "\fInvokeAction\x12$.c1.connector.v2.InvokeActionRequest\x1a%.c1.connector.v2.InvokeActionResponse\x12d\n" + "\x0fGetActionStatus\x12'.c1.connector.v2.GetActionStatusRequest\x1a(.c1.connector.v2.GetActionStatusResponse\x12d\n" + diff --git a/pb/c1/connectorapi/baton/v1/baton.pb.go b/pb/c1/connectorapi/baton/v1/baton.pb.go index 0e6cbdeb5..9a1883370 100644 --- a/pb/c1/connectorapi/baton/v1/baton.pb.go +++ b/pb/c1/connectorapi/baton/v1/baton.pb.go @@ -3656,10 +3656,12 @@ func (b0 Task_GetTicketTask_builder) Build() *Task_GetTicketTask { } type Task_ActionListSchemasTask struct { - state protoimpl.MessageState `protogen:"hybrid.v1"` - Annotations []*anypb.Any `protobuf:"bytes,1,rep,name=annotations,proto3" json:"annotations,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"hybrid.v1"` + Annotations []*anypb.Any `protobuf:"bytes,1,rep,name=annotations,proto3" json:"annotations,omitempty"` + // Optional: filter to only return actions for a specific resource type + ResourceTypeId string `protobuf:"bytes,2,opt,name=resource_type_id,json=resourceTypeId,proto3" json:"resource_type_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Task_ActionListSchemasTask) Reset() { @@ -3694,14 +3696,27 @@ func (x *Task_ActionListSchemasTask) GetAnnotations() []*anypb.Any { return nil } +func (x *Task_ActionListSchemasTask) GetResourceTypeId() string { + if x != nil { + return x.ResourceTypeId + } + return "" +} + func (x *Task_ActionListSchemasTask) SetAnnotations(v []*anypb.Any) { x.Annotations = v } +func (x *Task_ActionListSchemasTask) SetResourceTypeId(v string) { + x.ResourceTypeId = v +} + type Task_ActionListSchemasTask_builder struct { _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. Annotations []*anypb.Any + // Optional: filter to only return actions for a specific resource type + ResourceTypeId string } func (b0 Task_ActionListSchemasTask_builder) Build() *Task_ActionListSchemasTask { @@ -3709,6 +3724,7 @@ func (b0 Task_ActionListSchemasTask_builder) Build() *Task_ActionListSchemasTask b, x := &b0, m0 _, _ = b, x x.Annotations = b.Annotations + x.ResourceTypeId = b.ResourceTypeId return m0 } @@ -3784,12 +3800,14 @@ func (b0 Task_ActionGetSchemaTask_builder) Build() *Task_ActionGetSchemaTask { } type Task_ActionInvokeTask struct { - state protoimpl.MessageState `protogen:"hybrid.v1"` - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Args *structpb.Struct `protobuf:"bytes,2,opt,name=args,proto3" json:"args,omitempty"` - Annotations []*anypb.Any `protobuf:"bytes,3,rep,name=annotations,proto3" json:"annotations,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"hybrid.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Args *structpb.Struct `protobuf:"bytes,2,opt,name=args,proto3" json:"args,omitempty"` + Annotations []*anypb.Any `protobuf:"bytes,3,rep,name=annotations,proto3" json:"annotations,omitempty"` + // Optional: if set, invokes a resource-scoped action + ResourceTypeId string `protobuf:"bytes,4,opt,name=resource_type_id,json=resourceTypeId,proto3" json:"resource_type_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Task_ActionInvokeTask) Reset() { @@ -3838,6 +3856,13 @@ func (x *Task_ActionInvokeTask) GetAnnotations() []*anypb.Any { return nil } +func (x *Task_ActionInvokeTask) GetResourceTypeId() string { + if x != nil { + return x.ResourceTypeId + } + return "" +} + func (x *Task_ActionInvokeTask) SetName(v string) { x.Name = v } @@ -3850,6 +3875,10 @@ func (x *Task_ActionInvokeTask) SetAnnotations(v []*anypb.Any) { x.Annotations = v } +func (x *Task_ActionInvokeTask) SetResourceTypeId(v string) { + x.ResourceTypeId = v +} + func (x *Task_ActionInvokeTask) HasArgs() bool { if x == nil { return false @@ -3867,6 +3896,8 @@ type Task_ActionInvokeTask_builder struct { Name string Args *structpb.Struct Annotations []*anypb.Any + // Optional: if set, invokes a resource-scoped action + ResourceTypeId string } func (b0 Task_ActionInvokeTask_builder) Build() *Task_ActionInvokeTask { @@ -3876,6 +3907,7 @@ func (b0 Task_ActionInvokeTask_builder) Build() *Task_ActionInvokeTask { x.Name = b.Name x.Args = b.Args x.Annotations = b.Annotations + x.ResourceTypeId = b.ResourceTypeId return m0 } @@ -4840,7 +4872,7 @@ var File_c1_connectorapi_baton_v1_baton_proto protoreflect.FileDescriptor const file_c1_connectorapi_baton_v1_baton_proto_rawDesc = "" + "\n" + - "$c1/connectorapi/baton/v1/baton.proto\x12\x18c1.connectorapi.baton.v1\x1a\x1fc1/connector/v2/connector.proto\x1a!c1/connector/v2/entitlement.proto\x1a\x1bc1/connector/v2/grant.proto\x1a\x1ec1/connector/v2/resource.proto\x1a\x1cc1/connector/v2/ticket.proto\x1a\x19google/protobuf/any.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17google/rpc/status.proto\x1a\x17validate/validate.proto\"\xac(\n" + + "$c1/connectorapi/baton/v1/baton.proto\x12\x18c1.connectorapi.baton.v1\x1a\x1fc1/connector/v2/connector.proto\x1a!c1/connector/v2/entitlement.proto\x1a\x1bc1/connector/v2/grant.proto\x1a\x1ec1/connector/v2/resource.proto\x1a\x1cc1/connector/v2/ticket.proto\x1a\x19google/protobuf/any.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17google/rpc/status.proto\x1a\x17validate/validate.proto\"\x80)\n" + "\x04Task\x12\x0e\n" + "\x02id\x18\x01 \x01(\tR\x02id\x12=\n" + "\x06status\x18\x02 \x01(\x0e2%.c1.connectorapi.baton.v1.Task.StatusR\x06status\x12=\n" + @@ -4916,16 +4948,18 @@ const file_c1_connectorapi_baton_v1_baton_proto_rawDesc = "" + "\vannotations\x18\x01 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x1ad\n" + "\rGetTicketTask\x12\x1b\n" + "\tticket_id\x18\x01 \x01(\tR\bticketId\x126\n" + - "\vannotations\x18\x02 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x1aO\n" + + "\vannotations\x18\x02 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x1ay\n" + "\x15ActionListSchemasTask\x126\n" + - "\vannotations\x18\x01 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x1aa\n" + + "\vannotations\x18\x01 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x12(\n" + + "\x10resource_type_id\x18\x02 \x01(\tR\x0eresourceTypeId\x1aa\n" + "\x13ActionGetSchemaTask\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\x126\n" + - "\vannotations\x18\x02 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x1a\x8b\x01\n" + + "\vannotations\x18\x02 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x1a\xb5\x01\n" + "\x10ActionInvokeTask\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\x12+\n" + "\x04args\x18\x02 \x01(\v2\x17.google.protobuf.StructR\x04args\x126\n" + - "\vannotations\x18\x03 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x1an\n" + + "\vannotations\x18\x03 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x12(\n" + + "\x10resource_type_id\x18\x04 \x01(\tR\x0eresourceTypeId\x1an\n" + "\x10ActionStatusTask\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\x12\x0e\n" + "\x02id\x18\x02 \x01(\tR\x02id\x126\n" + diff --git a/pb/c1/connectorapi/baton/v1/baton.pb.validate.go b/pb/c1/connectorapi/baton/v1/baton.pb.validate.go index 3e9a11770..937bae11c 100644 --- a/pb/c1/connectorapi/baton/v1/baton.pb.validate.go +++ b/pb/c1/connectorapi/baton/v1/baton.pb.validate.go @@ -5556,6 +5556,8 @@ func (m *Task_ActionListSchemasTask) validate(all bool) error { } + // no validation rules for ResourceTypeId + if len(errors) > 0 { return Task_ActionListSchemasTaskMultiError(errors) } @@ -5861,6 +5863,8 @@ func (m *Task_ActionInvokeTask) validate(all bool) error { } + // no validation rules for ResourceTypeId + if len(errors) > 0 { return Task_ActionInvokeTaskMultiError(errors) } diff --git a/pb/c1/connectorapi/baton/v1/baton_protoopaque.pb.go b/pb/c1/connectorapi/baton/v1/baton_protoopaque.pb.go index 3ca4c3e3d..bdf204f7e 100644 --- a/pb/c1/connectorapi/baton/v1/baton_protoopaque.pb.go +++ b/pb/c1/connectorapi/baton/v1/baton_protoopaque.pb.go @@ -3645,10 +3645,11 @@ func (b0 Task_GetTicketTask_builder) Build() *Task_GetTicketTask { } type Task_ActionListSchemasTask struct { - state protoimpl.MessageState `protogen:"opaque.v1"` - xxx_hidden_Annotations *[]*anypb.Any `protobuf:"bytes,1,rep,name=annotations,proto3"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Annotations *[]*anypb.Any `protobuf:"bytes,1,rep,name=annotations,proto3"` + xxx_hidden_ResourceTypeId string `protobuf:"bytes,2,opt,name=resource_type_id,json=resourceTypeId,proto3"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Task_ActionListSchemasTask) Reset() { @@ -3685,14 +3686,27 @@ func (x *Task_ActionListSchemasTask) GetAnnotations() []*anypb.Any { return nil } +func (x *Task_ActionListSchemasTask) GetResourceTypeId() string { + if x != nil { + return x.xxx_hidden_ResourceTypeId + } + return "" +} + func (x *Task_ActionListSchemasTask) SetAnnotations(v []*anypb.Any) { x.xxx_hidden_Annotations = &v } +func (x *Task_ActionListSchemasTask) SetResourceTypeId(v string) { + x.xxx_hidden_ResourceTypeId = v +} + type Task_ActionListSchemasTask_builder struct { _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. Annotations []*anypb.Any + // Optional: filter to only return actions for a specific resource type + ResourceTypeId string } func (b0 Task_ActionListSchemasTask_builder) Build() *Task_ActionListSchemasTask { @@ -3700,6 +3714,7 @@ func (b0 Task_ActionListSchemasTask_builder) Build() *Task_ActionListSchemasTask b, x := &b0, m0 _, _ = b, x x.xxx_hidden_Annotations = &b.Annotations + x.xxx_hidden_ResourceTypeId = b.ResourceTypeId return m0 } @@ -3777,12 +3792,13 @@ func (b0 Task_ActionGetSchemaTask_builder) Build() *Task_ActionGetSchemaTask { } type Task_ActionInvokeTask struct { - state protoimpl.MessageState `protogen:"opaque.v1"` - xxx_hidden_Name string `protobuf:"bytes,1,opt,name=name,proto3"` - xxx_hidden_Args *structpb.Struct `protobuf:"bytes,2,opt,name=args,proto3"` - xxx_hidden_Annotations *[]*anypb.Any `protobuf:"bytes,3,rep,name=annotations,proto3"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Name string `protobuf:"bytes,1,opt,name=name,proto3"` + xxx_hidden_Args *structpb.Struct `protobuf:"bytes,2,opt,name=args,proto3"` + xxx_hidden_Annotations *[]*anypb.Any `protobuf:"bytes,3,rep,name=annotations,proto3"` + xxx_hidden_ResourceTypeId string `protobuf:"bytes,4,opt,name=resource_type_id,json=resourceTypeId,proto3"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Task_ActionInvokeTask) Reset() { @@ -3833,6 +3849,13 @@ func (x *Task_ActionInvokeTask) GetAnnotations() []*anypb.Any { return nil } +func (x *Task_ActionInvokeTask) GetResourceTypeId() string { + if x != nil { + return x.xxx_hidden_ResourceTypeId + } + return "" +} + func (x *Task_ActionInvokeTask) SetName(v string) { x.xxx_hidden_Name = v } @@ -3845,6 +3868,10 @@ func (x *Task_ActionInvokeTask) SetAnnotations(v []*anypb.Any) { x.xxx_hidden_Annotations = &v } +func (x *Task_ActionInvokeTask) SetResourceTypeId(v string) { + x.xxx_hidden_ResourceTypeId = v +} + func (x *Task_ActionInvokeTask) HasArgs() bool { if x == nil { return false @@ -3862,6 +3889,8 @@ type Task_ActionInvokeTask_builder struct { Name string Args *structpb.Struct Annotations []*anypb.Any + // Optional: if set, invokes a resource-scoped action + ResourceTypeId string } func (b0 Task_ActionInvokeTask_builder) Build() *Task_ActionInvokeTask { @@ -3871,6 +3900,7 @@ func (b0 Task_ActionInvokeTask_builder) Build() *Task_ActionInvokeTask { x.xxx_hidden_Name = b.Name x.xxx_hidden_Args = b.Args x.xxx_hidden_Annotations = &b.Annotations + x.xxx_hidden_ResourceTypeId = b.ResourceTypeId return m0 } @@ -4847,7 +4877,7 @@ var File_c1_connectorapi_baton_v1_baton_proto protoreflect.FileDescriptor const file_c1_connectorapi_baton_v1_baton_proto_rawDesc = "" + "\n" + - "$c1/connectorapi/baton/v1/baton.proto\x12\x18c1.connectorapi.baton.v1\x1a\x1fc1/connector/v2/connector.proto\x1a!c1/connector/v2/entitlement.proto\x1a\x1bc1/connector/v2/grant.proto\x1a\x1ec1/connector/v2/resource.proto\x1a\x1cc1/connector/v2/ticket.proto\x1a\x19google/protobuf/any.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17google/rpc/status.proto\x1a\x17validate/validate.proto\"\xac(\n" + + "$c1/connectorapi/baton/v1/baton.proto\x12\x18c1.connectorapi.baton.v1\x1a\x1fc1/connector/v2/connector.proto\x1a!c1/connector/v2/entitlement.proto\x1a\x1bc1/connector/v2/grant.proto\x1a\x1ec1/connector/v2/resource.proto\x1a\x1cc1/connector/v2/ticket.proto\x1a\x19google/protobuf/any.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17google/rpc/status.proto\x1a\x17validate/validate.proto\"\x80)\n" + "\x04Task\x12\x0e\n" + "\x02id\x18\x01 \x01(\tR\x02id\x12=\n" + "\x06status\x18\x02 \x01(\x0e2%.c1.connectorapi.baton.v1.Task.StatusR\x06status\x12=\n" + @@ -4923,16 +4953,18 @@ const file_c1_connectorapi_baton_v1_baton_proto_rawDesc = "" + "\vannotations\x18\x01 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x1ad\n" + "\rGetTicketTask\x12\x1b\n" + "\tticket_id\x18\x01 \x01(\tR\bticketId\x126\n" + - "\vannotations\x18\x02 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x1aO\n" + + "\vannotations\x18\x02 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x1ay\n" + "\x15ActionListSchemasTask\x126\n" + - "\vannotations\x18\x01 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x1aa\n" + + "\vannotations\x18\x01 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x12(\n" + + "\x10resource_type_id\x18\x02 \x01(\tR\x0eresourceTypeId\x1aa\n" + "\x13ActionGetSchemaTask\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\x126\n" + - "\vannotations\x18\x02 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x1a\x8b\x01\n" + + "\vannotations\x18\x02 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x1a\xb5\x01\n" + "\x10ActionInvokeTask\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\x12+\n" + "\x04args\x18\x02 \x01(\v2\x17.google.protobuf.StructR\x04args\x126\n" + - "\vannotations\x18\x03 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x1an\n" + + "\vannotations\x18\x03 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x12(\n" + + "\x10resource_type_id\x18\x04 \x01(\tR\x0eresourceTypeId\x1an\n" + "\x10ActionStatusTask\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\x12\x0e\n" + "\x02id\x18\x02 \x01(\tR\x02id\x126\n" + diff --git a/pkg/actions/actions.go b/pkg/actions/actions.go index 585618734..ca26d7e4a 100644 --- a/pkg/actions/actions.go +++ b/pkg/actions/actions.go @@ -82,17 +82,44 @@ func (oa *OutstandingAction) SetError(ctx context.Context, err error) { const maxOldActions = 1000 +// ActionRegistry provides methods for registering actions. +// Used by both GlobalActionProvider (global actions) and ResourceActionProvider (resource-scoped actions). +type ActionRegistry interface { + // Register registers an action using the name from the schema. + Register(ctx context.Context, schema *v2.BatonActionSchema, handler ActionHandler) error + + // Deprecated: Use Register instead. + // RegisterAction registers an action. + RegisterAction(ctx context.Context, name string, schema *v2.BatonActionSchema, handler ActionHandler) error +} + +// Deprecated: Use ActionRegistry instead. +// ResourceTypeActionRegistry is an alias for ActionRegistry for backwards compatibility. +type ResourceTypeActionRegistry = ActionRegistry + +// ActionManager manages both global actions and resource-scoped actions. type ActionManager struct { - schemas map[string]*v2.BatonActionSchema // map of action name to schema - handlers map[string]ActionHandler - actions map[string]*OutstandingAction // map of actions IDs + // Global actions (no resource type) + schemas map[string]*v2.BatonActionSchema // actionName -> schema + handlers map[string]ActionHandler // actionName -> handler + + // Resource-scoped actions (keyed by resource type) + resourceSchemas map[string]map[string]*v2.BatonActionSchema // resourceTypeID -> actionName -> schema + resourceHandlers map[string]map[string]ActionHandler // resourceTypeID -> actionName -> handler + + // Outstanding actions (shared across global and resource-scoped) + actions map[string]*OutstandingAction // actionID -> outstanding action + + mu sync.RWMutex } func NewActionManager(_ context.Context) *ActionManager { return &ActionManager{ - schemas: make(map[string]*v2.BatonActionSchema), - handlers: make(map[string]ActionHandler), - actions: make(map[string]*OutstandingAction), + schemas: make(map[string]*v2.BatonActionSchema), + handlers: make(map[string]ActionHandler), + resourceSchemas: make(map[string]map[string]*v2.BatonActionSchema), + resourceHandlers: make(map[string]map[string]ActionHandler), + actions: make(map[string]*OutstandingAction), } } @@ -102,6 +129,8 @@ func (a *ActionManager) GetNewActionId() string { } func (a *ActionManager) GetNewAction(name string) *OutstandingAction { + a.mu.Lock() + defer a.mu.Unlock() actionId := a.GetNewActionId() oa := NewOutstandingAction(actionId, name) a.actions[actionId] = oa @@ -109,6 +138,9 @@ func (a *ActionManager) GetNewAction(name string) *OutstandingAction { } func (a *ActionManager) CleanupOldActions(ctx context.Context) { + a.mu.Lock() + defer a.mu.Unlock() + if len(a.actions) < maxOldActions { return } @@ -138,7 +170,7 @@ func (a *ActionManager) CleanupOldActions(ctx context.Context) { l.Debug("cleaned up old actions", zap.Int("count", count)) } -func (a *ActionManager) registerActionSchema(ctx context.Context, name string, schema *v2.BatonActionSchema) error { +func (a *ActionManager) registerActionSchema(_ context.Context, name string, schema *v2.BatonActionSchema) error { if name == "" { return errors.New("action name cannot be empty") } @@ -152,7 +184,20 @@ func (a *ActionManager) registerActionSchema(ctx context.Context, name string, s return nil } +// Register registers a global action using the name from the schema. +func (a *ActionManager) Register(ctx context.Context, schema *v2.BatonActionSchema, handler ActionHandler) error { + if schema == nil { + return errors.New("action schema cannot be nil") + } + return a.RegisterAction(ctx, schema.GetName(), schema, handler) +} + +// Deprecated: Use Register instead. +// RegisterAction registers a global action (not scoped to a resource type). func (a *ActionManager) RegisterAction(ctx context.Context, name string, schema *v2.BatonActionSchema, handler ActionHandler) error { + a.mu.Lock() + defer a.mu.Unlock() + if handler == nil { return errors.New("action handler cannot be nil") } @@ -172,7 +217,108 @@ func (a *ActionManager) RegisterAction(ctx context.Context, name string, schema return nil } +func (a *ActionManager) HasActions() bool { + a.mu.RLock() + defer a.mu.RUnlock() + return len(a.schemas) > 0 || len(a.resourceSchemas) > 0 +} + +// RegisterResourceAction registers a resource-scoped action. +func (a *ActionManager) RegisterResourceAction( + ctx context.Context, + resourceTypeID string, + schema *v2.BatonActionSchema, + handler ActionHandler, +) error { + if resourceTypeID == "" { + return errors.New("resource type ID cannot be empty") + } + if schema == nil { + return errors.New("action schema cannot be nil") + } + if schema.GetName() == "" { + return errors.New("action schema name cannot be empty") + } + if handler == nil { + return fmt.Errorf("handler cannot be nil for action %s", schema.GetName()) + } + + a.mu.Lock() + defer a.mu.Unlock() + + // Set the resource type ID on the schema + schema.SetResourceTypeId(resourceTypeID) + + if a.resourceSchemas[resourceTypeID] == nil { + a.resourceSchemas[resourceTypeID] = make(map[string]*v2.BatonActionSchema) + } + if a.resourceHandlers[resourceTypeID] == nil { + a.resourceHandlers[resourceTypeID] = make(map[string]ActionHandler) + } + + actionName := schema.GetName() + + // Check for duplicate action names + if _, ok := a.resourceSchemas[resourceTypeID][actionName]; ok { + return fmt.Errorf("action schema %s already registered for resource type %s", actionName, resourceTypeID) + } + + // Check for duplicate action types + if len(schema.GetActionType()) > 0 { + for existingName, existingSchema := range a.resourceSchemas[resourceTypeID] { + if existingSchema == nil || len(existingSchema.GetActionType()) == 0 { + continue + } + // Check if any ActionType in the new schema matches any in existing schemas + for _, newActionType := range schema.GetActionType() { + if newActionType == v2.ActionType_ACTION_TYPE_UNSPECIFIED || newActionType == v2.ActionType_ACTION_TYPE_DYNAMIC { + continue // Skip unspecified and dynamic types as they can overlap + } + for _, existingActionType := range existingSchema.GetActionType() { + if newActionType == existingActionType { + return fmt.Errorf("action type %s already registered for resource type %s (existing action: %s)", newActionType.String(), resourceTypeID, existingName) + } + } + } + } + } + + a.resourceSchemas[resourceTypeID][actionName] = schema + a.resourceHandlers[resourceTypeID][actionName] = handler + + ctxzap.Extract(ctx).Debug("registered resource action", zap.String("resource_type", resourceTypeID), zap.String("action_name", actionName)) + + return nil +} + +// resourceTypeActionRegistry implements ResourceTypeActionRegistry for a specific resource type. +type resourceTypeActionRegistry struct { + resourceTypeID string + actionManager *ActionManager +} + +func (r *resourceTypeActionRegistry) Register(ctx context.Context, schema *v2.BatonActionSchema, handler ActionHandler) error { + return r.actionManager.RegisterResourceAction(ctx, r.resourceTypeID, schema, handler) +} + +// Deprecated: Use Register instead. +// RegisterAction registers a resource-scoped action. The name parameter is ignored; the name from schema is used. +func (r *resourceTypeActionRegistry) RegisterAction(ctx context.Context, name string, schema *v2.BatonActionSchema, handler ActionHandler) error { + return r.Register(ctx, schema, handler) +} + +// GetTypeRegistry returns an ActionRegistry for registering actions scoped to a specific resource type. +func (a *ActionManager) GetTypeRegistry(_ context.Context, resourceTypeID string) (ActionRegistry, error) { + if resourceTypeID == "" { + return nil, errors.New("resource type ID cannot be empty") + } + return &resourceTypeActionRegistry{resourceTypeID: resourceTypeID, actionManager: a}, nil +} + func (a *ActionManager) UnregisterAction(ctx context.Context, name string) error { + a.mu.Lock() + defer a.mu.Unlock() + if _, ok := a.schemas[name]; !ok { return fmt.Errorf("action %s not registered", name) } @@ -190,16 +336,48 @@ func (a *ActionManager) UnregisterAction(ctx context.Context, name string) error return nil } -func (a *ActionManager) ListActionSchemas(ctx context.Context) ([]*v2.BatonActionSchema, annotations.Annotations, error) { - rv := make([]*v2.BatonActionSchema, 0, len(a.schemas)) - for _, schema := range a.schemas { - rv = append(rv, schema) +// ListActionSchemas returns all action schemas, optionally filtered by resource type. +// If resourceTypeID is empty, returns all global actions plus all resource-scoped actions. +// If resourceTypeID is set, returns only actions for that resource type. +func (a *ActionManager) ListActionSchemas(_ context.Context, resourceTypeID string) ([]*v2.BatonActionSchema, annotations.Annotations, error) { + a.mu.RLock() + defer a.mu.RUnlock() + + var rv []*v2.BatonActionSchema + + if resourceTypeID == "" { + // Return all global actions + rv = make([]*v2.BatonActionSchema, 0, len(a.schemas)) + for _, schema := range a.schemas { + rv = append(rv, schema) + } + + // Also return all resource-scoped actions + for _, schemas := range a.resourceSchemas { + for _, schema := range schemas { + rv = append(rv, schema) + } + } + } else { + // Return only actions for the specified resource type + schemas, ok := a.resourceSchemas[resourceTypeID] + if !ok { + return []*v2.BatonActionSchema{}, nil, nil + } + + rv = make([]*v2.BatonActionSchema, 0, len(schemas)) + for _, schema := range schemas { + rv = append(rv, schema) + } } return rv, nil, nil } -func (a *ActionManager) GetActionSchema(ctx context.Context, name string) (*v2.BatonActionSchema, annotations.Annotations, error) { +func (a *ActionManager) GetActionSchema(_ context.Context, name string) (*v2.BatonActionSchema, annotations.Annotations, error) { + a.mu.RLock() + defer a.mu.RUnlock() + schema, ok := a.schemas[name] if !ok { return nil, nil, status.Error(codes.NotFound, fmt.Sprintf("action %s not found", name)) @@ -207,7 +385,10 @@ func (a *ActionManager) GetActionSchema(ctx context.Context, name string) (*v2.B return schema, nil, nil } -func (a *ActionManager) GetActionStatus(ctx context.Context, actionId string) (v2.BatonActionStatus, string, *structpb.Struct, annotations.Annotations, error) { +func (a *ActionManager) GetActionStatus(_ context.Context, actionId string) (v2.BatonActionStatus, string, *structpb.Struct, annotations.Annotations, error) { + a.mu.RLock() + defer a.mu.RUnlock() + oa := a.actions[actionId] if oa == nil { return v2.BatonActionStatus_BATON_ACTION_STATUS_UNKNOWN, "", nil, nil, status.Error(codes.NotFound, fmt.Sprintf("action id %s not found", actionId)) @@ -218,8 +399,27 @@ func (a *ActionManager) GetActionStatus(ctx context.Context, actionId string) (v return oa.Status, oa.Name, oa.Rv, oa.Annos, nil } -func (a *ActionManager) InvokeAction(ctx context.Context, name string, args *structpb.Struct) (string, v2.BatonActionStatus, *structpb.Struct, annotations.Annotations, error) { +// InvokeAction invokes an action. If resourceTypeID is set, it invokes a resource-scoped action. +// Otherwise, it invokes a global action. +func (a *ActionManager) InvokeAction( + ctx context.Context, + name string, + resourceTypeID string, + args *structpb.Struct, +) (string, v2.BatonActionStatus, *structpb.Struct, annotations.Annotations, error) { + if resourceTypeID != "" { + return a.invokeResourceAction(ctx, resourceTypeID, name, args) + } + + return a.invokeGlobalAction(ctx, name, args) +} + +// invokeGlobalAction invokes a global (non-resource-scoped) action. +func (a *ActionManager) invokeGlobalAction(ctx context.Context, name string, args *structpb.Struct) (string, v2.BatonActionStatus, *structpb.Struct, annotations.Annotations, error) { + a.mu.RLock() handler, ok := a.handlers[name] + a.mu.RUnlock() + if !ok { return "", v2.BatonActionStatus_BATON_ACTION_STATUS_FAILED, nil, nil, status.Error(codes.NotFound, fmt.Sprintf("handler for action %s not found", name)) } @@ -255,3 +455,65 @@ func (a *ActionManager) InvokeAction(ctx context.Context, name string, args *str return oa.Id, oa.Status, oa.Rv, oa.Annos, ctx.Err() } } + +// invokeResourceAction invokes a resource-scoped action. +func (a *ActionManager) invokeResourceAction( + ctx context.Context, + resourceTypeID string, + actionName string, + args *structpb.Struct, +) (string, v2.BatonActionStatus, *structpb.Struct, annotations.Annotations, error) { + if resourceTypeID == "" { + return "", v2.BatonActionStatus_BATON_ACTION_STATUS_FAILED, nil, nil, status.Error(codes.InvalidArgument, "resource type ID is required") + } + if actionName == "" { + return "", v2.BatonActionStatus_BATON_ACTION_STATUS_FAILED, nil, nil, status.Error(codes.InvalidArgument, "action name is required") + } + + a.mu.RLock() + handlers, ok := a.resourceHandlers[resourceTypeID] + if !ok { + a.mu.RUnlock() + return "", v2.BatonActionStatus_BATON_ACTION_STATUS_FAILED, nil, nil, status.Error(codes.NotFound, fmt.Sprintf("no actions found for resource type %s", resourceTypeID)) + } + + handler, ok := handlers[actionName] + if !ok { + a.mu.RUnlock() + return "", + v2.BatonActionStatus_BATON_ACTION_STATUS_FAILED, + nil, + nil, + status.Error(codes.NotFound, fmt.Sprintf("handler for action %s not found for resource type %s", actionName, resourceTypeID)) + } + a.mu.RUnlock() + + oa := a.GetNewAction(actionName) + done := make(chan struct{}) + + // Invoke handler in goroutine + go func() { + oa.SetStatus(ctx, v2.BatonActionStatus_BATON_ACTION_STATUS_RUNNING) + handlerCtx, cancel := context.WithTimeoutCause(context.Background(), 1*time.Hour, errors.New("action handler timed out")) + defer cancel() + var oaErr error + oa.Rv, oa.Annos, oaErr = handler(handlerCtx, args) + if oaErr == nil { + oa.SetStatus(ctx, v2.BatonActionStatus_BATON_ACTION_STATUS_COMPLETE) + } else { + oa.SetError(ctx, oaErr) + } + done <- struct{}{} + }() + + // Wait for completion or timeout + select { + case <-done: + return oa.Id, oa.Status, oa.Rv, oa.Annos, nil + case <-time.After(1 * time.Second): + return oa.Id, oa.Status, oa.Rv, oa.Annos, nil + case <-ctx.Done(): + oa.SetError(ctx, ctx.Err()) + return oa.Id, oa.Status, oa.Rv, oa.Annos, ctx.Err() + } +} diff --git a/pkg/actions/actions_test.go b/pkg/actions/actions_test.go index b6c419cbc..b6b2e0f84 100644 --- a/pkg/actions/actions_test.go +++ b/pkg/actions/actions_test.go @@ -124,10 +124,10 @@ func TestActionHandler(t *testing.T) { m := NewActionManager(ctx) require.NotNil(t, m) - err := m.RegisterAction(ctx, "lock_account", testActionSchema, testActionHandler) + err := m.Register(ctx, testActionSchema, testActionHandler) require.NoError(t, err) - schemas, _, err := m.ListActionSchemas(ctx) + schemas, _, err := m.ListActionSchemas(ctx, "") require.NoError(t, err) require.Len(t, schemas, 1) require.Equal(t, testActionSchema, schemas[0]) @@ -136,7 +136,7 @@ func TestActionHandler(t *testing.T) { require.NoError(t, err) require.Equal(t, testActionSchema, schema) - _, status, returnArgs, _, err := m.InvokeAction(ctx, "lock_account", testInput) + _, status, returnArgs, _, err := m.InvokeAction(ctx, "lock_account", "", testInput) require.NoError(t, err) require.Equal(t, v2.BatonActionStatus_BATON_ACTION_STATUS_COMPLETE, status) require.NotNil(t, returnArgs) @@ -144,7 +144,7 @@ func TestActionHandler(t *testing.T) { require.True(t, ok) require.True(t, success.BoolValue) - _, status, rv, _, err := m.InvokeAction(ctx, "lock_account", &structpb.Struct{ + _, status, rv, _, err := m.InvokeAction(ctx, "lock_account", "", &structpb.Struct{ Fields: map[string]*structpb.Value{}, }) expectedRv := &structpb.Struct{ @@ -164,10 +164,10 @@ func TestAsyncActionHandler(t *testing.T) { m := NewActionManager(ctx) require.NotNil(t, m) - err := m.RegisterAction(ctx, "lock_account", testActionSchema, testAsyncActionHandler) + err := m.Register(ctx, testActionSchema, testAsyncActionHandler) require.NoError(t, err) - schemas, _, err := m.ListActionSchemas(ctx) + schemas, _, err := m.ListActionSchemas(ctx, "") require.NoError(t, err) require.Len(t, schemas, 1) require.Equal(t, testActionSchema, schemas[0]) @@ -176,7 +176,7 @@ func TestAsyncActionHandler(t *testing.T) { require.NoError(t, err) require.Equal(t, testActionSchema, schema) - actionId, status, rv, _, err := m.InvokeAction(ctx, "lock_account", testInput) + actionId, status, rv, _, err := m.InvokeAction(ctx, "lock_account", "", testInput) require.NoError(t, err) require.Equal(t, v2.BatonActionStatus_BATON_ACTION_STATUS_RUNNING, status) require.Nil(t, rv) @@ -205,13 +205,13 @@ func TestActionHandlerGoroutineLeaks(t *testing.T) { m := NewActionManager(ctx) require.NotNil(t, m) - err := m.RegisterAction(ctx, "lock_account", testActionSchema, testAsyncActionHandler) + err := m.Register(ctx, testActionSchema, testAsyncActionHandler) require.NoError(t, err) // Get initial goroutine count initialCount := runtime.NumGoroutine() - actionId, status, _, _, err := m.InvokeAction(ctx, "lock_account", testInput) + actionId, status, _, _, err := m.InvokeAction(ctx, "lock_account", "", testInput) require.NoError(t, err) require.Equal(t, v2.BatonActionStatus_BATON_ACTION_STATUS_RUNNING, status) @@ -238,13 +238,13 @@ func TestActionHandlerGoroutineLeaks(t *testing.T) { m := NewActionManager(ctx) require.NotNil(t, m) - err := m.RegisterAction(ctx, "lock_account", testActionSchema, testAsyncCancelActionHandler) + err := m.Register(ctx, testActionSchema, testAsyncCancelActionHandler) require.NoError(t, err) // Get initial goroutine count initialCount := runtime.NumGoroutine() - _, status, rv, _, err := m.InvokeAction(ctx, "lock_account", testInput) + _, status, rv, _, err := m.InvokeAction(ctx, "lock_account", "", testInput) require.NoError(t, err) require.Equal(t, v2.BatonActionStatus_BATON_ACTION_STATUS_FAILED, status) diff --git a/pkg/actions/args.go b/pkg/actions/args.go new file mode 100644 index 000000000..367b32876 --- /dev/null +++ b/pkg/actions/args.go @@ -0,0 +1,543 @@ +package actions + +import ( + "fmt" + + config "github.com/conductorone/baton-sdk/pb/c1/config/v1" + v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/types/known/structpb" +) + +// GetStringArg extracts a string value from the args struct by key. +// Returns the value and true if found, empty string and false otherwise. +func GetStringArg(args *structpb.Struct, key string) (string, bool) { + if args == nil || args.Fields == nil { + return "", false + } + + value, ok := args.Fields[key] + if !ok { + return "", false + } + + stringValue, ok := value.GetKind().(*structpb.Value_StringValue) + if !ok { + return "", false + } + + return stringValue.StringValue, true +} + +// GetIntArg extracts an int64 value from the args struct by key. +// Returns the value and true if found, 0 and false otherwise. +func GetIntArg(args *structpb.Struct, key string) (int64, bool) { + if args == nil || args.Fields == nil { + return 0, false + } + + value, ok := args.Fields[key] + if !ok { + return 0, false + } + + numberValue, ok := value.GetKind().(*structpb.Value_NumberValue) + if !ok { + return 0, false + } + + return int64(numberValue.NumberValue), true +} + +// GetBoolArg extracts a bool value from the args struct by key. +// Returns the value and true if found, false and false otherwise. +func GetBoolArg(args *structpb.Struct, key string) (bool, bool) { + if args == nil || args.Fields == nil { + return false, false + } + + value, ok := args.Fields[key] + if !ok { + return false, false + } + + boolValue, ok := value.GetKind().(*structpb.Value_BoolValue) + if !ok { + return false, false + } + + return boolValue.BoolValue, true +} + +// GetResourceIDArg extracts a ResourceId from the args struct by key. +// The value is expected to be a struct with "resource_type_id" and "resource_id" fields +// (as stored by ResourceField). Returns the ResourceId and true if found, nil and false otherwise. +func GetResourceIDArg(args *structpb.Struct, key string) (*v2.ResourceId, bool) { + if args == nil || args.Fields == nil { + return nil, false + } + + value, ok := args.Fields[key] + if !ok { + return nil, false + } + + structValue, ok := value.GetKind().(*structpb.Value_StructValue) + if !ok { + return nil, false + } + + // Try to get resource_type_id and resource_id fields + resourceTypeID, ok := GetStringArg(structValue.StructValue, "resource_type_id") + if !ok { + // Also try resource_type as an alternative + resourceTypeID, ok = GetStringArg(structValue.StructValue, "resource_type") + if !ok { + return nil, false + } + } + + resourceID, ok := GetStringArg(structValue.StructValue, "resource_id") + if !ok { + // Also try resource as an alternative + resourceID, ok = GetStringArg(structValue.StructValue, "resource") + if !ok { + return nil, false + } + } + + return &v2.ResourceId{ + ResourceType: resourceTypeID, + Resource: resourceID, + }, true +} + +// GetStringSliceArg extracts a string slice from the args struct by key. +// Returns the slice and true if found, nil and false otherwise. +func GetStringSliceArg(args *structpb.Struct, key string) ([]string, bool) { + if args == nil || args.Fields == nil { + return nil, false + } + + value, ok := args.Fields[key] + if !ok { + return nil, false + } + + listValue, ok := value.GetKind().(*structpb.Value_ListValue) + if !ok { + return nil, false + } + + result := make([]string, 0, len(listValue.ListValue.Values)) + for _, v := range listValue.ListValue.Values { + stringValue, ok := v.GetKind().(*structpb.Value_StringValue) + if !ok { + return nil, false + } + result = append(result, stringValue.StringValue) + } + + return result, true +} + +// GetStructArg extracts a nested struct from the args struct by key. +// Returns the struct and true if found, nil and false otherwise. +func GetStructArg(args *structpb.Struct, key string) (*structpb.Struct, bool) { + if args == nil || args.Fields == nil { + return nil, false + } + + value, ok := args.Fields[key] + if !ok { + return nil, false + } + + structValue, ok := value.GetKind().(*structpb.Value_StructValue) + if !ok { + return nil, false + } + + return structValue.StructValue, true +} + +// RequireStringArg extracts a string value from the args struct by key. +// Returns the value or an error if not found or invalid. +func RequireStringArg(args *structpb.Struct, key string) (string, error) { + value, ok := GetStringArg(args, key) + if !ok { + return "", fmt.Errorf("required argument %s is missing or invalid", key) + } + return value, nil +} + +// RequireResourceIDArg extracts a ResourceId from the args struct by key. +// Returns the ResourceId or an error if not found or invalid. +func RequireResourceIDArg(args *structpb.Struct, key string) (*v2.ResourceId, error) { + value, ok := GetResourceIDArg(args, key) + if !ok { + return nil, fmt.Errorf("required argument %s is missing or invalid", key) + } + return value, nil +} + +// RequireResourceIdListArg extracts a list of ResourceId from the args struct by key. +// Returns the list of ResourceId or an error if not found or invalid. +func RequireResourceIdListArg(args *structpb.Struct, key string) ([]*v2.ResourceId, error) { + list, ok := GetResourceIdListArg(args, key) + if !ok { + return nil, fmt.Errorf("required argument %s is missing or invalid", key) + } + return list, nil +} + +// GetResourceIdListArg extracts a list of ResourceId from the args struct by key. +// Returns the list and true if found and valid, or nil and false otherwise. +func GetResourceIdListArg(args *structpb.Struct, key string) ([]*v2.ResourceId, bool) { + if args == nil || args.Fields == nil { + return nil, false + } + + value, ok := args.Fields[key] + if !ok { + return nil, false + } + + listValue, ok := value.GetKind().(*structpb.Value_ListValue) + if !ok { + return nil, false + } + + var resourceIDs []*v2.ResourceId + for _, v := range listValue.ListValue.Values { + structValue, ok := v.GetKind().(*structpb.Value_StructValue) + if !ok { + return nil, false + } + // Try to get resource_type_id and resource_id fields + resourceTypeID, ok := GetStringArg(structValue.StructValue, "resource_type_id") + if !ok { + // Also try resource_type as an alternative + resourceTypeID, ok = GetStringArg(structValue.StructValue, "resource_type") + if !ok { + return nil, false + } + } + + resourceID, ok := GetStringArg(structValue.StructValue, "resource_id") + if !ok { + // Also try resource as an alternative + resourceID, ok = GetStringArg(structValue.StructValue, "resource") + if !ok { + return nil, false + } + } + resourceIDs = append(resourceIDs, &v2.ResourceId{ + ResourceType: resourceTypeID, + Resource: resourceID, + }) + } + + return resourceIDs, true +} + +// GetResourceFieldArg extracts a Resource proto message from the args struct by key. +// The Resource is expected to be stored as a JSON-serialized struct value. +// Returns the Resource and true if found and valid, or nil and false otherwise. +func GetResourceFieldArg(args *structpb.Struct, key string) (*v2.Resource, bool) { + if args == nil || args.Fields == nil { + return nil, false + } + value, ok := args.Fields[key] + if !ok { + return nil, false + } + structValue, ok := value.GetKind().(*structpb.Value_StructValue) + if !ok { + return nil, false + } + + // Marshal the struct value back to JSON, then unmarshal into the proto message + jsonBytes, err := protojson.Marshal(structValue.StructValue) + if err != nil { + return nil, false + } + + basicResource := &config.Resource{} + if err := protojson.Unmarshal(jsonBytes, basicResource); err != nil { + return nil, false + } + + return basicResourceToResource(basicResource), true +} + +func resourceToBasicResource(resource *v2.Resource) *config.Resource { + var resourceId *config.ResourceId + if resource.Id != nil { + resourceId = config.ResourceId_builder{ + ResourceTypeId: resource.Id.ResourceType, + ResourceId: resource.Id.Resource, + }.Build() + } + var parentResourceId *config.ResourceId + if resource.ParentResourceId != nil { + parentResourceId = config.ResourceId_builder{ + ResourceTypeId: resource.ParentResourceId.ResourceType, + ResourceId: resource.ParentResourceId.Resource, + }.Build() + } + return config.Resource_builder{ + ResourceId: resourceId, + ParentResourceId: parentResourceId, + DisplayName: resource.DisplayName, + Description: resource.Description, + Annotations: resource.Annotations, + }.Build() +} + +func basicResourceToResource(basicResource *config.Resource) *v2.Resource { + var resourceId *v2.ResourceId + if basicResource.GetResourceId() != nil { + resourceId = &v2.ResourceId{ + ResourceType: basicResource.GetResourceId().GetResourceTypeId(), + Resource: basicResource.GetResourceId().GetResourceId(), + } + } + var parentResourceId *v2.ResourceId + if basicResource.GetParentResourceId() != nil { + parentResourceId = &v2.ResourceId{ + ResourceType: basicResource.GetParentResourceId().GetResourceTypeId(), + Resource: basicResource.GetParentResourceId().GetResourceId(), + } + } + return &v2.Resource{ + Id: resourceId, + ParentResourceId: parentResourceId, + DisplayName: basicResource.GetDisplayName(), + Description: basicResource.GetDescription(), + Annotations: basicResource.GetAnnotations(), + } +} + +// GetResourceListFieldArg extracts a list of Resource proto messages from the args struct by key. +// Each Resource is expected to be stored as a JSON-serialized struct value. +// Returns the list of Resource and true if found and valid, or nil and false otherwise. +func GetResourceListFieldArg(args *structpb.Struct, key string) ([]*v2.Resource, bool) { + if args == nil || args.Fields == nil { + return nil, false + } + value, ok := args.Fields[key] + if !ok { + return nil, false + } + listValue, ok := value.GetKind().(*structpb.Value_ListValue) + if !ok { + return nil, false + } + var resources []*v2.Resource + for _, v := range listValue.ListValue.Values { + structValue, ok := v.GetKind().(*structpb.Value_StructValue) + if !ok { + return nil, false + } + + // Marshal the struct value back to JSON, then unmarshal into the proto message + jsonBytes, err := protojson.Marshal(structValue.StructValue) + if err != nil { + return nil, false + } + + basicResource := &config.Resource{} + if err := protojson.Unmarshal(jsonBytes, basicResource); err != nil { + return nil, false + } + + resources = append(resources, basicResourceToResource(basicResource)) + } + return resources, true +} + +// SetResourceFieldArg stores a Resource proto message in the args struct by key. +// The Resource is serialized as a JSON struct value. +func SetResourceFieldArg(args *structpb.Struct, key string, resource *v2.Resource) error { + if args == nil { + return fmt.Errorf("args cannot be nil") + } + if resource == nil { + return fmt.Errorf("resource cannot be nil") + } + + basicResource := resourceToBasicResource(resource) + + // Marshal the proto message to JSON, then unmarshal into a struct value + jsonBytes, err := protojson.Marshal(basicResource) + if err != nil { + return fmt.Errorf("failed to marshal resource: %w", err) + } + + structValue := &structpb.Struct{} + if err := protojson.Unmarshal(jsonBytes, structValue); err != nil { + return fmt.Errorf("failed to unmarshal resource to struct: %w", err) + } + + if args.Fields == nil { + args.Fields = make(map[string]*structpb.Value) + } + args.Fields[key] = structpb.NewStructValue(structValue) + return nil +} + +// ReturnField represents a key-value pair for action return values. +type ReturnField struct { + Key string + Value *structpb.Value +} + +// NewReturnField creates a new return field with the given key and value. +func NewReturnField(key string, value *structpb.Value) ReturnField { + return ReturnField{Key: key, Value: value} +} + +// NewStringReturnField creates a return field with a string value. +func NewStringReturnField(key string, value string) ReturnField { + return ReturnField{Key: key, Value: structpb.NewStringValue(value)} +} + +// NewBoolReturnField creates a return field with a bool value. +func NewBoolReturnField(key string, value bool) ReturnField { + return ReturnField{Key: key, Value: structpb.NewBoolValue(value)} +} + +// NewNumberReturnField creates a return field with a number value. +func NewNumberReturnField(key string, value float64) ReturnField { + return ReturnField{Key: key, Value: structpb.NewNumberValue(value)} +} + +// NewResourceReturnField creates a return field with a Resource proto value. +func NewResourceReturnField(key string, resource *v2.Resource) (ReturnField, error) { + if resource == nil { + return ReturnField{}, fmt.Errorf("resource cannot be nil") + } + basicResource := resourceToBasicResource(resource) + jsonBytes, err := protojson.Marshal(basicResource) + if err != nil { + return ReturnField{}, fmt.Errorf("failed to marshal resource: %w", err) + } + + structValue := &structpb.Struct{} + if err := protojson.Unmarshal(jsonBytes, structValue); err != nil { + return ReturnField{}, fmt.Errorf("failed to unmarshal resource to struct: %w", err) + } + + return ReturnField{Key: key, Value: structpb.NewStructValue(structValue)}, nil +} + +// NewResourceIdReturnField creates a return field with a ResourceId proto value. +func NewResourceIdReturnField(key string, resourceId *v2.ResourceId) (ReturnField, error) { + if resourceId == nil { + return ReturnField{}, fmt.Errorf("resource ID cannot be nil") + } + basicResourceId := config.ResourceId_builder{ + ResourceTypeId: resourceId.ResourceType, + ResourceId: resourceId.Resource, + }.Build() + jsonBytes, err := protojson.Marshal(basicResourceId) + if err != nil { + return ReturnField{}, fmt.Errorf("failed to marshal resource id: %w", err) + } + + structValue := &structpb.Struct{} + if err := protojson.Unmarshal(jsonBytes, structValue); err != nil { + return ReturnField{}, fmt.Errorf("failed to unmarshal resource id to struct: %w", err) + } + + return ReturnField{Key: key, Value: structpb.NewStructValue(structValue)}, nil +} + +// NewStringListReturnField creates a return field with a list of string values. +func NewStringListReturnField(key string, values []string) ReturnField { + listValues := make([]*structpb.Value, len(values)) + for i, v := range values { + listValues[i] = structpb.NewStringValue(v) + } + return ReturnField{Key: key, Value: structpb.NewListValue(&structpb.ListValue{Values: listValues})} +} + +// NewNumberListReturnField creates a return field with a list of number values. +func NewNumberListReturnField(key string, values []float64) ReturnField { + listValues := make([]*structpb.Value, len(values)) + for i, v := range values { + listValues[i] = structpb.NewNumberValue(v) + } + return ReturnField{Key: key, Value: structpb.NewListValue(&structpb.ListValue{Values: listValues})} +} + +// NewResourceListReturnField creates a return field with a list of Resource proto values. +func NewResourceListReturnField(key string, resources []*v2.Resource) (ReturnField, error) { + listValues := make([]*structpb.Value, len(resources)) + for i, resource := range resources { + if resource == nil { + return ReturnField{}, fmt.Errorf("resource at index %d cannot be nil", i) + } + basicResource := resourceToBasicResource(resource) + jsonBytes, err := protojson.Marshal(basicResource) + if err != nil { + return ReturnField{}, fmt.Errorf("failed to marshal resource: %w", err) + } + + structValue := &structpb.Struct{} + if err := protojson.Unmarshal(jsonBytes, structValue); err != nil { + return ReturnField{}, fmt.Errorf("failed to unmarshal resource to struct: %w", err) + } + + listValues[i] = structpb.NewStructValue(structValue) + } + return ReturnField{Key: key, Value: structpb.NewListValue(&structpb.ListValue{Values: listValues})}, nil +} + +// NewResourceIdListReturnField creates a return field with a list of ResourceId proto values. +func NewResourceIdListReturnField(key string, resourceIDs []*v2.ResourceId) (ReturnField, error) { + listValues := make([]*structpb.Value, len(resourceIDs)) + for i, resourceId := range resourceIDs { + if resourceId == nil { + return ReturnField{}, fmt.Errorf("resource id at index %d cannot be nil", i) + } + basicResourceId := config.ResourceId_builder{ + ResourceTypeId: resourceId.ResourceType, + ResourceId: resourceId.Resource, + }.Build() + jsonBytes, err := protojson.Marshal(basicResourceId) + if err != nil { + return ReturnField{}, fmt.Errorf("failed to marshal resource id: %w", err) + } + + structValue := &structpb.Struct{} + if err := protojson.Unmarshal(jsonBytes, structValue); err != nil { + return ReturnField{}, fmt.Errorf("failed to unmarshal resource id to struct: %w", err) + } + + listValues[i] = structpb.NewStructValue(structValue) + } + return ReturnField{Key: key, Value: structpb.NewListValue(&structpb.ListValue{Values: listValues})}, nil +} + +// NewListReturnField creates a return field with a list of arbitrary values. +func NewListReturnField(key string, values []*structpb.Value) ReturnField { + return ReturnField{Key: key, Value: structpb.NewListValue(&structpb.ListValue{Values: values})} +} + +// NewReturnValues creates a return struct with the specified success status and fields. +// This helps users avoid having to remember the correct structure for return values. +func NewReturnValues(success bool, fields ...ReturnField) *structpb.Struct { + rv := &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "success": structpb.NewBoolValue(success), + }, + } + + for _, field := range fields { + rv.Fields[field.Key] = field.Value + } + + return rv +} diff --git a/pkg/actions/args_test.go b/pkg/actions/args_test.go new file mode 100644 index 000000000..3b714e729 --- /dev/null +++ b/pkg/actions/args_test.go @@ -0,0 +1,1162 @@ +package actions + +import ( + "testing" + + v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/types/known/structpb" +) + +func TestGetStringArg(t *testing.T) { + tests := []struct { + name string + args *structpb.Struct + key string + wantVal string + wantOk bool + }{ + { + name: "nil args", + args: nil, + key: "test", + wantVal: "", + wantOk: false, + }, + { + name: "nil fields", + args: &structpb.Struct{}, + key: "test", + wantVal: "", + wantOk: false, + }, + { + name: "key not found", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "other": structpb.NewStringValue("value"), + }, + }, + key: "test", + wantVal: "", + wantOk: false, + }, + { + name: "wrong type", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewNumberValue(123), + }, + }, + key: "test", + wantVal: "", + wantOk: false, + }, + { + name: "success", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewStringValue("hello"), + }, + }, + key: "test", + wantVal: "hello", + wantOk: true, + }, + { + name: "empty string", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewStringValue(""), + }, + }, + key: "test", + wantVal: "", + wantOk: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + val, ok := GetStringArg(tt.args, tt.key) + require.Equal(t, tt.wantOk, ok) + require.Equal(t, tt.wantVal, val) + }) + } +} + +func TestGetIntArg(t *testing.T) { + tests := []struct { + name string + args *structpb.Struct + key string + wantVal int64 + wantOk bool + }{ + { + name: "nil args", + args: nil, + key: "test", + wantVal: 0, + wantOk: false, + }, + { + name: "nil fields", + args: &structpb.Struct{}, + key: "test", + wantVal: 0, + wantOk: false, + }, + { + name: "key not found", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "other": structpb.NewNumberValue(42), + }, + }, + key: "test", + wantVal: 0, + wantOk: false, + }, + { + name: "wrong type", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewStringValue("not a number"), + }, + }, + key: "test", + wantVal: 0, + wantOk: false, + }, + { + name: "success", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewNumberValue(42), + }, + }, + key: "test", + wantVal: 42, + wantOk: true, + }, + { + name: "negative number", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewNumberValue(-100), + }, + }, + key: "test", + wantVal: -100, + wantOk: true, + }, + { + name: "zero", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewNumberValue(0), + }, + }, + key: "test", + wantVal: 0, + wantOk: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + val, ok := GetIntArg(tt.args, tt.key) + require.Equal(t, tt.wantOk, ok) + require.Equal(t, tt.wantVal, val) + }) + } +} + +func TestGetBoolArg(t *testing.T) { + tests := []struct { + name string + args *structpb.Struct + key string + wantVal bool + wantOk bool + }{ + { + name: "nil args", + args: nil, + key: "test", + wantVal: false, + wantOk: false, + }, + { + name: "nil fields", + args: &structpb.Struct{}, + key: "test", + wantVal: false, + wantOk: false, + }, + { + name: "key not found", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "other": structpb.NewBoolValue(true), + }, + }, + key: "test", + wantVal: false, + wantOk: false, + }, + { + name: "wrong type", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewStringValue("true"), + }, + }, + key: "test", + wantVal: false, + wantOk: false, + }, + { + name: "success true", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewBoolValue(true), + }, + }, + key: "test", + wantVal: true, + wantOk: true, + }, + { + name: "success false", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewBoolValue(false), + }, + }, + key: "test", + wantVal: false, + wantOk: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + val, ok := GetBoolArg(tt.args, tt.key) + require.Equal(t, tt.wantOk, ok) + require.Equal(t, tt.wantVal, val) + }) + } +} + +func TestGetResourceIDArg(t *testing.T) { + tests := []struct { + name string + args *structpb.Struct + key string + wantVal *v2.ResourceId + wantOk bool + }{ + { + name: "nil args", + args: nil, + key: "test", + wantVal: nil, + wantOk: false, + }, + { + name: "nil fields", + args: &structpb.Struct{}, + key: "test", + wantVal: nil, + wantOk: false, + }, + { + name: "key not found", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "other": structpb.NewStringValue("value"), + }, + }, + key: "test", + wantVal: nil, + wantOk: false, + }, + { + name: "wrong type - not struct", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewStringValue("not a struct"), + }, + }, + key: "test", + wantVal: nil, + wantOk: false, + }, + { + name: "success with resource_type_id and resource_id", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewStructValue(&structpb.Struct{ + Fields: map[string]*structpb.Value{ + "resource_type_id": structpb.NewStringValue("user"), + "resource_id": structpb.NewStringValue("123"), + }, + }), + }, + }, + key: "test", + wantVal: &v2.ResourceId{ + ResourceType: "user", + Resource: "123", + }, + wantOk: true, + }, + { + name: "success with resource_type and resource (alternative)", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewStructValue(&structpb.Struct{ + Fields: map[string]*structpb.Value{ + "resource_type": structpb.NewStringValue("group"), + "resource": structpb.NewStringValue("456"), + }, + }), + }, + }, + key: "test", + wantVal: &v2.ResourceId{ + ResourceType: "group", + Resource: "456", + }, + wantOk: true, + }, + { + name: "missing resource_type_id", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewStructValue(&structpb.Struct{ + Fields: map[string]*structpb.Value{ + "resource_id": structpb.NewStringValue("123"), + }, + }), + }, + }, + key: "test", + wantVal: nil, + wantOk: false, + }, + { + name: "missing resource_id", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewStructValue(&structpb.Struct{ + Fields: map[string]*structpb.Value{ + "resource_type_id": structpb.NewStringValue("user"), + }, + }), + }, + }, + key: "test", + wantVal: nil, + wantOk: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + val, ok := GetResourceIDArg(tt.args, tt.key) + require.Equal(t, tt.wantOk, ok) + if tt.wantVal != nil { + require.NotNil(t, val) + require.Equal(t, tt.wantVal.ResourceType, val.ResourceType) + require.Equal(t, tt.wantVal.Resource, val.Resource) + } else { + require.Nil(t, val) + } + }) + } +} + +func TestGetStringSliceArg(t *testing.T) { + tests := []struct { + name string + args *structpb.Struct + key string + wantVal []string + wantOk bool + }{ + { + name: "nil args", + args: nil, + key: "test", + wantVal: nil, + wantOk: false, + }, + { + name: "nil fields", + args: &structpb.Struct{}, + key: "test", + wantVal: nil, + wantOk: false, + }, + { + name: "key not found", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "other": structpb.NewListValue(&structpb.ListValue{ + Values: []*structpb.Value{structpb.NewStringValue("a")}, + }), + }, + }, + key: "test", + wantVal: nil, + wantOk: false, + }, + { + name: "wrong type - not list", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewStringValue("not a list"), + }, + }, + key: "test", + wantVal: nil, + wantOk: false, + }, + { + name: "wrong type - list with non-strings", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewListValue(&structpb.ListValue{ + Values: []*structpb.Value{structpb.NewNumberValue(123)}, + }), + }, + }, + key: "test", + wantVal: nil, + wantOk: false, + }, + { + name: "success", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewListValue(&structpb.ListValue{ + Values: []*structpb.Value{ + structpb.NewStringValue("a"), + structpb.NewStringValue("b"), + structpb.NewStringValue("c"), + }, + }), + }, + }, + key: "test", + wantVal: []string{"a", "b", "c"}, + wantOk: true, + }, + { + name: "empty list", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewListValue(&structpb.ListValue{ + Values: []*structpb.Value{}, + }), + }, + }, + key: "test", + wantVal: []string{}, + wantOk: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + val, ok := GetStringSliceArg(tt.args, tt.key) + require.Equal(t, tt.wantOk, ok) + require.Equal(t, tt.wantVal, val) + }) + } +} + +func TestGetStructArg(t *testing.T) { + tests := []struct { + name string + args *structpb.Struct + key string + wantOk bool + }{ + { + name: "nil args", + args: nil, + key: "test", + wantOk: false, + }, + { + name: "nil fields", + args: &structpb.Struct{}, + key: "test", + wantOk: false, + }, + { + name: "key not found", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "other": structpb.NewStructValue(&structpb.Struct{}), + }, + }, + key: "test", + wantOk: false, + }, + { + name: "wrong type", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewStringValue("not a struct"), + }, + }, + key: "test", + wantOk: false, + }, + { + name: "success", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewStructValue(&structpb.Struct{ + Fields: map[string]*structpb.Value{ + "nested": structpb.NewStringValue("value"), + }, + }), + }, + }, + key: "test", + wantOk: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + val, ok := GetStructArg(tt.args, tt.key) + require.Equal(t, tt.wantOk, ok) + if tt.wantOk { + require.NotNil(t, val) + } else { + require.Nil(t, val) + } + }) + } +} + +func TestRequireStringArg(t *testing.T) { + tests := []struct { + name string + args *structpb.Struct + key string + wantVal string + wantErr bool + }{ + { + name: "nil args", + args: nil, + key: "test", + wantVal: "", + wantErr: true, + }, + { + name: "success", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewStringValue("hello"), + }, + }, + key: "test", + wantVal: "hello", + wantErr: false, + }, + { + name: "key not found", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "other": structpb.NewStringValue("value"), + }, + }, + key: "test", + wantVal: "", + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + val, err := RequireStringArg(tt.args, tt.key) + if tt.wantErr { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, tt.wantVal, val) + } + }) + } +} + +func TestRequireResourceIDArg(t *testing.T) { + tests := []struct { + name string + args *structpb.Struct + key string + wantVal *v2.ResourceId + wantErr bool + }{ + { + name: "nil args", + args: nil, + key: "test", + wantVal: nil, + wantErr: true, + }, + { + name: "success", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewStructValue(&structpb.Struct{ + Fields: map[string]*structpb.Value{ + "resource_type_id": structpb.NewStringValue("user"), + "resource_id": structpb.NewStringValue("123"), + }, + }), + }, + }, + key: "test", + wantVal: &v2.ResourceId{ + ResourceType: "user", + Resource: "123", + }, + wantErr: false, + }, + { + name: "key not found", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "other": structpb.NewStringValue("value"), + }, + }, + key: "test", + wantVal: nil, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + val, err := RequireResourceIDArg(tt.args, tt.key) + if tt.wantErr { + require.Error(t, err) + } else { + require.NoError(t, err) + require.NotNil(t, val) + require.Equal(t, tt.wantVal.ResourceType, val.ResourceType) + require.Equal(t, tt.wantVal.Resource, val.Resource) + } + }) + } +} + +func TestGetResourceIdListArg(t *testing.T) { + tests := []struct { + name string + args *structpb.Struct + key string + wantLen int + wantOk bool + }{ + { + name: "nil args", + args: nil, + key: "test", + wantLen: 0, + wantOk: false, + }, + { + name: "success", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewListValue(&structpb.ListValue{ + Values: []*structpb.Value{ + structpb.NewStructValue(&structpb.Struct{ + Fields: map[string]*structpb.Value{ + "resource_type_id": structpb.NewStringValue("user"), + "resource_id": structpb.NewStringValue("123"), + }, + }), + structpb.NewStructValue(&structpb.Struct{ + Fields: map[string]*structpb.Value{ + "resource_type_id": structpb.NewStringValue("group"), + "resource_id": structpb.NewStringValue("456"), + }, + }), + }, + }), + }, + }, + key: "test", + wantLen: 2, + wantOk: true, + }, + { + name: "empty list", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewListValue(&structpb.ListValue{ + Values: []*structpb.Value{}, + }), + }, + }, + key: "test", + wantLen: 0, + wantOk: true, + }, + { + name: "wrong type - not list", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewStringValue("not a list"), + }, + }, + key: "test", + wantLen: 0, + wantOk: false, + }, + { + name: "invalid item in list", + args: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewListValue(&structpb.ListValue{ + Values: []*structpb.Value{ + structpb.NewStringValue("not a struct"), + }, + }), + }, + }, + key: "test", + wantLen: 0, + wantOk: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + val, ok := GetResourceIdListArg(tt.args, tt.key) + require.Equal(t, tt.wantOk, ok) + if tt.wantOk { + require.Len(t, val, tt.wantLen) + } + }) + } +} + +func TestSetResourceFieldArg(t *testing.T) { + t.Run("nil args", func(t *testing.T) { + err := SetResourceFieldArg(nil, "test", &v2.Resource{}) + require.Error(t, err) + }) + + t.Run("nil resource", func(t *testing.T) { + args := &structpb.Struct{Fields: map[string]*structpb.Value{}} + err := SetResourceFieldArg(args, "test", nil) + require.Error(t, err) + }) + + t.Run("success", func(t *testing.T) { + args := &structpb.Struct{Fields: map[string]*structpb.Value{}} + resource := &v2.Resource{ + Id: &v2.ResourceId{ + ResourceType: "user", + Resource: "123", + }, + DisplayName: "Test User", + Description: "A test user", + } + + err := SetResourceFieldArg(args, "test", resource) + require.NoError(t, err) + + // Verify we can read it back + retrieved, ok := GetResourceFieldArg(args, "test") + require.True(t, ok) + require.NotNil(t, retrieved) + require.Equal(t, resource.Id.ResourceType, retrieved.Id.ResourceType) + require.Equal(t, resource.Id.Resource, retrieved.Id.Resource) + require.Equal(t, resource.DisplayName, retrieved.DisplayName) + require.Equal(t, resource.Description, retrieved.Description) + }) + + t.Run("success with nil fields", func(t *testing.T) { + args := &structpb.Struct{} + resource := &v2.Resource{ + Id: &v2.ResourceId{ + ResourceType: "user", + Resource: "123", + }, + } + + err := SetResourceFieldArg(args, "test", resource) + require.NoError(t, err) + require.NotNil(t, args.Fields) + }) +} + +func TestGetResourceFieldArg(t *testing.T) { + t.Run("nil args", func(t *testing.T) { + val, ok := GetResourceFieldArg(nil, "test") + require.False(t, ok) + require.Nil(t, val) + }) + + t.Run("key not found", func(t *testing.T) { + args := &structpb.Struct{Fields: map[string]*structpb.Value{}} + val, ok := GetResourceFieldArg(args, "test") + require.False(t, ok) + require.Nil(t, val) + }) + + t.Run("wrong type", func(t *testing.T) { + args := &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewStringValue("not a struct"), + }, + } + val, ok := GetResourceFieldArg(args, "test") + require.False(t, ok) + require.Nil(t, val) + }) + + t.Run("roundtrip", func(t *testing.T) { + args := &structpb.Struct{Fields: map[string]*structpb.Value{}} + resource := &v2.Resource{ + Id: &v2.ResourceId{ + ResourceType: "group", + Resource: "456", + }, + DisplayName: "Test Group", + Description: "A test group", + } + + err := SetResourceFieldArg(args, "myresource", resource) + require.NoError(t, err) + + retrieved, ok := GetResourceFieldArg(args, "myresource") + require.True(t, ok) + require.NotNil(t, retrieved) + require.Equal(t, "group", retrieved.Id.ResourceType) + require.Equal(t, "456", retrieved.Id.Resource) + require.Equal(t, "Test Group", retrieved.DisplayName) + require.Equal(t, "A test group", retrieved.Description) + }) +} + +func TestGetResourceListFieldArg(t *testing.T) { + t.Run("nil args", func(t *testing.T) { + val, ok := GetResourceListFieldArg(nil, "test") + require.False(t, ok) + require.Nil(t, val) + }) + + t.Run("key not found", func(t *testing.T) { + args := &structpb.Struct{Fields: map[string]*structpb.Value{}} + val, ok := GetResourceListFieldArg(args, "test") + require.False(t, ok) + require.Nil(t, val) + }) + + t.Run("wrong type - not list", func(t *testing.T) { + args := &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewStringValue("not a list"), + }, + } + val, ok := GetResourceListFieldArg(args, "test") + require.False(t, ok) + require.Nil(t, val) + }) +} + +func TestNewReturnValues(t *testing.T) { + t.Run("success with no fields", func(t *testing.T) { + rv := NewReturnValues(true) + require.NotNil(t, rv) + require.NotNil(t, rv.Fields) + + success, ok := GetBoolArg(rv, "success") + require.True(t, ok) + require.True(t, success) + }) + + t.Run("failure with no fields", func(t *testing.T) { + rv := NewReturnValues(false) + require.NotNil(t, rv) + + success, ok := GetBoolArg(rv, "success") + require.True(t, ok) + require.False(t, success) + }) + + t.Run("success with string field", func(t *testing.T) { + rv := NewReturnValues(true, NewStringReturnField("message", "hello")) + require.NotNil(t, rv) + + success, ok := GetBoolArg(rv, "success") + require.True(t, ok) + require.True(t, success) + + message, ok := GetStringArg(rv, "message") + require.True(t, ok) + require.Equal(t, "hello", message) + }) + + t.Run("success with multiple fields", func(t *testing.T) { + rv := NewReturnValues(true, + NewStringReturnField("name", "test"), + NewNumberReturnField("count", 42), + NewBoolReturnField("active", true), + ) + require.NotNil(t, rv) + + name, ok := GetStringArg(rv, "name") + require.True(t, ok) + require.Equal(t, "test", name) + + count, ok := GetIntArg(rv, "count") + require.True(t, ok) + require.Equal(t, int64(42), count) + + active, ok := GetBoolArg(rv, "active") + require.True(t, ok) + require.True(t, active) + }) +} + +func TestNewStringReturnField(t *testing.T) { + field := NewStringReturnField("name", "value") + require.Equal(t, "name", field.Key) + require.NotNil(t, field.Value) + + stringVal, ok := field.Value.GetKind().(*structpb.Value_StringValue) + require.True(t, ok) + require.Equal(t, "value", stringVal.StringValue) +} + +func TestNewBoolReturnField(t *testing.T) { + field := NewBoolReturnField("active", true) + require.Equal(t, "active", field.Key) + require.NotNil(t, field.Value) + + boolVal, ok := field.Value.GetKind().(*structpb.Value_BoolValue) + require.True(t, ok) + require.True(t, boolVal.BoolValue) +} + +func TestNewNumberReturnField(t *testing.T) { + field := NewNumberReturnField("count", 3.14) + require.Equal(t, "count", field.Key) + require.NotNil(t, field.Value) + + numVal, ok := field.Value.GetKind().(*structpb.Value_NumberValue) + require.True(t, ok) + require.Equal(t, 3.14, numVal.NumberValue) +} + +func TestNewResourceReturnField(t *testing.T) { + resource := &v2.Resource{ + Id: &v2.ResourceId{ + ResourceType: "user", + Resource: "123", + }, + DisplayName: "Test User", + } + + field, err := NewResourceReturnField("user", resource) + require.NoError(t, err) + require.Equal(t, "user", field.Key) + require.NotNil(t, field.Value) + + // Verify it's a struct value + _, ok := field.Value.GetKind().(*structpb.Value_StructValue) + require.True(t, ok) +} + +func TestNewResourceIdReturnField(t *testing.T) { + resourceId := &v2.ResourceId{ + ResourceType: "user", + Resource: "123", + } + + field, err := NewResourceIdReturnField("user_id", resourceId) + require.NoError(t, err) + require.Equal(t, "user_id", field.Key) + require.NotNil(t, field.Value) + + // Verify it's a struct value + _, ok := field.Value.GetKind().(*structpb.Value_StructValue) + require.True(t, ok) +} + +func TestNewStringListReturnField(t *testing.T) { + field := NewStringListReturnField("names", []string{"a", "b", "c"}) + require.Equal(t, "names", field.Key) + require.NotNil(t, field.Value) + + listVal, ok := field.Value.GetKind().(*structpb.Value_ListValue) + require.True(t, ok) + require.Len(t, listVal.ListValue.Values, 3) + + // Verify values + for i, expected := range []string{"a", "b", "c"} { + strVal, ok := listVal.ListValue.Values[i].GetKind().(*structpb.Value_StringValue) + require.True(t, ok) + require.Equal(t, expected, strVal.StringValue) + } +} + +func TestNewNumberListReturnField(t *testing.T) { + field := NewNumberListReturnField("scores", []float64{1.0, 2.5, 3.7}) + require.Equal(t, "scores", field.Key) + require.NotNil(t, field.Value) + + listVal, ok := field.Value.GetKind().(*structpb.Value_ListValue) + require.True(t, ok) + require.Len(t, listVal.ListValue.Values, 3) + + // Verify values + for i, expected := range []float64{1.0, 2.5, 3.7} { + numVal, ok := listVal.ListValue.Values[i].GetKind().(*structpb.Value_NumberValue) + require.True(t, ok) + require.Equal(t, expected, numVal.NumberValue) + } +} + +func TestNewResourceListReturnField(t *testing.T) { + resources := []*v2.Resource{ + { + Id: &v2.ResourceId{ + ResourceType: "user", + Resource: "1", + }, + DisplayName: "User 1", + }, + { + Id: &v2.ResourceId{ + ResourceType: "user", + Resource: "2", + }, + DisplayName: "User 2", + }, + } + + field, err := NewResourceListReturnField("users", resources) + require.NoError(t, err) + require.Equal(t, "users", field.Key) + require.NotNil(t, field.Value) + + listVal, ok := field.Value.GetKind().(*structpb.Value_ListValue) + require.True(t, ok) + require.Len(t, listVal.ListValue.Values, 2) +} + +func TestNewResourceIdListReturnField(t *testing.T) { + resourceIDs := []*v2.ResourceId{ + {ResourceType: "user", Resource: "1"}, + {ResourceType: "user", Resource: "2"}, + {ResourceType: "group", Resource: "3"}, + } + + field, err := NewResourceIdListReturnField("ids", resourceIDs) + require.NoError(t, err) + require.Equal(t, "ids", field.Key) + require.NotNil(t, field.Value) + + listVal, ok := field.Value.GetKind().(*structpb.Value_ListValue) + require.True(t, ok) + require.Len(t, listVal.ListValue.Values, 3) +} + +func TestNewListReturnField(t *testing.T) { + values := []*structpb.Value{ + structpb.NewStringValue("a"), + structpb.NewNumberValue(42), + structpb.NewBoolValue(true), + } + + field := NewListReturnField("mixed", values) + require.Equal(t, "mixed", field.Key) + require.NotNil(t, field.Value) + + listVal, ok := field.Value.GetKind().(*structpb.Value_ListValue) + require.True(t, ok) + require.Len(t, listVal.ListValue.Values, 3) +} + +func TestNewReturnField(t *testing.T) { + value := structpb.NewStringValue("test") + field := NewReturnField("custom", value) + require.Equal(t, "custom", field.Key) + require.Equal(t, value, field.Value) +} + +func TestRequireResourceIdListArg(t *testing.T) { + t.Run("success", func(t *testing.T) { + args := &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "test": structpb.NewListValue(&structpb.ListValue{ + Values: []*structpb.Value{ + structpb.NewStructValue(&structpb.Struct{ + Fields: map[string]*structpb.Value{ + "resource_type_id": structpb.NewStringValue("user"), + "resource_id": structpb.NewStringValue("123"), + }, + }), + }, + }), + }, + } + + val, err := RequireResourceIdListArg(args, "test") + require.NoError(t, err) + require.Len(t, val, 1) + require.Equal(t, "user", val[0].ResourceType) + require.Equal(t, "123", val[0].Resource) + }) + + t.Run("missing key", func(t *testing.T) { + args := &structpb.Struct{Fields: map[string]*structpb.Value{}} + val, err := RequireResourceIdListArg(args, "test") + require.Error(t, err) + require.Nil(t, val) + }) +} + +func TestResourceConversionHelpers(t *testing.T) { + t.Run("resourceToBasicResource and back", func(t *testing.T) { + original := &v2.Resource{ + Id: &v2.ResourceId{ + ResourceType: "user", + Resource: "test-123", + }, + DisplayName: "Test User", + Description: "A test user description", + } + + basic := resourceToBasicResource(original) + require.NotNil(t, basic) + require.Equal(t, "user", basic.GetResourceId().GetResourceTypeId()) + require.Equal(t, "test-123", basic.GetResourceId().GetResourceId()) + require.Equal(t, "Test User", basic.GetDisplayName()) + require.Equal(t, "A test user description", basic.GetDescription()) + + converted := basicResourceToResource(basic) + require.NotNil(t, converted) + require.Equal(t, original.Id.ResourceType, converted.Id.ResourceType) + require.Equal(t, original.Id.Resource, converted.Id.Resource) + require.Equal(t, original.DisplayName, converted.DisplayName) + require.Equal(t, original.Description, converted.Description) + }) +} diff --git a/pkg/cli/commands.go b/pkg/cli/commands.go index 2e56e53c8..93c0e5b81 100644 --- a/pkg/cli/commands.go +++ b/pkg/cli/commands.go @@ -270,8 +270,16 @@ func MakeMainCommand[T field.Configurable]( connectorrunner.WithOnDemandInvokeAction( v.GetString("file"), v.GetString("invoke-action"), + v.GetString("invoke-action-resource-type"), // Optional resource type for resource-scoped actions invokeActionArgsStruct, )) + case v.GetBool("list-action-schemas"): + opts = append(opts, + connectorrunner.WithActionsEnabled(), + connectorrunner.WithOnDemandListActionSchemas( + v.GetString("file"), + v.GetString("list-action-schemas-resource-type"), // Optional resource type filter + )) case v.GetString("delete-resource") != "": opts = append(opts, connectorrunner.WithProvisioningEnabled(), diff --git a/pkg/connectorbuilder/actions.go b/pkg/connectorbuilder/actions.go index f8e0ccc73..0edab281a 100644 --- a/pkg/connectorbuilder/actions.go +++ b/pkg/connectorbuilder/actions.go @@ -5,33 +5,94 @@ import ( "fmt" v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2" + "github.com/conductorone/baton-sdk/pkg/actions" "github.com/conductorone/baton-sdk/pkg/annotations" "github.com/conductorone/baton-sdk/pkg/types/tasks" "google.golang.org/protobuf/types/known/structpb" ) -// CustomActionManager defines capabilities for handling custom actions. -// -// Note: RegisterActionManager is preferred for new connectors. +// ActionManager defines the interface for managing actions in the connector builder. +// This is the internal interface used by the builder for dispatch. +// The *actions.ActionManager type implements this interface. +type ActionManager interface { + // ListActionSchemas returns all action schemas, optionally filtered by resource type. + // If resourceTypeID is empty, returns all actions (both global and resource-scoped). + // If resourceTypeID is set, returns only actions for that resource type. + ListActionSchemas(ctx context.Context, resourceTypeID string) ([]*v2.BatonActionSchema, annotations.Annotations, error) + + // GetActionSchema returns the schema for a specific action by name. + GetActionSchema(ctx context.Context, name string) (*v2.BatonActionSchema, annotations.Annotations, error) + + // InvokeAction invokes an action. If resourceTypeID is set, invokes a resource-scoped action. + InvokeAction( + ctx context.Context, + name string, + resourceTypeID string, + args *structpb.Struct, + ) (string, v2.BatonActionStatus, *structpb.Struct, annotations.Annotations, error) + + // GetActionStatus returns the status of an outstanding action. + GetActionStatus(ctx context.Context, id string) (v2.BatonActionStatus, string, *structpb.Struct, annotations.Annotations, error) + + // GetTypeRegistry returns a registry for registering resource-scoped actions. + GetTypeRegistry(ctx context.Context, resourceTypeID string) (actions.ActionRegistry, error) + + // HasActions returns true if there are any registered actions. + HasActions() bool +} + +// GlobalActionProvider allows connectors to register global (non-resource-scoped) actions. +// This is the preferred method for registering global actions in new connectors. +// Implement this interface instead of the deprecated CustomActionManager or RegisterActionManagerLimited. +type GlobalActionProvider interface { + GlobalActions(ctx context.Context, registry actions.ActionRegistry) error +} + +// ResourceActionProvider is an interface that resource builders can implement +// to provide resource-scoped actions for their resource type. +type ResourceActionProvider interface { + // ResourceActions returns the schemas and handlers for all resource actions + // supported by this resource type. + ResourceActions(ctx context.Context, registry actions.ActionRegistry) error +} + +// Deprecated: CustomActionManager is deprecated. Implement GlobalActionProvider instead, +// which registers actions directly into the SDK's ActionManager. // // This interface allows connectors to define and execute custom actions -// that can be triggered from Baton. +// that can be triggered from Baton. It supports both global actions and +// resource-scoped actions through the resourceTypeID parameter. type CustomActionManager interface { - ListActionSchemas(ctx context.Context) ([]*v2.BatonActionSchema, annotations.Annotations, error) + // ListActionSchemas returns all action schemas, optionally filtered by resource type. + // If resourceTypeID is empty, returns all actions (both global and resource-scoped). + // If resourceTypeID is set, returns only actions for that resource type. + ListActionSchemas(ctx context.Context, resourceTypeID string) ([]*v2.BatonActionSchema, annotations.Annotations, error) + + // GetActionSchema returns the schema for a specific action by name. GetActionSchema(ctx context.Context, name string) (*v2.BatonActionSchema, annotations.Annotations, error) - InvokeAction(ctx context.Context, name string, args *structpb.Struct) (string, v2.BatonActionStatus, *structpb.Struct, annotations.Annotations, error) + + // InvokeAction invokes an action. If resourceTypeID is set, invokes a resource-scoped action. + InvokeAction( + ctx context.Context, + name string, + resourceTypeID string, + args *structpb.Struct, + ) (string, v2.BatonActionStatus, *structpb.Struct, annotations.Annotations, error) + + // GetActionStatus returns the status of an outstanding action. GetActionStatus(ctx context.Context, id string) (v2.BatonActionStatus, string, *structpb.Struct, annotations.Annotations, error) } -// RegisterActionManager extends ConnectorBuilder to add capabilities for registering custom actions. +// Deprecated: RegisterActionManager is deprecated. Implement GlobalActionProvider instead. // -// This is the recommended interface for implementing custom action support in new connectors. +// RegisterActionManager extends ConnectorBuilder to add capabilities for registering custom actions. // It provides a mechanism to register a CustomActionManager with the connector. type RegisterActionManager interface { ConnectorBuilder RegisterActionManagerLimited } +// Deprecated: RegisterActionManagerLimited is deprecated. Implement GlobalActionProvider instead. type RegisterActionManagerLimited interface { RegisterActionManager(ctx context.Context) (CustomActionManager, error) } @@ -42,20 +103,17 @@ func (b *builder) ListActionSchemas(ctx context.Context, request *v2.ListActionS start := b.nowFunc() tt := tasks.ActionListSchemasType - if b.actionManager == nil { - b.m.RecordTaskFailure(ctx, tt, b.nowFunc().Sub(start)) - return nil, fmt.Errorf("error: action manager not implemented") - } - actionSchemas, annos, err := b.actionManager.ListActionSchemas(ctx) + resourceTypeID := request.GetResourceTypeId() + + actionSchemas, _, err := b.actionManager.ListActionSchemas(ctx, resourceTypeID) if err != nil { b.m.RecordTaskFailure(ctx, tt, b.nowFunc().Sub(start)) return nil, fmt.Errorf("error: listing action schemas failed: %w", err) } rv := v2.ListActionSchemasResponse_builder{ - Schemas: actionSchemas, - Annotations: annos, + Schemas: actionSchemas, }.Build() b.m.RecordTaskSuccess(ctx, tt, b.nowFunc().Sub(start)) @@ -68,22 +126,17 @@ func (b *builder) GetActionSchema(ctx context.Context, request *v2.GetActionSche start := b.nowFunc() tt := tasks.ActionGetSchemaType - if b.actionManager == nil { - b.m.RecordTaskFailure(ctx, tt, b.nowFunc().Sub(start)) - return nil, fmt.Errorf("error: action manager not implemented") - } actionSchema, annos, err := b.actionManager.GetActionSchema(ctx, request.GetName()) if err != nil { b.m.RecordTaskFailure(ctx, tt, b.nowFunc().Sub(start)) - return nil, fmt.Errorf("error: getting action schema failed: %w", err) + return nil, fmt.Errorf("error: action schema %s not found: %w", request.GetName(), err) } rv := v2.GetActionSchemaResponse_builder{ Schema: actionSchema, Annotations: annos, }.Build() - b.m.RecordTaskSuccess(ctx, tt, b.nowFunc().Sub(start)) return rv, nil } @@ -94,12 +147,10 @@ func (b *builder) InvokeAction(ctx context.Context, request *v2.InvokeActionRequ start := b.nowFunc() tt := tasks.ActionInvokeType - if b.actionManager == nil { - b.m.RecordTaskFailure(ctx, tt, b.nowFunc().Sub(start)) - return nil, fmt.Errorf("error: action manager not implemented") - } - id, status, resp, annos, err := b.actionManager.InvokeAction(ctx, request.GetName(), request.GetArgs()) + resourceTypeID := request.GetResourceTypeId() + + id, actionStatus, resp, annos, err := b.actionManager.InvokeAction(ctx, request.GetName(), resourceTypeID, request.GetArgs()) if err != nil { b.m.RecordTaskFailure(ctx, tt, b.nowFunc().Sub(start)) return nil, fmt.Errorf("error: invoking action failed: %w", err) @@ -108,7 +159,7 @@ func (b *builder) InvokeAction(ctx context.Context, request *v2.InvokeActionRequ rv := v2.InvokeActionResponse_builder{ Id: id, Name: request.GetName(), - Status: status, + Status: actionStatus, Annotations: annos, Response: resp, }.Build() @@ -123,49 +174,68 @@ func (b *builder) GetActionStatus(ctx context.Context, request *v2.GetActionStat start := b.nowFunc() tt := tasks.ActionStatusType - if b.actionManager == nil { - b.m.RecordTaskFailure(ctx, tt, b.nowFunc().Sub(start)) - return nil, fmt.Errorf("error: action manager not implemented") - } - status, name, rv, annos, err := b.actionManager.GetActionStatus(ctx, request.GetId()) + actionStatus, name, rv, annos, err := b.actionManager.GetActionStatus(ctx, request.GetId()) if err != nil { b.m.RecordTaskFailure(ctx, tt, b.nowFunc().Sub(start)) - return nil, fmt.Errorf("error: getting action status failed: %w", err) + return nil, fmt.Errorf("error: action status for id %s not found: %w", request.GetId(), err) } resp := v2.GetActionStatusResponse_builder{ Id: request.GetId(), Name: name, - Status: status, + Status: actionStatus, Annotations: annos, Response: rv, }.Build() - b.m.RecordTaskSuccess(ctx, tt, b.nowFunc().Sub(start)) return resp, nil } -func (b *builder) addActionManager(ctx context.Context, in interface{}) error { - if actionManager, ok := in.(CustomActionManager); ok { - if b.actionManager != nil { - return fmt.Errorf("error: cannot set multiple action managers") +// registerLegacyAction wraps a legacy CustomActionManager action as an ActionHandler and registers it. +func registerLegacyAction(ctx context.Context, registry actions.ActionRegistry, schema *v2.BatonActionSchema, legacyManager CustomActionManager) error { + handler := func(ctx context.Context, args *structpb.Struct) (*structpb.Struct, annotations.Annotations, error) { + _, _, resp, annos, err := legacyManager.InvokeAction(ctx, schema.GetName(), "", args) + return resp, annos, err + } + return registry.Register(ctx, schema, handler) +} + +// addActionManager handles deprecated CustomActionManager and RegisterActionManagerLimited interfaces +// by extracting their actions and registering them into the unified ActionManager. +func (b *builder) addActionManager(ctx context.Context, in interface{}, registry actions.ActionRegistry) error { + // Handle deprecated CustomActionManager - extract and re-register actions + if customManager, ok := in.(CustomActionManager); ok { + schemas, _, err := customManager.ListActionSchemas(ctx, "") + if err != nil { + return fmt.Errorf("error listing schemas from custom action manager: %w", err) + } + for _, schema := range schemas { + if err := registerLegacyAction(ctx, registry, schema, customManager); err != nil { + return fmt.Errorf("error registering legacy action %s: %w", schema.GetName(), err) + } } - b.actionManager = actionManager + return nil } - if registerActionManager, ok := in.(RegisterActionManagerLimited); ok { - if b.actionManager != nil { - return fmt.Errorf("error: cannot register multiple action managers") + // Handle deprecated RegisterActionManagerLimited + if registerManager, ok := in.(RegisterActionManagerLimited); ok { + customManager, err := registerManager.RegisterActionManager(ctx) + if err != nil { + return fmt.Errorf("error registering action manager: %w", err) + } + if customManager == nil { + return nil // No action manager provided } - actionManager, err := registerActionManager.RegisterActionManager(ctx) + schemas, _, err := customManager.ListActionSchemas(ctx, "") if err != nil { - return fmt.Errorf("error: registering action manager failed: %w", err) + return fmt.Errorf("error listing schemas from custom action manager: %w", err) } - if actionManager == nil { - return fmt.Errorf("error: action manager is nil") + for _, schema := range schemas { + if err := registerLegacyAction(ctx, registry, schema, customManager); err != nil { + return fmt.Errorf("error registering legacy action %s: %w", schema.GetName(), err) + } } - b.actionManager = actionManager } return nil } diff --git a/pkg/connectorbuilder/connectorbuilder.go b/pkg/connectorbuilder/connectorbuilder.go index 98a679dfb..40df7dfd0 100644 --- a/pkg/connectorbuilder/connectorbuilder.go +++ b/pkg/connectorbuilder/connectorbuilder.go @@ -16,6 +16,7 @@ import ( "google.golang.org/grpc/status" v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2" + "github.com/conductorone/baton-sdk/pkg/actions" "github.com/conductorone/baton-sdk/pkg/annotations" "github.com/conductorone/baton-sdk/pkg/crypto" "github.com/conductorone/baton-sdk/pkg/metrics" @@ -68,7 +69,6 @@ type builder struct { validateProvider ValidateProvider ticketManager TicketManagerLimited accountManager AccountManagerLimited - actionManager CustomActionManager resourceSyncers map[string]ResourceSyncerV2 resourceProvisioners map[string]ResourceProvisionerV2Limited resourceManagers map[string]ResourceManagerV2Limited @@ -77,6 +77,7 @@ type builder struct { credentialManagers map[string]CredentialManagerLimited eventFeeds map[string]EventFeed accountManagers map[string]AccountManagerLimited // NOTE(kans): currently unused + actionManager ActionManager // Unified action manager for all actions } // NewConnector creates a new ConnectorServer for a new resource. @@ -97,12 +98,14 @@ func NewConnector(ctx context.Context, in interface{}, opts ...Opt) (types.Conne clientSecretValue := ctx.Value(crypto.ContextClientSecretKey) clientSecretJWK, _ := clientSecretValue.(*jose.JSONWebKey) + // Create the action manager (concrete type for registration, stored as interface for dispatch) + actionMgr := actions.NewActionManager(ctx) + b := &builder{ metadataProvider: nil, validateProvider: nil, ticketManager: nil, accountManager: nil, - actionManager: nil, nowFunc: time.Now, clientSecret: clientSecretJWK, resourceSyncers: make(map[string]ResourceSyncerV2), @@ -113,6 +116,7 @@ func NewConnector(ctx context.Context, in interface{}, opts ...Opt) (types.Conne credentialManagers: make(map[string]CredentialManagerLimited), eventFeeds: make(map[string]EventFeed), accountManagers: make(map[string]AccountManagerLimited), + actionManager: actionMgr, } // WithTicketingEnabled checks for the ticketManager @@ -137,10 +141,18 @@ func NewConnector(ctx context.Context, in interface{}, opts ...Opt) (types.Conne return nil, err } - if err := b.addActionManager(ctx, in); err != nil { + // Handle deprecated action manager interfaces (pass concrete type for registration) + if err := b.addActionManager(ctx, in, actionMgr); err != nil { return nil, err } + // Handle the new GlobalActionProvider interface + if globalActionProvider, ok := in.(GlobalActionProvider); ok { + if err := globalActionProvider.GlobalActions(ctx, actionMgr); err != nil { + return nil, fmt.Errorf("error registering global actions: %w", err) + } + } + addResourceType := func(ctx context.Context, rType string, rs interface{}) error { if err := b.addResourceSyncers(ctx, rType, rs); err != nil { return err @@ -389,7 +401,7 @@ func (b *builder) getCapabilities(ctx context.Context) (*v2.ConnectorCapabilitie connectorCaps[v2.Capability_CAPABILITY_TICKETING] = struct{}{} } - if b.actionManager != nil { + if b.actionManager.HasActions() { connectorCaps[v2.Capability_CAPABILITY_ACTIONS] = struct{}{} } diff --git a/pkg/connectorbuilder/connectorbuilder_test.go b/pkg/connectorbuilder/connectorbuilder_test.go index 9d7e746ad..5fff21eb3 100644 --- a/pkg/connectorbuilder/connectorbuilder_test.go +++ b/pkg/connectorbuilder/connectorbuilder_test.go @@ -7,6 +7,7 @@ import ( "time" v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2" + "github.com/conductorone/baton-sdk/pkg/actions" "github.com/conductorone/baton-sdk/pkg/annotations" "github.com/conductorone/baton-sdk/pkg/pagination" "github.com/conductorone/baton-sdk/pkg/types/resource" @@ -486,7 +487,7 @@ func newTestCustomActionManager() CustomActionManager { return &testCustomActionManager{} } -func (t *testCustomActionManager) ListActionSchemas(ctx context.Context) ([]*v2.BatonActionSchema, annotations.Annotations, error) { +func (t *testCustomActionManager) ListActionSchemas(ctx context.Context, resourceTypeID string) ([]*v2.BatonActionSchema, annotations.Annotations, error) { return []*v2.BatonActionSchema{ v2.BatonActionSchema_builder{ Name: "test-action", @@ -502,7 +503,12 @@ func (t *testCustomActionManager) GetActionSchema(ctx context.Context, name stri }.Build(), annotations.Annotations{}, nil } -func (t *testCustomActionManager) InvokeAction(ctx context.Context, name string, args *structpb.Struct) (string, v2.BatonActionStatus, *structpb.Struct, annotations.Annotations, error) { +func (t *testCustomActionManager) InvokeAction( + ctx context.Context, + name string, + resourceTypeID string, + args *structpb.Struct, +) (string, v2.BatonActionStatus, *structpb.Struct, annotations.Annotations, error) { return "action-id-123", v2.BatonActionStatus_BATON_ACTION_STATUS_COMPLETE, &structpb.Struct{}, annotations.Annotations{}, nil } @@ -510,6 +516,10 @@ func (t *testCustomActionManager) GetActionStatus(ctx context.Context, id string return v2.BatonActionStatus_BATON_ACTION_STATUS_COMPLETE, "Action completed successfully", &structpb.Struct{}, annotations.Annotations{}, nil } +func (t *testCustomActionManager) GetTypeRegistry(ctx context.Context, resourceTypeID string) (actions.ActionRegistry, error) { + return nil, nil +} + type testRegisterActionManager struct { ConnectorBuilder } @@ -1155,16 +1165,211 @@ func TestCustomActionManager(t *testing.T) { Args: &structpb.Struct{}, }.Build()) require.NoError(t, err) - require.Equal(t, "action-id-123", invokeResp.GetId()) + require.NotEmpty(t, invokeResp.GetId()) + require.Equal(t, v2.BatonActionStatus_BATON_ACTION_STATUS_COMPLETE, invokeResp.GetStatus()) + + // Test GetActionStatus using the ID returned from InvokeAction + statusResp, err := connector.GetActionStatus(ctx, v2.GetActionStatusRequest_builder{ + Id: invokeResp.GetId(), + }.Build()) + require.NoError(t, err) + require.Equal(t, v2.BatonActionStatus_BATON_ACTION_STATUS_COMPLETE, statusResp.GetStatus()) + require.Equal(t, "test-action", statusResp.GetName()) +} + +// testGlobalActionProvider implements GlobalActionProvider for testing. +type testGlobalActionProvider struct { + ConnectorBuilder +} + +func newTestGlobalActionProvider() *testGlobalActionProvider { + return &testGlobalActionProvider{newTestConnector([]ResourceSyncer{})} +} + +func (t *testGlobalActionProvider) GlobalActions(ctx context.Context, registry actions.ActionRegistry) error { + schema := v2.BatonActionSchema_builder{ + Name: "global-test-action", + DisplayName: "Global Test Action", + }.Build() + handler := func(ctx context.Context, args *structpb.Struct) (*structpb.Struct, annotations.Annotations, error) { + return &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "result": structpb.NewStringValue("global-action-executed"), + }, + }, nil, nil + } + return registry.Register(ctx, schema, handler) +} + +func TestGlobalActionProvider(t *testing.T) { + ctx := context.Background() + + provider := newTestGlobalActionProvider() + connector, err := NewConnector(ctx, provider) + require.NoError(t, err) + + // Test ListActionSchemas + listSchemasResp, err := connector.ListActionSchemas(ctx, &v2.ListActionSchemasRequest{}) + require.NoError(t, err) + require.Len(t, listSchemasResp.GetSchemas(), 1) + require.Equal(t, "global-test-action", listSchemasResp.GetSchemas()[0].GetName()) + + // Test GetActionSchema + getSchemaResp, err := connector.GetActionSchema(ctx, v2.GetActionSchemaRequest_builder{ + Name: "global-test-action", + }.Build()) + require.NoError(t, err) + require.Equal(t, "global-test-action", getSchemaResp.GetSchema().GetName()) + + // Test InvokeAction + invokeResp, err := connector.InvokeAction(ctx, v2.InvokeActionRequest_builder{ + Name: "global-test-action", + Args: &structpb.Struct{}, + }.Build()) + require.NoError(t, err) + require.NotEmpty(t, invokeResp.GetId()) require.Equal(t, v2.BatonActionStatus_BATON_ACTION_STATUS_COMPLETE, invokeResp.GetStatus()) + require.Equal(t, "global-action-executed", invokeResp.GetResponse().GetFields()["result"].GetStringValue()) // Test GetActionStatus statusResp, err := connector.GetActionStatus(ctx, v2.GetActionStatusRequest_builder{ - Id: "action-id-123", + Id: invokeResp.GetId(), + }.Build()) + require.NoError(t, err) + require.Equal(t, v2.BatonActionStatus_BATON_ACTION_STATUS_COMPLETE, statusResp.GetStatus()) +} + +// testResourceActionProviderSyncer implements ResourceActionProvider for testing. +type testResourceActionProviderSyncer struct { + resourceType *v2.ResourceType +} + +func newTestResourceActionProviderSyncer(resourceType string) *testResourceActionProviderSyncer { + return &testResourceActionProviderSyncer{ + resourceType: v2.ResourceType_builder{ + Id: resourceType, + DisplayName: "Test " + resourceType, + }.Build(), + } +} + +func (t *testResourceActionProviderSyncer) ResourceType(ctx context.Context) *v2.ResourceType { + return t.resourceType +} + +func (t *testResourceActionProviderSyncer) List(ctx context.Context, parentResourceID *v2.ResourceId, pToken *pagination.Token) ([]*v2.Resource, string, annotations.Annotations, error) { + return nil, "", nil, nil +} + +func (t *testResourceActionProviderSyncer) Entitlements(ctx context.Context, resource *v2.Resource, pToken *pagination.Token) ([]*v2.Entitlement, string, annotations.Annotations, error) { + return nil, "", nil, nil +} + +func (t *testResourceActionProviderSyncer) Grants(ctx context.Context, resource *v2.Resource, pToken *pagination.Token) ([]*v2.Grant, string, annotations.Annotations, error) { + return nil, "", nil, nil +} + +func (t *testResourceActionProviderSyncer) ResourceActions(ctx context.Context, registry actions.ActionRegistry) error { + schema := v2.BatonActionSchema_builder{ + Name: "resource-test-action", + DisplayName: "Resource Test Action", + }.Build() + handler := func(ctx context.Context, args *structpb.Struct) (*structpb.Struct, annotations.Annotations, error) { + return &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "result": structpb.NewStringValue("resource-action-executed"), + }, + }, nil, nil + } + return registry.Register(ctx, schema, handler) +} + +func TestResourceActionProvider(t *testing.T) { + ctx := context.Background() + + rsSyncer := newTestResourceActionProviderSyncer("test-resource") + connector, err := NewConnector(ctx, newTestConnector([]ResourceSyncer{rsSyncer})) + require.NoError(t, err) + + // Test ListActionSchemas with resource type filter + listSchemasResp, err := connector.ListActionSchemas(ctx, v2.ListActionSchemasRequest_builder{ + ResourceTypeId: "test-resource", + }.Build()) + require.NoError(t, err) + require.Len(t, listSchemasResp.GetSchemas(), 1) + require.Equal(t, "resource-test-action", listSchemasResp.GetSchemas()[0].GetName()) + require.Equal(t, "test-resource", listSchemasResp.GetSchemas()[0].GetResourceTypeId()) + + // Test ListActionSchemas without filter - should include all actions + listAllResp, err := connector.ListActionSchemas(ctx, &v2.ListActionSchemasRequest{}) + require.NoError(t, err) + require.Len(t, listAllResp.GetSchemas(), 1) + + // Test InvokeAction with resource type + invokeResp, err := connector.InvokeAction(ctx, v2.InvokeActionRequest_builder{ + Name: "resource-test-action", + ResourceTypeId: "test-resource", + Args: &structpb.Struct{}, + }.Build()) + require.NoError(t, err) + require.NotEmpty(t, invokeResp.GetId()) + require.Equal(t, v2.BatonActionStatus_BATON_ACTION_STATUS_COMPLETE, invokeResp.GetStatus()) + require.Equal(t, "resource-action-executed", invokeResp.GetResponse().GetFields()["result"].GetStringValue()) +} + +func TestHasActionsMethod(t *testing.T) { + ctx := context.Background() + + // Test without any actions + m := actions.NewActionManager(ctx) + require.False(t, m.HasActions()) + + // Test with global action + schema := v2.BatonActionSchema_builder{Name: "test"}.Build() + handler := func(ctx context.Context, args *structpb.Struct) (*structpb.Struct, annotations.Annotations, error) { + return nil, nil, nil + } + err := m.Register(ctx, schema, handler) + require.NoError(t, err) + require.True(t, m.HasActions()) + + // Test with only resource-scoped action + m2 := actions.NewActionManager(ctx) + require.False(t, m2.HasActions()) + err = m2.RegisterResourceAction(ctx, "resource-type", schema, handler) + require.NoError(t, err) + require.True(t, m2.HasActions()) +} + +func TestBackwardCompatibilityWrapper(t *testing.T) { + ctx := context.Background() + + // Use the legacy RegisterActionManager interface + actionManager := newTestRegisterActionManager() + connector, err := NewConnector(ctx, actionManager) + require.NoError(t, err) + + // Verify actions are registered through the wrapper + listSchemasResp, err := connector.ListActionSchemas(ctx, &v2.ListActionSchemasRequest{}) + require.NoError(t, err) + require.Len(t, listSchemasResp.GetSchemas(), 1) + require.Equal(t, "test-action", listSchemasResp.GetSchemas()[0].GetName()) + + // Invoke action - should work through the wrapper + invokeResp, err := connector.InvokeAction(ctx, v2.InvokeActionRequest_builder{ + Name: "test-action", + Args: &structpb.Struct{}, + }.Build()) + require.NoError(t, err) + require.NotEmpty(t, invokeResp.GetId()) + require.Equal(t, v2.BatonActionStatus_BATON_ACTION_STATUS_COMPLETE, invokeResp.GetStatus()) + + // Get status - should work with SDK-generated ID + statusResp, err := connector.GetActionStatus(ctx, v2.GetActionStatusRequest_builder{ + Id: invokeResp.GetId(), }.Build()) require.NoError(t, err) require.Equal(t, v2.BatonActionStatus_BATON_ACTION_STATUS_COMPLETE, statusResp.GetStatus()) - require.Equal(t, "Action completed successfully", statusResp.GetName()) } func TestDeleteResourceV2(t *testing.T) { diff --git a/pkg/connectorbuilder/connectorbuilder_v2_test.go b/pkg/connectorbuilder/connectorbuilder_v2_test.go index ad1ec2321..104029c0c 100644 --- a/pkg/connectorbuilder/connectorbuilder_v2_test.go +++ b/pkg/connectorbuilder/connectorbuilder_v2_test.go @@ -98,7 +98,7 @@ func TestConnectorBuilderV2_FullCapabilities(t *testing.T) { require.NotNil(t, actionResp) require.NotNil(t, actionResp.GetResponse()) - require.Equal(t, "action-id-123", actionResp.GetId()) + require.NotEmpty(t, actionResp.GetId()) // Test legacy event feed functionality eventResp, err := connector.ListEventFeeds(ctx, &v2.ListEventFeedsRequest{}) diff --git a/pkg/connectorbuilder/resource_syncer.go b/pkg/connectorbuilder/resource_syncer.go index bd95f56f1..4d52b8307 100644 --- a/pkg/connectorbuilder/resource_syncer.go +++ b/pkg/connectorbuilder/resource_syncer.go @@ -368,7 +368,7 @@ func (b *builder) addTargetedSyncer(_ context.Context, typeId string, in any) er return nil } -func (b *builder) addResourceSyncers(_ context.Context, typeId string, in any) error { +func (b *builder) addResourceSyncers(ctx context.Context, typeId string, in any) error { // no duplicates if _, ok := b.resourceSyncers[typeId]; ok { return fmt.Errorf("error: duplicate resource type found for resource builder %s", typeId) @@ -387,5 +387,17 @@ func (b *builder) addResourceSyncers(_ context.Context, typeId string, in any) e return fmt.Errorf("error: the resource syncer interface must be implemented for all types (%s)", typeId) } + // Check for resource actions + if actionProvider, ok := in.(ResourceActionProvider); ok { + registry, err := b.actionManager.GetTypeRegistry(ctx, typeId) + if err != nil { + return fmt.Errorf("error getting resource type action registry for %s: %w", typeId, err) + } + err = actionProvider.ResourceActions(ctx, registry) + if err != nil { + return fmt.Errorf("error getting resource actions for %s: %w", typeId, err) + } + } + return nil } diff --git a/pkg/connectorrunner/runner.go b/pkg/connectorrunner/runner.go index d705f052b..7974ef459 100644 --- a/pkg/connectorrunner/runner.go +++ b/pkg/connectorrunner/runner.go @@ -286,8 +286,13 @@ type createAccountConfig struct { } type invokeActionConfig struct { - action string - args *structpb.Struct + action string + resourceTypeID string // Optional: if set, invokes a resource-scoped action + args *structpb.Struct +} + +type listActionSchemasConfig struct { + resourceTypeID string // Optional: filter by resource type } type deleteResourceConfig struct { @@ -334,6 +339,7 @@ type runnerConfig struct { tempDir string createAccountConfig *createAccountConfig invokeActionConfig *invokeActionConfig + listActionSchemasConfig *listActionSchemasConfig deleteResourceConfig *deleteResourceConfig rotateCredentialsConfig *rotateCredentialsConfig createTicketConfig *createTicketConfig @@ -477,13 +483,29 @@ func WithOnDemandCreateAccount(c1zPath string, login string, email string, profi } } -func WithOnDemandInvokeAction(c1zPath string, action string, args *structpb.Struct) Option { +// WithOnDemandInvokeAction creates an option for invoking an action. +// If resourceTypeID is provided, it invokes a resource-scoped action. +func WithOnDemandInvokeAction(c1zPath string, action string, resourceTypeID string, args *structpb.Struct) Option { return func(ctx context.Context, cfg *runnerConfig) error { cfg.onDemand = true cfg.c1zPath = c1zPath cfg.invokeActionConfig = &invokeActionConfig{ - action: action, - args: args, + action: action, + resourceTypeID: resourceTypeID, + args: args, + } + return nil + } +} + +// WithOnDemandListActionSchemas creates an option for listing action schemas. +// If resourceTypeID is provided, it filters schemas for that specific resource type. +func WithOnDemandListActionSchemas(c1zPath string, resourceTypeID string) Option { + return func(ctx context.Context, cfg *runnerConfig) error { + cfg.onDemand = true + cfg.c1zPath = c1zPath + cfg.listActionSchemasConfig = &listActionSchemasConfig{ + resourceTypeID: resourceTypeID, } return nil } @@ -750,7 +772,13 @@ func NewConnectorRunner(ctx context.Context, c types.ConnectorServer, opts ...Op runner.cw = cw if cfg.onDemand { - if cfg.c1zPath == "" && cfg.eventFeedConfig == nil && cfg.createTicketConfig == nil && cfg.listTicketSchemasConfig == nil && cfg.getTicketConfig == nil && cfg.bulkCreateTicketConfig == nil { + if cfg.c1zPath == "" && + cfg.eventFeedConfig == nil && + cfg.createTicketConfig == nil && + cfg.listTicketSchemasConfig == nil && + cfg.getTicketConfig == nil && + cfg.bulkCreateTicketConfig == nil && + cfg.listActionSchemasConfig == nil { return nil, errors.New("c1zPath must be set when in on-demand mode") } @@ -772,7 +800,10 @@ func NewConnectorRunner(ctx context.Context, c types.ConnectorServer, opts ...Op tm = local.NewCreateAccountManager(ctx, cfg.c1zPath, cfg.createAccountConfig.login, cfg.createAccountConfig.email, cfg.createAccountConfig.profile) case cfg.invokeActionConfig != nil: - tm = local.NewActionInvoker(ctx, cfg.c1zPath, cfg.invokeActionConfig.action, cfg.invokeActionConfig.args) + tm = local.NewActionInvoker(ctx, cfg.c1zPath, cfg.invokeActionConfig.action, cfg.invokeActionConfig.resourceTypeID, cfg.invokeActionConfig.args) + + case cfg.listActionSchemasConfig != nil: + tm = local.NewListActionSchemas(ctx, cfg.listActionSchemasConfig.resourceTypeID) case cfg.deleteResourceConfig != nil: tm = local.NewResourceDeleter(ctx, cfg.c1zPath, cfg.deleteResourceConfig.resourceId, cfg.deleteResourceConfig.resourceType) diff --git a/pkg/field/defaults.go b/pkg/field/defaults.go index bdaabe960..5805b9f0f 100644 --- a/pkg/field/defaults.go +++ b/pkg/field/defaults.go @@ -172,6 +172,52 @@ var ( WithPersistent(true), WithExportTarget(ExportTargetNone), ) + invokeActionResourceTypeField = StringField("invoke-action-resource-type", + WithHidden(true), + WithDescription("The resource type ID for resource-scoped actions"), + WithPersistent(true), + WithExportTarget(ExportTargetNone), + ) + + listActionSchemasField = BoolField("list-action-schemas", + WithHidden(true), + WithDescription("List available action schemas"), + WithPersistent(true), + WithExportTarget(ExportTargetNone), + ) + listActionSchemasResourceTypeField = StringField("list-action-schemas-resource-type", + WithHidden(true), + WithDescription("Filter action schemas by resource type ID"), + WithPersistent(true), + WithExportTarget(ExportTargetNone), + ) + + listResourceActionsField = StringField("list-resource-actions", + WithDescription("The resource type ID to list actions for"), + WithHidden(true), + WithPersistent(true), + WithExportTarget(ExportTargetNone), + ) + + invokeResourceActionField = StringField("invoke-resource-action", + WithDescription("The name of the action to invoke"), + WithHidden(true), + WithPersistent(true), + WithExportTarget(ExportTargetNone), + ) + invokeResourceActionTypeField = StringField("invoke-resource-action-resource-type", + WithDescription("The resource type of the action to invoke"), + WithHidden(true), + WithPersistent(true), + WithExportTarget(ExportTargetNone), + ) + invokeResourceActionArgsField = StringField("invoke-resource-action-args", + WithHidden(true), + WithDescription("JSON-formatted object of map keys and values like '{ 'key': 'value' }'"), + WithDefaultValue("{}"), + WithPersistent(true), + WithExportTarget(ExportTargetNone), + ) otelCollectorEndpoint = StringField(OtelCollectorEndpointFieldName, WithDescription("The endpoint of the OpenTelemetry collector to send observability data to (used for both tracing and logging if specific endpoints are not provided)"), @@ -303,6 +349,13 @@ var DefaultFields = []SchemaField{ compactSyncsField, invokeActionField, invokeActionArgsField, + invokeActionResourceTypeField, + listActionSchemasField, + listActionSchemasResourceTypeField, + listResourceActionsField, + invokeResourceActionField, + invokeResourceActionTypeField, + invokeResourceActionArgsField, ServerSessionStoreMaximumSizeField, otelCollectorEndpoint, diff --git a/pkg/ratelimit/grpc.go b/pkg/ratelimit/grpc.go index 7bc885515..cd6351cb7 100644 --- a/pkg/ratelimit/grpc.go +++ b/pkg/ratelimit/grpc.go @@ -63,19 +63,23 @@ func getRatelimitDescriptors(ctx context.Context, method string, in interface{}, // ListEntitlements, ListGrants if req, ok := in.(hasResource); ok { - ret.SetEntries(append(ret.GetEntries(), ratelimitV1.RateLimitDescriptors_Entry_builder{ - Key: descriptorKeyConnectorResourceType, - Value: req.GetResource().GetId().GetResourceType(), - }.Build())) + if resourceType := req.GetResource().GetId().GetResourceType(); resourceType != "" { + ret.SetEntries(append(ret.GetEntries(), ratelimitV1.RateLimitDescriptors_Entry_builder{ + Key: descriptorKeyConnectorResourceType, + Value: resourceType, + }.Build())) + } return ret } - // ListResources + // ListResources, ListActionSchemas if req, ok := in.(hasResourceType); ok { - ret.SetEntries(append(ret.GetEntries(), ratelimitV1.RateLimitDescriptors_Entry_builder{ - Key: descriptorKeyConnectorResourceType, - Value: req.GetResourceTypeId(), - }.Build())) + if resourceTypeID := req.GetResourceTypeId(); resourceTypeID != "" { + ret.SetEntries(append(ret.GetEntries(), ratelimitV1.RateLimitDescriptors_Entry_builder{ + Key: descriptorKeyConnectorResourceType, + Value: resourceTypeID, + }.Build())) + } return ret } diff --git a/pkg/tasks/c1api/actions.go b/pkg/tasks/c1api/actions.go index 91219a2af..5ceda817a 100644 --- a/pkg/tasks/c1api/actions.go +++ b/pkg/tasks/c1api/actions.go @@ -36,9 +36,13 @@ func (c *actionListSchemasTaskHandler) HandleTask(ctx context.Context) error { if t == nil { return c.helpers.FinishTask(ctx, nil, nil, errors.New("action list schemas task is nil")) } - resp, err := cc.ListActionSchemas(ctx, v2.ListActionSchemasRequest_builder{ + reqBuilder := v2.ListActionSchemasRequest_builder{ Annotations: t.GetAnnotations(), - }.Build()) + } + if resourceTypeID := t.GetResourceTypeId(); resourceTypeID != "" { + reqBuilder.ResourceTypeId = resourceTypeID + } + resp, err := cc.ListActionSchemas(ctx, reqBuilder.Build()) if err != nil { return c.helpers.FinishTask(ctx, nil, nil, err) } @@ -120,15 +124,16 @@ func (c *actionInvokeTaskHandler) HandleTask(ctx context.Context) error { if t == nil || t.GetName() == "" { return c.helpers.FinishTask(ctx, nil, nil, errors.New("action name required")) } - if t.GetArgs() == nil { - return c.helpers.FinishTask(ctx, nil, nil, errors.New("args required")) - } - resp, err := cc.InvokeAction(ctx, v2.InvokeActionRequest_builder{ + reqBuilder := v2.InvokeActionRequest_builder{ Name: t.GetName(), Args: t.GetArgs(), Annotations: t.GetAnnotations(), - }.Build()) + } + if resourceTypeID := t.GetResourceTypeId(); resourceTypeID != "" { + reqBuilder.ResourceTypeId = resourceTypeID + } + resp, err := cc.InvokeAction(ctx, reqBuilder.Build()) if err != nil { return c.helpers.FinishTask(ctx, nil, nil, err) } @@ -177,7 +182,7 @@ func (c *actionStatusTaskHandler) HandleTask(ctx context.Context) error { return c.helpers.FinishTask(ctx, nil, nil, err) } - l.Debug("ActionInvoke response", zap.Any("resp", resp)) + l.Debug("ActionStatus response", zap.Any("resp", resp)) return c.helpers.FinishTask(ctx, resp, nil, nil) } diff --git a/pkg/tasks/local/action_invoker.go b/pkg/tasks/local/action_invoker.go index 4ff4a6968..eb38605ac 100644 --- a/pkg/tasks/local/action_invoker.go +++ b/pkg/tasks/local/action_invoker.go @@ -21,8 +21,9 @@ type localActionInvoker struct { dbPath string o sync.Once - action string - args *structpb.Struct + action string + resourceTypeID string // Optional: if set, invokes a resource-scoped action + args *structpb.Struct } func (m *localActionInvoker) GetTempDir() string { @@ -38,8 +39,9 @@ func (m *localActionInvoker) Next(ctx context.Context) (*v1.Task, time.Duration, m.o.Do(func() { task = v1.Task_builder{ ActionInvoke: v1.Task_ActionInvokeTask_builder{ - Name: m.action, - Args: m.args, + Name: m.action, + Args: m.args, + ResourceTypeId: m.resourceTypeID, }.Build(), }.Build() }) @@ -52,17 +54,27 @@ func (m *localActionInvoker) Process(ctx context.Context, task *v1.Task, cc type defer span.End() t := task.GetActionInvoke() - resp, err := cc.InvokeAction(ctx, v2.InvokeActionRequest_builder{ + reqBuilder := v2.InvokeActionRequest_builder{ Name: t.GetName(), Args: t.GetArgs(), Annotations: t.GetAnnotations(), - }.Build()) + } + if resourceTypeID := t.GetResourceTypeId(); resourceTypeID != "" { + reqBuilder.ResourceTypeId = resourceTypeID + } + resp, err := cc.InvokeAction(ctx, reqBuilder.Build()) if err != nil { return err } status := resp.GetStatus() finalResp := resp.GetResponse() + l.Info("ActionInvoke response", + zap.String("action_id", resp.GetId()), + zap.String("name", resp.GetName()), + zap.String("status", resp.GetStatus().String()), + zap.Any("response", resp.GetResponse()), + ) ticker := time.NewTicker(1 * time.Second) defer ticker.Stop() @@ -93,10 +105,12 @@ func (m *localActionInvoker) Process(ctx context.Context, task *v1.Task, cc type } // NewActionInvoker returns a task manager that queues an action invoke task. -func NewActionInvoker(ctx context.Context, dbPath string, action string, args *structpb.Struct) tasks.Manager { +// If resourceTypeID is provided, it invokes a resource-scoped action. +func NewActionInvoker(ctx context.Context, dbPath string, action string, resourceTypeID string, args *structpb.Struct) tasks.Manager { return &localActionInvoker{ - dbPath: dbPath, - action: action, - args: args, + dbPath: dbPath, + action: action, + resourceTypeID: resourceTypeID, + args: args, } } diff --git a/pkg/tasks/local/action_schema_list.go b/pkg/tasks/local/action_schema_list.go new file mode 100644 index 000000000..5e4a261d0 --- /dev/null +++ b/pkg/tasks/local/action_schema_list.go @@ -0,0 +1,77 @@ +package local + +import ( + "context" + "sync" + "time" + + "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap" + "go.uber.org/zap" + + v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2" + v1 "github.com/conductorone/baton-sdk/pb/c1/connectorapi/baton/v1" + "github.com/conductorone/baton-sdk/pkg/tasks" + "github.com/conductorone/baton-sdk/pkg/types" +) + +type localListActionSchemas struct { + o sync.Once + resourceTypeID string // Optional: filter by resource type +} + +func (m *localListActionSchemas) GetTempDir() string { + return "" +} + +func (m *localListActionSchemas) ShouldDebug() bool { + return false +} + +func (m *localListActionSchemas) Next(ctx context.Context) (*v1.Task, time.Duration, error) { + var task *v1.Task + m.o.Do(func() { + task = v1.Task_builder{ + ActionListSchemas: v1.Task_ActionListSchemasTask_builder{ + ResourceTypeId: m.resourceTypeID, + }.Build(), + }.Build() + }) + return task, 0, nil +} + +func (m *localListActionSchemas) Process(ctx context.Context, task *v1.Task, cc types.ConnectorClient) error { + l := ctxzap.Extract(ctx) + + reqBuilder := v2.ListActionSchemasRequest_builder{} + if m.resourceTypeID != "" { + reqBuilder.ResourceTypeId = m.resourceTypeID + } + + resp, err := cc.ListActionSchemas(ctx, reqBuilder.Build()) + if err != nil { + return err + } + + if m.resourceTypeID != "" { + l.Info("Action Schemas", + zap.String("resource_type_id", m.resourceTypeID), + zap.Int("count", len(resp.GetSchemas())), + zap.Any("schemas", resp.GetSchemas()), + ) + } else { + l.Info("Action Schemas", + zap.Int("count", len(resp.GetSchemas())), + zap.Any("schemas", resp.GetSchemas()), + ) + } + + return nil +} + +// NewListActionSchemas returns a task manager that queues a list action schemas task. +// If resourceTypeID is provided, it filters schemas for that specific resource type. +func NewListActionSchemas(ctx context.Context, resourceTypeID string) tasks.Manager { + return &localListActionSchemas{ + resourceTypeID: resourceTypeID, + } +} diff --git a/proto/c1/config/v1/config.proto b/proto/c1/config/v1/config.proto index 8f1bb731e..06d51c682 100644 --- a/proto/c1/config/v1/config.proto +++ b/proto/c1/config/v1/config.proto @@ -61,9 +61,48 @@ message Field { BoolField bool_field = 102; StringSliceField string_slice_field = 103; StringMapField string_map_field = 104; + ResourceIdField resource_id_field = 105; + ResourceIdSliceField resource_id_slice_field = 106; + + // These are meant to serve as return types for actions. + ResourceField resource_field = 107; + ResourceSliceField resource_slice_field = 108; } } +// These are partially duplicate with the Resource proto in the connector package. +// This is to avoid import cycles +message Resource { + ResourceId resource_id = 1; + ResourceId parent_resource_id = 2; + string display_name = 3; + string description = 4; + repeated google.protobuf.Any annotations = 5; +} + +message ResourceId { + string resource_type_id = 1; + string resource_id = 2; +} + +message ResourceField { + Resource default_value = 1; +} + +message ResourceSliceField { + repeated Resource default_value = 1; +} + +message ResourceIdField { + ResourceId default_value = 1; + optional ResourceIDRules rules = 3; +} + +message ResourceIdSliceField { + repeated ResourceIdField default_value = 1; + optional RepeatedResourceIdRules rules = 2; +} + message IntField { // rules int64 default_value = 1; diff --git a/proto/c1/config/v1/rules.proto b/proto/c1/config/v1/rules.proto index b85db5b6c..50f46a9fa 100644 --- a/proto/c1/config/v1/rules.proto +++ b/proto/c1/config/v1/rules.proto @@ -194,3 +194,11 @@ message StringMapRules { bool validate_empty = 1; bool is_required = 2; } + +message ResourceIDRules { + repeated string allowed_resource_type_ids = 1; +} + +message RepeatedResourceIdRules { + repeated string allowed_resource_type_ids = 1; +} diff --git a/proto/c1/connector/v2/action.proto b/proto/c1/connector/v2/action.proto index 1c5ff65ac..48514c4f8 100644 --- a/proto/c1/connector/v2/action.proto +++ b/proto/c1/connector/v2/action.proto @@ -36,6 +36,7 @@ message BatonActionSchema { repeated ActionType action_type = 7; + // Optional: if set, this action is scoped to a specific resource type string resource_type_id = 8; } @@ -47,12 +48,20 @@ enum ActionType { ACTION_TYPE_ACCOUNT_UPDATE_PROFILE = 3; ACTION_TYPE_ACCOUNT_DISABLE = 4; ACTION_TYPE_ACCOUNT_ENABLE = 5; + + // Generic resource actions + ACTION_TYPE_RESOURCE_CREATE = 6; + ACTION_TYPE_RESOURCE_DELETE = 7; + ACTION_TYPE_RESOURCE_ENABLE = 8; + ACTION_TYPE_RESOURCE_DISABLE = 9; } message InvokeActionRequest { string name = 1; google.protobuf.Struct args = 2; repeated google.protobuf.Any annotations = 3; + // Optional: if set, invokes a resource-scoped action + string resource_type_id = 4; } message InvokeActionResponse { @@ -89,6 +98,8 @@ message GetActionSchemaResponse { message ListActionSchemasRequest { repeated google.protobuf.Any annotations = 1; + // Optional: filter to only return actions for a specific resource type + string resource_type_id = 2; } message ListActionSchemasResponse { diff --git a/proto/c1/connectorapi/baton/v1/baton.proto b/proto/c1/connectorapi/baton/v1/baton.proto index 976d05aeb..19cea13b5 100644 --- a/proto/c1/connectorapi/baton/v1/baton.proto +++ b/proto/c1/connectorapi/baton/v1/baton.proto @@ -115,6 +115,8 @@ message Task { message ActionListSchemasTask { repeated google.protobuf.Any annotations = 1; + // Optional: filter to only return actions for a specific resource type + string resource_type_id = 2; } message ActionGetSchemaTask { @@ -126,6 +128,8 @@ message Task { string name = 1; google.protobuf.Struct args = 2; repeated google.protobuf.Any annotations = 3; + // Optional: if set, invokes a resource-scoped action + string resource_type_id = 4; } message ActionStatusTask {