Skip to content

Commit 4895ceb

Browse files
daehyeokDaehyeok Mun
authored and
Daehyeok Mun
committed
Check profile, node name to prevent duplication
Check profile and node name before add to prevent conflict with machine name on multinode cluster.
1 parent 44f5b17 commit 4895ceb

File tree

5 files changed

+96
-5
lines changed

5 files changed

+96
-5
lines changed

Diff for: cmd/minikube/cmd/start.go

+24
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ func runStart(cmd *cobra.Command, args []string) {
178178
upgradeExistingConfig(existing)
179179
}
180180

181+
validateProfileName(existing)
181182
validateSpecifiedDriver(existing)
182183
validateKubernetesVersion(existing)
183184

@@ -638,6 +639,29 @@ func hostDriver(existing *config.ClusterConfig) string {
638639
return h.Driver.DriverName()
639640
}
640641

642+
// validateProfileName makes sure that new profile name not duplicated with any of machine names in existing multi-node clusters.
643+
func validateProfileName(existing *config.ClusterConfig) {
644+
if existing != nil {
645+
return
646+
}
647+
648+
profiles, err := config.ListProfilesLight()
649+
if err != nil {
650+
exit.Message(reason.InternalListConfig, "Unable to list profiles: {{.error}}", out.V{"error": err})
651+
}
652+
for _, p := range profiles {
653+
for _, n := range p.Config.Nodes {
654+
machineName := config.MachineName(*p.Config, n)
655+
if ClusterFlagValue() == machineName {
656+
out.WarningT("Profile name '{{.name}}' is duplicated with machine name '{{.machine}}' in profile '{{.profile}}'", out.V{"name": ClusterFlagValue(),
657+
"machine": machineName,
658+
"profile": p.Name})
659+
exit.Message(reason.Usage, "Profile name should be unique")
660+
}
661+
}
662+
}
663+
}
664+
641665
// validateSpecifiedDriver makes sure that if a user has passed in a driver
642666
// it matches the existing cluster if there is one
643667
func validateSpecifiedDriver(existing *config.ClusterConfig) {

Diff for: pkg/minikube/config/profile.go

+20-2
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,25 @@ func ListProfiles(miniHome ...string) (validPs []*Profile, inValidPs []*Profile,
223223
return validPs, inValidPs, nil
224224
}
225225

226-
// removeDupes removes duplicates
226+
// ListProfilesLight returns profiles in minikube home dir
227+
// Unlike `ListProfiles` this function doens't try to get profile from container
228+
func ListProfilesLight(miniHome ...string) (ps []*Profile, err error) {
229+
// try to get profiles list based on left over evidences such as directory
230+
pDirs, err := profileDirs(miniHome...)
231+
if err != nil {
232+
return nil, err
233+
}
234+
235+
for _, n := range pDirs {
236+
p, err := LoadProfile(n, miniHome...)
237+
if err == nil && p.IsValid() {
238+
ps = append(ps, p)
239+
}
240+
}
241+
return ps, nil
242+
}
243+
244+
// removeDupes removes duplipcates
227245
func removeDupes(profiles []string) []string {
228246
// Use map to record duplicates as we find them.
229247
seen := map[string]bool{}
@@ -291,7 +309,7 @@ func ProfileFolderPath(profile string, miniHome ...string) string {
291309
// MachineName returns the name of the machine, as seen by the hypervisor given the cluster and node names
292310
func MachineName(cc ClusterConfig, n Node) string {
293311
// For single node cluster, default to back to old naming
294-
if len(cc.Nodes) == 1 || n.ControlPlane {
312+
if (len(cc.Nodes) == 1 && cc.Nodes[0].Name == n.Name) || n.ControlPlane {
295313
return cc.Name
296314
}
297315
return fmt.Sprintf("%s-%s", cc.Name, n.Name)

Diff for: pkg/minikube/machine/cluster_test.go

+1-3
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,8 @@ func TestStartHostExists(t *testing.T) {
146146
mc := defaultClusterConfig
147147
mc.Name = ih.Name
148148

149-
n := config.Node{Name: ih.Name}
150-
151149
// This should pass without calling Create because the host exists already.
152-
h, _, err := StartHost(api, &mc, &n)
150+
h, _, err := StartHost(api, &mc, &(mc.Nodes[0]))
153151
if err != nil {
154152
t.Fatalf("Error starting host: %v", err)
155153
}

Diff for: pkg/minikube/node/node.go

+14
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,20 @@ const (
3838

3939
// Add adds a new node config to an existing cluster.
4040
func Add(cc *config.ClusterConfig, n config.Node, delOnFail bool) error {
41+
profiles, err := config.ListProfilesLight()
42+
if err != nil {
43+
return err
44+
}
45+
46+
machineName := config.MachineName(*cc, n)
47+
for _, p := range profiles {
48+
for _, existNode := range p.Config.Nodes {
49+
if machineName == config.MachineName(*p.Config, existNode) {
50+
return errors.Errorf("Node %s already exists in %s profile", machineName, p.Name)
51+
}
52+
}
53+
}
54+
4155
if err := config.SaveNode(cc, &n); err != nil {
4256
return errors.Wrap(err, "save node")
4357
}

Diff for: test/integration/multinode_test.go

+37
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ func TestMultiNode(t *testing.T) {
4848
{"DeleteNode", validateDeleteNodeFromMultiNode},
4949
{"StopMultiNode", validateStopMultiNodeCluster},
5050
{"RestartMultiNode", validateRestartMultiNodeCluster},
51+
{"ValidateNameConflict", validatNameConflict},
5152
}
5253
for _, tc := range tests {
5354
tc := tc
@@ -308,3 +309,39 @@ func validateDeleteNodeFromMultiNode(ctx context.Context, t *testing.T, profile
308309
t.Errorf("expected 2 nodes Ready status to be True, got %v", rr.Output())
309310
}
310311
}
312+
313+
func validatNameConflict(ctx context.Context, t *testing.T, profile string) {
314+
rr, err := Run(t, exec.CommandContext(ctx, Target(), "node", "list", "-p", profile))
315+
if err != nil {
316+
t.Errorf("failed to run node list. args %q : %v", rr.Command(), err)
317+
}
318+
curNodeNum := strings.Count(rr.Stdout.String(), profile)
319+
320+
// Start new profile. It's expected failture
321+
profileName := fmt.Sprintf("%s-m0%d", profile, curNodeNum)
322+
startArgs := append([]string{"start", "-p", profileName}, StartArgs()...)
323+
rr, err = Run(t, exec.CommandContext(ctx, Target(), startArgs...))
324+
if err == nil {
325+
t.Errorf("expected start profile command to fail. args %q", rr.Command())
326+
}
327+
328+
// Start new profile temporary profile to conflict node name.
329+
profileName = fmt.Sprintf("%s-m0%d", profile, curNodeNum+1)
330+
startArgs = append([]string{"start", "-p", profileName}, StartArgs()...)
331+
rr, err = Run(t, exec.CommandContext(ctx, Target(), startArgs...))
332+
if err != nil {
333+
t.Errorf("failed to start profile. args %q : %v", rr.Command(), err)
334+
}
335+
336+
// Add a node to the current cluster. It's expected failture
337+
addArgs := []string{"node", "add", "-p", profile}
338+
rr, err = Run(t, exec.CommandContext(ctx, Target(), addArgs...))
339+
if err == nil {
340+
t.Errorf("expected add node command to fail fail. args %q : %v", rr.Command(), err)
341+
}
342+
343+
rr, err = Run(t, exec.CommandContext(ctx, Target(), "delete", "-p", profileName))
344+
if err != nil {
345+
t.Logf("failed to clean temporary profile. args %q : %v", rr.Command(), err)
346+
}
347+
}

0 commit comments

Comments
 (0)