Merge pull request #110263 from claudiubelu/unittests

unittests: Fixes unit tests for Windows
This commit is contained in:
Kubernetes Prow Robot 2022-10-25 14:50:34 -07:00 committed by GitHub
commit 244c035b87
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 175 additions and 46 deletions

View File

@ -351,6 +351,13 @@ func loadConfigFile(name string) (*kubeletconfiginternal.KubeletConfiguration, e
if err != nil {
return nil, fmt.Errorf(errFmt, name, err)
}
// EvictionHard may be nil if it was not set in kubelet's config file.
// EvictionHard can have OS-specific fields, which is why there's no default value for it.
// See: https://github.com/kubernetes/kubernetes/pull/110263
if kc.EvictionHard == nil {
kc.EvictionHard = eviction.DefaultEvictionHard
}
return kc, err
}

View File

@ -28,6 +28,7 @@ import (
"k8s.io/kubernetes/pkg/cluster/ports"
kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/config/v1beta1"
"k8s.io/kubernetes/pkg/kubelet/eviction"
"k8s.io/kubernetes/pkg/kubelet/qos"
kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
utilpointer "k8s.io/utils/pointer"
@ -91,7 +92,7 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
obj.KubeAPIQPS = 5
obj.KubeAPIBurst = 10
obj.HairpinMode = v1beta1.PromiscuousBridge
obj.EvictionHard = kubeletconfigv1beta1.DefaultEvictionHard
obj.EvictionHard = eviction.DefaultEvictionHard
obj.EvictionPressureTransitionPeriod = metav1.Duration{Duration: 5 * time.Minute}
obj.MakeIPTablesUtilChains = true
obj.IPTablesMasqueradeBit = kubeletconfigv1beta1.DefaultIPTablesMasqueradeBit

View File

@ -32,11 +32,6 @@ enforceNodeAllocatable:
- pods
eventBurst: 10
eventRecordQPS: 5
evictionHard:
imagefs.available: 15%
memory.available: 100Mi
nodefs.available: 10%
nodefs.inodesFree: 5%
evictionPressureTransitionPeriod: 5m0s
failSwapOn: true
fileCheckFrequency: 20s

View File

@ -32,11 +32,6 @@ enforceNodeAllocatable:
- pods
eventBurst: 10
eventRecordQPS: 5
evictionHard:
imagefs.available: 15%
memory.available: 100Mi
nodefs.available: 10%
nodefs.inodesFree: 5%
evictionPressureTransitionPeriod: 5m0s
failSwapOn: true
fileCheckFrequency: 20s

View File

@ -289,6 +289,7 @@ type KubeletConfiguration struct {
// serializeImagePulls when enabled, tells the Kubelet to pull images one at a time.
SerializeImagePulls bool
// Map of signal names to quantities that defines hard eviction thresholds. For example: {"memory.available": "300Mi"}.
// Some default signals are Linux only: nodefs.inodesFree
EvictionHard map[string]string
// Map of signal names to quantities that defines soft eviction thresholds. For example: {"memory.available": "300Mi"}.
EvictionSoft map[string]string

View File

@ -208,9 +208,6 @@ func SetDefaults_KubeletConfiguration(obj *kubeletconfigv1beta1.KubeletConfigura
if obj.SerializeImagePulls == nil {
obj.SerializeImagePulls = utilpointer.BoolPtr(true)
}
if obj.EvictionHard == nil {
obj.EvictionHard = DefaultEvictionHard
}
if obj.EvictionPressureTransitionPeriod == zeroDuration {
obj.EvictionPressureTransitionPeriod = metav1.Duration{Duration: 5 * time.Minute}
}

View File

@ -99,7 +99,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) {
KubeAPIQPS: utilpointer.Int32Ptr(5),
KubeAPIBurst: 10,
SerializeImagePulls: utilpointer.BoolPtr(true),
EvictionHard: DefaultEvictionHard,
EvictionHard: nil,
EvictionPressureTransitionPeriod: metav1.Duration{Duration: 5 * time.Minute},
EnableControllerAttachDetach: utilpointer.BoolPtr(true),
MakeIPTablesUtilChains: utilpointer.BoolPtr(true),
@ -698,7 +698,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) {
KubeAPIQPS: utilpointer.Int32Ptr(5),
KubeAPIBurst: 10,
SerializeImagePulls: utilpointer.BoolPtr(true),
EvictionHard: DefaultEvictionHard,
EvictionHard: nil,
EvictionPressureTransitionPeriod: metav1.Duration{Duration: 5 * time.Minute},
EnableControllerAttachDetach: utilpointer.BoolPtr(true),
MakeIPTablesUtilChains: utilpointer.BoolPtr(true),

View File

@ -0,0 +1,25 @@
//go:build !windows
// +build !windows
/*
Copyright 2022 The Kubernetes Authors.
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 validation_test
var (
cgroupsPerQOS = true
enforceNodeAllocatable = []string{"pods", "system-reserved", "kube-reserved"}
)

View File

@ -34,8 +34,8 @@ import (
var (
successConfig = kubeletconfig.KubeletConfiguration{
CgroupsPerQOS: true,
EnforceNodeAllocatable: []string{"pods", "system-reserved", "kube-reserved"},
CgroupsPerQOS: cgroupsPerQOS,
EnforceNodeAllocatable: enforceNodeAllocatable,
SystemReservedCgroup: "/system.slice",
KubeReservedCgroup: "/kubelet.service",
SystemCgroups: "",

View File

@ -0,0 +1,26 @@
//go:build windows
// +build windows
/*
Copyright 2022 The Kubernetes Authors.
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 validation_test
var (
// These config options are not supported on Windows.
cgroupsPerQOS = false
enforceNodeAllocatable = []string{}
)

View File

@ -21,6 +21,7 @@ import (
"fmt"
"io"
"os"
"path/filepath"
"reflect"
"testing"
@ -104,6 +105,8 @@ users:
if err != nil {
t.Fatal(err)
}
// os.CreateTemp also opens the file, and removing it without closing it will result in a failure.
defer filevalid.Close()
os.WriteFile(filevalid.Name(), testDataValid, os.FileMode(0755))
testDataInvalid := []byte(`
@ -144,6 +147,7 @@ users:
if err != nil {
t.Fatal(err)
}
defer fileinvalid.Close()
os.WriteFile(fileinvalid.Name(), testDataInvalid, os.FileMode(0755))
testDatabootstrap := []byte(`
@ -181,6 +185,7 @@ users:
if err != nil {
t.Fatal(err)
}
defer fileboot.Close()
os.WriteFile(fileboot.Name(), testDatabootstrap, os.FileMode(0755))
dir, err := os.MkdirTemp(fileDir, "k8s-test-certstore-current")
@ -209,16 +214,16 @@ users:
expectedCertConfig: &restclient.Config{
Host: "https://cluster-b.com",
TLSClientConfig: restclient.TLSClientConfig{
CertFile: fileDir + "/mycertvalid.crt",
KeyFile: fileDir + "/mycertvalid.key",
CertFile: filepath.Join(fileDir, "mycertvalid.crt"),
KeyFile: filepath.Join(fileDir, "mycertvalid.key"),
},
BearerToken: "",
},
expectedClientConfig: &restclient.Config{
Host: "https://cluster-b.com",
TLSClientConfig: restclient.TLSClientConfig{
CertFile: fileDir + "/mycertvalid.crt",
KeyFile: fileDir + "/mycertvalid.key",
CertFile: filepath.Join(fileDir, "mycertvalid.crt"),
KeyFile: filepath.Join(fileDir, "mycertvalid.key"),
},
BearerToken: "",
},
@ -231,16 +236,16 @@ users:
expectedCertConfig: &restclient.Config{
Host: "https://cluster-b.com",
TLSClientConfig: restclient.TLSClientConfig{
CertFile: fileDir + "/mycertvalid.crt",
KeyFile: fileDir + "/mycertvalid.key",
CertFile: filepath.Join(fileDir, "mycertvalid.crt"),
KeyFile: filepath.Join(fileDir, "mycertvalid.key"),
},
BearerToken: "",
},
expectedClientConfig: &restclient.Config{
Host: "https://cluster-b.com",
TLSClientConfig: restclient.TLSClientConfig{
CertFile: fileDir + "/mycertvalid.crt",
KeyFile: fileDir + "/mycertvalid.key",
CertFile: filepath.Join(fileDir, "mycertvalid.crt"),
KeyFile: filepath.Join(fileDir, "mycertvalid.key"),
},
BearerToken: "",
},

View File

@ -627,7 +627,7 @@ func TestCPUManagerGenerate(t *testing.T) {
if testCase.isTopologyBroken {
machineInfo = &cadvisorapi.MachineInfo{}
}
sDir, err := os.MkdirTemp("/tmp/", "cpu_manager_test")
sDir, err := os.MkdirTemp("", "cpu_manager_test")
if err != nil {
t.Errorf("cannot create state file: %s", err.Error())
}
@ -1347,7 +1347,7 @@ func TestCPUManagerHandlePolicyOptions(t *testing.T) {
t.Run(testCase.description, func(t *testing.T) {
machineInfo := &mockedMachineInfo
nodeAllocatableReservation := v1.ResourceList{}
sDir, err := os.MkdirTemp("/tmp/", "cpu_manager_test")
sDir, err := os.MkdirTemp("", "cpu_manager_test")
if err != nil {
t.Errorf("cannot create state file: %s", err.Error())
}

View File

@ -18,6 +18,7 @@ package devicemanager
import (
"fmt"
"os"
"path"
"sync"
"testing"
@ -71,7 +72,7 @@ func esocketName() string {
}
func TestNewEndpoint(t *testing.T) {
socket := path.Join("/tmp", esocketName())
socket := path.Join(os.TempDir(), esocketName())
devs := []*pluginapi.Device{
{ID: "ADeviceId", Health: pluginapi.Healthy},
@ -82,7 +83,7 @@ func TestNewEndpoint(t *testing.T) {
}
func TestRun(t *testing.T) {
socket := path.Join("/tmp", esocketName())
socket := path.Join(os.TempDir(), esocketName())
devs := []*pluginapi.Device{
{ID: "ADeviceId", Health: pluginapi.Healthy},
@ -147,7 +148,7 @@ func TestRun(t *testing.T) {
}
func TestAllocate(t *testing.T) {
socket := path.Join("/tmp", esocketName())
socket := path.Join(os.TempDir(), esocketName())
devs := []*pluginapi.Device{
{ID: "ADeviceId", Health: pluginapi.Healthy},
}
@ -200,7 +201,7 @@ func TestAllocate(t *testing.T) {
}
func TestGetPreferredAllocation(t *testing.T) {
socket := path.Join("/tmp", esocketName())
socket := path.Join(os.TempDir(), esocketName())
callbackCount := 0
callbackChan := make(chan int)
p, e := esetup(t, []*pluginapi.Device{}, socket, "mock", func(n string, d []pluginapi.Device) {

View File

@ -1981,7 +1981,7 @@ func TestNewManager(t *testing.T) {
}
for _, testCase := range testCases {
t.Run(testCase.description, func(t *testing.T) {
stateFileDirectory, err := os.MkdirTemp("/tmp/", "memory_manager_tests")
stateFileDirectory, err := os.MkdirTemp("", "memory_manager_tests")
if err != nil {
t.Errorf("Cannot create state file: %s", err.Error())
}

View File

@ -17,7 +17,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
package eviction
// DefaultEvictionHard includes default options for hard eviction.
var DefaultEvictionHard = map[string]string{

View File

@ -17,7 +17,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
package eviction
// DefaultEvictionHard includes default options for hard eviction.
var DefaultEvictionHard = map[string]string{

View File

@ -462,7 +462,9 @@ func TestFreeSpaceRemoveByLeastRecentlyUsed(t *testing.T) {
require.NoError(t, err)
require.Equal(t, manager.imageRecordsLen(), 2)
spaceFreed, err := manager.freeSpace(1024, time.Now())
// We're setting the delete time one minute in the future, so the time the image
// was first detected and the delete time are different.
spaceFreed, err := manager.freeSpace(1024, time.Now().Add(time.Minute))
assert := assert.New(t)
require.NoError(t, err)
assert.EqualValues(1024, spaceFreed)

View File

@ -17,9 +17,12 @@ limitations under the License.
package kubelet
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1"
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
"k8s.io/kubernetes/pkg/volume/util/hostutil"
@ -84,7 +87,11 @@ func TestMakeMountsWindows(t *testing.T) {
fhu := hostutil.NewFakeHostUtil(nil)
fsp := &subpath.FakeSubpath{}
mounts, _, _ := makeMounts(&pod, "/pod", &container, "fakepodname", "", []string{""}, podVolumes, fhu, fsp, nil)
podDir, err := os.MkdirTemp("", "test-rotate-logs")
require.NoError(t, err)
defer os.RemoveAll(podDir)
mounts, _, err := makeMounts(&pod, podDir, &container, "fakepodname", "", []string{""}, podVolumes, fhu, fsp, nil)
require.NoError(t, err)
expectedMounts := []kubecontainer.Mount{
{
@ -136,6 +143,13 @@ func TestMakeMountsWindows(t *testing.T) {
ReadOnly: false,
SELinuxRelabel: false,
},
{
Name: "k8s-managed-etc-hosts",
ContainerPath: `C:\Windows\System32\drivers\etc\hosts`,
HostPath: filepath.Join(podDir, "etc-hosts"),
ReadOnly: false,
SELinuxRelabel: true,
},
}
assert.Equal(t, expectedMounts, mounts, "mounts of container %+v", container)
}

View File

@ -57,10 +57,11 @@ func (f *file) write(fs utilfs.Filesystem, dir string) error {
return err
}
_, err = handle.Write([]byte(f.data))
// The file should always be closed, not just in error cases.
if cerr := handle.Close(); cerr != nil {
return fmt.Errorf("error closing file: %v", cerr)
}
if err != nil {
if cerr := handle.Close(); cerr != nil {
return fmt.Errorf("error %v closing file after error: %v", cerr, err)
}
return err
}
} else {
@ -195,12 +196,12 @@ func TestHelpers(t *testing.T) {
{
desc: "missing file",
expects: []file{{name: "foo", data: "bar"}},
err: "no such file or directory",
err: missingFileError,
},
{
desc: "missing directory",
expects: []file{{name: "foo/bar", mode: os.ModeDir}},
err: "no such file or directory",
err: missingFolderError,
},
}
for _, c := range cases {
@ -312,7 +313,7 @@ func TestReplaceFile(t *testing.T) {
return nil
},
desc: "neither parent nor file exists",
err: "no such file or directory",
err: missingFileError,
},
}
for _, c := range cases {

View File

@ -0,0 +1,25 @@
//go:build !windows
// +build !windows
/*
Copyright 2022 The Kubernetes Authors.
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 files
const (
missingFileError = "no such file or directory"
missingFolderError = "no such file or directory"
)

View File

@ -0,0 +1,25 @@
//go:build windows
// +build windows
/*
Copyright 2022 The Kubernetes Authors.
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 files
const (
missingFileError = "The system cannot find the file specified."
missingFolderError = "The system cannot find the path specified."
)

View File

@ -70,6 +70,7 @@ func TestRemoveContainer(t *testing.T) {
fakeOS := m.osInterface.(*containertest.FakeOS)
fakeOS.GlobFn = func(pattern, path string) bool {
pattern = strings.Replace(pattern, "*", ".*", -1)
pattern = strings.Replace(pattern, "\\", "\\\\", -1)
return regexp.MustCompile(pattern).MatchString(path)
}
expectedContainerLogPath := filepath.Join(podLogsRootDirectory, "new_bar_12345678", "foo", "0.log")

View File

@ -328,6 +328,7 @@ func TestCompressLog(t *testing.T) {
testContent := "test log content"
_, err = testFile.Write([]byte(testContent))
require.NoError(t, err)
testFile.Close()
testLog := testFile.Name()
c := &containerLogManager{osInterface: container.RealOS{}}
@ -388,6 +389,7 @@ func TestRotateLatestLog(t *testing.T) {
}
testFile, err := os.CreateTemp(dir, "test-rotate-latest-log")
require.NoError(t, err)
testFile.Close()
defer testFile.Close()
testLog := testFile.Name()
rotatedLog := fmt.Sprintf("%s.%s", testLog, now.Format(timestampFormat))

View File

@ -67,12 +67,14 @@ func TestSummaryProvider(t *testing.T) {
mockStatsProvider.EXPECT().RlimitStats().Return(nil, nil).AnyTimes()
mockStatsProvider.EXPECT().GetCgroupStats("/", true).Return(cgroupStatsMap["/"].cs, cgroupStatsMap["/"].ns, nil).AnyTimes()
provider := NewSummaryProvider(mockStatsProvider)
kubeletCreationTime := metav1.Now()
systemBootTime := metav1.Now()
provider := summaryProviderImpl{kubeletCreationTime: kubeletCreationTime, systemBootTime: systemBootTime, provider: mockStatsProvider}
summary, err := provider.Get(true)
assert.NoError(err)
assert.Equal(summary.Node.NodeName, "test-node")
assert.Equal(summary.Node.StartTime, cgroupStatsMap["/"].cs.StartTime)
assert.Equal(summary.Node.StartTime, systemBootTime)
assert.Equal(summary.Node.CPU, cgroupStatsMap["/"].cs.CPU)
assert.Equal(summary.Node.Memory, cgroupStatsMap["/"].cs.Memory)
assert.Equal(summary.Node.Network, cgroupStatsMap["/"].ns)

View File

@ -1319,7 +1319,11 @@ func TestDoNotDeleteMirrorPods(t *testing.T) {
}
func TestUpdateLastTransitionTime(t *testing.T) {
old := metav1.Now()
// On Windows, time.Now() is not as precise, which means that 2 consecutive calls may
// return the same timestamp. This test expects the old timestamp to be updated with a
// newer one, so we set the old timestamp to one second in the past.
// See: https://github.com/golang/go/issues/8687
old := metav1.NewTime(time.Now().Add(-time.Second))
for desc, test := range map[string]struct {
condition *v1.PodCondition
oldCondition *v1.PodCondition