From 1a02b70a1c3b078ab4ae47194dad35b54a271649 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Thu, 27 Jun 2024 12:09:57 +0200 Subject: [PATCH] feat: make any struct common to all api versions (#10553) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles-Edouard Brétéché --- api/kyverno/any.go | 61 +++++++++++++++++ api/kyverno/v2/condition.go | 68 ++----------------- api/kyverno/v2/condition_test.go | 9 +-- docs/user/crd/index.html | 50 +------------- .../kyverno/v2/condition.go | 9 +-- pkg/utils/conditions/condition_test.go | 5 +- 6 files changed, 83 insertions(+), 119 deletions(-) create mode 100644 api/kyverno/any.go diff --git a/api/kyverno/any.go b/api/kyverno/any.go new file mode 100644 index 0000000000..1d1b12474b --- /dev/null +++ b/api/kyverno/any.go @@ -0,0 +1,61 @@ +package kyverno + +import ( + "encoding/json" + + "github.com/jinzhu/copier" +) + +type Value any + +// Any can be any type. +// +k8s:deepcopy-gen=false +type Any struct { + // Value contains the value of the Any object. + // +optional + Value `json:"-"` +} + +func ToAny(in any) *Any { + var new *Any + if in != nil { + new = &Any{in} + } + return new +} + +func FromAny(in *Any) any { + if in == nil { + return nil + } + return in.Value +} + +func (in *Any) DeepCopyInto(out *Any) { + if err := copier.Copy(out, in); err != nil { + panic("deep copy failed") + } +} + +func (in *Any) DeepCopy() *Any { + if in == nil { + return nil + } + out := new(Any) + in.DeepCopyInto(out) + return out +} + +func (a *Any) MarshalJSON() ([]byte, error) { + return json.Marshal(a.Value) +} + +func (a *Any) UnmarshalJSON(data []byte) error { + var v any + err := json.Unmarshal(data, &v) + if err != nil { + return err + } + a.Value = v + return nil +} diff --git a/api/kyverno/v2/condition.go b/api/kyverno/v2/condition.go index 8e434a61c0..acb5c143da 100644 --- a/api/kyverno/v2/condition.go +++ b/api/kyverno/v2/condition.go @@ -1,49 +1,9 @@ package v2 import ( - "github.com/jinzhu/copier" - "k8s.io/apimachinery/pkg/util/json" + "github.com/kyverno/kyverno/api/kyverno" ) -type Value any - -// Any can be any type. -// +k8s:deepcopy-gen=false -type Any struct { - // Value contains the value of the Any object. - // +optional - Value `json:"-"` -} - -func (in *Any) DeepCopyInto(out *Any) { - if err := copier.Copy(out, in); err != nil { - panic("deep copy failed") - } -} - -func (in *Any) DeepCopy() *Any { - if in == nil { - return nil - } - out := new(Any) - in.DeepCopyInto(out) - return out -} - -func (a *Any) MarshalJSON() ([]byte, error) { - return json.Marshal(a.Value) -} - -func (a *Any) UnmarshalJSON(data []byte) error { - var v any - err := json.Unmarshal(data, &v) - if err != nil { - return err - } - a.Value = v - return nil -} - // ConditionOperator is the operation performed on condition key and value. // +kubebuilder:validation:Enum=Equals;NotEquals;AnyIn;AllIn;AnyNotIn;AllNotIn;GreaterThanOrEquals;GreaterThan;LessThanOrEquals;LessThan;DurationGreaterThanOrEquals;DurationGreaterThan;DurationLessThanOrEquals;DurationLessThan type ConditionOperator string @@ -84,7 +44,7 @@ type Condition struct { // Key is the context entry (using JMESPath) for conditional rule evaluation. // +kubebuilder:validation:Schemaless // +kubebuilder:pruning:PreserveUnknownFields - RawKey *Any `json:"key,omitempty" yaml:"key,omitempty"` + RawKey *kyverno.Any `json:"key,omitempty" yaml:"key,omitempty"` // Operator is the conditional operation to perform. Valid operators are: // Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, @@ -96,40 +56,26 @@ type Condition struct { // or can be variables declared using JMESPath. // +kubebuilder:validation:Schemaless // +kubebuilder:pruning:PreserveUnknownFields - RawValue *Any `json:"value,omitempty" yaml:"value,omitempty"` + RawValue *kyverno.Any `json:"value,omitempty" yaml:"value,omitempty"` // Message is an optional display message Message string `json:"message,omitempty" yaml:"message,omitempty"` } func (c *Condition) GetKey() any { - if c.RawKey == nil { - return nil - } - return c.RawKey.Value + return kyverno.FromAny(c.RawKey) } func (c *Condition) SetKey(in any) { - var new *Any - if in != nil { - new = &Any{in} - } - c.RawKey = new + c.RawKey = kyverno.ToAny(in) } func (c *Condition) GetValue() any { - if c.RawValue == nil { - return nil - } - return c.RawValue.Value + return kyverno.FromAny(c.RawValue) } func (c *Condition) SetValue(in any) { - var new *Any - if in != nil { - new = &Any{in} - } - c.RawValue = new + c.RawValue = kyverno.ToAny(in) } type AnyAllConditions struct { diff --git a/api/kyverno/v2/condition_test.go b/api/kyverno/v2/condition_test.go index 5e550af9c2..aef703e303 100644 --- a/api/kyverno/v2/condition_test.go +++ b/api/kyverno/v2/condition_test.go @@ -3,15 +3,16 @@ package v2 import ( "testing" + "github.com/kyverno/kyverno/api/kyverno" "github.com/stretchr/testify/assert" "k8s.io/apimachinery/pkg/util/json" ) func TestCondition_Marshal(t *testing.T) { type fields struct { - RawKey *Any + RawKey *kyverno.Any Operator ConditionOperator - RawValue *Any + RawValue *kyverno.Any Message string } tests := []struct { @@ -25,11 +26,11 @@ func TestCondition_Marshal(t *testing.T) { }, { name: "with key", fields: fields{ - RawKey: &Any{ + RawKey: &kyverno.Any{ Value: "{{ request.object.name }}", }, Operator: ConditionOperators["Equals"], - RawValue: &Any{ + RawValue: &kyverno.Any{ Value: "dummy", }, }, diff --git a/docs/user/crd/index.html b/docs/user/crd/index.html index ca95056a5f..b8b8253dce 100644 --- a/docs/user/crd/index.html +++ b/docs/user/crd/index.html @@ -5875,40 +5875,6 @@ Kubernetes admission/v1.Operation
-

Any -

-

-(Appears on: -Condition) -

-

-

Any can be any type.

-

- - - - - - - - - - - - - -
FieldDescription
--
- - -Value - - -
-(Optional) -

Value contains the value of the Any object.

-
-

AnyAllConditions

@@ -6126,9 +6092,7 @@ Kubernetes meta/v1.Time key
- -Any - +github.com/kyverno/kyverno/api/kyverno.Any @@ -6155,9 +6119,7 @@ DurationLessThanOrEquals, DurationLessThan

value
- -Any - +github.com/kyverno/kyverno/api/kyverno.Any @@ -6615,14 +6577,6 @@ int
-

Value -

-

-(Appears on: -Any) -

-

-

kyverno.io/v2alpha1

diff --git a/pkg/client/applyconfigurations/kyverno/v2/condition.go b/pkg/client/applyconfigurations/kyverno/v2/condition.go index 01ddd61f5e..02cb2596e4 100644 --- a/pkg/client/applyconfigurations/kyverno/v2/condition.go +++ b/pkg/client/applyconfigurations/kyverno/v2/condition.go @@ -19,15 +19,16 @@ limitations under the License. package v2 import ( + kyverno "github.com/kyverno/kyverno/api/kyverno" v2 "github.com/kyverno/kyverno/api/kyverno/v2" ) // ConditionApplyConfiguration represents an declarative configuration of the Condition type for use // with apply. type ConditionApplyConfiguration struct { - RawKey *v2.Any `json:"key,omitempty"` + RawKey *kyverno.Any `json:"key,omitempty"` Operator *v2.ConditionOperator `json:"operator,omitempty"` - RawValue *v2.Any `json:"value,omitempty"` + RawValue *kyverno.Any `json:"value,omitempty"` Message *string `json:"message,omitempty"` } @@ -40,7 +41,7 @@ func Condition() *ConditionApplyConfiguration { // WithRawKey sets the RawKey field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the RawKey field is set to the value of the last call. -func (b *ConditionApplyConfiguration) WithRawKey(value v2.Any) *ConditionApplyConfiguration { +func (b *ConditionApplyConfiguration) WithRawKey(value kyverno.Any) *ConditionApplyConfiguration { b.RawKey = &value return b } @@ -56,7 +57,7 @@ func (b *ConditionApplyConfiguration) WithOperator(value v2.ConditionOperator) * // WithRawValue sets the RawValue field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the RawValue field is set to the value of the last call. -func (b *ConditionApplyConfiguration) WithRawValue(value v2.Any) *ConditionApplyConfiguration { +func (b *ConditionApplyConfiguration) WithRawValue(value kyverno.Any) *ConditionApplyConfiguration { b.RawValue = &value return b } diff --git a/pkg/utils/conditions/condition_test.go b/pkg/utils/conditions/condition_test.go index 4347863c15..9138e16a32 100644 --- a/pkg/utils/conditions/condition_test.go +++ b/pkg/utils/conditions/condition_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/go-logr/logr" + "github.com/kyverno/kyverno/api/kyverno" kyvernov2 "github.com/kyverno/kyverno/api/kyverno/v2" "github.com/kyverno/kyverno/pkg/config" enginecontext "github.com/kyverno/kyverno/pkg/engine/context" @@ -34,11 +35,11 @@ func Test_checkCondition(t *testing.T) { logger: logging.GlobalLogger(), ctx: ctx, condition: kyvernov2.Condition{ - RawKey: &kyvernov2.Any{ + RawKey: &kyverno.Any{ Value: "{{ request.object.name }}", }, Operator: kyvernov2.ConditionOperators["Equals"], - RawValue: &kyvernov2.Any{ + RawValue: &kyverno.Any{ Value: "dummy", }, },