Merge pull request #42683 from perotinus/annotations

Automatic merge from submit-queue

[Federation][kubefed] Annotate all Federation API objects with the federation name and (if applicable) the cluster name.

Address part of #42324.

```release-note
Adds annotations to all Federation objects created by kubefed.
```
This commit is contained in:
Kubernetes Submit Queue 2017-04-10 18:42:00 -07:00 committed by GitHub
commit 3c7616eb19
8 changed files with 183 additions and 58 deletions

View File

@ -10,6 +10,7 @@ load(
go_library(
name = "go_default_library",
srcs = [
"annotations.go",
"doc.go",
"register.go",
"types.go",

View File

@ -0,0 +1,28 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package federation
// FederationNameAnnotation is the annotation which holds the name of
// the federation that an object is associated with. It must be
// applied to all API objects associated with that federation.
const FederationNameAnnotation = "federation.alpha.kubernetes.io/federation-name"
// ClusterNameAnnotation is the annotation which holds the name of
// the cluster that an object is associated with. If the object is
// not associated with any cluster, then this annotation is not
// required.
const ClusterNameAnnotation = "federation.alpha.kubernetes.io/cluster-name"

View File

@ -14,6 +14,7 @@ go_library(
tags = ["automanaged"],
deps = [
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
"//federation/apis/federation:go_default_library",
"//federation/pkg/kubefed/util:go_default_library",
"//pkg/api:go_default_library",
"//pkg/api/v1:go_default_library",
@ -42,6 +43,7 @@ go_test(
library = ":go_default_library",
tags = ["automanaged"],
deps = [
"//federation/apis/federation:go_default_library",
"//federation/pkg/kubefed/testing:go_default_library",
"//federation/pkg/kubefed/util:go_default_library",
"//pkg/api:go_default_library",

View File

@ -40,6 +40,7 @@ import (
certutil "k8s.io/client-go/util/cert"
triple "k8s.io/client-go/util/cert/triple"
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
"k8s.io/kubernetes/federation/apis/federation"
"k8s.io/kubernetes/federation/pkg/kubefed/util"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/v1"
@ -276,13 +277,13 @@ func (i *initFederation) Run(cmdOut io.Writer, config util.AdminConfig) error {
}
// 1. Create a namespace for federation system components
_, err = createNamespace(hostClientset, i.commonOptions.FederationSystemNamespace, i.options.dryRun)
_, err = createNamespace(hostClientset, i.commonOptions.Name, i.commonOptions.FederationSystemNamespace, i.options.dryRun)
if err != nil {
return err
}
// 2. Expose a network endpoint for the federation API server
svc, ips, hostnames, err := createService(hostClientset, i.commonOptions.FederationSystemNamespace, serverName, i.options.apiServerAdvertiseAddress, i.options.apiServerServiceType, i.options.dryRun)
svc, ips, hostnames, err := createService(hostClientset, i.commonOptions.FederationSystemNamespace, serverName, i.commonOptions.Name, i.options.apiServerAdvertiseAddress, i.options.apiServerServiceType, i.options.dryRun)
if err != nil {
return err
}
@ -294,7 +295,7 @@ func (i *initFederation) Run(cmdOut io.Writer, config util.AdminConfig) error {
}
// 3b. Create the secret containing the credentials.
_, err = createAPIServerCredentialsSecret(hostClientset, i.commonOptions.FederationSystemNamespace, serverCredName, credentials, i.options.dryRun)
_, err = createAPIServerCredentialsSecret(hostClientset, i.commonOptions.FederationSystemNamespace, serverCredName, i.commonOptions.Name, credentials, i.options.dryRun)
if err != nil {
return err
}
@ -310,7 +311,7 @@ func (i *initFederation) Run(cmdOut io.Writer, config util.AdminConfig) error {
// stores its data.
var pvc *api.PersistentVolumeClaim
if i.options.etcdPersistentStorage {
pvc, err = createPVC(hostClientset, i.commonOptions.FederationSystemNamespace, svc.Name, i.options.etcdPVCapacity, i.options.dryRun)
pvc, err = createPVC(hostClientset, i.commonOptions.FederationSystemNamespace, svc.Name, i.commonOptions.Name, i.options.etcdPVCapacity, i.options.dryRun)
if err != nil {
return err
}
@ -325,7 +326,7 @@ func (i *initFederation) Run(cmdOut io.Writer, config util.AdminConfig) error {
}
// 6. Create federation API server
_, err = createAPIServer(hostClientset, i.commonOptions.FederationSystemNamespace, serverName, i.options.image, advertiseAddress, serverCredName, i.options.apiServerEnableHTTPBasicAuth, i.options.apiServerEnableTokenAuth, i.options.apiServerOverrides, pvc, i.options.dryRun)
_, err = createAPIServer(hostClientset, i.commonOptions.FederationSystemNamespace, serverName, i.commonOptions.Name, i.options.image, advertiseAddress, serverCredName, i.options.apiServerEnableHTTPBasicAuth, i.options.apiServerEnableTokenAuth, i.options.apiServerOverrides, pvc, i.options.dryRun)
if err != nil {
return err
}
@ -339,21 +340,21 @@ func (i *initFederation) Run(cmdOut io.Writer, config util.AdminConfig) error {
if rbacAvailable {
// 7a. Create a service account in the host cluster for federation
// controller manager.
sa, err = createControllerManagerSA(rbacVersionedClientset, i.commonOptions.FederationSystemNamespace, i.options.dryRun)
sa, err = createControllerManagerSA(rbacVersionedClientset, i.commonOptions.FederationSystemNamespace, i.commonOptions.Name, i.options.dryRun)
if err != nil {
return err
}
// 7b. Create RBAC role and role binding for federation controller
// manager service account.
_, _, err = createRoleBindings(rbacVersionedClientset, i.commonOptions.FederationSystemNamespace, sa.Name, i.options.dryRun)
_, _, err = createRoleBindings(rbacVersionedClientset, i.commonOptions.FederationSystemNamespace, sa.Name, i.commonOptions.Name, i.options.dryRun)
if err != nil {
return err
}
}
// 7c. Create a dns-provider config secret
dnsProviderSecret, err := createDNSProviderConfigSecret(hostClientset, i.commonOptions.FederationSystemNamespace, dnsProviderSecretName, dnsProviderConfigBytes, i.options.dryRun)
dnsProviderSecret, err := createDNSProviderConfigSecret(hostClientset, i.commonOptions.FederationSystemNamespace, dnsProviderSecretName, i.commonOptions.Name, dnsProviderConfigBytes, i.options.dryRun)
if err != nil {
return err
}
@ -400,10 +401,11 @@ func (i *initFederation) Run(cmdOut io.Writer, config util.AdminConfig) error {
return err
}
func createNamespace(clientset client.Interface, namespace string, dryRun bool) (*api.Namespace, error) {
func createNamespace(clientset client.Interface, federationName, namespace string, dryRun bool) (*api.Namespace, error) {
ns := &api.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: namespace,
Name: namespace,
Annotations: map[string]string{federation.FederationNameAnnotation: federationName},
},
}
@ -414,12 +416,13 @@ func createNamespace(clientset client.Interface, namespace string, dryRun bool)
return clientset.Core().Namespaces().Create(ns)
}
func createService(clientset client.Interface, namespace, svcName, apiserverAdvertiseAddress string, apiserverServiceType v1.ServiceType, dryRun bool) (*api.Service, []string, []string, error) {
func createService(clientset client.Interface, namespace, svcName, federationName, apiserverAdvertiseAddress string, apiserverServiceType v1.ServiceType, dryRun bool) (*api.Service, []string, []string, error) {
svc := &api.Service{
ObjectMeta: metav1.ObjectMeta{
Name: svcName,
Namespace: namespace,
Labels: componentLabel,
Name: svcName,
Namespace: namespace,
Labels: componentLabel,
Annotations: map[string]string{federation.FederationNameAnnotation: federationName},
},
Spec: api.ServiceSpec{
Type: api.ServiceType(apiserverServiceType),
@ -563,7 +566,7 @@ func genCerts(svcNamespace, name, svcName, localDNSZoneName string, ips, hostnam
}, nil
}
func createAPIServerCredentialsSecret(clientset client.Interface, namespace, credentialsName string, credentials *credentials, dryRun bool) (*api.Secret, error) {
func createAPIServerCredentialsSecret(clientset client.Interface, namespace, credentialsName, federationName string, credentials *credentials, dryRun bool) (*api.Secret, error) {
// Build the secret object with API server credentials.
data := map[string][]byte{
"ca.crt": certutil.EncodeCertPEM(credentials.certEntKeyPairs.ca.Cert),
@ -579,8 +582,9 @@ func createAPIServerCredentialsSecret(clientset client.Interface, namespace, cre
secret := &api.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: credentialsName,
Namespace: namespace,
Name: credentialsName,
Namespace: namespace,
Annotations: map[string]string{federation.FederationNameAnnotation: federationName},
},
Data: data,
}
@ -602,10 +606,10 @@ func createControllerManagerKubeconfigSecret(clientset client.Interface, namespa
certutil.EncodeCertPEM(entKeyPairs.controllerManager.Cert),
)
return util.CreateKubeconfigSecret(clientset, config, namespace, kubeconfigName, dryRun)
return util.CreateKubeconfigSecret(clientset, config, namespace, kubeconfigName, name, "", dryRun)
}
func createPVC(clientset client.Interface, namespace, svcName, etcdPVCapacity string, dryRun bool) (*api.PersistentVolumeClaim, error) {
func createPVC(clientset client.Interface, namespace, svcName, federationName, etcdPVCapacity string, dryRun bool) (*api.PersistentVolumeClaim, error) {
capacity, err := resource.ParseQuantity(etcdPVCapacity)
if err != nil {
return nil, err
@ -618,7 +622,7 @@ func createPVC(clientset client.Interface, namespace, svcName, etcdPVCapacity st
Labels: componentLabel,
Annotations: map[string]string{
"volume.alpha.kubernetes.io/storage-class": "yes",
},
federation.FederationNameAnnotation: federationName},
},
Spec: api.PersistentVolumeClaimSpec{
AccessModes: []api.PersistentVolumeAccessMode{
@ -639,7 +643,7 @@ func createPVC(clientset client.Interface, namespace, svcName, etcdPVCapacity st
return clientset.Core().PersistentVolumeClaims(namespace).Create(pvc)
}
func createAPIServer(clientset client.Interface, namespace, name, image, advertiseAddress, credentialsName string, hasHTTPBasicAuthFile, hasTokenAuthFile bool, argOverrides map[string]string, pvc *api.PersistentVolumeClaim, dryRun bool) (*extensions.Deployment, error) {
func createAPIServer(clientset client.Interface, namespace, name, federationName, image, advertiseAddress, credentialsName string, hasHTTPBasicAuthFile, hasTokenAuthFile bool, argOverrides map[string]string, pvc *api.PersistentVolumeClaim, dryRun bool) (*extensions.Deployment, error) {
command := []string{
"/hyperkube",
"federation-apiserver",
@ -669,16 +673,18 @@ func createAPIServer(clientset client.Interface, namespace, name, image, adverti
dep := &extensions.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Labels: componentLabel,
Name: name,
Namespace: namespace,
Labels: componentLabel,
Annotations: map[string]string{federation.FederationNameAnnotation: federationName},
},
Spec: extensions.DeploymentSpec{
Replicas: 1,
Template: api.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Labels: apiserverPodLabels,
Name: name,
Labels: apiserverPodLabels,
Annotations: map[string]string{federation.FederationNameAnnotation: federationName},
},
Spec: api.PodSpec{
Containers: []api.Container{
@ -756,15 +762,17 @@ func createAPIServer(clientset client.Interface, namespace, name, image, adverti
return dep, nil
}
return clientset.Extensions().Deployments(namespace).Create(dep)
createdDep, err := clientset.Extensions().Deployments(namespace).Create(dep)
return createdDep, err
}
func createControllerManagerSA(clientset client.Interface, namespace string, dryRun bool) (*api.ServiceAccount, error) {
func createControllerManagerSA(clientset client.Interface, namespace, federationName string, dryRun bool) (*api.ServiceAccount, error) {
sa := &api.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
Name: ControllerManagerSA,
Namespace: namespace,
Labels: componentLabel,
Name: ControllerManagerSA,
Namespace: namespace,
Labels: componentLabel,
Annotations: map[string]string{federation.FederationNameAnnotation: federationName},
},
}
if dryRun {
@ -773,15 +781,16 @@ func createControllerManagerSA(clientset client.Interface, namespace string, dry
return clientset.Core().ServiceAccounts(namespace).Create(sa)
}
func createRoleBindings(clientset client.Interface, namespace, saName string, dryRun bool) (*rbac.Role, *rbac.RoleBinding, error) {
func createRoleBindings(clientset client.Interface, namespace, saName, federationName string, dryRun bool) (*rbac.Role, *rbac.RoleBinding, error) {
roleName := "federation-system:federation-controller-manager"
role := &rbac.Role{
// a role to use for bootstrapping the federation-controller-manager so it can access
// secrets in the host cluster to access other clusters.
ObjectMeta: metav1.ObjectMeta{
Name: roleName,
Namespace: namespace,
Labels: componentLabel,
Name: roleName,
Namespace: namespace,
Labels: componentLabel,
Annotations: map[string]string{federation.FederationNameAnnotation: federationName},
},
Rules: []rbac.PolicyRule{
rbac.NewRule("get", "list", "watch").Groups(legacyAPIGroup).Resources("secrets").RuleOrDie(),
@ -793,6 +802,7 @@ func createRoleBindings(clientset client.Interface, namespace, saName string, dr
return nil, nil, err
}
rolebinding.Labels = componentLabel
rolebinding.Annotations = map[string]string{federation.FederationNameAnnotation: federationName}
if dryRun {
return role, &rolebinding, nil
@ -839,15 +849,17 @@ func createControllerManager(clientset client.Interface, namespace, name, svcNam
// https://github.com/kubernetes/dns/blob/master/pkg/dns/federation/federation.go
// TODO v2: Until kube-dns can handle trailing periods we strip them all.
// See https://github.com/kubernetes/dns/issues/67
util.FedDomainMapKey: fmt.Sprintf("%s=%s", name, strings.TrimRight(dnsZoneName, ".")),
util.FedDomainMapKey: fmt.Sprintf("%s=%s", name, strings.TrimRight(dnsZoneName, ".")),
federation.FederationNameAnnotation: name,
},
},
Spec: extensions.DeploymentSpec{
Replicas: 1,
Template: api.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Name: cmName,
Labels: controllerManagerPodLabels,
Name: cmName,
Labels: controllerManagerPodLabels,
Annotations: map[string]string{federation.FederationNameAnnotation: name},
},
Spec: api.PodSpec{
Containers: []api.Container{
@ -1049,15 +1061,16 @@ func updateKubeconfig(config util.AdminConfig, name, endpoint, kubeConfigPath st
return nil
}
func createDNSProviderConfigSecret(clientset client.Interface, namespace, name string, dnsProviderConfigBytes []byte, dryRun bool) (*api.Secret, error) {
func createDNSProviderConfigSecret(clientset client.Interface, namespace, name, federationName string, dnsProviderConfigBytes []byte, dryRun bool) (*api.Secret, error) {
if dnsProviderConfigBytes == nil {
return nil, nil
}
secretSpec := &api.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Name: name,
Namespace: namespace,
Annotations: map[string]string{federation.FederationNameAnnotation: federationName},
},
Data: map[string][]byte{
name: dnsProviderConfigBytes,

View File

@ -42,6 +42,7 @@ import (
"k8s.io/client-go/dynamic"
"k8s.io/client-go/rest/fake"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/kubernetes/federation/apis/federation"
kubefedtesting "k8s.io/kubernetes/federation/pkg/kubefed/testing"
"k8s.io/kubernetes/federation/pkg/kubefed/util"
"k8s.io/kubernetes/pkg/api"
@ -619,6 +620,9 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
},
ObjectMeta: metav1.ObjectMeta{
Name: namespaceName,
Annotations: map[string]string{
federation.FederationNameAnnotation: federationName,
},
},
}
@ -631,6 +635,9 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
Namespace: namespaceName,
Name: svcName,
Labels: componentLabel,
Annotations: map[string]string{
federation.FederationNameAnnotation: federationName,
},
},
Spec: v1.ServiceSpec{
Type: apiserverServiceType,
@ -664,6 +671,9 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
ObjectMeta: metav1.ObjectMeta{
Name: credSecretName,
Namespace: namespaceName,
Annotations: map[string]string{
federation.FederationNameAnnotation: federationName,
},
},
Data: nil,
}
@ -676,6 +686,9 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
ObjectMeta: metav1.ObjectMeta{
Name: cmKubeconfigSecretName,
Namespace: namespaceName,
Annotations: map[string]string{
federation.FederationNameAnnotation: federationName,
},
},
Data: nil,
}
@ -688,6 +701,9 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
ObjectMeta: metav1.ObjectMeta{
Name: dnsProviderSecretName,
Namespace: namespaceName,
Annotations: map[string]string{
federation.FederationNameAnnotation: federationName,
},
},
Data: nil,
}
@ -703,6 +719,7 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
Labels: componentLabel,
Annotations: map[string]string{
"volume.alpha.kubernetes.io/storage-class": "yes",
federation.FederationNameAnnotation: federationName,
},
},
Spec: v1.PersistentVolumeClaimSpec{
@ -726,6 +743,9 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
Name: "federation-controller-manager",
Namespace: namespaceName,
Labels: componentLabel,
Annotations: map[string]string{
federation.FederationNameAnnotation: federationName,
},
},
}
@ -738,6 +758,9 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
Name: "federation-system:federation-controller-manager",
Namespace: namespaceName,
Labels: componentLabel,
Annotations: map[string]string{
federation.FederationNameAnnotation: federationName,
},
},
Rules: []rbacv1beta1.PolicyRule{
{
@ -757,6 +780,9 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
Name: "federation-system:federation-controller-manager",
Namespace: namespaceName,
Labels: componentLabel,
Annotations: map[string]string{
federation.FederationNameAnnotation: federationName,
},
},
Subjects: []rbacv1beta1.Subject{
{
@ -838,17 +864,19 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
APIVersion: testapi.Extensions.GroupVersion().String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: svcName,
Namespace: namespaceName,
Labels: componentLabel,
Name: svcName,
Namespace: namespaceName,
Labels: componentLabel,
Annotations: map[string]string{federation.FederationNameAnnotation: federationName},
},
Spec: v1beta1.DeploymentSpec{
Replicas: &replicas,
Selector: nil,
Template: v1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Name: svcName,
Labels: apiserverPodLabels,
Name: svcName,
Labels: apiserverPodLabels,
Annotations: map[string]string{federation.FederationNameAnnotation: federationName},
},
Spec: v1.PodSpec{
Containers: []v1.Container{
@ -954,7 +982,8 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
Namespace: namespaceName,
Labels: componentLabel,
Annotations: map[string]string{
util.FedDomainMapKey: fmt.Sprintf("%s=%s", federationName, strings.TrimRight(dnsZoneName, ".")),
util.FedDomainMapKey: fmt.Sprintf("%s=%s", federationName, strings.TrimRight(dnsZoneName, ".")),
federation.FederationNameAnnotation: federationName,
},
},
Spec: v1beta1.DeploymentSpec{
@ -962,8 +991,9 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
Selector: nil,
Template: v1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Name: cmName,
Labels: controllerManagerPodLabels,
Name: cmName,
Labels: controllerManagerPodLabels,
Annotations: map[string]string{federation.FederationNameAnnotation: federationName},
},
Spec: v1.PodSpec{
Containers: []v1.Container{
@ -1196,6 +1226,7 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
case cmName:
want = *cm
}
//want = *cm
if !apiequality.Semantic.DeepEqual(got, want) {
return nil, fmt.Errorf("unexpected deployment object\n\tDiff: %s", diff.ObjectGoPrintDiff(got, want))
}

View File

@ -23,6 +23,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"k8s.io/kubernetes/federation/apis/federation"
"k8s.io/kubernetes/federation/pkg/kubefed/util"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/kubectl"
@ -150,6 +151,12 @@ func (j *joinFederation) Run(f cmdutil.Factory, cmdOut io.Writer, config util.Ad
return err
}
federationName, err := getFederationName(hostClientset, j.commonOptions.FederationSystemNamespace)
if err != nil {
glog.V(2).Infof("Failed to get the federation name: %v", err)
return err
}
// We are not using the `kubectl create secret` machinery through
// `RunCreateSubcommand` as we do to the cluster resource below
// because we have a bunch of requirements that the machinery does
@ -165,7 +172,7 @@ func (j *joinFederation) Run(f cmdutil.Factory, cmdOut io.Writer, config util.Ad
// don't have to print the created secret in the default case.
// Having said that, secret generation machinery could be altered to
// suit our needs, but it is far less invasive and readable this way.
_, err = createSecret(hostClientset, clientConfig, j.commonOptions.FederationSystemNamespace, j.options.clusterContext, j.options.secretName, j.options.dryRun)
_, err = createSecret(hostClientset, clientConfig, j.commonOptions.FederationSystemNamespace, federationName, j.commonOptions.Name, j.options.clusterContext, j.options.secretName, j.options.dryRun)
if err != nil {
glog.V(2).Infof("Failed creating the cluster credentials secret: %v", err)
return err
@ -185,7 +192,7 @@ func (j *joinFederation) Run(f cmdutil.Factory, cmdOut io.Writer, config util.Ad
// We further need to create a configmap named kube-config in the
// just registered cluster which will be consumed by the kube-dns
// of this cluster.
_, err = createConfigMap(hostClientset, config, j.commonOptions.FederationSystemNamespace, j.options.clusterContext, j.commonOptions.Kubeconfig, j.options.dryRun)
_, err = createConfigMap(hostClientset, config, j.commonOptions.FederationSystemNamespace, federationName, j.commonOptions.Name, j.options.clusterContext, j.commonOptions.Kubeconfig, j.options.dryRun)
if err != nil {
glog.V(2).Infof("Failed creating the config map in cluster: %v", err)
return err
@ -213,7 +220,7 @@ func minifyConfig(clientConfig *clientcmdapi.Config, context string) (*clientcmd
// createSecret extracts the kubeconfig for a given cluster and populates
// a secret with that kubeconfig.
func createSecret(clientset internalclientset.Interface, clientConfig *clientcmdapi.Config, namespace, contextName, secretName string, dryRun bool) (runtime.Object, error) {
func createSecret(clientset internalclientset.Interface, clientConfig *clientcmdapi.Config, namespace, federationName, clusterName, contextName, secretName string, dryRun bool) (runtime.Object, error) {
// Minify the kubeconfig to ensure that there is only information
// relevant to the cluster we are registering.
newClientConfig, err := minifyConfig(clientConfig, contextName)
@ -230,13 +237,13 @@ func createSecret(clientset internalclientset.Interface, clientConfig *clientcmd
return nil, err
}
return util.CreateKubeconfigSecret(clientset, newClientConfig, namespace, secretName, dryRun)
return util.CreateKubeconfigSecret(clientset, newClientConfig, namespace, secretName, federationName, clusterName, dryRun)
}
// createConfigMap creates a configmap with name kube-dns in the joining cluster
// which stores the information about this federation zone name.
// If the configmap with this name already exists, its updated with this information.
func createConfigMap(hostClientSet internalclientset.Interface, config util.AdminConfig, fedSystemNamespace, targetClusterContext, kubeconfigPath string, dryRun bool) (*api.ConfigMap, error) {
func createConfigMap(hostClientSet internalclientset.Interface, config util.AdminConfig, fedSystemNamespace, federationName, targetClusterName, targetClusterContext, kubeconfigPath string, dryRun bool) (*api.ConfigMap, error) {
cmDep, err := getCMDeployment(hostClientSet, fedSystemNamespace)
if err != nil {
return nil, err
@ -258,6 +265,10 @@ func createConfigMap(hostClientSet internalclientset.Interface, config util.Admi
ObjectMeta: metav1.ObjectMeta{
Name: util.KubeDnsConfigmapName,
Namespace: metav1.NamespaceSystem,
Annotations: map[string]string{
federation.FederationNameAnnotation: federationName,
federation.ClusterNameAnnotation: targetClusterName,
},
},
Data: map[string]string{
util.FedDomainMapKey: domainMap,
@ -366,3 +377,19 @@ func appendConfigMapString(existing string, toAppend string) string {
}
return fmt.Sprintf("%s,%s", existing, toAppend)
}
// getFederationName gets the federation name from the appropriate annotation on the
// control manager deployment.
func getFederationName(hostClientSet internalclientset.Interface, fedNamespace string) (string, error) {
d, err := getCMDeployment(hostClientSet, fedNamespace)
if err != nil {
return "", err
}
name, ok := d.Annotations[federation.FederationNameAnnotation]
if !ok {
return "", fmt.Errorf("Federation control manager does not have federation name annotation. Please recreate the federation with a newer version of kubefed, or use an older version of kubefed to join this cluster.")
}
return name, nil
}

View File

@ -30,6 +30,7 @@ import (
"k8s.io/client-go/rest/fake"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"k8s.io/kubernetes/federation/apis/federation"
federationapi "k8s.io/kubernetes/federation/apis/federation/v1beta1"
kubefedtesting "k8s.io/kubernetes/federation/pkg/kubefed/testing"
"k8s.io/kubernetes/federation/pkg/kubefed/util"
@ -41,6 +42,11 @@ import (
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
)
// testFederationName is a name to use for the federation in tests. Since the federation
// name is recovered from the federation itself, this constant is an appropriate
// functional replica.
const testFederationName = "test-federation"
func TestJoinFederation(t *testing.T) {
cmdErrMsg := ""
cmdutil.BehaviorOnFatal(func(str string, code int) {
@ -253,6 +259,10 @@ func fakeJoinHostFactory(clusterName, clusterCtx, secretName, server, token stri
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
Namespace: util.DefaultFederationSystemNamespace,
Annotations: map[string]string{
federation.FederationNameAnnotation: testFederationName,
federation.ClusterNameAnnotation: clusterName,
},
},
Data: map[string][]byte{
"kubeconfig": configBytes,
@ -275,7 +285,8 @@ func fakeJoinHostFactory(clusterName, clusterCtx, secretName, server, token stri
Name: cmName,
Namespace: util.DefaultFederationSystemNamespace,
Annotations: map[string]string{
util.FedDomainMapKey: fmt.Sprintf("%s=%s", clusterCtx, "test-dns-zone"),
util.FedDomainMapKey: fmt.Sprintf("%s=%s", clusterCtx, "test-dns-zone"),
federation.FederationNameAnnotation: testFederationName,
},
},
},
@ -324,6 +335,10 @@ func fakeJoinTargetClusterFactory(clusterName, clusterCtx string) (cmdutil.Facto
ObjectMeta: metav1.ObjectMeta{
Name: util.KubeDnsConfigmapName,
Namespace: metav1.NamespaceSystem,
Annotations: map[string]string{
federation.FederationNameAnnotation: testFederationName,
federation.ClusterNameAnnotation: clusterName,
},
},
Data: map[string]string{
util.FedDomainMapKey: fmt.Sprintf("%s=%s", clusterCtx, "test-dns-zone"),

View File

@ -148,18 +148,26 @@ func (o *SubcommandOptions) SetName(cmd *cobra.Command, args []string) error {
return nil
}
func CreateKubeconfigSecret(clientset client.Interface, kubeconfig *clientcmdapi.Config, namespace, name string, dryRun bool) (*api.Secret, error) {
func CreateKubeconfigSecret(clientset client.Interface, kubeconfig *clientcmdapi.Config, namespace, name, federationName, clusterName string, dryRun bool) (*api.Secret, error) {
configBytes, err := clientcmd.Write(*kubeconfig)
if err != nil {
return nil, err
}
annotations := map[string]string{
federationapi.FederationNameAnnotation: federationName,
}
if clusterName != "" {
annotations[federationapi.ClusterNameAnnotation] = clusterName
}
// Build the secret object with the minified and flattened
// kubeconfig content.
secret := &api.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Name: name,
Namespace: namespace,
Annotations: annotations,
},
Data: map[string][]byte{
KubeconfigSecretDataKey: configBytes,