mirror of
https://github.com/intel/intel-device-plugins-for-kubernetes.git
synced 2025-06-03 03:59:37 +00:00

klog has added ktesting/textlogger and is going to deprecate klogr. The deprecation is going to trigger golangci-lint (staticcheck) errors so rework the logging and move to ktesting/textlogger. The commit also fixes the loglevel setting with operator. Signed-off-by: Mikko Ylinen <mikko.ylinen@intel.com>
521 lines
14 KiB
Go
521 lines
14 KiB
Go
// Copyright 2018 Intel Corporation. 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 patcher
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
"k8s.io/apimachinery/pkg/api/resource"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
ctrl "sigs.k8s.io/controller-runtime"
|
|
|
|
fpgav2 "github.com/intel/intel-device-plugins-for-kubernetes/pkg/apis/fpga/v2"
|
|
"k8s.io/klog/v2/ktesting"
|
|
)
|
|
|
|
func checkExpectedError(t *testing.T, expectedErr bool, err error, testName string) {
|
|
t.Helper()
|
|
|
|
if expectedErr && err == nil {
|
|
t.Errorf("Test case '%s': no error returned", testName)
|
|
}
|
|
|
|
if !expectedErr && err != nil {
|
|
t.Errorf("Test case '%s': unexpected error: %+v", testName, err)
|
|
}
|
|
}
|
|
|
|
func TestPatcherStorageFunctions(t *testing.T) {
|
|
goodAf := &fpgav2.AcceleratorFunction{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "arria10-nlb0",
|
|
},
|
|
Spec: fpgav2.AcceleratorFunctionSpec{
|
|
AfuID: "d8424dc4a4a3c413f89e433683f9040b",
|
|
InterfaceID: "ce48969398f05f33946d560708be108a",
|
|
Mode: af,
|
|
},
|
|
}
|
|
brokenAf := &fpgav2.AcceleratorFunction{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "arria10-nlb0",
|
|
},
|
|
Spec: fpgav2.AcceleratorFunctionSpec{
|
|
AfuID: "wrong string",
|
|
InterfaceID: "wrong string",
|
|
Mode: af,
|
|
},
|
|
}
|
|
region := &fpgav2.FpgaRegion{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "arria10",
|
|
},
|
|
Spec: fpgav2.FpgaRegionSpec{
|
|
InterfaceID: "ce48969398f05f33946d560708be108a",
|
|
},
|
|
}
|
|
regionAlias := &fpgav2.FpgaRegion{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "arria10-alias",
|
|
},
|
|
Spec: fpgav2.FpgaRegionSpec{
|
|
InterfaceID: "ce48969398f05f33946d560708be108a",
|
|
},
|
|
}
|
|
|
|
tcases := []struct {
|
|
name string
|
|
afsToAdd []*fpgav2.AcceleratorFunction
|
|
afsToRemove []*fpgav2.AcceleratorFunction
|
|
regionsToAdd []*fpgav2.FpgaRegion
|
|
regionsToRemove []*fpgav2.FpgaRegion
|
|
expectedResourceModeMapSize int
|
|
expectedResourceMapSize int
|
|
expectedIdentitySetSize int
|
|
expectedErr bool
|
|
}{
|
|
{
|
|
name: "Add one good af",
|
|
afsToAdd: []*fpgav2.AcceleratorFunction{goodAf},
|
|
expectedResourceModeMapSize: 1,
|
|
expectedResourceMapSize: 1,
|
|
expectedIdentitySetSize: 1,
|
|
},
|
|
{
|
|
name: "Add one broken af",
|
|
afsToAdd: []*fpgav2.AcceleratorFunction{brokenAf},
|
|
expectedErr: true,
|
|
},
|
|
{
|
|
name: "Add one and remove one good af",
|
|
afsToAdd: []*fpgav2.AcceleratorFunction{goodAf},
|
|
afsToRemove: []*fpgav2.AcceleratorFunction{goodAf},
|
|
},
|
|
{
|
|
name: "Add one good region",
|
|
regionsToAdd: []*fpgav2.FpgaRegion{region},
|
|
expectedResourceModeMapSize: 1,
|
|
expectedResourceMapSize: 1,
|
|
expectedIdentitySetSize: 1,
|
|
},
|
|
{
|
|
name: "Add one and remove one good region",
|
|
regionsToAdd: []*fpgav2.FpgaRegion{region},
|
|
regionsToRemove: []*fpgav2.FpgaRegion{region},
|
|
},
|
|
{
|
|
name: "Add one region and one alias then remove one alias",
|
|
regionsToAdd: []*fpgav2.FpgaRegion{region, regionAlias},
|
|
regionsToRemove: []*fpgav2.FpgaRegion{region},
|
|
expectedResourceModeMapSize: 1,
|
|
expectedResourceMapSize: 1,
|
|
expectedIdentitySetSize: 1,
|
|
},
|
|
{
|
|
name: "Add one region and one alias",
|
|
regionsToAdd: []*fpgav2.FpgaRegion{region, regionAlias},
|
|
expectedResourceModeMapSize: 2,
|
|
expectedResourceMapSize: 2,
|
|
expectedIdentitySetSize: 1,
|
|
},
|
|
{
|
|
name: "Add one region and one alias then remove all",
|
|
regionsToAdd: []*fpgav2.FpgaRegion{region, regionAlias},
|
|
regionsToRemove: []*fpgav2.FpgaRegion{region, regionAlias},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tcases {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
logger, _ := ktesting.NewTestContext(t)
|
|
p := newPatcher(logger)
|
|
for _, af := range tt.afsToAdd {
|
|
err := p.AddAf(af)
|
|
checkExpectedError(t, tt.expectedErr, err, tt.name)
|
|
}
|
|
for _, reg := range tt.regionsToAdd {
|
|
p.AddRegion(reg)
|
|
}
|
|
for _, af := range tt.afsToRemove {
|
|
p.RemoveAf(af.Name)
|
|
}
|
|
for _, reg := range tt.regionsToRemove {
|
|
p.RemoveRegion(reg.Name)
|
|
}
|
|
if tt.expectedResourceModeMapSize != len(p.resourceModeMap) {
|
|
t.Errorf("wrong size of resourceModeMap. Expected %d, but got %d", tt.expectedResourceModeMapSize, len(p.resourceModeMap))
|
|
}
|
|
if tt.expectedResourceMapSize != len(p.resourceMap) {
|
|
t.Errorf("wrong size of resourceMap. Expected %d, but got %d", tt.expectedResourceMapSize, len(p.resourceMap))
|
|
}
|
|
if tt.expectedIdentitySetSize != len(p.identitySet) {
|
|
t.Errorf("wrong size of identitySet. Expected %d, but got %d", tt.expectedIdentitySetSize, len(p.identitySet))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSanitizeContainerEnv(t *testing.T) {
|
|
tcases := []struct {
|
|
name string
|
|
container corev1.Container
|
|
expectedContainer corev1.Container
|
|
}{
|
|
{
|
|
name: "Container OK",
|
|
container: corev1.Container{},
|
|
expectedContainer: corev1.Container{},
|
|
},
|
|
{
|
|
name: "Wrong ENV FPGA_AFU",
|
|
container: corev1.Container{
|
|
Env: []corev1.EnvVar{
|
|
{
|
|
Name: "FPGA_AFU",
|
|
Value: "fake value",
|
|
},
|
|
},
|
|
},
|
|
expectedContainer: corev1.Container{},
|
|
},
|
|
{
|
|
name: "Wrong ENV FPGA_REGION",
|
|
container: corev1.Container{
|
|
Env: []corev1.EnvVar{
|
|
{
|
|
Name: "FPGA_REGION",
|
|
Value: "fake value",
|
|
},
|
|
},
|
|
},
|
|
expectedContainer: corev1.Container{},
|
|
},
|
|
{
|
|
name: "Wrong ENV FPGA_REGION and unrelated env var",
|
|
container: corev1.Container{
|
|
Env: []corev1.EnvVar{
|
|
{
|
|
Name: "FPGA_REGION",
|
|
Value: "fake value",
|
|
},
|
|
{
|
|
Name: "FAKE_VAR",
|
|
Value: "fake value",
|
|
},
|
|
},
|
|
},
|
|
expectedContainer: corev1.Container{
|
|
Env: []corev1.EnvVar{
|
|
{
|
|
Name: "FAKE_VAR",
|
|
Value: "fake value",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tcases {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
c := sanitizeContainer(tt.container)
|
|
if tt.expectedContainer.Env != nil && !reflect.DeepEqual(c.Env, tt.expectedContainer.Env) {
|
|
t.Errorf("Got wrong container Env %+v instead of expected %+v", c.Env, tt.expectedContainer.Env)
|
|
}
|
|
if tt.expectedContainer.Env == nil && c.Env != nil {
|
|
t.Errorf("Got wrong container Env %+v instead of expected 'nil'", c.Env)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetPatchOps(t *testing.T) {
|
|
tcases := []struct {
|
|
name string
|
|
container corev1.Container
|
|
afs []*fpgav2.AcceleratorFunction
|
|
regions []*fpgav2.FpgaRegion
|
|
expectedErr bool
|
|
expectedOps int
|
|
}{
|
|
{
|
|
name: "Successful handling for region mode",
|
|
container: corev1.Container{
|
|
Resources: corev1.ResourceRequirements{
|
|
Limits: corev1.ResourceList{
|
|
"fpga.intel.com/arria10-nlb0": resource.MustParse("1"),
|
|
"fpga.intel.com/arria10-nlb0-alias": resource.MustParse("2"),
|
|
"cpu": resource.MustParse("1"),
|
|
},
|
|
Requests: corev1.ResourceList{
|
|
"fpga.intel.com/arria10-nlb0": resource.MustParse("1"),
|
|
"fpga.intel.com/arria10-nlb0-alias": resource.MustParse("2"),
|
|
"cpu": resource.MustParse("3"),
|
|
},
|
|
},
|
|
Env: []corev1.EnvVar{
|
|
{
|
|
Name: "SOME_VAR",
|
|
Value: "fake value",
|
|
},
|
|
},
|
|
},
|
|
afs: []*fpgav2.AcceleratorFunction{
|
|
{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "arria10-nlb0",
|
|
},
|
|
Spec: fpgav2.AcceleratorFunctionSpec{
|
|
AfuID: "d8424dc4a4a3c413f89e433683f9040b",
|
|
InterfaceID: "ce48969398f05f33946d560708be108a",
|
|
Mode: region,
|
|
},
|
|
},
|
|
{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "arria10-nlb0-alias",
|
|
},
|
|
Spec: fpgav2.AcceleratorFunctionSpec{
|
|
AfuID: "d8424dc4a4a3c413f89e433683f9040b",
|
|
InterfaceID: "ce48969398f05f33946d560708be108a",
|
|
Mode: region,
|
|
},
|
|
},
|
|
},
|
|
expectedOps: 7,
|
|
},
|
|
{
|
|
name: "Successful handling for af mode",
|
|
container: corev1.Container{
|
|
Resources: corev1.ResourceRequirements{
|
|
Limits: corev1.ResourceList{
|
|
"fpga.intel.com/arria10-nlb0": resource.MustParse("1"),
|
|
},
|
|
Requests: corev1.ResourceList{
|
|
"fpga.intel.com/arria10-nlb0": resource.MustParse("1"),
|
|
},
|
|
},
|
|
},
|
|
afs: []*fpgav2.AcceleratorFunction{
|
|
{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "arria10-nlb0",
|
|
},
|
|
Spec: fpgav2.AcceleratorFunctionSpec{
|
|
AfuID: "d8424dc4a4a3c413f89e433683f9040b",
|
|
InterfaceID: "ce48969398f05f33946d560708be108a",
|
|
Mode: af,
|
|
},
|
|
},
|
|
},
|
|
expectedOps: 4,
|
|
},
|
|
{
|
|
name: "Skip handling for an identity mapping",
|
|
container: corev1.Container{
|
|
Resources: corev1.ResourceRequirements{
|
|
Limits: corev1.ResourceList{
|
|
"fpga.intel.com/af-ce4.d84.zkiWk5jwXzOUbVYHCL4QithCTcSko8QT-J5DNoP5BAs": resource.MustParse("1"),
|
|
},
|
|
Requests: corev1.ResourceList{
|
|
"fpga.intel.com/af-ce4.d84.zkiWk5jwXzOUbVYHCL4QithCTcSko8QT-J5DNoP5BAs": resource.MustParse("1"),
|
|
},
|
|
},
|
|
},
|
|
afs: []*fpgav2.AcceleratorFunction{
|
|
{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "arria10-nlb0",
|
|
},
|
|
Spec: fpgav2.AcceleratorFunctionSpec{
|
|
AfuID: "d8424dc4a4a3c413f89e433683f9040b",
|
|
InterfaceID: "ce48969398f05f33946d560708be108a",
|
|
Mode: af,
|
|
},
|
|
},
|
|
{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "arria10-nlb0-alias",
|
|
},
|
|
Spec: fpgav2.AcceleratorFunctionSpec{
|
|
AfuID: "d8424dc4a4a3c413f89e433683f9040b",
|
|
InterfaceID: "ce48969398f05f33946d560708be108a",
|
|
Mode: af,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "Successful handling for regiondevel mode",
|
|
container: corev1.Container{
|
|
Resources: corev1.ResourceRequirements{
|
|
Limits: corev1.ResourceList{
|
|
"fpga.intel.com/arria10": resource.MustParse("1"),
|
|
},
|
|
Requests: corev1.ResourceList{
|
|
"fpga.intel.com/arria10": resource.MustParse("1"),
|
|
},
|
|
},
|
|
},
|
|
regions: []*fpgav2.FpgaRegion{
|
|
{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "arria10",
|
|
},
|
|
Spec: fpgav2.FpgaRegionSpec{
|
|
InterfaceID: "ce48969398f05f33946d560708be108a",
|
|
},
|
|
},
|
|
},
|
|
expectedOps: 4,
|
|
},
|
|
{
|
|
name: "Unequal FPGA resources in Limits and Requests 1",
|
|
container: corev1.Container{
|
|
Resources: corev1.ResourceRequirements{
|
|
Limits: corev1.ResourceList{
|
|
"fpga.intel.com/arria10-nlb0": resource.MustParse("1"),
|
|
"fpga.intel.com/arria10-nlb3": resource.MustParse("2"),
|
|
},
|
|
},
|
|
},
|
|
expectedErr: true,
|
|
},
|
|
{
|
|
name: "Unequal FPGA resources in Limits and Requests 2",
|
|
container: corev1.Container{
|
|
Resources: corev1.ResourceRequirements{
|
|
Requests: corev1.ResourceList{
|
|
"fpga.intel.com/arria10-nlb0": resource.MustParse("1"),
|
|
"fpga.intel.com/arria10-nlb3": resource.MustParse("2"),
|
|
},
|
|
},
|
|
},
|
|
expectedErr: true,
|
|
},
|
|
{
|
|
name: "Unknown FPGA resources in container requirements",
|
|
container: corev1.Container{
|
|
Resources: corev1.ResourceRequirements{
|
|
Requests: corev1.ResourceList{
|
|
"fpga.intel.com/unknown-nlb0": resource.MustParse("1"),
|
|
},
|
|
Limits: corev1.ResourceList{
|
|
"fpga.intel.com/unknown-nlb0": resource.MustParse("1"),
|
|
},
|
|
},
|
|
},
|
|
expectedErr: true,
|
|
},
|
|
{
|
|
name: "Wrong type of quantity",
|
|
container: corev1.Container{
|
|
Resources: corev1.ResourceRequirements{
|
|
Limits: corev1.ResourceList{
|
|
"fpga.intel.com/arria10-nlb0": resource.MustParse("1.1"),
|
|
},
|
|
Requests: corev1.ResourceList{
|
|
"fpga.intel.com/arria10-nlb0": resource.MustParse("1.1"),
|
|
},
|
|
},
|
|
},
|
|
expectedErr: true,
|
|
},
|
|
{
|
|
name: "Require resources operated in af and region modes",
|
|
container: corev1.Container{
|
|
Resources: corev1.ResourceRequirements{
|
|
Limits: corev1.ResourceList{
|
|
"fpga.intel.com/arria10-nlb0": resource.MustParse("1"),
|
|
"fpga.intel.com/arria10-nlb3": resource.MustParse("2"),
|
|
"cpu": resource.MustParse("1"),
|
|
},
|
|
Requests: corev1.ResourceList{
|
|
"fpga.intel.com/arria10-nlb0": resource.MustParse("1"),
|
|
"fpga.intel.com/arria10-nlb3": resource.MustParse("2"),
|
|
"cpu": resource.MustParse("3"),
|
|
},
|
|
},
|
|
},
|
|
afs: []*fpgav2.AcceleratorFunction{
|
|
{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "arria10-nlb0",
|
|
},
|
|
Spec: fpgav2.AcceleratorFunctionSpec{
|
|
AfuID: "d8424dc4a4a3c413f89e433683f9040b",
|
|
InterfaceID: "ce48969398f05f33946d560708be108a",
|
|
Mode: region,
|
|
},
|
|
},
|
|
{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "arria10-nlb3",
|
|
},
|
|
Spec: fpgav2.AcceleratorFunctionSpec{
|
|
AfuID: "d8424dc4a4a3c413f89e433683f9040b",
|
|
InterfaceID: "f7df405cbd7acf7222f144b0b93acd18",
|
|
Mode: af,
|
|
},
|
|
},
|
|
},
|
|
expectedErr: true,
|
|
},
|
|
{
|
|
name: "Unknown mode",
|
|
container: corev1.Container{
|
|
Resources: corev1.ResourceRequirements{
|
|
Limits: corev1.ResourceList{
|
|
"fpga.intel.com/arria10-nlb0": resource.MustParse("1"),
|
|
},
|
|
Requests: corev1.ResourceList{
|
|
"fpga.intel.com/arria10-nlb0": resource.MustParse("1"),
|
|
},
|
|
},
|
|
},
|
|
afs: []*fpgav2.AcceleratorFunction{
|
|
{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "arria10-nlb0",
|
|
},
|
|
Spec: fpgav2.AcceleratorFunctionSpec{
|
|
AfuID: "d8424dc4a4a3c413f89e433683f9040b",
|
|
InterfaceID: "ce48969398f05f33946d560708be108a",
|
|
Mode: "unknown",
|
|
},
|
|
},
|
|
},
|
|
expectedErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tcases {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
p := newPatcher(ctrl.Log.WithName("test"))
|
|
for _, af := range tt.afs {
|
|
_ = p.AddAf(af)
|
|
}
|
|
for _, region := range tt.regions {
|
|
p.AddRegion(region)
|
|
}
|
|
ops, err := p.getPatchOps(0, tt.container)
|
|
checkExpectedError(t, tt.expectedErr, err, tt.name)
|
|
if len(ops) != tt.expectedOps {
|
|
t.Errorf("test case '%s': expected %d ops, but got %d\n%v", tt.name, tt.expectedOps, len(ops), ops)
|
|
}
|
|
})
|
|
}
|
|
}
|