talos/internal/pkg/kubeconfig/merge_test.go
Andrey Smirnov 16eb47a1a3 feat: use kubeconfig merge in talosctl kubeconfig by default
Kubeconfig merge was completely rewritten to be "smarter":

* automatically apply renames done at previous stages to avoid asking
over and over again (in general should ask just once)

* skip checks if parts of the config match exactly

* allow overwrite as an option

* flexible way to control the output

* activating context in the end

* custom merged context name

Fixes #2578

Fixes #2587

Fixes #2577

Signed-off-by: Andrey Smirnov <smirnov.andrey@gmail.com>
2020-10-03 05:36:15 -07:00

376 lines
8.5 KiB
Go

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package kubeconfig_test
import (
"fmt"
"os"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"github.com/talos-systems/talos/internal/pkg/kubeconfig"
)
func TestMerger(t *testing.T) {
errorAlways := func(kubeconfig.ConfigComponent, string) (kubeconfig.ConflictDecision, error) {
return "", fmt.Errorf("shouldn't be here")
}
renameAlways := func(kubeconfig.ConfigComponent, string) (kubeconfig.ConflictDecision, error) {
return kubeconfig.RenameDecision, nil
}
overwriteAlways := func(kubeconfig.ConfigComponent, string) (kubeconfig.ConflictDecision, error) {
return kubeconfig.OverwriteDecision, nil
}
for _, tt := range []struct {
name string
initial clientcmdapi.Config
new clientcmdapi.Config
expected clientcmdapi.Config
options kubeconfig.MergeOptions
}{
{ // MergeIntoEmpty
name: "MergeIntoEmpty",
initial: clientcmdapi.Config{
AuthInfos: map[string]*clientcmdapi.AuthInfo{},
Clusters: map[string]*clientcmdapi.Cluster{},
Contexts: map[string]*clientcmdapi.Context{},
},
new: clientcmdapi.Config{
AuthInfos: map[string]*clientcmdapi.AuthInfo{
"foo@bar": {
ClientCertificate: "cert1",
},
},
Clusters: map[string]*clientcmdapi.Cluster{
"bar": {
Server: "example.com",
},
},
Contexts: map[string]*clientcmdapi.Context{
"foo@bar": {
Cluster: "bar",
AuthInfo: "foo@bar",
},
},
CurrentContext: "nothing",
},
expected: clientcmdapi.Config{
AuthInfos: map[string]*clientcmdapi.AuthInfo{
"foo@bar": {
ClientCertificate: "cert1",
},
},
Clusters: map[string]*clientcmdapi.Cluster{
"bar": {
Server: "example.com",
},
},
Contexts: map[string]*clientcmdapi.Context{
"foo@bar": {
Cluster: "bar",
AuthInfo: "foo@bar",
},
},
},
options: kubeconfig.MergeOptions{
ConflictHandler: errorAlways,
OutputWriter: os.Stdout,
},
},
{ // MergeClean
name: "MergeClean",
initial: clientcmdapi.Config{
AuthInfos: map[string]*clientcmdapi.AuthInfo{
"foo@bar": {
ClientCertificate: "cert1",
},
},
Clusters: map[string]*clientcmdapi.Cluster{
"bar": {
Server: "example.com",
},
},
Contexts: map[string]*clientcmdapi.Context{
"foo@bar": {
Cluster: "bar",
AuthInfo: "foo@bar",
},
},
CurrentContext: "foo@bar",
},
new: clientcmdapi.Config{
AuthInfos: map[string]*clientcmdapi.AuthInfo{
"fiz@buzz": {
ClientCertificate: "cert2",
},
},
Clusters: map[string]*clientcmdapi.Cluster{
"buzz": {
Server: "another.com",
},
},
Contexts: map[string]*clientcmdapi.Context{
"fiz@buzz": {
Cluster: "buzz",
AuthInfo: "fiz@buzz",
},
},
},
expected: clientcmdapi.Config{
AuthInfos: map[string]*clientcmdapi.AuthInfo{
"foo@bar": {
ClientCertificate: "cert1",
},
"fiz@buzz": {
ClientCertificate: "cert2",
},
},
Clusters: map[string]*clientcmdapi.Cluster{
"bar": {
Server: "example.com",
},
"buzz": {
Server: "another.com",
},
},
Contexts: map[string]*clientcmdapi.Context{
"foo@bar": {
Cluster: "bar",
AuthInfo: "foo@bar",
},
"fiz@buzz": {
Cluster: "buzz",
AuthInfo: "fiz@buzz",
},
},
CurrentContext: "fiz@buzz",
},
options: kubeconfig.MergeOptions{
ActivateContext: true,
ConflictHandler: errorAlways,
OutputWriter: os.Stdout,
},
},
{ // MergeRename
name: "MergeRename",
initial: clientcmdapi.Config{
AuthInfos: map[string]*clientcmdapi.AuthInfo{
"foo@bar": {
ClientCertificate: "cert1",
},
},
Clusters: map[string]*clientcmdapi.Cluster{
"bar": {
Server: "example.com",
},
},
Contexts: map[string]*clientcmdapi.Context{
"foo@bar": {
Cluster: "bar",
AuthInfo: "foo@bar",
},
},
CurrentContext: "foo@bar",
},
new: clientcmdapi.Config{
AuthInfos: map[string]*clientcmdapi.AuthInfo{
"foo@bar": {
ClientCertificate: "cert2",
},
},
Clusters: map[string]*clientcmdapi.Cluster{
"bar": {
Server: "another.com",
},
},
Contexts: map[string]*clientcmdapi.Context{
"foo@bar": {
Cluster: "bar",
AuthInfo: "foo@bar",
},
},
},
expected: clientcmdapi.Config{
AuthInfos: map[string]*clientcmdapi.AuthInfo{
"foo@bar": {
ClientCertificate: "cert1",
},
"foo@bar-1": {
ClientCertificate: "cert2",
},
},
Clusters: map[string]*clientcmdapi.Cluster{
"bar": {
Server: "example.com",
},
"bar-1": {
Server: "another.com",
},
},
Contexts: map[string]*clientcmdapi.Context{
"foo@bar": {
Cluster: "bar",
AuthInfo: "foo@bar",
},
"foo@bar-1": {
Cluster: "bar-1",
AuthInfo: "foo@bar-1",
},
},
CurrentContext: "foo@bar",
},
options: kubeconfig.MergeOptions{
ConflictHandler: renameAlways,
OutputWriter: os.Stdout,
},
},
{ // MergeOverwrite
name: "MergeOverwrite",
initial: clientcmdapi.Config{
AuthInfos: map[string]*clientcmdapi.AuthInfo{
"foo@bar": {
ClientCertificate: "cert1",
},
},
Clusters: map[string]*clientcmdapi.Cluster{
"bar": {
Server: "example.com",
},
},
Contexts: map[string]*clientcmdapi.Context{
"foo@bar": {
Cluster: "bar",
AuthInfo: "foo@bar",
},
},
CurrentContext: "foo@bar",
},
new: clientcmdapi.Config{
AuthInfos: map[string]*clientcmdapi.AuthInfo{
"foo@bar": {
ClientCertificate: "cert2",
},
},
Clusters: map[string]*clientcmdapi.Cluster{
"bar": {
Server: "another.com",
},
},
Contexts: map[string]*clientcmdapi.Context{
"foo@bar": {
Cluster: "bar",
AuthInfo: "foo@bar",
},
},
},
expected: clientcmdapi.Config{
AuthInfos: map[string]*clientcmdapi.AuthInfo{
"foo@bar": {
ClientCertificate: "cert2",
},
},
Clusters: map[string]*clientcmdapi.Cluster{
"bar": {
Server: "another.com",
},
},
Contexts: map[string]*clientcmdapi.Context{
"foo@bar": {
Cluster: "bar",
AuthInfo: "foo@bar",
},
},
CurrentContext: "foo@bar",
},
options: kubeconfig.MergeOptions{
ConflictHandler: overwriteAlways,
OutputWriter: os.Stdout,
},
},
{ // MergeEqual
name: "MergeEqual",
initial: clientcmdapi.Config{
AuthInfos: map[string]*clientcmdapi.AuthInfo{
"foo@bar": {
ClientCertificate: "cert1",
},
},
Clusters: map[string]*clientcmdapi.Cluster{
"bar": {
Server: "example.com",
},
},
Contexts: map[string]*clientcmdapi.Context{
"foo@bar": {
Cluster: "bar",
AuthInfo: "foo@bar",
},
},
CurrentContext: "foo@bar",
},
new: clientcmdapi.Config{
AuthInfos: map[string]*clientcmdapi.AuthInfo{
"foo@bar": {
ClientCertificate: "cert1",
},
},
Clusters: map[string]*clientcmdapi.Cluster{
"bar": {
Server: "example.com",
},
},
Contexts: map[string]*clientcmdapi.Context{
"foo@bar": {
Cluster: "bar",
AuthInfo: "foo@bar",
},
},
CurrentContext: "foo@bar",
},
expected: clientcmdapi.Config{
AuthInfos: map[string]*clientcmdapi.AuthInfo{
"foo@bar": {
ClientCertificate: "cert1",
},
},
Clusters: map[string]*clientcmdapi.Cluster{
"bar": {
Server: "example.com",
},
},
Contexts: map[string]*clientcmdapi.Context{
"foo@bar": {
Cluster: "bar",
AuthInfo: "foo@bar",
},
},
CurrentContext: "foo@bar",
},
options: kubeconfig.MergeOptions{
ConflictHandler: errorAlways,
OutputWriter: os.Stdout,
},
},
} {
tt := tt
t.Run(tt.name, func(t *testing.T) {
merger := kubeconfig.Merger(*tt.initial.DeepCopy())
err := merger.Merge(&tt.new, tt.options)
require.NoError(t, err)
assert.Equal(t, tt.expected.Clusters, merger.Clusters)
assert.Equal(t, tt.expected.AuthInfos, merger.AuthInfos)
assert.Equal(t, tt.expected.Contexts, merger.Contexts)
assert.Equal(t, tt.expected.CurrentContext, merger.CurrentContext)
})
}
}