From de1063bc7ddb41c7ee3d1dd3504ff468549744c1 Mon Sep 17 00:00:00 2001 From: Klaudiusz Dembler Date: Mon, 21 May 2018 14:50:31 +0200 Subject: [PATCH] Add compatibility tests --- pkg/kubelet/cm/cpumanager/cpu_manager.go | 6 +- .../cm/cpumanager/state/state_checkpoint.go | 13 ++-- .../cpumanager/state/state_checkpoint_test.go | 23 +++--- .../state/state_compatibility_test.go | 78 +++++++++++++++++++ 4 files changed, 100 insertions(+), 20 deletions(-) create mode 100644 pkg/kubelet/cm/cpumanager/state/state_compatibility_test.go diff --git a/pkg/kubelet/cm/cpumanager/cpu_manager.go b/pkg/kubelet/cm/cpumanager/cpu_manager.go index c7ad7d8e55f..05936184052 100644 --- a/pkg/kubelet/cm/cpumanager/cpu_manager.go +++ b/pkg/kubelet/cm/cpumanager/cpu_manager.go @@ -44,8 +44,8 @@ type runtimeService interface { type policyName string -// CPUManagerStateFileName is the name file name where cpu manager stores it's state -const CPUManagerStateFileName = "cpu_manager_state" +// cpuManagerStateFileName is the name file name where cpu manager stores it's state +const cpuManagerStateFileName = "cpu_manager_state" // Manager interface provides methods for Kubelet to manage pod cpus. type Manager interface { @@ -136,7 +136,7 @@ func NewManager(cpuPolicyName string, reconcilePeriod time.Duration, machineInfo policy = NewNonePolicy() } - stateImpl, err := state.NewCheckpointState(stateFileDirecory, policy.Name()) + stateImpl, err := state.NewCheckpointState(stateFileDirecory, cpuManagerStateFileName, policy.Name()) if err != nil { return nil, fmt.Errorf("could not initialize checkpoint manager: %v", err) } diff --git a/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go b/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go index bf1302e2432..6d92573b866 100644 --- a/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go +++ b/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go @@ -27,9 +27,6 @@ import ( "k8s.io/kubernetes/pkg/kubelet/cm/cpuset" ) -// cpuManagerCheckpointName is the name of checkpoint file -const cpuManagerCheckpointName = "cpu_manager_state" - var _ State = &stateCheckpoint{} type stateCheckpoint struct { @@ -37,10 +34,11 @@ type stateCheckpoint struct { policyName string cache State checkpointManager checkpointmanager.CheckpointManager + checkpointName string } // NewCheckpointState creates new State for keeping track of cpu/pod assignment with checkpoint backend -func NewCheckpointState(stateDir string, policyName string) (State, error) { +func NewCheckpointState(stateDir, checkpointName, policyName string) (State, error) { checkpointManager, err := checkpointmanager.NewCheckpointManager(stateDir) if err != nil { return nil, fmt.Errorf("failed to initialize checkpoint manager: %v", err) @@ -49,12 +47,13 @@ func NewCheckpointState(stateDir string, policyName string) (State, error) { cache: NewMemoryState(), policyName: policyName, checkpointManager: checkpointManager, + checkpointName: checkpointName, } if err := stateCheckpoint.restoreState(); err != nil { return nil, fmt.Errorf("could not restore state from checkpoint: %v\n"+ "Please drain this node and delete the CPU manager checkpoint file %q before restarting Kubelet.", - err, path.Join(stateDir, cpuManagerCheckpointName)) + err, path.Join(stateDir, checkpointName)) } return stateCheckpoint, nil @@ -72,7 +71,7 @@ func (sc *stateCheckpoint) restoreState() error { tmpContainerCPUSet := cpuset.NewCPUSet() checkpoint := NewCPUManagerCheckpoint() - if err = sc.checkpointManager.GetCheckpoint(cpuManagerCheckpointName, checkpoint); err != nil { + if err = sc.checkpointManager.GetCheckpoint(sc.checkpointName, checkpoint); err != nil { if err == errors.ErrCheckpointNotFound { sc.storeState() return nil @@ -114,7 +113,7 @@ func (sc *stateCheckpoint) storeState() { checkpoint.Entries[containerID] = cset.String() } - err := sc.checkpointManager.CreateCheckpoint(cpuManagerCheckpointName, checkpoint) + err := sc.checkpointManager.CreateCheckpoint(sc.checkpointName, checkpoint) if err != nil { panic("[cpumanager] could not save checkpoint: " + err.Error()) diff --git a/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go b/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go index ed3891085f4..2471ecdf341 100644 --- a/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go +++ b/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go @@ -17,6 +17,7 @@ limitations under the License. package state import ( + "os" "strings" "testing" @@ -25,7 +26,9 @@ import ( "k8s.io/kubernetes/pkg/kubelet/cm/cpuset" ) -const testingDir = "/tmp" +const testingCheckpoint = "cpumanager_checkpoint_test" + +var testingDir = os.TempDir() func TestCheckpointStateRestore(t *testing.T) { testCases := []struct { @@ -146,17 +149,17 @@ func TestCheckpointStateRestore(t *testing.T) { for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { // ensure there is no previous checkpoint - cpm.RemoveCheckpoint(cpuManagerCheckpointName) + cpm.RemoveCheckpoint(testingCheckpoint) // prepare checkpoint for testing if strings.TrimSpace(tc.checkpointContent) != "" { checkpoint := &testutil.MockCheckpoint{Content: tc.checkpointContent} - if err := cpm.CreateCheckpoint(cpuManagerCheckpointName, checkpoint); err != nil { + if err := cpm.CreateCheckpoint(testingCheckpoint, checkpoint); err != nil { t.Fatalf("could not create testing checkpoint: %v", err) } } - restoredState, err := NewCheckpointState(testingDir, tc.policyName) + restoredState, err := NewCheckpointState(testingDir, testingCheckpoint, tc.policyName) if err != nil { if strings.TrimSpace(tc.expectedError) != "" { tc.expectedError = "could not restore state from checkpoint: " + tc.expectedError @@ -201,9 +204,9 @@ func TestCheckpointStateStore(t *testing.T) { for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { // ensure there is no previous checkpoint - cpm.RemoveCheckpoint(cpuManagerCheckpointName) + cpm.RemoveCheckpoint(testingCheckpoint) - cs1, err := NewCheckpointState(testingDir, "none") + cs1, err := NewCheckpointState(testingDir, testingCheckpoint, "none") if err != nil { t.Fatalf("could not create testing checkpointState instance: %v", err) } @@ -213,7 +216,7 @@ func TestCheckpointStateStore(t *testing.T) { cs1.SetCPUAssignments(tc.expectedState.assignments) // restore checkpoint with previously stored values - cs2, err := NewCheckpointState(testingDir, "none") + cs2, err := NewCheckpointState(testingDir, testingCheckpoint, "none") if err != nil { t.Fatalf("could not create testing checkpointState instance: %v", err) } @@ -261,9 +264,9 @@ func TestCheckpointStateHelpers(t *testing.T) { for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { // ensure there is no previous checkpoint - cpm.RemoveCheckpoint(cpuManagerCheckpointName) + cpm.RemoveCheckpoint(testingCheckpoint) - state, err := NewCheckpointState(testingDir, "none") + state, err := NewCheckpointState(testingDir, testingCheckpoint, "none") if err != nil { t.Fatalf("could not create testing checkpointState instance: %v", err) } @@ -301,7 +304,7 @@ func TestCheckpointStateClear(t *testing.T) { for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { - state, err := NewCheckpointState(testingDir, "none") + state, err := NewCheckpointState(testingDir, testingCheckpoint, "none") if err != nil { t.Fatalf("could not create testing checkpointState instance: %v", err) } diff --git a/pkg/kubelet/cm/cpumanager/state/state_compatibility_test.go b/pkg/kubelet/cm/cpumanager/state/state_compatibility_test.go new file mode 100644 index 00000000000..6c2e375af6f --- /dev/null +++ b/pkg/kubelet/cm/cpumanager/state/state_compatibility_test.go @@ -0,0 +1,78 @@ +/* +Copyright 2018 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 state + +import ( + "os" + "path" + "testing" + + "k8s.io/kubernetes/pkg/kubelet/cm/cpuset" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" +) + +const compatibilityTestingCheckpoint = "cpumanager_state_compatibility_test" + +var state = &stateMemory{ + assignments: ContainerCPUAssignments{ + "container1": cpuset.NewCPUSet(4, 5, 6), + "container2": cpuset.NewCPUSet(1, 2, 3), + }, + defaultCPUSet: cpuset.NewCPUSet(1, 2, 3), +} + +func TestFileToCheckpointCompatibility(t *testing.T) { + statePath := path.Join(testingDir, compatibilityTestingCheckpoint) + + // ensure there is no previous state saved at testing path + os.Remove(statePath) + // ensure testing state is removed after testing + defer os.Remove(statePath) + + fileState := NewFileState(statePath, "none") + + fileState.SetDefaultCPUSet(state.defaultCPUSet) + fileState.SetCPUAssignments(state.assignments) + + restoredState, err := NewCheckpointState(testingDir, compatibilityTestingCheckpoint, "none") + if err != nil { + t.Fatalf("could not restore file state: %v", err) + } + + AssertStateEqual(t, restoredState, state) +} + +func TestCheckpointToFileCompatibility(t *testing.T) { + cpm, err := checkpointmanager.NewCheckpointManager(testingDir) + if err != nil { + t.Fatalf("could not create testing checkpoint manager: %v", err) + } + + // ensure there is no previous checkpoint + cpm.RemoveCheckpoint(compatibilityTestingCheckpoint) + // ensure testing checkpoint is removed after testing + defer cpm.RemoveCheckpoint(compatibilityTestingCheckpoint) + + checkpointState, err := NewCheckpointState(testingDir, compatibilityTestingCheckpoint, "none") + + checkpointState.SetDefaultCPUSet(state.defaultCPUSet) + checkpointState.SetCPUAssignments(state.assignments) + + restoredState := NewFileState(path.Join(testingDir, compatibilityTestingCheckpoint), "none") + + AssertStateEqual(t, restoredState, state) +}