Skip to content

Commit 74d7c68

Browse files
committed
fix (crc/machine) : KubeContext left in invalid state after crc stop
At the moment, we are only cleaning up crc context from kubeconfig during `crc delete`. This can be problematic if user tries to run any cluster related command after running `crc stop` as kubeconfig still points to CRC cluster that is not active. I checked minikube's behavior and noticed it's cleaning up kube config in case of both stop and delete commands. Make crc behavior consistent with minikube and perform kubeconfig cleanup in both sub commands. Signed-off-by: Rohan Kumar <[email protected]>
1 parent 410a6db commit 74d7c68

File tree

4 files changed

+128
-0
lines changed

4 files changed

+128
-0
lines changed

Diff for: pkg/crc/machine/kubeconfig_test.go

+26
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,32 @@ func TestCleanKubeconfig(t *testing.T) {
5252
assert.YAMLEq(t, string(expected), string(actual))
5353
}
5454

55+
func TestCleanKubeConfigIdempotency(t *testing.T) {
56+
// Given
57+
dir := t.TempDir()
58+
// When
59+
assert.NoError(t, cleanKubeconfig(filepath.Join("testdata", "kubeconfig.out"), filepath.Join(dir, "kubeconfig")))
60+
actual, err := os.ReadFile(filepath.Join(dir, "kubeconfig"))
61+
// Then
62+
assert.NoError(t, err)
63+
expected, err := os.ReadFile(filepath.Join("testdata", "kubeconfig.out"))
64+
assert.NoError(t, err)
65+
assert.YAMLEq(t, string(expected), string(actual))
66+
}
67+
68+
func TestCleanKubeConfigShouldDoNothingWhenClusterDomainIsNotEqualToCrcTesting(t *testing.T) {
69+
// Given
70+
dir := t.TempDir()
71+
// When
72+
assert.NoError(t, cleanKubeconfig(filepath.Join("testdata", "kubeconfig-without-api-crc-testing-cluster-domain"), filepath.Join(dir, "kubeconfig")))
73+
actual, err := os.ReadFile(filepath.Join(dir, "kubeconfig"))
74+
// Then
75+
assert.NoError(t, err)
76+
expected, err := os.ReadFile(filepath.Join("testdata", "kubeconfig-without-api-crc-testing-cluster-domain"))
77+
assert.NoError(t, err)
78+
assert.YAMLEq(t, string(expected), string(actual))
79+
}
80+
5581
func TestUpdateUserCaAndKeyToKubeconfig(t *testing.T) {
5682
f, err := os.CreateTemp("", "kubeconfig")
5783
assert.NoError(t, err, "")

Diff for: pkg/crc/machine/stop.go

+7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package machine
22

33
import (
4+
"os"
5+
46
"github.com/crc-org/crc/v2/pkg/crc/logging"
57
"github.com/crc-org/crc/v2/pkg/crc/machine/state"
68
crcPreset "github.com/crc-org/crc/v2/pkg/crc/preset"
@@ -9,6 +11,11 @@ import (
911
)
1012

1113
func (client *client) Stop() (state.State, error) {
14+
if err := cleanKubeconfig(getGlobalKubeConfigPath(), getGlobalKubeConfigPath()); err != nil {
15+
if !errors.Is(err, os.ErrNotExist) {
16+
logging.Warnf("Failed to remove crc contexts from kubeconfig: %v", err)
17+
}
18+
}
1219
if running, _ := client.IsRunning(); !running {
1320
return state.Error, errors.New("Instance is already stopped")
1421
}

Diff for: pkg/crc/machine/stop_test.go

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package machine
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
"testing"
7+
8+
crcConfig "github.com/crc-org/crc/v2/pkg/crc/config"
9+
"github.com/crc-org/crc/v2/pkg/crc/machine/state"
10+
crcOs "github.com/crc-org/crc/v2/pkg/os"
11+
"github.com/stretchr/testify/assert"
12+
)
13+
14+
func TestClient_WhenStopInvokedWithNonExistentVM_ThenThrowError(t *testing.T) {
15+
// Given
16+
dir := t.TempDir()
17+
oldKubeConfigEnvVarValue := os.Getenv("KUBECONFIG")
18+
kubeConfigPath := filepath.Join(dir, "kubeconfig")
19+
err := crcOs.CopyFile(filepath.Join("testdata", "kubeconfig.in"), kubeConfigPath)
20+
assert.NoError(t, err)
21+
err = os.Setenv("KUBECONFIG", kubeConfigPath)
22+
assert.NoError(t, err)
23+
crcConfigStorage := crcConfig.New(crcConfig.NewEmptyInMemoryStorage(), crcConfig.NewEmptyInMemorySecretStorage())
24+
client := NewClient("i-dont-exist", false, crcConfigStorage)
25+
26+
// When
27+
clusterState, stopErr := client.Stop()
28+
29+
// Then
30+
assert.EqualError(t, stopErr, "Instance is already stopped")
31+
assert.Equal(t, clusterState, state.Error)
32+
err = os.Setenv("KUBECONFIG", oldKubeConfigEnvVarValue)
33+
assert.NoError(t, err)
34+
}
35+
36+
var testArguments = map[string]struct {
37+
inputKubeConfigPath string
38+
expectedKubeConfigPath string
39+
}{
40+
"When KubeConfig contains crc context, then cleanup KubeConfig": {
41+
"kubeconfig.in", "kubeconfig.out",
42+
},
43+
"When KubeConfig does not contain crc context, then KubeConfig remains unchanged": {
44+
"kubeconfig.out", "kubeconfig.out",
45+
},
46+
}
47+
48+
func TestClient_WhenStopInvoked_ThenKubeConfigUpdatedIfRequired(t *testing.T) {
49+
for name, test := range testArguments {
50+
t.Run(name, func(t *testing.T) {
51+
t.Parallel()
52+
// Given
53+
dir := t.TempDir()
54+
oldKubeConfigEnvVarValue := os.Getenv("KUBECONFIG")
55+
kubeConfigPath := filepath.Join(dir, "kubeconfig")
56+
err := crcOs.CopyFile(filepath.Join("testdata", test.inputKubeConfigPath), kubeConfigPath)
57+
assert.NoError(t, err)
58+
err = os.Setenv("KUBECONFIG", kubeConfigPath)
59+
assert.NoError(t, err)
60+
crcConfigStorage := crcConfig.New(crcConfig.NewEmptyInMemoryStorage(), crcConfig.NewEmptyInMemorySecretStorage())
61+
client := NewClient("test-client", false, crcConfigStorage)
62+
63+
// When
64+
clusterState, _ := client.Stop()
65+
66+
// Then
67+
actualKubeConfigFile, err := os.ReadFile(kubeConfigPath)
68+
assert.NoError(t, err)
69+
expectedKubeConfigPath, err := os.ReadFile(filepath.Join("testdata", test.expectedKubeConfigPath))
70+
assert.NoError(t, err)
71+
assert.YAMLEq(t, string(expectedKubeConfigPath), string(actualKubeConfigFile))
72+
assert.Equal(t, clusterState, state.Error)
73+
err = os.Setenv("KUBECONFIG", oldKubeConfigEnvVarValue)
74+
assert.NoError(t, err)
75+
})
76+
}
77+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
apiVersion: v1
2+
clusters:
3+
- cluster:
4+
server: https://api.unknown.testing:6443
5+
name: api-crc-testing:6443
6+
contexts:
7+
- context:
8+
cluster: api-crc-testing:6443
9+
namespace: default
10+
user: kubeadmin/api-crc-testing:6443
11+
name: default/api-crc-testing:6443/kubeadmin
12+
current-context: default/api-crc-testing:6443/kubeadmin
13+
kind: Config
14+
preferences: {}
15+
users:
16+
- name: kubeadmin/api-crc-testing:6443
17+
user:
18+
token: sha256~secret

0 commit comments

Comments
 (0)