Skip to content

Commit

Permalink
resmgr: move/generate resmgr API/types to pkg/apis.
Browse files Browse the repository at this point in the history
Move resmgr API and types to pkg/apis/resmgr/v1alpha1,
next to other generated APIs (currently config). This
allows annotating the types for better CRD validation
which is useful if we use them in our config CRDs.

Annotate Expression operator for better validation.

Signed-off-by: Krisztian Litkey <[email protected]>
  • Loading branch information
klihub committed Feb 9, 2024
1 parent 3fe486f commit e8fe97e
Show file tree
Hide file tree
Showing 11 changed files with 168 additions and 76 deletions.
2 changes: 1 addition & 1 deletion cmd/plugins/topology-aware/policy/affinity.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
package topologyaware

import (
resmgr "github.com/containers/nri-plugins/pkg/resmgr/apis"
resmgr "github.com/containers/nri-plugins/pkg/apis/resmgr/v1alpha1"
"github.com/containers/nri-plugins/pkg/resmgr/cache"
)

Expand Down
2 changes: 1 addition & 1 deletion cmd/plugins/topology-aware/policy/mocks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
"time"

nri "github.com/containerd/nri/pkg/api"
resmgr "github.com/containers/nri-plugins/pkg/resmgr/apis"
resmgr "github.com/containers/nri-plugins/pkg/apis/resmgr/v1alpha1"
"github.com/containers/nri-plugins/pkg/resmgr/cache"
system "github.com/containers/nri-plugins/pkg/sysfs"
"github.com/containers/nri-plugins/pkg/topology"
Expand Down
20 changes: 20 additions & 0 deletions pkg/apis/resmgr/v1alpha1/evaluable.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright The NRI Plugins Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package resmgr

// Evaluable is the interface objects need to implement to be evaluable against Expressions.
type Evaluable interface {
Eval(string) interface{}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019-2020 Intel Corporation. All Rights Reserved.
// Copyright The NRI Plugins Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -23,57 +23,6 @@ import (
logger "github.com/containers/nri-plugins/pkg/log"
)

// Evaluable is the interface objects need to implement to be evaluable against Expressions.
type Evaluable interface {
Eval(string) interface{}
}

// Expression is used to describe a criteria to select objects within a domain.
type Expression struct {
Key string `json:"key"` // key to check values of/against
Op Operator `json:"operator"` // operator to apply to value of Key and Values
Values []string `json:"values,omitempty"` // value(s) for domain key
}

const (
KeyPod = "pod"
KeyID = "id"
KeyUID = "uid"
KeyName = "name"
KeyNamespace = "namespace"
KeyQOSClass = "qosclass"
KeyLabels = "labels"
KeyTags = "tags"
)

// Operator defines the possible operators for an Expression.
type Operator string

const (
// Equals tests for equality with a single value.
Equals Operator = "Equals"
// NotEqual test for inequality with a single value.
NotEqual Operator = "NotEqual"
// In tests if the key's value is one of the specified set.
In Operator = "In"
// NotIn tests if the key's value is not one of the specified set.
NotIn Operator = "NotIn"
// Exists evalutes to true if the named key exists.
Exists Operator = "Exists"
// NotExist evalutes to true if the named key does not exist.
NotExist Operator = "NotExist"
// AlwaysTrue always evaluates to true.
AlwaysTrue Operator = "AlwaysTrue"
// Matches tests if the key value matches the only given globbing pattern.
Matches Operator = "Matches"
// MatchesNot is true if Matches would be false for the same key and pattern.
MatchesNot Operator = "MatchesNot"
// MatchesAny tests if the key value matches any of the given globbing patterns.
MatchesAny Operator = "MatchesAny"
// MatchesNone is true if MatchesAny would be false for the same key and patterns.
MatchesNone Operator = "MatchesNone"
)

// Our logger instance.
var log = logger.NewLogger("expression")

Expand Down Expand Up @@ -192,9 +141,15 @@ func (e *Expression) KeyValue(subject Evaluable) (string, bool) {
}

func splitKeys(keys string) ([]string, string) {
// joint key specs have two valid forms:
// We don't support boolean expressions but we support 'joint keys'.
// These can be used to emulate a boolean AND of multiple keys.
//
// Joint keys have two valid forms:
// - ":keylist" (equivalent to ":::<colon-separated-keylist>")
// - ":<ksep><vsep><ksep-separated-keylist>"
// - ":<key-sep><value-sep><key-sep-separated-keylist>"
//
// The value of dereferencing such a key is the values of all individual
// keys concatenated and separated by value-sep.

if len(keys) < 4 || keys[0] != ':' {
return []string{keys}, ""
Expand Down Expand Up @@ -229,6 +184,12 @@ func validSeparator(b byte) bool {
}

// ResolveRef walks an object trying to resolve a reference to a value.
//
// Keys can be combined into compound keys using '/' as the separator.
// For instance, "pod/labels/io.test.domain/my-label" refers to the
// value of the "io.test.domain/my-label"label key of the pod of the
// evaluated object (which then needs to be a container for successful
// evaluation).
func ResolveRef(subject Evaluable, spec string) (string, bool, error) {
var obj interface{}

Expand Down Expand Up @@ -291,21 +252,6 @@ func (e *Expression) String() string {
return fmt.Sprintf("<%s %s %s>", e.Key, e.Op, strings.Join(e.Values, ","))
}

// DeepCopy creates a deep copy of the expression.
func (e *Expression) DeepCopy() *Expression {
out := &Expression{}
e.DeepCopyInto(out)
return out
}

// DeepCopyInto copies the expression into another one.
func (e *Expression) DeepCopyInto(out *Expression) {
out.Key = e.Key
out.Op = e.Op
out.Values = make([]string, len(e.Values))
copy(out.Values, e.Values)
}

// exprError returns a formatted error specific to expressions.
func exprError(format string, args ...interface{}) error {
return fmt.Errorf("expression: "+format, args...)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019-2020 Intel Corporation. All Rights Reserved.
// Copyright The NRI Plugins Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down
84 changes: 84 additions & 0 deletions pkg/apis/resmgr/v1alpha1/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright The NRI Plugins Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package resmgr

// Expression describes some runtime-evaluated condition. An expression
// consist of a key, an operator and a set of values. An expressions is
// evaluated against an object which implements the Evaluable interface.
// Evaluating an expression consists of looking up the value for the key
// in the object, then using the operator to check it agains the values
// of the expression. The result is a single boolean value. An object is
// said to satisfy the evaluated expression if this value is true. An
// expression can contain 0, 1 or more values depending on the operator.
// +k8s:deepcopy-gen=true
type Expression struct {
// Key is the expression key.
Key string `json:"key"`
// Op is the expression operator.
// +kubebuilder:validation:Enum=Equals;NotEqual;In;NotIn;Exists;NotExist;AlwaysTrue;Matches;MatchesNot;MatchesAny;MatchesNone
// +kubebuilder:validation:Format:string
Op Operator `json:"operator"`
// Values contains the values the key value is evaluated against.
Values []string `json:"values,omitempty"`
}

// Operator is an expression operator.
type Operator string

// supported operators
const (
// Equals tests for equality with a single value.
Equals Operator = "Equals"
// NotEqual test for inequality with a single value.
NotEqual Operator = "NotEqual"
// In tests for any value for the given set.
In Operator = "In"
// NotIn tests for the lack of value in a given set.
NotIn Operator = "NotIn"
// Exists tests if the given key exists with any value.
Exists Operator = "Exists"
// NotExist tests if the given key does not exist.
NotExist Operator = "NotExist"
// AlwaysTrue always evaluates to true.
AlwaysTrue Operator = "AlwaysTrue"
// Matches tests if the key value matches a single globbing pattern.
Matches Operator = "Matches"
// MatchesNot tests if the key value does not match a single globbing pattern.
MatchesNot Operator = "MatchesNot"
// MatchesAny tests if the key value matches any of a set of globbing patterns.
MatchesAny Operator = "MatchesAny"
// MatchesNone tests if the key value matches none of a set of globbing patterns.
MatchesNone Operator = "MatchesNone"
)

// Keys of supported object properties.
const (
// Pod of the object.
KeyPod = "pod"
// ID of the object.
KeyID = "id"
// UID of the object.
KeyUID = "uid"
// Name of the object.
KeyName = "name"
// Namespace of the object.
KeyNamespace = "namespace"
// QoSClass of the object.
KeyQOSClass = "qosclass"
// Labels of the object.
KeyLabels = "labels"
// Tags of the object.
KeyTags = "tags"
)
42 changes: 42 additions & 0 deletions pkg/apis/resmgr/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/resmgr/cache/affinity.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import (

"sigs.k8s.io/yaml"

resmgr "github.com/containers/nri-plugins/pkg/apis/resmgr/v1alpha1"
"github.com/containers/nri-plugins/pkg/kubernetes"
resmgr "github.com/containers/nri-plugins/pkg/resmgr/apis"
)

const (
Expand Down
2 changes: 1 addition & 1 deletion pkg/resmgr/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ import (

"github.com/containers/nri-plugins/pkg/utils/cpuset"

resmgr "github.com/containers/nri-plugins/pkg/apis/resmgr/v1alpha1"
"github.com/containers/nri-plugins/pkg/kubernetes"
logger "github.com/containers/nri-plugins/pkg/log"
resmgr "github.com/containers/nri-plugins/pkg/resmgr/apis"
"github.com/containers/nri-plugins/pkg/topology"
)

Expand Down
2 changes: 1 addition & 1 deletion pkg/resmgr/cache/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ import (
"strconv"
"strings"

resmgr "github.com/containers/nri-plugins/pkg/apis/resmgr/v1alpha1"
"github.com/containers/nri-plugins/pkg/cgroups"
"github.com/containers/nri-plugins/pkg/kubernetes"
resmgr "github.com/containers/nri-plugins/pkg/resmgr/apis"
"github.com/containers/nri-plugins/pkg/topology"

nri "github.com/containerd/nri/pkg/api"
Expand Down
2 changes: 1 addition & 1 deletion pkg/resmgr/cache/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ import (
nri "github.com/containerd/nri/pkg/api"
v1 "k8s.io/api/core/v1"

resmgr "github.com/containers/nri-plugins/pkg/apis/resmgr/v1alpha1"
"github.com/containers/nri-plugins/pkg/cgroups"
"github.com/containers/nri-plugins/pkg/kubernetes"
resmgr "github.com/containers/nri-plugins/pkg/resmgr/apis"
)

// Create and initialize a cached pod.
Expand Down

0 comments on commit e8fe97e

Please sign in to comment.