mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-13 13:55:41 +00:00
[Federation][init-10b] Update local kubeconfig with the new federation API server credentials.
This commit is contained in:
parent
8d8eca5f2a
commit
41b39f3019
@ -21,6 +21,8 @@ go_library(
|
|||||||
"//pkg/api/resource:go_default_library",
|
"//pkg/api/resource:go_default_library",
|
||||||
"//pkg/apis/extensions:go_default_library",
|
"//pkg/apis/extensions:go_default_library",
|
||||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||||
|
"//pkg/client/unversioned/clientcmd:go_default_library",
|
||||||
|
"//pkg/client/unversioned/clientcmd/api:go_default_library",
|
||||||
"//pkg/kubectl/cmd/templates:go_default_library",
|
"//pkg/kubectl/cmd/templates:go_default_library",
|
||||||
"//pkg/kubectl/cmd/util:go_default_library",
|
"//pkg/kubectl/cmd/util:go_default_library",
|
||||||
"//pkg/util/cert:go_default_library",
|
"//pkg/util/cert:go_default_library",
|
||||||
@ -49,6 +51,7 @@ go_test(
|
|||||||
"//pkg/apis/extensions/v1beta1:go_default_library",
|
"//pkg/apis/extensions/v1beta1:go_default_library",
|
||||||
"//pkg/client/restclient/fake:go_default_library",
|
"//pkg/client/restclient/fake:go_default_library",
|
||||||
"//pkg/client/typed/dynamic:go_default_library",
|
"//pkg/client/typed/dynamic:go_default_library",
|
||||||
|
"//pkg/client/unversioned/clientcmd:go_default_library",
|
||||||
"//pkg/kubectl/cmd/testing:go_default_library",
|
"//pkg/kubectl/cmd/testing:go_default_library",
|
||||||
"//pkg/kubectl/cmd/util:go_default_library",
|
"//pkg/kubectl/cmd/util:go_default_library",
|
||||||
"//pkg/util/intstr:go_default_library",
|
"//pkg/util/intstr:go_default_library",
|
||||||
|
@ -42,6 +42,8 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/api/resource"
|
"k8s.io/kubernetes/pkg/api/resource"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
client "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
client "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||||
|
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
|
||||||
|
clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||||
certutil "k8s.io/kubernetes/pkg/util/cert"
|
certutil "k8s.io/kubernetes/pkg/util/cert"
|
||||||
@ -56,6 +58,7 @@ import (
|
|||||||
const (
|
const (
|
||||||
APIServerCN = "federation-apiserver"
|
APIServerCN = "federation-apiserver"
|
||||||
ControllerManagerCN = "federation-controller-manager"
|
ControllerManagerCN = "federation-controller-manager"
|
||||||
|
AdminCN = "admin"
|
||||||
HostClusterLocalDNSZoneName = "cluster.local."
|
HostClusterLocalDNSZoneName = "cluster.local."
|
||||||
|
|
||||||
lbAddrRetryInterval = 5 * time.Second
|
lbAddrRetryInterval = 5 * time.Second
|
||||||
@ -122,6 +125,7 @@ type entityKeyPairs struct {
|
|||||||
ca *triple.KeyPair
|
ca *triple.KeyPair
|
||||||
server *triple.KeyPair
|
server *triple.KeyPair
|
||||||
controllerManager *triple.KeyPair
|
controllerManager *triple.KeyPair
|
||||||
|
admin *triple.KeyPair
|
||||||
}
|
}
|
||||||
|
|
||||||
// initFederation initializes a federation control plane.
|
// initFederation initializes a federation control plane.
|
||||||
@ -194,6 +198,11 @@ func initFederation(cmdOut io.Writer, config util.AdminConfig, cmd *cobra.Comman
|
|||||||
advertiseAddress = ips[0]
|
advertiseAddress = ips[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
endpoint := advertiseAddress
|
||||||
|
if advertiseAddress == "" && len(hostnames) > 0 {
|
||||||
|
endpoint = hostnames[0]
|
||||||
|
}
|
||||||
|
|
||||||
// 6. Create federation API server
|
// 6. Create federation API server
|
||||||
_, err = createAPIServer(hostClientset, initFlags.FederationSystemNamespace, serverName, image, serverCredName, pvc.Name, advertiseAddress)
|
_, err = createAPIServer(hostClientset, initFlags.FederationSystemNamespace, serverName, image, serverCredName, pvc.Name, advertiseAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -206,6 +215,13 @@ func initFederation(cmdOut io.Writer, config util.AdminConfig, cmd *cobra.Comman
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 8. Write the federation API server endpoint info, credentials
|
||||||
|
// and context to kubeconfig
|
||||||
|
err = updateKubeconfig(config, initFlags.Name, endpoint, entKeyPairs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return printSuccess(cmdOut, ips, hostnames)
|
return printSuccess(cmdOut, ips, hostnames)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,10 +303,15 @@ func genCerts(svcNamespace, name, svcName, localDNSZoneName string, ips, hostnam
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create federation controller manager client key and certificate: %v", err)
|
return nil, fmt.Errorf("failed to create federation controller manager client key and certificate: %v", err)
|
||||||
}
|
}
|
||||||
|
admin, err := triple.NewClientKeyPair(ca, AdminCN)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create client key and certificate for an admin: %v", err)
|
||||||
|
}
|
||||||
return &entityKeyPairs{
|
return &entityKeyPairs{
|
||||||
ca: ca,
|
ca: ca,
|
||||||
server: server,
|
server: server,
|
||||||
controllerManager: cm,
|
controllerManager: cm,
|
||||||
|
admin: admin,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,7 +331,6 @@ func createAPIServerCredentialsSecret(clientset *client.Clientset, namespace, cr
|
|||||||
|
|
||||||
// Boilerplate to create the secret in the host cluster.
|
// Boilerplate to create the secret in the host cluster.
|
||||||
return clientset.Core().Secrets(namespace).Create(secret)
|
return clientset.Core().Secrets(namespace).Create(secret)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func createControllerManagerKubeconfigSecret(clientset *client.Clientset, namespace, name, svcName, kubeconfigName string, entKeyPairs *entityKeyPairs) (*api.Secret, error) {
|
func createControllerManagerKubeconfigSecret(clientset *client.Clientset, namespace, name, svcName, kubeconfigName string, entKeyPairs *entityKeyPairs) (*api.Secret, error) {
|
||||||
@ -532,3 +552,44 @@ func printSuccess(cmdOut io.Writer, ips, hostnames []string) error {
|
|||||||
_, err := fmt.Fprintf(cmdOut, "Federation API server is running at: %s\n", strings.Join(svcEndpoints, ", "))
|
_, err := fmt.Fprintf(cmdOut, "Federation API server is running at: %s\n", strings.Join(svcEndpoints, ", "))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateKubeconfig(config util.AdminConfig, name, endpoint string, entKeyPairs *entityKeyPairs) error {
|
||||||
|
po := config.PathOptions()
|
||||||
|
kubeconfig, err := po.GetStartingConfig()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate API server endpoint info.
|
||||||
|
cluster := clientcmdapi.NewCluster()
|
||||||
|
// Prefix "https" as the URL scheme to endpoint.
|
||||||
|
if !strings.HasPrefix(endpoint, "https://") {
|
||||||
|
endpoint = fmt.Sprintf("https://%s", endpoint)
|
||||||
|
}
|
||||||
|
cluster.Server = endpoint
|
||||||
|
cluster.CertificateAuthorityData = certutil.EncodeCertPEM(entKeyPairs.ca.Cert)
|
||||||
|
|
||||||
|
// Populate credentials.
|
||||||
|
authInfo := clientcmdapi.NewAuthInfo()
|
||||||
|
authInfo.ClientCertificateData = certutil.EncodeCertPEM(entKeyPairs.admin.Cert)
|
||||||
|
authInfo.ClientKeyData = certutil.EncodePrivateKeyPEM(entKeyPairs.admin.Key)
|
||||||
|
authInfo.Username = AdminCN
|
||||||
|
|
||||||
|
// Populate context.
|
||||||
|
context := clientcmdapi.NewContext()
|
||||||
|
context.Cluster = name
|
||||||
|
context.AuthInfo = name
|
||||||
|
|
||||||
|
// Update the config struct with API server endpoint info,
|
||||||
|
// credentials and context.
|
||||||
|
kubeconfig.Clusters[name] = cluster
|
||||||
|
kubeconfig.AuthInfos[name] = authInfo
|
||||||
|
kubeconfig.Contexts[name] = context
|
||||||
|
|
||||||
|
// Write the update kubeconfig.
|
||||||
|
if err := clientcmd.ModifyConfig(po, *kubeconfig, true); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -42,6 +42,7 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
"k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
||||||
"k8s.io/kubernetes/pkg/client/restclient/fake"
|
"k8s.io/kubernetes/pkg/client/restclient/fake"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/dynamic"
|
"k8s.io/kubernetes/pkg/client/typed/dynamic"
|
||||||
|
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
|
||||||
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
|
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
|
||||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"k8s.io/kubernetes/pkg/util/intstr"
|
"k8s.io/kubernetes/pkg/util/intstr"
|
||||||
@ -125,6 +126,8 @@ func TestInitFederation(t *testing.T) {
|
|||||||
t.Errorf("[%d] expected error: %s, got: %s, output: %s", i, tc.expectedErr, cmdErrMsg, buf.String())
|
t.Errorf("[%d] expected error: %s, got: %s, output: %s", i, tc.expectedErr, cmdErrMsg, buf.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testKubeconfigUpdate(t, tc.federation, tc.lbIP, tc.kubeconfigGlobal, tc.kubeconfigExplicit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -744,6 +747,60 @@ func fakeInitHostFactory(federationName, namespaceName, ip, dnsZoneName, image s
|
|||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testKubeconfigUpdate(t *testing.T, federationName, lbIP, kubeconfigGlobal, kubeconfigExplicit string) {
|
||||||
|
filename := kubeconfigGlobal
|
||||||
|
if kubeconfigExplicit != "" {
|
||||||
|
filename = kubeconfigExplicit
|
||||||
|
}
|
||||||
|
config, err := clientcmd.LoadFromFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to open kubeconfig file: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cluster, ok := config.Clusters[federationName]
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("No cluster info for %q", federationName)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
endpoint := lbIP
|
||||||
|
if !strings.HasSuffix(lbIP, "https://") {
|
||||||
|
endpoint = fmt.Sprintf("https://%s", lbIP)
|
||||||
|
}
|
||||||
|
if cluster.Server != endpoint {
|
||||||
|
t.Errorf("Want federation API server endpoint %q, got %q", endpoint, cluster.Server)
|
||||||
|
}
|
||||||
|
|
||||||
|
authInfo, ok := config.AuthInfos[federationName]
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("No credentials for %q", federationName)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(authInfo.ClientCertificateData) == 0 {
|
||||||
|
t.Errorf("Expected client certificate to be non-empty")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(authInfo.ClientKeyData) == 0 {
|
||||||
|
t.Errorf("Expected client key to be non-empty")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if authInfo.Username != AdminCN {
|
||||||
|
t.Errorf("Want username: %q, got: %q", AdminCN, authInfo.Username)
|
||||||
|
}
|
||||||
|
|
||||||
|
context, ok := config.Contexts[federationName]
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("No context for %q", federationName)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if context.Cluster != federationName {
|
||||||
|
t.Errorf("Want context cluster name: %q, got: %q", federationName, context.Cluster)
|
||||||
|
}
|
||||||
|
if context.AuthInfo != federationName {
|
||||||
|
t.Errorf("Want context auth info: %q, got: %q", federationName, context.AuthInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type clientServerTLSConfigs struct {
|
type clientServerTLSConfigs struct {
|
||||||
server *tls.Config
|
server *tls.Config
|
||||||
client *tls.Config
|
client *tls.Config
|
||||||
|
Loading…
Reference in New Issue
Block a user