use union member DV in the DRA

This commit is contained in:
Lalit Chauhan 2025-10-23 17:52:04 +00:00
parent ab34215bab
commit 8a6b3caaa0
12 changed files with 447 additions and 31 deletions

View file

@ -174,7 +174,21 @@ func Validate_AllocationResult(ctx context.Context, op operation.Operation, fldP
// to declarative validation rules in the API schema.
func Validate_Device(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *resourcev1.Device) (errs field.ErrorList) {
// field resourcev1.Device.Name has no validation
// field resourcev1.Device.Attributes has no validation
// field resourcev1.Device.Attributes
errs = append(errs,
func(fldPath *field.Path, obj, oldObj map[resourcev1.QualifiedName]resourcev1.DeviceAttribute) (errs field.ErrorList) {
// don't revalidate unchanged data
if op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
return nil
}
// iterate the map and call the value type's validation function
errs = append(errs, validate.EachMapVal(ctx, op, fldPath, obj, oldObj, validate.SemanticDeepEqual, Validate_DeviceAttribute)...)
return
}(fldPath.Child("attributes"), obj.Attributes, safe.Field(oldObj, func(oldObj *resourcev1.Device) map[resourcev1.QualifiedName]resourcev1.DeviceAttribute {
return oldObj.Attributes
}))...)
// field resourcev1.Device.Capacity has no validation
// field resourcev1.Device.ConsumesCounters has no validation
// field resourcev1.Device.NodeName has no validation
@ -350,6 +364,108 @@ func Validate_DeviceAllocationResult(ctx context.Context, op operation.Operation
return errs
}
var unionMembershipFor_k8s_io_api_resource_v1_DeviceAttribute_ = validate.NewUnionMembership(validate.NewUnionMember("int"), validate.NewUnionMember("bool"), validate.NewUnionMember("string"), validate.NewUnionMember("version"))
// Validate_DeviceAttribute validates an instance of DeviceAttribute according
// to declarative validation rules in the API schema.
func Validate_DeviceAttribute(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *resourcev1.DeviceAttribute) (errs field.ErrorList) {
errs = append(errs, validate.Union(ctx, op, fldPath, obj, oldObj, unionMembershipFor_k8s_io_api_resource_v1_DeviceAttribute_, func(obj *resourcev1.DeviceAttribute) bool {
if obj == nil {
return false
}
return obj.IntValue != nil
}, func(obj *resourcev1.DeviceAttribute) bool {
if obj == nil {
return false
}
return obj.BoolValue != nil
}, func(obj *resourcev1.DeviceAttribute) bool {
if obj == nil {
return false
}
return obj.StringValue != nil
}, func(obj *resourcev1.DeviceAttribute) bool {
if obj == nil {
return false
}
return obj.VersionValue != nil
})...)
// field resourcev1.DeviceAttribute.IntValue
errs = append(errs,
func(fldPath *field.Path, obj, oldObj *int64) (errs field.ErrorList) {
// don't revalidate unchanged data
if op.Type == operation.Update && (obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj)) {
return nil
}
// call field-attached validations
earlyReturn := false
if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
earlyReturn = true
}
if earlyReturn {
return // do not proceed
}
return
}(fldPath.Child("int"), obj.IntValue, safe.Field(oldObj, func(oldObj *resourcev1.DeviceAttribute) *int64 { return oldObj.IntValue }))...)
// field resourcev1.DeviceAttribute.BoolValue
errs = append(errs,
func(fldPath *field.Path, obj, oldObj *bool) (errs field.ErrorList) {
// don't revalidate unchanged data
if op.Type == operation.Update && (obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj)) {
return nil
}
// call field-attached validations
earlyReturn := false
if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
earlyReturn = true
}
if earlyReturn {
return // do not proceed
}
return
}(fldPath.Child("bool"), obj.BoolValue, safe.Field(oldObj, func(oldObj *resourcev1.DeviceAttribute) *bool { return oldObj.BoolValue }))...)
// field resourcev1.DeviceAttribute.StringValue
errs = append(errs,
func(fldPath *field.Path, obj, oldObj *string) (errs field.ErrorList) {
// don't revalidate unchanged data
if op.Type == operation.Update && (obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj)) {
return nil
}
// call field-attached validations
earlyReturn := false
if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
earlyReturn = true
}
if earlyReturn {
return // do not proceed
}
return
}(fldPath.Child("string"), obj.StringValue, safe.Field(oldObj, func(oldObj *resourcev1.DeviceAttribute) *string { return oldObj.StringValue }))...)
// field resourcev1.DeviceAttribute.VersionValue
errs = append(errs,
func(fldPath *field.Path, obj, oldObj *string) (errs field.ErrorList) {
// don't revalidate unchanged data
if op.Type == operation.Update && (obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj)) {
return nil
}
// call field-attached validations
earlyReturn := false
if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
earlyReturn = true
}
if earlyReturn {
return // do not proceed
}
return
}(fldPath.Child("version"), obj.VersionValue, safe.Field(oldObj, func(oldObj *resourcev1.DeviceAttribute) *string { return oldObj.VersionValue }))...)
return errs
}
// Validate_DeviceClaim validates an instance of DeviceClaim according
// to declarative validation rules in the API schema.
func Validate_DeviceClaim(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *resourcev1.DeviceClaim) (errs field.ErrorList) {

View file

@ -175,7 +175,20 @@ func Validate_AllocationResult(ctx context.Context, op operation.Operation, fldP
// Validate_BasicDevice validates an instance of BasicDevice according
// to declarative validation rules in the API schema.
func Validate_BasicDevice(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *resourcev1beta1.BasicDevice) (errs field.ErrorList) {
// field resourcev1beta1.BasicDevice.Attributes has no validation
// field resourcev1beta1.BasicDevice.Attributes
errs = append(errs,
func(fldPath *field.Path, obj, oldObj map[resourcev1beta1.QualifiedName]resourcev1beta1.DeviceAttribute) (errs field.ErrorList) {
// don't revalidate unchanged data
if op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
return nil
}
// iterate the map and call the value type's validation function
errs = append(errs, validate.EachMapVal(ctx, op, fldPath, obj, oldObj, validate.SemanticDeepEqual, Validate_DeviceAttribute)...)
return
}(fldPath.Child("attributes"), obj.Attributes, safe.Field(oldObj, func(oldObj *resourcev1beta1.BasicDevice) map[resourcev1beta1.QualifiedName]resourcev1beta1.DeviceAttribute {
return oldObj.Attributes
}))...)
// field resourcev1beta1.BasicDevice.Capacity has no validation
// field resourcev1beta1.BasicDevice.ConsumesCounters has no validation
// field resourcev1beta1.BasicDevice.NodeName has no validation
@ -371,6 +384,108 @@ func Validate_DeviceAllocationResult(ctx context.Context, op operation.Operation
return errs
}
var unionMembershipFor_k8s_io_api_resource_v1beta1_DeviceAttribute_ = validate.NewUnionMembership(validate.NewUnionMember("int"), validate.NewUnionMember("bool"), validate.NewUnionMember("string"), validate.NewUnionMember("version"))
// Validate_DeviceAttribute validates an instance of DeviceAttribute according
// to declarative validation rules in the API schema.
func Validate_DeviceAttribute(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *resourcev1beta1.DeviceAttribute) (errs field.ErrorList) {
errs = append(errs, validate.Union(ctx, op, fldPath, obj, oldObj, unionMembershipFor_k8s_io_api_resource_v1beta1_DeviceAttribute_, func(obj *resourcev1beta1.DeviceAttribute) bool {
if obj == nil {
return false
}
return obj.IntValue != nil
}, func(obj *resourcev1beta1.DeviceAttribute) bool {
if obj == nil {
return false
}
return obj.BoolValue != nil
}, func(obj *resourcev1beta1.DeviceAttribute) bool {
if obj == nil {
return false
}
return obj.StringValue != nil
}, func(obj *resourcev1beta1.DeviceAttribute) bool {
if obj == nil {
return false
}
return obj.VersionValue != nil
})...)
// field resourcev1beta1.DeviceAttribute.IntValue
errs = append(errs,
func(fldPath *field.Path, obj, oldObj *int64) (errs field.ErrorList) {
// don't revalidate unchanged data
if op.Type == operation.Update && (obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj)) {
return nil
}
// call field-attached validations
earlyReturn := false
if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
earlyReturn = true
}
if earlyReturn {
return // do not proceed
}
return
}(fldPath.Child("int"), obj.IntValue, safe.Field(oldObj, func(oldObj *resourcev1beta1.DeviceAttribute) *int64 { return oldObj.IntValue }))...)
// field resourcev1beta1.DeviceAttribute.BoolValue
errs = append(errs,
func(fldPath *field.Path, obj, oldObj *bool) (errs field.ErrorList) {
// don't revalidate unchanged data
if op.Type == operation.Update && (obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj)) {
return nil
}
// call field-attached validations
earlyReturn := false
if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
earlyReturn = true
}
if earlyReturn {
return // do not proceed
}
return
}(fldPath.Child("bool"), obj.BoolValue, safe.Field(oldObj, func(oldObj *resourcev1beta1.DeviceAttribute) *bool { return oldObj.BoolValue }))...)
// field resourcev1beta1.DeviceAttribute.StringValue
errs = append(errs,
func(fldPath *field.Path, obj, oldObj *string) (errs field.ErrorList) {
// don't revalidate unchanged data
if op.Type == operation.Update && (obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj)) {
return nil
}
// call field-attached validations
earlyReturn := false
if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
earlyReturn = true
}
if earlyReturn {
return // do not proceed
}
return
}(fldPath.Child("string"), obj.StringValue, safe.Field(oldObj, func(oldObj *resourcev1beta1.DeviceAttribute) *string { return oldObj.StringValue }))...)
// field resourcev1beta1.DeviceAttribute.VersionValue
errs = append(errs,
func(fldPath *field.Path, obj, oldObj *string) (errs field.ErrorList) {
// don't revalidate unchanged data
if op.Type == operation.Update && (obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj)) {
return nil
}
// call field-attached validations
earlyReturn := false
if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
earlyReturn = true
}
if earlyReturn {
return // do not proceed
}
return
}(fldPath.Child("version"), obj.VersionValue, safe.Field(oldObj, func(oldObj *resourcev1beta1.DeviceAttribute) *string { return oldObj.VersionValue }))...)
return errs
}
// Validate_DeviceClaim validates an instance of DeviceClaim according
// to declarative validation rules in the API schema.
func Validate_DeviceClaim(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *resourcev1beta1.DeviceClaim) (errs field.ErrorList) {

View file

@ -176,7 +176,21 @@ func Validate_AllocationResult(ctx context.Context, op operation.Operation, fldP
// to declarative validation rules in the API schema.
func Validate_Device(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *resourcev1beta2.Device) (errs field.ErrorList) {
// field resourcev1beta2.Device.Name has no validation
// field resourcev1beta2.Device.Attributes has no validation
// field resourcev1beta2.Device.Attributes
errs = append(errs,
func(fldPath *field.Path, obj, oldObj map[resourcev1beta2.QualifiedName]resourcev1beta2.DeviceAttribute) (errs field.ErrorList) {
// don't revalidate unchanged data
if op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
return nil
}
// iterate the map and call the value type's validation function
errs = append(errs, validate.EachMapVal(ctx, op, fldPath, obj, oldObj, validate.SemanticDeepEqual, Validate_DeviceAttribute)...)
return
}(fldPath.Child("attributes"), obj.Attributes, safe.Field(oldObj, func(oldObj *resourcev1beta2.Device) map[resourcev1beta2.QualifiedName]resourcev1beta2.DeviceAttribute {
return oldObj.Attributes
}))...)
// field resourcev1beta2.Device.Capacity has no validation
// field resourcev1beta2.Device.ConsumesCounters has no validation
// field resourcev1beta2.Device.NodeName has no validation
@ -352,6 +366,108 @@ func Validate_DeviceAllocationResult(ctx context.Context, op operation.Operation
return errs
}
var unionMembershipFor_k8s_io_api_resource_v1beta2_DeviceAttribute_ = validate.NewUnionMembership(validate.NewUnionMember("int"), validate.NewUnionMember("bool"), validate.NewUnionMember("string"), validate.NewUnionMember("version"))
// Validate_DeviceAttribute validates an instance of DeviceAttribute according
// to declarative validation rules in the API schema.
func Validate_DeviceAttribute(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *resourcev1beta2.DeviceAttribute) (errs field.ErrorList) {
errs = append(errs, validate.Union(ctx, op, fldPath, obj, oldObj, unionMembershipFor_k8s_io_api_resource_v1beta2_DeviceAttribute_, func(obj *resourcev1beta2.DeviceAttribute) bool {
if obj == nil {
return false
}
return obj.IntValue != nil
}, func(obj *resourcev1beta2.DeviceAttribute) bool {
if obj == nil {
return false
}
return obj.BoolValue != nil
}, func(obj *resourcev1beta2.DeviceAttribute) bool {
if obj == nil {
return false
}
return obj.StringValue != nil
}, func(obj *resourcev1beta2.DeviceAttribute) bool {
if obj == nil {
return false
}
return obj.VersionValue != nil
})...)
// field resourcev1beta2.DeviceAttribute.IntValue
errs = append(errs,
func(fldPath *field.Path, obj, oldObj *int64) (errs field.ErrorList) {
// don't revalidate unchanged data
if op.Type == operation.Update && (obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj)) {
return nil
}
// call field-attached validations
earlyReturn := false
if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
earlyReturn = true
}
if earlyReturn {
return // do not proceed
}
return
}(fldPath.Child("int"), obj.IntValue, safe.Field(oldObj, func(oldObj *resourcev1beta2.DeviceAttribute) *int64 { return oldObj.IntValue }))...)
// field resourcev1beta2.DeviceAttribute.BoolValue
errs = append(errs,
func(fldPath *field.Path, obj, oldObj *bool) (errs field.ErrorList) {
// don't revalidate unchanged data
if op.Type == operation.Update && (obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj)) {
return nil
}
// call field-attached validations
earlyReturn := false
if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
earlyReturn = true
}
if earlyReturn {
return // do not proceed
}
return
}(fldPath.Child("bool"), obj.BoolValue, safe.Field(oldObj, func(oldObj *resourcev1beta2.DeviceAttribute) *bool { return oldObj.BoolValue }))...)
// field resourcev1beta2.DeviceAttribute.StringValue
errs = append(errs,
func(fldPath *field.Path, obj, oldObj *string) (errs field.ErrorList) {
// don't revalidate unchanged data
if op.Type == operation.Update && (obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj)) {
return nil
}
// call field-attached validations
earlyReturn := false
if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
earlyReturn = true
}
if earlyReturn {
return // do not proceed
}
return
}(fldPath.Child("string"), obj.StringValue, safe.Field(oldObj, func(oldObj *resourcev1beta2.DeviceAttribute) *string { return oldObj.StringValue }))...)
// field resourcev1beta2.DeviceAttribute.VersionValue
errs = append(errs,
func(fldPath *field.Path, obj, oldObj *string) (errs field.ErrorList) {
// don't revalidate unchanged data
if op.Type == operation.Update && (obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj)) {
return nil
}
// call field-attached validations
earlyReturn := false
if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
earlyReturn = true
}
if earlyReturn {
return // do not proceed
}
return
}(fldPath.Child("version"), obj.VersionValue, safe.Field(oldObj, func(oldObj *resourcev1beta2.DeviceAttribute) *string { return oldObj.VersionValue }))...)
return errs
}
// Validate_DeviceClaim validates an instance of DeviceClaim according
// to declarative validation rules in the API schema.
func Validate_DeviceClaim(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *resourcev1beta2.DeviceClaim) (errs field.ErrorList) {

View file

@ -910,11 +910,11 @@ func validateDeviceAttribute(attribute resource.DeviceAttribute, fldPath *field.
switch numFields {
case 0:
allErrs = append(allErrs, field.Required(fldPath, "exactly one value must be specified"))
allErrs = append(allErrs, field.Invalid(fldPath, "", "exactly one value must be specified").MarkCoveredByDeclarative())
case 1:
// Okay.
default:
allErrs = append(allErrs, field.Invalid(fldPath, attribute, "exactly one value must be specified"))
allErrs = append(allErrs, field.Invalid(fldPath, attribute, "exactly one value must be specified").MarkCoveredByDeclarative())
}
return allErrs
}

View file

@ -336,8 +336,8 @@ func TestValidateResourceSlice(t *testing.T) {
"bad-attribute": {
wantFailures: field.ErrorList{
field.Invalid(field.NewPath("spec", "devices").Index(1).Child("attributes").Key(badName), badName, "a valid C identifier must start with alphabetic character or '_', followed by a string of alphanumeric characters or '_' (e.g. 'my_name', or 'MY_NAME', or 'MyName', regex used for validation is '[A-Za-z_][A-Za-z0-9_]*')"),
field.Required(field.NewPath("spec", "devices").Index(1).Child("attributes").Key(badName), "exactly one value must be specified"),
field.Invalid(field.NewPath("spec", "devices").Index(2).Child("attributes").Key(goodName), resourceapi.DeviceAttribute{StringValue: ptr.To("x"), VersionValue: ptr.To("1.2.3")}, "exactly one value must be specified"),
field.Invalid(field.NewPath("spec", "devices").Index(1).Child("attributes").Key(badName), "", "exactly one value must be specified").MarkCoveredByDeclarative(),
field.Invalid(field.NewPath("spec", "devices").Index(2).Child("attributes").Key(goodName), resourceapi.DeviceAttribute{StringValue: ptr.To("x"), VersionValue: ptr.To("1.2.3")}, "exactly one value must be specified").MarkCoveredByDeclarative(),
field.Invalid(field.NewPath("spec", "devices").Index(3).Child("attributes").Key(goodName).Child("version"), strings.Repeat("x", resourceapi.DeviceAttributeMaxValueLength+1), "must be a string compatible with semver.org spec 2.0.0"),
field.TooLongMaxLength(field.NewPath("spec", "devices").Index(3).Child("attributes").Key(goodName).Child("version"), strings.Repeat("x", resourceapi.DeviceAttributeMaxValueLength+1), resourceapi.DeviceAttributeMaxValueLength),
field.TooLongMaxLength(field.NewPath("spec", "devices").Index(4).Child("attributes").Key(goodName).Child("string"), strings.Repeat("x", resourceapi.DeviceAttributeMaxValueLength+1), resourceapi.DeviceAttributeMaxValueLength),

View file

@ -97,6 +97,31 @@ func TestDeclarativeValidate(t *testing.T) {
field.Required(field.NewPath("spec", "devices").Index(0).Child("taints").Index(0).Child("effect"), ""),
},
},
// spec.Devices[%].attribute
"valid: device attribute int": {
input: mkResourceSlice(tweakDeviceAttribute("test.io/int", resource.DeviceAttribute{IntValue: ptr.To[int64](123)})),
},
"valid: device attribute bool": {
input: mkResourceSlice(tweakDeviceAttribute("test.io/bool", resource.DeviceAttribute{BoolValue: ptr.To(true)})),
},
"valid: device attribute string": {
input: mkResourceSlice(tweakDeviceAttribute("test.io/string", resource.DeviceAttribute{StringValue: ptr.To("value")})),
},
"valid: device attribute version": {
input: mkResourceSlice(tweakDeviceAttribute("test.io/version", resource.DeviceAttribute{VersionValue: ptr.To("1.2.3")})),
},
"invalid: device attribute with multiple values": {
input: mkResourceSlice(tweakDeviceAttribute("test.io/multiple", resource.DeviceAttribute{IntValue: ptr.To[int64](123), BoolValue: ptr.To(true)})),
expectedErrs: field.ErrorList{
field.Invalid(field.NewPath("spec", "devices").Index(0).Child("attributes").Key("test.io/multiple"), "", ""),
},
},
"invalid: device attribute no value": {
input: mkResourceSlice(tweakDeviceAttribute("test.io/multiple", resource.DeviceAttribute{})),
expectedErrs: field.ErrorList{
field.Invalid(field.NewPath("spec", "devices").Index(0).Child("attributes").Key("test.io/multiple"), "", ""),
},
},
// TODO: Add more test cases
}
@ -176,6 +201,17 @@ func TestDeclarativeValidateUpdate(t *testing.T) {
field.Required(field.NewPath("spec", "devices").Index(0).Child("taints").Index(0).Child("effect"), ""),
},
},
"valid update: device attribute": {
old: mkResourceSlice(tweakDeviceAttribute("test.io/int", resource.DeviceAttribute{IntValue: ptr.To[int64](123)})),
update: mkResourceSlice(tweakDeviceAttribute("test.io/int", resource.DeviceAttribute{BoolValue: ptr.To(true)})),
},
"invalid update: device attribute with multiple values": {
old: mkResourceSlice(),
update: mkResourceSlice(tweakDeviceAttribute("test.io/multiple", resource.DeviceAttribute{IntValue: ptr.To[int64](123), BoolValue: ptr.To(true)})),
expectedErrs: field.ErrorList{
field.Invalid(field.NewPath("spec", "devices").Index(0).Child("attributes").Key("test.io/multiple"), "", "may have only one of the following fields set: bool, int, string, version"),
},
},
}
for k, tc := range testCases {
t.Run(k, func(t *testing.T) {
@ -249,3 +285,12 @@ func tweakDeviceTaintEffect(effect string) func(*resource.ResourceSlice) {
rs.Spec.Devices[0].Taints[0].Effect = resource.DeviceTaintEffect(effect)
}
}
func tweakDeviceAttribute(name resource.QualifiedName, value resource.DeviceAttribute) func(*resource.ResourceSlice) {
return func(rs *resource.ResourceSlice) {
if rs.Spec.Devices[0].Attributes == nil {
rs.Spec.Devices[0].Attributes = make(map[resource.QualifiedName]resource.DeviceAttribute)
}
rs.Spec.Devices[0].Attributes[name] = value
}
}

View file

@ -513,26 +513,30 @@ message DeviceAttribute {
// IntValue is a number.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
optional int64 int = 2;
// BoolValue is a true/false value.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
optional bool bool = 3;
// StringValue is a string. Must not be longer than 64 characters.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
optional string string = 4;
// VersionValue is a semantic version according to semver.org spec 2.0.0.
// Must not be longer than 64 characters.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
optional string version = 5;
}

View file

@ -581,26 +581,30 @@ type DeviceAttribute struct {
// IntValue is a number.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
IntValue *int64 `json:"int,omitempty" protobuf:"varint,2,opt,name=int"`
// BoolValue is a true/false value.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
BoolValue *bool `json:"bool,omitempty" protobuf:"varint,3,opt,name=bool"`
// StringValue is a string. Must not be longer than 64 characters.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
StringValue *string `json:"string,omitempty" protobuf:"bytes,4,opt,name=string"`
// VersionValue is a semantic version according to semver.org spec 2.0.0.
// Must not be longer than 64 characters.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
VersionValue *string `json:"version,omitempty" protobuf:"bytes,5,opt,name=version"`
}

View file

@ -521,26 +521,30 @@ message DeviceAttribute {
// IntValue is a number.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
optional int64 int = 2;
// BoolValue is a true/false value.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
optional bool bool = 3;
// StringValue is a string. Must not be longer than 64 characters.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
optional string string = 4;
// VersionValue is a semantic version according to semver.org spec 2.0.0.
// Must not be longer than 64 characters.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
optional string version = 5;
}

View file

@ -585,26 +585,30 @@ type DeviceAttribute struct {
// IntValue is a number.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
IntValue *int64 `json:"int,omitempty" protobuf:"varint,2,opt,name=int"`
// BoolValue is a true/false value.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
BoolValue *bool `json:"bool,omitempty" protobuf:"varint,3,opt,name=bool"`
// StringValue is a string. Must not be longer than 64 characters.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
StringValue *string `json:"string,omitempty" protobuf:"bytes,4,opt,name=string"`
// VersionValue is a semantic version according to semver.org spec 2.0.0.
// Must not be longer than 64 characters.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
VersionValue *string `json:"version,omitempty" protobuf:"bytes,5,opt,name=version"`
}

View file

@ -513,26 +513,30 @@ message DeviceAttribute {
// IntValue is a number.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
optional int64 int = 2;
// BoolValue is a true/false value.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
optional bool bool = 3;
// StringValue is a string. Must not be longer than 64 characters.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
optional string string = 4;
// VersionValue is a semantic version according to semver.org spec 2.0.0.
// Must not be longer than 64 characters.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
optional string version = 5;
}

View file

@ -581,26 +581,30 @@ type DeviceAttribute struct {
// IntValue is a number.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
IntValue *int64 `json:"int,omitempty" protobuf:"varint,2,opt,name=int"`
// BoolValue is a true/false value.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
BoolValue *bool `json:"bool,omitempty" protobuf:"varint,3,opt,name=bool"`
// StringValue is a string. Must not be longer than 64 characters.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
StringValue *string `json:"string,omitempty" protobuf:"bytes,4,opt,name=string"`
// VersionValue is a semantic version according to semver.org spec 2.0.0.
// Must not be longer than 64 characters.
//
// +optional
// +oneOf=ValueType
// +k8s:optional
// +k8s:unionMember
VersionValue *string `json:"version,omitempty" protobuf:"bytes,5,opt,name=version"`
}