-
Notifications
You must be signed in to change notification settings - Fork 94
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Jian Qiu <jqiu@redhat.com>
- Loading branch information
Showing
21 changed files
with
871 additions
and
848 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package register | ||
|
||
import ( | ||
"fmt" | ||
"reflect" | ||
|
||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api" | ||
) | ||
|
||
// BaseKubeConfigFromBootStrap builds kubeconfig from bootstrap without authInfo configurations | ||
func BaseKubeConfigFromBootStrap(bootstrapConfig *clientcmdapi.Config) (*clientcmdapi.Config, error) { | ||
kubeConfigCtx, cluster, err := currentKubeConfigCluster(bootstrapConfig) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Build kubeconfig. | ||
kubeconfig := &clientcmdapi.Config{ | ||
// Define a cluster stanza based on the bootstrap kubeconfig. | ||
Clusters: map[string]*clientcmdapi.Cluster{ | ||
kubeConfigCtx.Cluster: { | ||
Server: cluster.Server, | ||
InsecureSkipTLSVerify: false, | ||
CertificateAuthorityData: cluster.CertificateAuthorityData, | ||
ProxyURL: cluster.ProxyURL, | ||
}}, | ||
// Define a context that connects the auth info and cluster, and set it as the default | ||
Contexts: map[string]*clientcmdapi.Context{DefaultKubeConfigContext: { | ||
Cluster: kubeConfigCtx.Cluster, | ||
AuthInfo: DefaultKubeConfigAuth, | ||
Namespace: "configuration", | ||
}}, | ||
CurrentContext: DefaultKubeConfigContext, | ||
} | ||
|
||
return kubeconfig, nil | ||
} | ||
|
||
func currentKubeConfigCluster(config *clientcmdapi.Config) (*clientcmdapi.Context, *clientcmdapi.Cluster, error) { | ||
kubeConfigCtx, ok := config.Contexts[config.CurrentContext] | ||
if !ok { | ||
return nil, nil, fmt.Errorf("kubeconfig does not contains context: %s", config.CurrentContext) | ||
} | ||
|
||
cluster, ok := config.Clusters[kubeConfigCtx.Cluster] | ||
if !ok { | ||
return nil, nil, fmt.Errorf("kubeconfig does not contains cluster: %s", kubeConfigCtx.Cluster) | ||
} | ||
|
||
return kubeConfigCtx, cluster, nil | ||
} | ||
|
||
// The hub kubeconfig is valid when it shares the same value of the following with the | ||
// bootstrap hub kubeconfig. | ||
// 1. The hub server | ||
// 2. The proxy url | ||
// 3. The CA bundle | ||
// 4. The current context cluster name | ||
func IsHubKubeconfigValid(bootstrapKubeConfig, hubeKubeConfig *clientcmdapi.Config) (bool, error) { | ||
if bootstrapKubeConfig == nil { | ||
return false, nil | ||
} | ||
bootstrapCtx, bootstrapCluster, err := currentKubeConfigCluster(bootstrapKubeConfig) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
if hubeKubeConfig == nil { | ||
return false, nil | ||
} | ||
hubKubeConfigCtx, hubKubeConfigCluster, err := currentKubeConfigCluster(hubeKubeConfig) | ||
switch { | ||
case err != nil: | ||
return false, err | ||
case bootstrapCluster.Server != hubKubeConfigCluster.Server, | ||
bootstrapCluster.ProxyURL != hubKubeConfigCluster.ProxyURL, | ||
!reflect.DeepEqual(bootstrapCluster.CertificateAuthorityData, hubKubeConfigCluster.CertificateAuthorityData), | ||
// Here in addition to the server, proxyURL and CA bundle, we also need to compare the cluster name, | ||
// because in some cases even the hub cluster API server serving certificate(kubeconfig ca bundle) | ||
// is the same, but the signer certificate may be different(i.e the hub kubernetes cluster is rebuilt | ||
// with a same serving certificate and url), so setting the cluster name in the bootstrap kubeconfig | ||
// can help to distinguish the different clusters(signer certificate). And comparing the cluster name | ||
// can help to avoid the situation that the hub kubeconfig is valid but not for the current cluster. | ||
bootstrapCtx.Cluster != hubKubeConfigCtx.Cluster: | ||
return false, nil | ||
default: | ||
return true, nil | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package register | ||
|
||
import ( | ||
"reflect" | ||
"testing" | ||
|
||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api" | ||
) | ||
|
||
func TestBaseKubeConfigFromBootStrap(t *testing.T) { | ||
server1 := "https://127.0.0.1:6443" | ||
server2 := "https://api.cluster1.example.com:6443" | ||
caData1 := []byte("fake-ca-data1") | ||
caData2 := []byte("fake-ca-data2") | ||
proxyURL := "https://127.0.0.1:3129" | ||
|
||
cases := []struct { | ||
name string | ||
kubeconfig clientcmdapi.Config | ||
expectedServer string | ||
expectedCAData []byte | ||
expectedProxyURL string | ||
}{ | ||
{ | ||
name: "without proxy url", | ||
kubeconfig: clientcmdapi.Config{ | ||
Clusters: map[string]*clientcmdapi.Cluster{ | ||
"test-cluster": { | ||
Server: server1, | ||
CertificateAuthorityData: caData1, | ||
}}, | ||
// Define a context that connects the auth info and cluster, and set it as the default | ||
Contexts: map[string]*clientcmdapi.Context{DefaultKubeConfigContext: { | ||
Cluster: "test-cluster", | ||
AuthInfo: DefaultKubeConfigAuth, | ||
Namespace: "configuration", | ||
}}, | ||
CurrentContext: DefaultKubeConfigContext, | ||
AuthInfos: map[string]*clientcmdapi.AuthInfo{ | ||
DefaultKubeConfigAuth: { | ||
ClientCertificate: "tls.crt", | ||
ClientKey: "tls.key", | ||
}, | ||
}, | ||
}, | ||
expectedServer: server1, | ||
expectedCAData: caData1, | ||
expectedProxyURL: "", | ||
}, | ||
{ | ||
name: "with proxy url", | ||
kubeconfig: clientcmdapi.Config{ | ||
Clusters: map[string]*clientcmdapi.Cluster{ | ||
"test-cluster": { | ||
Server: server2, | ||
CertificateAuthorityData: caData2, | ||
ProxyURL: proxyURL, | ||
}}, | ||
// Define a context that connects the auth info and cluster, and set it as the default | ||
Contexts: map[string]*clientcmdapi.Context{DefaultKubeConfigContext: { | ||
Cluster: "test-cluster", | ||
AuthInfo: DefaultKubeConfigAuth, | ||
Namespace: "configuration", | ||
}}, | ||
CurrentContext: DefaultKubeConfigContext, | ||
AuthInfos: map[string]*clientcmdapi.AuthInfo{ | ||
DefaultKubeConfigAuth: { | ||
ClientCertificate: "tls.crt", | ||
ClientKey: "tls.key", | ||
}, | ||
}, | ||
}, | ||
expectedServer: server2, | ||
expectedCAData: caData2, | ||
expectedProxyURL: proxyURL, | ||
}, | ||
} | ||
for _, c := range cases { | ||
t.Run(c.name, func(t *testing.T) { | ||
config, err := BaseKubeConfigFromBootStrap(&c.kubeconfig) | ||
if err != nil { | ||
t.Errorf("unexpected error: %v", err) | ||
} | ||
|
||
cluster := config.Contexts[DefaultKubeConfigContext].Cluster | ||
|
||
if cluster != "test-cluster" { | ||
t.Errorf("expect context cluster %s, but %s", "test-cluster", | ||
config.Contexts[DefaultKubeConfigContext].Cluster) | ||
} | ||
|
||
if c.expectedServer != config.Clusters[cluster].Server { | ||
t.Errorf("expect server %s, but %s", c.expectedServer, config.Clusters[cluster].Server) | ||
} | ||
|
||
if c.expectedProxyURL != config.Clusters[cluster].ProxyURL { | ||
t.Errorf("expect proxy url %s, but %s", c.expectedProxyURL, proxyURL) | ||
} | ||
|
||
if !reflect.DeepEqual(c.expectedCAData, config.Clusters[cluster].CertificateAuthorityData) { | ||
t.Errorf("expect ca data %v, but %v", c.expectedCAData, config.Clusters[cluster].CertificateAuthorityData) | ||
} | ||
}) | ||
} | ||
} |
Oops, something went wrong.