Skip to content

Commit 0e3c65c

Browse files
roycaihwk8s-publishing-bot
authored andcommitted
Raise error on duplicate name in kubeconfig
for NamedCluster, NamedContext, NamedUser, NamedExtension Kubernetes-commit: e9454a383b52c3909e7bb73a0263c4d2c0c2c2db
1 parent fd32386 commit 0e3c65c

File tree

2 files changed

+189
-4
lines changed

2 files changed

+189
-4
lines changed

tools/clientcmd/api/v1/conversion.go

+21-4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package v1
1818

1919
import (
20+
"fmt"
2021
"sort"
2122

2223
"k8s.io/apimachinery/pkg/conversion"
@@ -105,7 +106,11 @@ func addConversionFuncs(scheme *runtime.Scheme) error {
105106
if err := s.Convert(&curr.Cluster, newCluster, 0); err != nil {
106107
return err
107108
}
108-
(*out)[curr.Name] = newCluster
109+
if (*out)[curr.Name] == nil {
110+
(*out)[curr.Name] = newCluster
111+
} else {
112+
return fmt.Errorf("error converting *[]NamedCluster into *map[string]*api.Cluster: duplicate name \"%v\" in list: %v", curr.Name, *in)
113+
}
109114
}
110115

111116
return nil
@@ -136,7 +141,11 @@ func addConversionFuncs(scheme *runtime.Scheme) error {
136141
if err := s.Convert(&curr.AuthInfo, newAuthInfo, 0); err != nil {
137142
return err
138143
}
139-
(*out)[curr.Name] = newAuthInfo
144+
if (*out)[curr.Name] == nil {
145+
(*out)[curr.Name] = newAuthInfo
146+
} else {
147+
return fmt.Errorf("error converting *[]NamedAuthInfo into *map[string]*api.AuthInfo: duplicate name \"%v\" in list: %v", curr.Name, *in)
148+
}
140149
}
141150

142151
return nil
@@ -167,7 +176,11 @@ func addConversionFuncs(scheme *runtime.Scheme) error {
167176
if err := s.Convert(&curr.Context, newContext, 0); err != nil {
168177
return err
169178
}
170-
(*out)[curr.Name] = newContext
179+
if (*out)[curr.Name] == nil {
180+
(*out)[curr.Name] = newContext
181+
} else {
182+
return fmt.Errorf("error converting *[]NamedContext into *map[string]*api.Context: duplicate name \"%v\" in list: %v", curr.Name, *in)
183+
}
171184
}
172185

173186
return nil
@@ -198,7 +211,11 @@ func addConversionFuncs(scheme *runtime.Scheme) error {
198211
if err := s.Convert(&curr.Extension, &newExtension, 0); err != nil {
199212
return err
200213
}
201-
(*out)[curr.Name] = newExtension
214+
if (*out)[curr.Name] == nil {
215+
(*out)[curr.Name] = newExtension
216+
} else {
217+
return fmt.Errorf("error converting *[]NamedExtension into *map[string]runtime.Object: duplicate name \"%v\" in list: %v", curr.Name, *in)
218+
}
202219
}
203220

204221
return nil

tools/clientcmd/loader_test.go

+168
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,174 @@ func TestLoadingEmptyMaps(t *testing.T) {
201201
}
202202
}
203203

204+
func TestDuplicateClusterName(t *testing.T) {
205+
configFile, _ := ioutil.TempFile("", "")
206+
defer os.Remove(configFile.Name())
207+
208+
err := ioutil.WriteFile(configFile.Name(), []byte(`
209+
kind: Config
210+
apiVersion: v1
211+
clusters:
212+
- cluster:
213+
api-version: v1
214+
server: https://kubernetes.default.svc:443
215+
certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
216+
name: kubeconfig-cluster
217+
- cluster:
218+
api-version: v2
219+
server: https://test.example.server:443
220+
certificate-authority: /var/run/secrets/test.example.io/serviceaccount/ca.crt
221+
name: kubeconfig-cluster
222+
contexts:
223+
- context:
224+
cluster: kubeconfig-cluster
225+
namespace: default
226+
user: kubeconfig-user
227+
name: kubeconfig-context
228+
current-context: kubeconfig-context
229+
users:
230+
- name: kubeconfig-user
231+
user:
232+
tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
233+
`), os.FileMode(0755))
234+
235+
if err != nil {
236+
t.Errorf("Unexpected error: %v", err)
237+
}
238+
239+
_, err = LoadFromFile(configFile.Name())
240+
if err == nil || !strings.Contains(err.Error(),
241+
"error converting *[]NamedCluster into *map[string]*api.Cluster: duplicate name \"kubeconfig-cluster\" in list") {
242+
t.Error("Expected error in loading duplicate cluster name, got none")
243+
}
244+
}
245+
246+
func TestDuplicateContextName(t *testing.T) {
247+
configFile, _ := ioutil.TempFile("", "")
248+
defer os.Remove(configFile.Name())
249+
250+
err := ioutil.WriteFile(configFile.Name(), []byte(`
251+
kind: Config
252+
apiVersion: v1
253+
clusters:
254+
- cluster:
255+
api-version: v1
256+
server: https://kubernetes.default.svc:443
257+
certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
258+
name: kubeconfig-cluster
259+
contexts:
260+
- context:
261+
cluster: kubeconfig-cluster
262+
namespace: default
263+
user: kubeconfig-user
264+
name: kubeconfig-context
265+
- context:
266+
cluster: test-example-cluster
267+
namespace: test-example
268+
user: test-example-user
269+
name: kubeconfig-context
270+
current-context: kubeconfig-context
271+
users:
272+
- name: kubeconfig-user
273+
user:
274+
tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
275+
`), os.FileMode(0755))
276+
277+
if err != nil {
278+
t.Errorf("Unexpected error: %v", err)
279+
}
280+
281+
_, err = LoadFromFile(configFile.Name())
282+
if err == nil || !strings.Contains(err.Error(),
283+
"error converting *[]NamedContext into *map[string]*api.Context: duplicate name \"kubeconfig-context\" in list") {
284+
t.Error("Expected error in loading duplicate context name, got none")
285+
}
286+
}
287+
288+
func TestDuplicateUserName(t *testing.T) {
289+
configFile, _ := ioutil.TempFile("", "")
290+
defer os.Remove(configFile.Name())
291+
292+
err := ioutil.WriteFile(configFile.Name(), []byte(`
293+
kind: Config
294+
apiVersion: v1
295+
clusters:
296+
- cluster:
297+
api-version: v1
298+
server: https://kubernetes.default.svc:443
299+
certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
300+
name: kubeconfig-cluster
301+
contexts:
302+
- context:
303+
cluster: kubeconfig-cluster
304+
namespace: default
305+
user: kubeconfig-user
306+
name: kubeconfig-context
307+
current-context: kubeconfig-context
308+
users:
309+
- name: kubeconfig-user
310+
user:
311+
tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
312+
- name: kubeconfig-user
313+
user:
314+
tokenFile: /var/run/secrets/test.example.com/serviceaccount/token
315+
`), os.FileMode(0755))
316+
317+
if err != nil {
318+
t.Errorf("Unexpected error: %v", err)
319+
}
320+
321+
_, err = LoadFromFile(configFile.Name())
322+
if err == nil || !strings.Contains(err.Error(),
323+
"error converting *[]NamedAuthInfo into *map[string]*api.AuthInfo: duplicate name \"kubeconfig-user\" in list") {
324+
t.Error("Expected error in loading duplicate user name, got none")
325+
}
326+
}
327+
328+
func TestDuplicateExtensionName(t *testing.T) {
329+
configFile, _ := ioutil.TempFile("", "")
330+
defer os.Remove(configFile.Name())
331+
332+
err := ioutil.WriteFile(configFile.Name(), []byte(`
333+
kind: Config
334+
apiVersion: v1
335+
clusters:
336+
- cluster:
337+
api-version: v1
338+
server: https://kubernetes.default.svc:443
339+
certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
340+
name: kubeconfig-cluster
341+
contexts:
342+
- context:
343+
cluster: kubeconfig-cluster
344+
namespace: default
345+
user: kubeconfig-user
346+
name: kubeconfig-context
347+
current-context: kubeconfig-context
348+
users:
349+
- name: kubeconfig-user
350+
user:
351+
tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
352+
extensions:
353+
- extension:
354+
bytes: test
355+
name: test-extension
356+
- extension:
357+
bytes: some-example
358+
name: test-extension
359+
`), os.FileMode(0755))
360+
361+
if err != nil {
362+
t.Errorf("Unexpected error: %v", err)
363+
}
364+
365+
_, err = LoadFromFile(configFile.Name())
366+
if err == nil || !strings.Contains(err.Error(),
367+
"error converting *[]NamedExtension into *map[string]runtime.Object: duplicate name \"test-extension\" in list") {
368+
t.Error("Expected error in loading duplicate extension name, got none")
369+
}
370+
}
371+
204372
func TestResolveRelativePaths(t *testing.T) {
205373
pathResolutionConfig1 := clientcmdapi.Config{
206374
AuthInfos: map[string]*clientcmdapi.AuthInfo{

0 commit comments

Comments
 (0)