Example #1
0
// createSecret creates a secret containing TLS certificates for the given Ingress.
// If a secret with the same name already exists in the namespace of the
// Ingress, it's updated.
func createSecret(kubeClient clientset.Interface, ing *extensions.Ingress) (host string, rootCA, privKey []byte, err error) {
	var k, c bytes.Buffer
	tls := ing.Spec.TLS[0]
	host = strings.Join(tls.Hosts, ",")
	framework.Logf("Generating RSA cert for host %v", host)

	if err = generateRSACerts(host, true, &k, &c); err != nil {
		return
	}
	cert := c.Bytes()
	key := k.Bytes()
	secret := &v1.Secret{
		ObjectMeta: v1.ObjectMeta{
			Name: tls.SecretName,
		},
		Data: map[string][]byte{
			v1.TLSCertKey:       cert,
			v1.TLSPrivateKeyKey: key,
		},
	}
	var s *v1.Secret
	if s, err = kubeClient.Core().Secrets(ing.Namespace).Get(tls.SecretName, metav1.GetOptions{}); err == nil {
		// TODO: Retry the update. We don't really expect anything to conflict though.
		framework.Logf("Updating secret %v in ns %v with hosts %v for ingress %v", secret.Name, secret.Namespace, host, ing.Name)
		s.Data = secret.Data
		_, err = kubeClient.Core().Secrets(ing.Namespace).Update(s)
	} else {
		framework.Logf("Creating secret %v in ns %v with hosts %v for ingress %v", secret.Name, secret.Namespace, host, ing.Name)
		_, err = kubeClient.Core().Secrets(ing.Namespace).Create(secret)
	}
	return host, cert, key, err
}
func secretsEqual(a, b apiv1.Secret) bool {
	// Clear the SelfLink and ObjectMeta.Finalizers since they will be different
	// in resoure in federation control plane and resource in underlying cluster.
	a.SelfLink = ""
	b.SelfLink = ""
	a.ObjectMeta.Finalizers = []string{}
	b.ObjectMeta.Finalizers = []string{}
	return reflect.DeepEqual(a, b)
}
func TestSecretController(t *testing.T) {
	cluster1 := mkCluster("cluster1", api_v1.ConditionTrue)
	cluster2 := mkCluster("cluster2", api_v1.ConditionTrue)

	fakeClient := &fake_federation_release_1_4.Clientset{}
	RegisterList("clusters", &fakeClient.Fake, &federation_api.ClusterList{Items: []federation_api.Cluster{*cluster1}})
	RegisterList("secrets", &fakeClient.Fake, &api_v1.SecretList{Items: []api_v1.Secret{}})
	secretWatch := RegisterWatch("secrets", &fakeClient.Fake)
	clusterWatch := RegisterWatch("clusters", &fakeClient.Fake)

	cluster1Client := &fake_kube_release_1_4.Clientset{}
	cluster1Watch := RegisterWatch("secrets", &cluster1Client.Fake)
	RegisterList("secrets", &cluster1Client.Fake, &api_v1.SecretList{Items: []api_v1.Secret{}})
	cluster1CreateChan := RegisterCopyOnCreate("secrets", &cluster1Client.Fake, cluster1Watch)
	cluster1UpdateChan := RegisterCopyOnUpdate("secrets", &cluster1Client.Fake, cluster1Watch)

	cluster2Client := &fake_kube_release_1_4.Clientset{}
	cluster2Watch := RegisterWatch("secrets", &cluster2Client.Fake)
	RegisterList("secrets", &cluster2Client.Fake, &api_v1.SecretList{Items: []api_v1.Secret{}})
	cluster2CreateChan := RegisterCopyOnCreate("secrets", &cluster2Client.Fake, cluster2Watch)

	secretController := NewSecretController(fakeClient)
	informer := toFederatedInformerForTestOnly(secretController.secretFederatedInformer)
	informer.SetClientFactory(func(cluster *federation_api.Cluster) (kube_release_1_4.Interface, error) {
		switch cluster.Name {
		case cluster1.Name:
			return cluster1Client, nil
		case cluster2.Name:
			return cluster2Client, nil
		default:
			return nil, fmt.Errorf("Unknown cluster")
		}
	})

	secretController.clusterAvailableDelay = time.Second
	secretController.secretReviewDelay = 50 * time.Millisecond
	secretController.smallDelay = 20 * time.Millisecond
	secretController.updateTimeout = 5 * time.Second

	stop := make(chan struct{})
	secretController.Run(stop)

	secret1 := api_v1.Secret{
		ObjectMeta: api_v1.ObjectMeta{
			Name:      "test-secret",
			Namespace: "mynamespace",
		},
		Data: map[string][]byte{
			"A": []byte("ala ma kota"),
			"B": []byte("quick brown fox"),
		},
		Type: api_v1.SecretTypeOpaque,
	}

	// Test add federated secret.
	secretWatch.Add(&secret1)
	createdSecret := GetSecretFromChan(cluster1CreateChan)
	assert.NotNil(t, createdSecret)
	assert.Equal(t, secret1.Namespace, createdSecret.Namespace)
	assert.Equal(t, secret1.Name, createdSecret.Name)
	assert.True(t, reflect.DeepEqual(&secret1, createdSecret))

	// Test update federated secret.
	secret1.Annotations = map[string]string{
		"A": "B",
	}
	secretWatch.Modify(&secret1)
	updatedSecret := GetSecretFromChan(cluster1UpdateChan)
	assert.NotNil(t, updatedSecret)
	assert.Equal(t, secret1.Name, updatedSecret.Name)
	assert.Equal(t, secret1.Namespace, updatedSecret.Namespace)
	assert.True(t, reflect.DeepEqual(&secret1, updatedSecret))

	// Test add cluster
	clusterWatch.Add(cluster2)
	createdSecret2 := GetSecretFromChan(cluster2CreateChan)
	assert.NotNil(t, createdSecret2)
	assert.Equal(t, secret1.Name, createdSecret2.Name)
	assert.Equal(t, secret1.Namespace, createdSecret2.Namespace)
	assert.True(t, reflect.DeepEqual(&secret1, createdSecret2))

	close(stop)
}
func TestSecretController(t *testing.T) {
	cluster1 := NewCluster("cluster1", api_v1.ConditionTrue)
	cluster2 := NewCluster("cluster2", api_v1.ConditionTrue)

	fakeClient := &fake_fedclientset.Clientset{}
	RegisterFakeList("clusters", &fakeClient.Fake, &federation_api.ClusterList{Items: []federation_api.Cluster{*cluster1}})
	RegisterFakeList("secrets", &fakeClient.Fake, &api_v1.SecretList{Items: []api_v1.Secret{}})
	secretWatch := RegisterFakeWatch("secrets", &fakeClient.Fake)
	clusterWatch := RegisterFakeWatch("clusters", &fakeClient.Fake)

	cluster1Client := &fake_kubeclientset.Clientset{}
	cluster1Watch := RegisterFakeWatch("secrets", &cluster1Client.Fake)
	RegisterFakeList("secrets", &cluster1Client.Fake, &api_v1.SecretList{Items: []api_v1.Secret{}})
	cluster1CreateChan := RegisterFakeCopyOnCreate("secrets", &cluster1Client.Fake, cluster1Watch)
	cluster1UpdateChan := RegisterFakeCopyOnUpdate("secrets", &cluster1Client.Fake, cluster1Watch)

	cluster2Client := &fake_kubeclientset.Clientset{}
	cluster2Watch := RegisterFakeWatch("secrets", &cluster2Client.Fake)
	RegisterFakeList("secrets", &cluster2Client.Fake, &api_v1.SecretList{Items: []api_v1.Secret{}})
	cluster2CreateChan := RegisterFakeCopyOnCreate("secrets", &cluster2Client.Fake, cluster2Watch)

	secretController := NewSecretController(fakeClient)
	informer := ToFederatedInformerForTestOnly(secretController.secretFederatedInformer)
	informer.SetClientFactory(func(cluster *federation_api.Cluster) (kubeclientset.Interface, error) {
		switch cluster.Name {
		case cluster1.Name:
			return cluster1Client, nil
		case cluster2.Name:
			return cluster2Client, nil
		default:
			return nil, fmt.Errorf("Unknown cluster")
		}
	})

	secretController.clusterAvailableDelay = time.Second
	secretController.secretReviewDelay = 50 * time.Millisecond
	secretController.smallDelay = 20 * time.Millisecond
	secretController.updateTimeout = 5 * time.Second

	stop := make(chan struct{})
	secretController.Run(stop)

	secret1 := api_v1.Secret{
		ObjectMeta: api_v1.ObjectMeta{
			Name:      "test-secret",
			Namespace: "ns",
			SelfLink:  "/api/v1/namespaces/ns/secrets/test-secret",
		},
		Data: map[string][]byte{
			"A": []byte("ala ma kota"),
			"B": []byte("quick brown fox"),
		},
		Type: api_v1.SecretTypeOpaque,
	}

	// Test add federated secret.
	secretWatch.Add(&secret1)
	createdSecret := GetSecretFromChan(cluster1CreateChan)
	assert.NotNil(t, createdSecret)
	assert.Equal(t, secret1.Namespace, createdSecret.Namespace)
	assert.Equal(t, secret1.Name, createdSecret.Name)
	assert.True(t, secretsEqual(secret1, *createdSecret))

	// Wait for the secret to appear in the informer store
	err := WaitForStoreUpdate(
		secretController.secretFederatedInformer.GetTargetStore(),
		cluster1.Name, types.NamespacedName{Namespace: secret1.Namespace, Name: secret1.Name}.String(), wait.ForeverTestTimeout)
	assert.Nil(t, err, "secret should have appeared in the informer store")

	// Test update federated secret.
	secret1.Annotations = map[string]string{
		"A": "B",
	}
	secretWatch.Modify(&secret1)
	updatedSecret := GetSecretFromChan(cluster1UpdateChan)
	assert.NotNil(t, updatedSecret)
	assert.Equal(t, secret1.Name, updatedSecret.Name)
	assert.Equal(t, secret1.Namespace, updatedSecret.Namespace)
	assert.True(t, secretsEqual(secret1, *updatedSecret))

	// Test update federated secret.
	secret1.Data = map[string][]byte{
		"config": []byte("myconfigurationfile"),
	}
	secretWatch.Modify(&secret1)
	updatedSecret2 := GetSecretFromChan(cluster1UpdateChan)
	assert.NotNil(t, updatedSecret)
	assert.Equal(t, secret1.Name, updatedSecret.Name)
	assert.Equal(t, secret1.Namespace, updatedSecret.Namespace)
	assert.True(t, secretsEqual(secret1, *updatedSecret2))

	// Test add cluster
	clusterWatch.Add(cluster2)
	createdSecret2 := GetSecretFromChan(cluster2CreateChan)
	assert.NotNil(t, createdSecret2)
	assert.Equal(t, secret1.Name, createdSecret2.Name)
	assert.Equal(t, secret1.Namespace, createdSecret2.Namespace)
	assert.True(t, secretsEqual(secret1, *createdSecret2))

	close(stop)
}
func secretsEqual(a, b api_v1.Secret) bool {
	a.SelfLink = ""
	b.SelfLink = ""
	return reflect.DeepEqual(a, b)
}
func TestSecretController(t *testing.T) {
	cluster1 := NewCluster("cluster1", apiv1.ConditionTrue)
	cluster2 := NewCluster("cluster2", apiv1.ConditionTrue)

	fakeClient := &fakefedclientset.Clientset{}
	RegisterFakeList("clusters", &fakeClient.Fake, &federationapi.ClusterList{Items: []federationapi.Cluster{*cluster1}})
	RegisterFakeList("secrets", &fakeClient.Fake, &apiv1.SecretList{Items: []apiv1.Secret{}})
	secretWatch := RegisterFakeWatch("secrets", &fakeClient.Fake)
	secretUpdateChan := RegisterFakeCopyOnUpdate("secrets", &fakeClient.Fake, secretWatch)
	clusterWatch := RegisterFakeWatch("clusters", &fakeClient.Fake)

	cluster1Client := &fakekubeclientset.Clientset{}
	cluster1Watch := RegisterFakeWatch("secrets", &cluster1Client.Fake)
	RegisterFakeList("secrets", &cluster1Client.Fake, &apiv1.SecretList{Items: []apiv1.Secret{}})
	cluster1CreateChan := RegisterFakeCopyOnCreate("secrets", &cluster1Client.Fake, cluster1Watch)
	cluster1UpdateChan := RegisterFakeCopyOnUpdate("secrets", &cluster1Client.Fake, cluster1Watch)

	cluster2Client := &fakekubeclientset.Clientset{}
	cluster2Watch := RegisterFakeWatch("secrets", &cluster2Client.Fake)
	RegisterFakeList("secrets", &cluster2Client.Fake, &apiv1.SecretList{Items: []apiv1.Secret{}})
	cluster2CreateChan := RegisterFakeCopyOnCreate("secrets", &cluster2Client.Fake, cluster2Watch)

	secretController := NewSecretController(fakeClient)
	informerClientFactory := func(cluster *federationapi.Cluster) (kubeclientset.Interface, error) {
		switch cluster.Name {
		case cluster1.Name:
			return cluster1Client, nil
		case cluster2.Name:
			return cluster2Client, nil
		default:
			return nil, fmt.Errorf("Unknown cluster")
		}
	}
	setClientFactory(secretController.secretFederatedInformer, informerClientFactory)

	secretController.clusterAvailableDelay = time.Second
	secretController.secretReviewDelay = 50 * time.Millisecond
	secretController.smallDelay = 20 * time.Millisecond
	secretController.updateTimeout = 5 * time.Second

	stop := make(chan struct{})
	secretController.Run(stop)

	secret1 := apiv1.Secret{
		ObjectMeta: apiv1.ObjectMeta{
			Name:      "test-secret",
			Namespace: "ns",
			SelfLink:  "/api/v1/namespaces/ns/secrets/test-secret",
		},
		Data: map[string][]byte{
			"A": []byte("ala ma kota"),
			"B": []byte("quick brown fox"),
		},
		Type: apiv1.SecretTypeOpaque,
	}

	// Test add federated secret.
	secretWatch.Add(&secret1)
	// There should be 2 updates to add both the finalizers.
	updatedSecret := GetSecretFromChan(secretUpdateChan)
	assert.True(t, secretController.hasFinalizerFunc(updatedSecret, deletionhelper.FinalizerDeleteFromUnderlyingClusters))
	updatedSecret = GetSecretFromChan(secretUpdateChan)
	assert.True(t, secretController.hasFinalizerFunc(updatedSecret, apiv1.FinalizerOrphan))
	secret1 = *updatedSecret

	// Verify that the secret is created in underlying cluster1.
	createdSecret := GetSecretFromChan(cluster1CreateChan)
	assert.NotNil(t, createdSecret)
	assert.Equal(t, secret1.Namespace, createdSecret.Namespace)
	assert.Equal(t, secret1.Name, createdSecret.Name)
	assert.True(t, secretsEqual(secret1, *createdSecret),
		fmt.Sprintf("expected: %v, actual: %v", secret1, *createdSecret))

	// Wait for the secret to appear in the informer store
	err := WaitForStoreUpdate(
		secretController.secretFederatedInformer.GetTargetStore(),
		cluster1.Name, types.NamespacedName{Namespace: secret1.Namespace, Name: secret1.Name}.String(), wait.ForeverTestTimeout)
	assert.Nil(t, err, "secret should have appeared in the informer store")

	checkAll := func(expected apiv1.Secret) CheckingFunction {
		return func(obj runtime.Object) error {
			glog.V(4).Infof("Checking %v", obj)
			s := obj.(*apiv1.Secret)
			if err := CompareObjectMeta(expected.ObjectMeta, s.ObjectMeta); err != nil {
				return err
			}
			if !reflect.DeepEqual(expected.Data, s.Data) {
				return fmt.Errorf("Data is different expected:%v actual:%v", expected.Data, s.Data)
			}
			if expected.Type != s.Type {
				return fmt.Errorf("Type is different expected:%v actual:%v", expected.Type, s.Type)
			}
			return nil
		}
	}

	// Test update federated secret.
	secret1.Annotations = map[string]string{
		"A": "B",
	}
	secretWatch.Modify(&secret1)
	err = CheckObjectFromChan(cluster1UpdateChan, checkAll(secret1))
	assert.NoError(t, err)

	// Wait for the secret to be updated in the informer store.
	err = WaitForSecretStoreUpdate(
		secretController.secretFederatedInformer.GetTargetStore(),
		cluster1.Name, types.NamespacedName{Namespace: secret1.Namespace, Name: secret1.Name}.String(),
		&secret1, wait.ForeverTestTimeout)
	assert.NoError(t, err, "secret should have been updated in the informer store")

	// Test update federated secret.
	secret1.Data = map[string][]byte{
		"config": []byte("myconfigurationfile"),
	}
	secretWatch.Modify(&secret1)
	err = CheckObjectFromChan(cluster1UpdateChan, checkAll(secret1))
	assert.NoError(t, err)

	// Test add cluster
	clusterWatch.Add(cluster2)
	createdSecret2 := GetSecretFromChan(cluster2CreateChan)
	assert.NotNil(t, createdSecret2)
	assert.Equal(t, secret1.Name, createdSecret2.Name)
	assert.Equal(t, secret1.Namespace, createdSecret2.Namespace)
	assert.True(t, secretsEqual(secret1, *createdSecret2),
		fmt.Sprintf("expected: %v, actual: %v", secret1, *createdSecret2))

	close(stop)
}