mirror of https://github.com/k3s-io/k3s
Merge pull request #31139 from nikhiljindal/namespaceAdmissionControl
Automatic merge from submit-queue federation: Adding support for namespace admission controls in federation-apiserver Now that we have namespaces in federation apiserver, we can support namespace admission controls. There are 3 of these: namespace/autoprovision, namespace/exists and namespace/lifecycle. namespace/autoprovision, namespace/exists should be deprecated in kubernetes(https://github.com/kubernetes/kubernetes/issues/31195). Adding support for namespace/lifecycle to federation-apiserver. As in kube-apiserver, enabling namespace/lifecycle by default. ```release-note Action required: If you have a running federation control plane, you will have to ensure that for all federation resources, the corresponding namespace exists in federation control plane. federation-apiserver now supports NamespaceLifecycle admission control, which is enabled by default. Set the --admission-control flag on the server to change that. ``` cc @kubernetes/sig-cluster-federation @quinton-hoolepull/6/head
commit
13305ef0ff
|
@ -94,7 +94,7 @@ function create-federation-api-objects {
|
|||
export FEDERATION_API_NODEPORT=32111
|
||||
export FEDERATION_NAMESPACE
|
||||
export FEDERATION_NAME="${FEDERATION_NAME:-federation}"
|
||||
export DNS_ZONE_NAME="${DNS_ZONE_NAME:-federation.example}" # See https://tools.ietf.org/html/rfc2606
|
||||
export DNS_ZONE_NAME="${DNS_ZONE_NAME:-federation.example.}" # See https://tools.ietf.org/html/rfc2606
|
||||
|
||||
template="go run ${KUBE_ROOT}/federation/cluster/template.go"
|
||||
|
||||
|
@ -186,6 +186,9 @@ function create-federation-api-objects {
|
|||
export FEDERATION_APISERVER_CERT_BASE64="${FEDERATION_APISERVER_CERT_BASE64}"
|
||||
export FEDERATION_APISERVER_KEY_BASE64="${FEDERATION_APISERVER_KEY_BASE64}"
|
||||
|
||||
# Enable the NamespaceLifecycle admission control by default.
|
||||
export FEDERATION_ADMISSION_CONTROL="${FEDERATION_ADMISSION_CONTROL:-NamespaceLifecycle}"
|
||||
|
||||
for file in federation-etcd-pvc.yaml federation-apiserver-{deployment,secrets}.yaml federation-controller-manager-deployment.yaml; do
|
||||
$template "${manifests_root}/${file}" | $host_kubectl create -f -
|
||||
done
|
||||
|
|
|
@ -26,4 +26,5 @@ import (
|
|||
// Admission policies
|
||||
_ "k8s.io/kubernetes/plugin/pkg/admission/admit"
|
||||
_ "k8s.io/kubernetes/plugin/pkg/admission/deny"
|
||||
_ "k8s.io/kubernetes/plugin/pkg/admission/namespace/lifecycle"
|
||||
)
|
||||
|
|
|
@ -27,7 +27,7 @@ spec:
|
|||
- --basic-auth-file=/srv/kubernetes/basic_auth.csv
|
||||
- --tls-cert-file=/srv/kubernetes/server.cert
|
||||
- --tls-private-key-file=/srv/kubernetes/server.key
|
||||
# TODO: --admission-control values must be set when support is added for each type of control.
|
||||
- --admission-control={{.FEDERATION_ADMISSION_CONTROL}}
|
||||
- --token-auth-file=/srv/kubernetes/known-tokens.csv
|
||||
ports:
|
||||
- containerPort: 443
|
||||
|
|
|
@ -40,24 +40,27 @@ var _ = framework.KubeDescribe("Federation secrets [Feature:Federation]", func()
|
|||
AfterEach(func() {
|
||||
framework.SkipUnlessFederated(f.Client)
|
||||
|
||||
nsName := f.FederationNamespace.Name
|
||||
// Delete registered secrets.
|
||||
// This is if a test failed, it should not affect other tests.
|
||||
secretList, err := f.FederationClientset_1_4.Core().Secrets(f.Namespace.Name).List(api.ListOptions{})
|
||||
secretList, err := f.FederationClientset_1_4.Core().Secrets(nsName).List(api.ListOptions{})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
for _, secret := range secretList.Items {
|
||||
err := f.FederationClientset_1_4.Core().Secrets(f.Namespace.Name).Delete(secret.Name, &api.DeleteOptions{})
|
||||
err := f.FederationClientset_1_4.Core().Secrets(nsName).Delete(secret.Name, &api.DeleteOptions{})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
})
|
||||
|
||||
It("should be created and deleted successfully", func() {
|
||||
framework.SkipUnlessFederated(f.Client)
|
||||
secret := createSecretOrFail(f.FederationClientset_1_4, f.Namespace.Name)
|
||||
By(fmt.Sprintf("Creation of secret %q in namespace %q succeeded. Deleting secret.", secret.Name, f.Namespace.Name))
|
||||
|
||||
nsName := f.FederationNamespace.Name
|
||||
secret := createSecretOrFail(f.FederationClientset_1_4, nsName)
|
||||
By(fmt.Sprintf("Creation of secret %q in namespace %q succeeded. Deleting secret.", secret.Name, nsName))
|
||||
// Cleanup
|
||||
err := f.FederationClientset_1_4.Core().Secrets(f.Namespace.Name).Delete(secret.Name, &api.DeleteOptions{})
|
||||
err := f.FederationClientset_1_4.Core().Secrets(nsName).Delete(secret.Name, &api.DeleteOptions{})
|
||||
framework.ExpectNoError(err, "Error deleting secret %q in namespace %q", secret.Name, secret.Namespace)
|
||||
By(fmt.Sprintf("Deletion of secret %q in namespace %q succeeded.", secret.Name, f.Namespace.Name))
|
||||
By(fmt.Sprintf("Deletion of secret %q in namespace %q succeeded.", secret.Name, nsName))
|
||||
})
|
||||
|
||||
})
|
||||
|
|
|
@ -76,23 +76,27 @@ var _ = framework.KubeDescribe("[Feature:Federation]", func() {
|
|||
|
||||
It("should succeed", func() {
|
||||
framework.SkipUnlessFederated(f.Client)
|
||||
service := createServiceOrFail(f.FederationClientset_1_4, f.Namespace.Name, FederatedServiceName)
|
||||
By(fmt.Sprintf("Creation of service %q in namespace %q succeeded. Deleting service.", service.Name, f.Namespace.Name))
|
||||
|
||||
nsName := f.FederationNamespace.Name
|
||||
service := createServiceOrFail(f.FederationClientset_1_4, nsName, FederatedServiceName)
|
||||
By(fmt.Sprintf("Creation of service %q in namespace %q succeeded. Deleting service.", service.Name, nsName))
|
||||
// Cleanup
|
||||
err := f.FederationClientset_1_4.Services(f.Namespace.Name).Delete(service.Name, &api.DeleteOptions{})
|
||||
err := f.FederationClientset_1_4.Services(nsName).Delete(service.Name, &api.DeleteOptions{})
|
||||
framework.ExpectNoError(err, "Error deleting service %q in namespace %q", service.Name, service.Namespace)
|
||||
By(fmt.Sprintf("Deletion of service %q in namespace %q succeeded.", service.Name, f.Namespace.Name))
|
||||
By(fmt.Sprintf("Deletion of service %q in namespace %q succeeded.", service.Name, nsName))
|
||||
})
|
||||
|
||||
It("should create matching services in underlying clusters", func() {
|
||||
framework.SkipUnlessFederated(f.Client)
|
||||
service := createServiceOrFail(f.FederationClientset_1_4, f.Namespace.Name, FederatedServiceName)
|
||||
|
||||
nsName := f.FederationNamespace.Name
|
||||
service := createServiceOrFail(f.FederationClientset_1_4, nsName, FederatedServiceName)
|
||||
defer func() { // Cleanup
|
||||
By(fmt.Sprintf("Deleting service %q in namespace %q", service.Name, f.Namespace.Name))
|
||||
err := f.FederationClientset_1_4.Services(f.Namespace.Name).Delete(service.Name, &api.DeleteOptions{})
|
||||
framework.ExpectNoError(err, "Error deleting service %q in namespace %q", service.Name, f.Namespace.Name)
|
||||
By(fmt.Sprintf("Deleting service %q in namespace %q", service.Name, nsName))
|
||||
err := f.FederationClientset_1_4.Services(nsName).Delete(service.Name, &api.DeleteOptions{})
|
||||
framework.ExpectNoError(err, "Error deleting service %q in namespace %q", service.Name, nsName)
|
||||
}()
|
||||
waitForServiceShardsOrFail(f.Namespace.Name, service, clusters)
|
||||
waitForServiceShardsOrFail(nsName, service, clusters)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -104,17 +108,21 @@ var _ = framework.KubeDescribe("[Feature:Federation]", func() {
|
|||
|
||||
BeforeEach(func() {
|
||||
framework.SkipUnlessFederated(f.Client)
|
||||
createBackendPodsOrFail(clusters, f.Namespace.Name, FederatedServicePodName)
|
||||
service = createServiceOrFail(f.FederationClientset_1_4, f.Namespace.Name, FederatedServiceName)
|
||||
waitForServiceShardsOrFail(f.Namespace.Name, service, clusters)
|
||||
|
||||
nsName := f.FederationNamespace.Name
|
||||
createBackendPodsOrFail(clusters, nsName, FederatedServicePodName)
|
||||
service = createServiceOrFail(f.FederationClientset_1_4, nsName, FederatedServiceName)
|
||||
waitForServiceShardsOrFail(nsName, service, clusters)
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
framework.SkipUnlessFederated(f.Client)
|
||||
deleteBackendPodsOrFail(clusters, f.Namespace.Name)
|
||||
|
||||
nsName := f.FederationNamespace.Name
|
||||
deleteBackendPodsOrFail(clusters, nsName)
|
||||
|
||||
if service != nil {
|
||||
deleteServiceOrFail(f.FederationClientset_1_4, f.Namespace.Name, service.Name)
|
||||
deleteServiceOrFail(f.FederationClientset_1_4, nsName, service.Name)
|
||||
service = nil
|
||||
} else {
|
||||
By("No service to delete. Service is nil")
|
||||
|
@ -124,12 +132,13 @@ var _ = framework.KubeDescribe("[Feature:Federation]", func() {
|
|||
It("should be able to discover a federated service", func() {
|
||||
framework.SkipUnlessFederated(f.Client)
|
||||
|
||||
nsName := f.FederationNamespace.Name
|
||||
svcDNSNames := []string{
|
||||
FederatedServiceName,
|
||||
fmt.Sprintf("%s.%s", FederatedServiceName, f.Namespace.Name),
|
||||
fmt.Sprintf("%s.%s.svc.cluster.local.", FederatedServiceName, f.Namespace.Name),
|
||||
fmt.Sprintf("%s.%s.%s", FederatedServiceName, f.Namespace.Name, federationName),
|
||||
fmt.Sprintf("%s.%s.%s.svc.cluster.local.", FederatedServiceName, f.Namespace.Name, federationName),
|
||||
fmt.Sprintf("%s.%s", FederatedServiceName, nsName),
|
||||
fmt.Sprintf("%s.%s.svc.cluster.local.", FederatedServiceName, nsName),
|
||||
fmt.Sprintf("%s.%s.%s", FederatedServiceName, nsName, federationName),
|
||||
fmt.Sprintf("%s.%s.%s.svc.cluster.local.", FederatedServiceName, nsName, federationName),
|
||||
}
|
||||
// TODO(mml): This could be much faster. We can launch all the test
|
||||
// pods, perhaps in the BeforeEach, and then just poll until we get
|
||||
|
@ -151,9 +160,10 @@ var _ = framework.KubeDescribe("[Feature:Federation]", func() {
|
|||
It("should be able to discover a non-local federated service", func() {
|
||||
framework.SkipUnlessFederated(f.Client)
|
||||
|
||||
nsName := f.FederationNamespace.Name
|
||||
svcDNSNames := []string{
|
||||
fmt.Sprintf("%s.%s.%s", FederatedServiceName, f.Namespace.Name, federationName),
|
||||
fmt.Sprintf("%s.%s.%s.svc.cluster.local.", FederatedServiceName, f.Namespace.Name, federationName),
|
||||
fmt.Sprintf("%s.%s.%s", FederatedServiceName, nsName, federationName),
|
||||
fmt.Sprintf("%s.%s.%s.svc.cluster.local.", FederatedServiceName, nsName, federationName),
|
||||
}
|
||||
for i, name := range svcDNSNames {
|
||||
discoverService(f, name, true, "federated-service-e2e-discovery-pod-"+strconv.Itoa(i))
|
||||
|
@ -166,10 +176,11 @@ var _ = framework.KubeDescribe("[Feature:Federation]", func() {
|
|||
It("should never find DNS entries for a missing local service", func() {
|
||||
framework.SkipUnlessFederated(f.Client)
|
||||
|
||||
nsName := f.FederationNamespace.Name
|
||||
localSvcDNSNames := []string{
|
||||
FederatedServiceName,
|
||||
fmt.Sprintf("%s.%s", FederatedServiceName, f.Namespace.Name),
|
||||
fmt.Sprintf("%s.%s.svc.cluster.local.", FederatedServiceName, f.Namespace.Name),
|
||||
fmt.Sprintf("%s.%s", FederatedServiceName, nsName),
|
||||
fmt.Sprintf("%s.%s.svc.cluster.local.", FederatedServiceName, nsName),
|
||||
}
|
||||
for i, name := range localSvcDNSNames {
|
||||
discoverService(f, name, false, "federated-service-e2e-discovery-pod-"+strconv.Itoa(i))
|
||||
|
|
|
@ -84,8 +84,44 @@ var _ = framework.KubeDescribe("Federation apiserver [Feature:Federation]", func
|
|||
framework.Logf("Verified that zero clusters remain")
|
||||
})
|
||||
})
|
||||
Describe("Admission control", func() {
|
||||
AfterEach(func() {
|
||||
framework.SkipUnlessFederated(f.Client)
|
||||
})
|
||||
|
||||
It("should not be able to create resources if namespace does not exist", func() {
|
||||
framework.SkipUnlessFederated(f.Client)
|
||||
|
||||
// Creating a service in a non-existing namespace should fail.
|
||||
svcNamespace := "federation-admission-test-ns"
|
||||
svcName := "myns"
|
||||
clientset := f.FederationClientset_1_4
|
||||
framework.Logf("Trying to create service %s in namespace %s, expect to get error", svcName, svcNamespace)
|
||||
if _, err := clientset.Core().Services(svcNamespace).Create(newService(svcName, svcNamespace)); err == nil {
|
||||
framework.Failf("Expected to get an error while creating a service in a non-existing namespace")
|
||||
}
|
||||
|
||||
// Note: We have other tests that verify that we can create resources in existing namespaces, so we dont test it again here.
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
func newService(name, namespace string) *v1.Service {
|
||||
return &v1.Service{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: v1.ServiceSpec{
|
||||
Ports: []v1.ServicePort{
|
||||
{
|
||||
Port: 80,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Verify that the cluster is marked ready.
|
||||
func isReady(clusterName string, clientset *federation_release_1_4.Clientset) error {
|
||||
return wait.PollImmediate(time.Second, 5*time.Minute, func() (bool, error) {
|
||||
|
|
|
@ -40,8 +40,9 @@ var _ = framework.KubeDescribe("[Feature:Federation]", func() {
|
|||
It("should accept cluster resources when the client has right authentication credentials", func() {
|
||||
framework.SkipUnlessFederated(f.Client)
|
||||
|
||||
svc := createServiceOrFail(f.FederationClientset_1_4, f.Namespace.Name, FederatedServiceName)
|
||||
deleteServiceOrFail(f.FederationClientset_1_4, f.Namespace.Name, svc.Name)
|
||||
nsName := f.FederationNamespace.Name
|
||||
svc := createServiceOrFail(f.FederationClientset_1_4, nsName, FederatedServiceName)
|
||||
deleteServiceOrFail(f.FederationClientset_1_4, nsName, svc.Name)
|
||||
})
|
||||
|
||||
It("should not accept cluster resources when the client has invalid authentication credentials", func() {
|
||||
|
@ -57,10 +58,11 @@ var _ = framework.KubeDescribe("[Feature:Federation]", func() {
|
|||
fcs, err := invalidAuthFederationClientSet(contexts[0].User)
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
svc, err := createService(fcs, f.Namespace.Name, FederatedServiceName)
|
||||
nsName := f.FederationNamespace.Name
|
||||
svc, err := createService(fcs, nsName, FederatedServiceName)
|
||||
Expect(errors.IsUnauthorized(err)).To(BeTrue())
|
||||
if err == nil && svc != nil {
|
||||
deleteServiceOrFail(fcs, f.Namespace.Name, svc.Name)
|
||||
deleteServiceOrFail(fcs, nsName, svc.Name)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -70,10 +72,11 @@ var _ = framework.KubeDescribe("[Feature:Federation]", func() {
|
|||
fcs, err := invalidAuthFederationClientSet(nil)
|
||||
ExpectNoError(err)
|
||||
|
||||
svc, err := createService(fcs, f.Namespace.Name, FederatedServiceName)
|
||||
nsName := f.FederationNamespace.Name
|
||||
svc, err := createService(fcs, nsName, FederatedServiceName)
|
||||
Expect(errors.IsUnauthorized(err)).To(BeTrue())
|
||||
if err == nil && svc != nil {
|
||||
deleteServiceOrFail(fcs, f.Namespace.Name, svc.Name)
|
||||
deleteServiceOrFail(fcs, nsName, svc.Name)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
@ -40,23 +40,26 @@ var _ = framework.KubeDescribe("Federation events [Feature:Federation]", func()
|
|||
AfterEach(func() {
|
||||
framework.SkipUnlessFederated(f.Client)
|
||||
|
||||
nsName := f.FederationNamespace.Name
|
||||
// Delete registered events.
|
||||
eventList, err := f.FederationClientset_1_4.Core().Events(f.Namespace.Name).List(api.ListOptions{})
|
||||
eventList, err := f.FederationClientset_1_4.Core().Events(nsName).List(api.ListOptions{})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
for _, event := range eventList.Items {
|
||||
err := f.FederationClientset_1_4.Core().Events(f.Namespace.Name).Delete(event.Name, &api.DeleteOptions{})
|
||||
err := f.FederationClientset_1_4.Core().Events(nsName).Delete(event.Name, &api.DeleteOptions{})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
})
|
||||
|
||||
It("should be created and deleted successfully", func() {
|
||||
framework.SkipUnlessFederated(f.Client)
|
||||
event := createEventOrFail(f.FederationClientset_1_4, f.Namespace.Name)
|
||||
By(fmt.Sprintf("Creation of event %q in namespace %q succeeded. Deleting event.", event.Name, f.Namespace.Name))
|
||||
|
||||
nsName := f.FederationNamespace.Name
|
||||
event := createEventOrFail(f.FederationClientset_1_4, nsName)
|
||||
By(fmt.Sprintf("Creation of event %q in namespace %q succeeded. Deleting event.", event.Name, nsName))
|
||||
// Cleanup
|
||||
err := f.FederationClientset_1_4.Core().Events(f.Namespace.Name).Delete(event.Name, &api.DeleteOptions{})
|
||||
err := f.FederationClientset_1_4.Core().Events(nsName).Delete(event.Name, &api.DeleteOptions{})
|
||||
framework.ExpectNoError(err, "Error deleting event %q in namespace %q", event.Name, event.Namespace)
|
||||
By(fmt.Sprintf("Deletion of event %q in namespace %q succeeded.", event.Name, f.Namespace.Name))
|
||||
By(fmt.Sprintf("Deletion of event %q in namespace %q succeeded.", event.Name, nsName))
|
||||
})
|
||||
|
||||
})
|
||||
|
|
|
@ -42,23 +42,26 @@ var _ = framework.KubeDescribe("Federation ingresses [Feature:Federation]", func
|
|||
AfterEach(func() {
|
||||
framework.SkipUnlessFederated(f.Client)
|
||||
|
||||
nsName := f.FederationNamespace.Name
|
||||
// Delete registered ingresses.
|
||||
ingressList, err := f.FederationClientset_1_4.Extensions().Ingresses(f.Namespace.Name).List(api.ListOptions{})
|
||||
ingressList, err := f.FederationClientset_1_4.Extensions().Ingresses(nsName).List(api.ListOptions{})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
for _, ingress := range ingressList.Items {
|
||||
err := f.FederationClientset_1_4.Extensions().Ingresses(f.Namespace.Name).Delete(ingress.Name, &api.DeleteOptions{})
|
||||
err := f.FederationClientset_1_4.Extensions().Ingresses(nsName).Delete(ingress.Name, &api.DeleteOptions{})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
})
|
||||
|
||||
It("should be created and deleted successfully", func() {
|
||||
framework.SkipUnlessFederated(f.Client)
|
||||
ingress := createIngressOrFail(f.FederationClientset_1_4, f.Namespace.Name)
|
||||
By(fmt.Sprintf("Creation of ingress %q in namespace %q succeeded. Deleting ingress.", ingress.Name, f.Namespace.Name))
|
||||
|
||||
nsName := f.FederationNamespace.Name
|
||||
ingress := createIngressOrFail(f.FederationClientset_1_4, nsName)
|
||||
By(fmt.Sprintf("Creation of ingress %q in namespace %q succeeded. Deleting ingress.", ingress.Name, nsName))
|
||||
// Cleanup
|
||||
err := f.FederationClientset_1_4.Extensions().Ingresses(f.Namespace.Name).Delete(ingress.Name, &api.DeleteOptions{})
|
||||
err := f.FederationClientset_1_4.Extensions().Ingresses(nsName).Delete(ingress.Name, &api.DeleteOptions{})
|
||||
framework.ExpectNoError(err, "Error deleting ingress %q in namespace %q", ingress.Name, ingress.Namespace)
|
||||
By(fmt.Sprintf("Deletion of ingress %q in namespace %q succeeded.", ingress.Name, f.Namespace.Name))
|
||||
By(fmt.Sprintf("Deletion of ingress %q in namespace %q succeeded.", ingress.Name, nsName))
|
||||
})
|
||||
|
||||
})
|
||||
|
|
|
@ -42,22 +42,25 @@ var _ = framework.KubeDescribe("Federation replicasets [Feature:Federation]", fu
|
|||
framework.SkipUnlessFederated(f.Client)
|
||||
|
||||
// Delete registered replicasets.
|
||||
replicasetList, err := f.FederationClientset_1_4.Extensions().ReplicaSets(f.Namespace.Name).List(api.ListOptions{})
|
||||
nsName := f.FederationNamespace.Name
|
||||
replicasetList, err := f.FederationClientset_1_4.Extensions().ReplicaSets(nsName).List(api.ListOptions{})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
for _, replicaset := range replicasetList.Items {
|
||||
err := f.FederationClientset_1_4.Extensions().ReplicaSets(f.Namespace.Name).Delete(replicaset.Name, &api.DeleteOptions{})
|
||||
err := f.FederationClientset_1_4.Extensions().ReplicaSets(nsName).Delete(replicaset.Name, &api.DeleteOptions{})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
})
|
||||
|
||||
It("should be created and deleted successfully", func() {
|
||||
framework.SkipUnlessFederated(f.Client)
|
||||
replicaset := createReplicaSetOrFail(f.FederationClientset_1_4, f.Namespace.Name)
|
||||
By(fmt.Sprintf("Creation of replicaset %q in namespace %q succeeded. Deleting replicaset.", replicaset.Name, f.Namespace.Name))
|
||||
|
||||
nsName := f.FederationNamespace.Name
|
||||
replicaset := createReplicaSetOrFail(f.FederationClientset_1_4, nsName)
|
||||
By(fmt.Sprintf("Creation of replicaset %q in namespace %q succeeded. Deleting replicaset.", replicaset.Name, nsName))
|
||||
// Cleanup
|
||||
err := f.FederationClientset_1_4.Extensions().ReplicaSets(f.Namespace.Name).Delete(replicaset.Name, &api.DeleteOptions{})
|
||||
err := f.FederationClientset_1_4.Extensions().ReplicaSets(nsName).Delete(replicaset.Name, &api.DeleteOptions{})
|
||||
framework.ExpectNoError(err, "Error deleting replicaset %q in namespace %q", replicaset.Name, replicaset.Namespace)
|
||||
By(fmt.Sprintf("Deletion of replicaset %q in namespace %q succeeded.", replicaset.Name, f.Namespace.Name))
|
||||
By(fmt.Sprintf("Deletion of replicaset %q in namespace %q succeeded.", replicaset.Name, nsName))
|
||||
})
|
||||
|
||||
})
|
||||
|
@ -72,7 +75,8 @@ func createReplicaSetOrFail(clientset *federation_release_1_4.Clientset, namespa
|
|||
replicas := int32(5)
|
||||
replicaset := &v1beta1.ReplicaSet{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: FederationReplicaSetName,
|
||||
Name: FederationReplicaSetName,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: v1beta1.ReplicaSetSpec{
|
||||
Replicas: &replicas,
|
||||
|
|
|
@ -134,34 +134,41 @@ func createClientsetForCluster(c federationapi.Cluster, i int, userAgentName str
|
|||
return release_1_3.NewForConfigOrDie(restclient.AddUserAgent(cfg, userAgentName))
|
||||
}
|
||||
|
||||
// Creates the federation namespace in all underlying clusters.
|
||||
func createNamespaceInClusters(clusters map[string]*cluster, f *framework.Framework) {
|
||||
nsName := f.FederationNamespace.Name
|
||||
for name, c := range clusters {
|
||||
// The e2e Framework created the required namespace in one of the clusters, but we need to create it in all the others, if it doesn't yet exist.
|
||||
if _, err := c.Clientset.Core().Namespaces().Get(f.Namespace.Name); errors.IsNotFound(err) {
|
||||
// The e2e Framework created the required namespace in federation control plane, but we need to create it in all the others, if it doesn't yet exist.
|
||||
// TODO(nikhiljindal): remove this once we have the namespace controller working as expected.
|
||||
if _, err := c.Clientset.Core().Namespaces().Get(nsName); errors.IsNotFound(err) {
|
||||
ns := &v1.Namespace{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: f.Namespace.Name,
|
||||
Name: nsName,
|
||||
},
|
||||
}
|
||||
_, err := c.Clientset.Core().Namespaces().Create(ns)
|
||||
if err == nil {
|
||||
c.namespaceCreated = true
|
||||
}
|
||||
framework.ExpectNoError(err, "Couldn't create the namespace %s in cluster %q", f.Namespace.Name, name)
|
||||
framework.Logf("Namespace %s created in cluster %q", f.Namespace.Name, name)
|
||||
framework.ExpectNoError(err, "Couldn't create the namespace %s in cluster %q", nsName, name)
|
||||
framework.Logf("Namespace %s created in cluster %q", nsName, name)
|
||||
} else if err != nil {
|
||||
framework.Logf("Couldn't create the namespace %s in cluster %q: %v", f.Namespace.Name, name, err)
|
||||
framework.Logf("Couldn't create the namespace %s in cluster %q: %v", nsName, name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unregisters the given clusters from federation control plane.
|
||||
// Also deletes the federation namespace from each cluster.
|
||||
func unregisterClusters(clusters map[string]*cluster, f *framework.Framework) {
|
||||
nsName := f.FederationNamespace.Name
|
||||
for name, c := range clusters {
|
||||
if c.namespaceCreated {
|
||||
if _, err := c.Clientset.Core().Namespaces().Get(f.Namespace.Name); !errors.IsNotFound(err) {
|
||||
err := c.Clientset.Core().Namespaces().Delete(f.Namespace.Name, &api.DeleteOptions{})
|
||||
framework.ExpectNoError(err, "Couldn't delete the namespace %s in cluster %q: %v", f.Namespace.Name, name, err)
|
||||
if _, err := c.Clientset.Core().Namespaces().Get(nsName); !errors.IsNotFound(err) {
|
||||
err := c.Clientset.Core().Namespaces().Delete(nsName, &api.DeleteOptions{})
|
||||
framework.ExpectNoError(err, "Couldn't delete the namespace %s in cluster %q: %v", nsName, name, err)
|
||||
}
|
||||
framework.Logf("Namespace %s deleted in cluster %q", f.Namespace.Name, name)
|
||||
framework.Logf("Namespace %s deleted in cluster %q", nsName, name)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -248,7 +255,8 @@ func createService(clientset *federation_release_1_4.Clientset, namespace, name
|
|||
|
||||
service := &v1.Service{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: name,
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: v1.ServiceSpec{
|
||||
Selector: FederatedServiceLabels,
|
||||
|
@ -281,7 +289,7 @@ func deleteServiceOrFail(clientset *federation_release_1_4.Clientset, namespace
|
|||
framework.ExpectNoError(err, "Error deleting service %q from namespace %q", serviceName, namespace)
|
||||
}
|
||||
|
||||
func podExitCodeDetector(f *framework.Framework, name string, code int32) func() error {
|
||||
func podExitCodeDetector(f *framework.Framework, name, namespace string, code int32) func() error {
|
||||
// If we ever get any container logs, stash them here.
|
||||
logs := ""
|
||||
|
||||
|
@ -296,7 +304,7 @@ func podExitCodeDetector(f *framework.Framework, name string, code int32) func()
|
|||
}
|
||||
|
||||
return func() error {
|
||||
pod, err := f.Client.Pods(f.Namespace.Name).Get(name)
|
||||
pod, err := f.Client.Pods(namespace).Get(name)
|
||||
if err != nil {
|
||||
return logerr(err)
|
||||
}
|
||||
|
@ -305,7 +313,7 @@ func podExitCodeDetector(f *framework.Framework, name string, code int32) func()
|
|||
}
|
||||
|
||||
// Best effort attempt to grab pod logs for debugging
|
||||
logs, err = framework.GetPodLogs(f.Client, f.Namespace.Name, name, pod.Spec.Containers[0].Name)
|
||||
logs, err = framework.GetPodLogs(f.Client, namespace, name, pod.Spec.Containers[0].Name)
|
||||
if err != nil {
|
||||
framework.Logf("Cannot fetch pod logs: %v", err)
|
||||
}
|
||||
|
@ -342,23 +350,24 @@ func discoverService(f *framework.Framework, name string, exists bool, podName s
|
|||
},
|
||||
}
|
||||
|
||||
By(fmt.Sprintf("Creating pod %q in namespace %q", pod.Name, f.Namespace.Name))
|
||||
_, err := f.Client.Pods(f.Namespace.Name).Create(pod)
|
||||
nsName := f.FederationNamespace.Name
|
||||
By(fmt.Sprintf("Creating pod %q in namespace %q", pod.Name, nsName))
|
||||
_, err := f.Client.Pods(nsName).Create(pod)
|
||||
framework.ExpectNoError(err, "Trying to create pod to run %q", command)
|
||||
By(fmt.Sprintf("Successfully created pod %q in namespace %q", pod.Name, f.Namespace.Name))
|
||||
By(fmt.Sprintf("Successfully created pod %q in namespace %q", pod.Name, nsName))
|
||||
defer func() {
|
||||
By(fmt.Sprintf("Deleting pod %q from namespace %q", podName, f.Namespace.Name))
|
||||
err := f.Client.Pods(f.Namespace.Name).Delete(podName, api.NewDeleteOptions(0))
|
||||
framework.ExpectNoError(err, "Deleting pod %q from namespace %q", podName, f.Namespace.Name)
|
||||
By(fmt.Sprintf("Deleted pod %q from namespace %q", podName, f.Namespace.Name))
|
||||
By(fmt.Sprintf("Deleting pod %q from namespace %q", podName, nsName))
|
||||
err := f.Client.Pods(nsName).Delete(podName, api.NewDeleteOptions(0))
|
||||
framework.ExpectNoError(err, "Deleting pod %q from namespace %q", podName, nsName)
|
||||
By(fmt.Sprintf("Deleted pod %q from namespace %q", podName, nsName))
|
||||
}()
|
||||
|
||||
if exists {
|
||||
// TODO(mml): Eventually check the IP address is correct, too.
|
||||
Eventually(podExitCodeDetector(f, podName, 0), 3*DNSTTL, time.Second*2).
|
||||
Eventually(podExitCodeDetector(f, podName, nsName, 0), 3*DNSTTL, time.Second*2).
|
||||
Should(BeNil(), "%q should exit 0, but it never did", command)
|
||||
} else {
|
||||
Eventually(podExitCodeDetector(f, podName, 0), 3*DNSTTL, time.Second*2).
|
||||
Eventually(podExitCodeDetector(f, podName, nsName, 0), 3*DNSTTL, time.Second*2).
|
||||
ShouldNot(BeNil(), "%q should eventually not exit 0, but it always did", command)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import (
|
|||
"k8s.io/kubernetes/pkg/api"
|
||||
apierrs "k8s.io/kubernetes/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/release_1_2"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/release_1_3"
|
||||
"k8s.io/kubernetes/pkg/client/restclient"
|
||||
|
@ -62,8 +63,6 @@ type Framework struct {
|
|||
Clientset_1_3 *release_1_3.Clientset
|
||||
StagingClient *release_1_4.Clientset
|
||||
|
||||
FederationClientset_1_4 *federation_release_1_4.Clientset
|
||||
|
||||
Namespace *api.Namespace // Every test has at least one namespace
|
||||
namespacesToDelete []*api.Namespace // Some tests have more than one.
|
||||
NamespaceDeletionTimeout time.Duration
|
||||
|
@ -88,6 +87,10 @@ type Framework struct {
|
|||
|
||||
// will this framework exercise a federated cluster as well
|
||||
federated bool
|
||||
|
||||
// Federation specific params. These are set only if federated = true.
|
||||
FederationClientset_1_4 *federation_release_1_4.Clientset
|
||||
FederationNamespace *v1.Namespace
|
||||
}
|
||||
|
||||
type TestDataSummary interface {
|
||||
|
@ -192,12 +195,6 @@ func (f *Framework) BeforeEach() {
|
|||
}
|
||||
|
||||
if f.federated {
|
||||
if f.FederationClientset_1_4 == nil {
|
||||
By("Creating a release 1.4 federation Clientset")
|
||||
var err error
|
||||
f.FederationClientset_1_4, err = LoadFederationClientset_1_4()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
if f.FederationClientset_1_4 == nil {
|
||||
By("Creating a release 1.4 federation Clientset")
|
||||
var err error
|
||||
|
@ -208,6 +205,12 @@ func (f *Framework) BeforeEach() {
|
|||
err := WaitForFederationApiserverReady(f.FederationClientset_1_4)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
By("federation-apiserver is ready")
|
||||
|
||||
By("Creating a federation namespace")
|
||||
ns, err := f.createFederationNamespace(f.BaseName)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
f.FederationNamespace = ns
|
||||
By(fmt.Sprintf("Created federation namespace %s", ns.Name))
|
||||
}
|
||||
|
||||
By("Building a namespace api object")
|
||||
|
@ -250,6 +253,41 @@ func (f *Framework) BeforeEach() {
|
|||
}
|
||||
}
|
||||
|
||||
func (f *Framework) deleteFederationNs() {
|
||||
ns := f.FederationNamespace
|
||||
By(fmt.Sprintf("Destroying federation namespace %q for this suite.", ns.Name))
|
||||
timeout := 5 * time.Minute
|
||||
if f.NamespaceDeletionTimeout != 0 {
|
||||
timeout = f.NamespaceDeletionTimeout
|
||||
}
|
||||
|
||||
clientset := f.FederationClientset_1_4
|
||||
// First delete the namespace from federation apiserver.
|
||||
if err := clientset.Core().Namespaces().Delete(ns.Name, &api.DeleteOptions{}); err != nil {
|
||||
Failf("Error while deleting federation namespace %s: %s", ns.Name, err)
|
||||
}
|
||||
// Verify that it got deleted.
|
||||
err := wait.PollImmediate(5*time.Second, timeout, func() (bool, error) {
|
||||
if _, err := clientset.Core().Namespaces().Get(ns.Name); err != nil {
|
||||
if apierrs.IsNotFound(err) {
|
||||
return true, nil
|
||||
}
|
||||
Logf("Error while waiting for namespace to be terminated: %v", err)
|
||||
return false, nil
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
if err != nil {
|
||||
if !apierrs.IsNotFound(err) {
|
||||
Failf("Couldn't delete ns %q: %s", ns.Name, err)
|
||||
} else {
|
||||
Logf("Namespace %v was already deleted", ns.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Delete the namespace from underlying clusters.
|
||||
}
|
||||
|
||||
// AfterEach deletes the namespace, after reading its events.
|
||||
func (f *Framework) AfterEach() {
|
||||
RemoveCleanupAction(f.cleanupHandle)
|
||||
|
@ -274,12 +312,20 @@ func (f *Framework) AfterEach() {
|
|||
}
|
||||
}
|
||||
f.namespacesToDelete = nil
|
||||
|
||||
// Delete the federation namespace.
|
||||
// TODO(nikhiljindal): Uncomment this, once https://github.com/kubernetes/kubernetes/issues/31077 is fixed.
|
||||
// In the meantime, we will have these extra namespaces in all clusters.
|
||||
// Note: this will not cause any failure since we create a new namespace for each test in BeforeEach().
|
||||
// f.deleteFederationNs()
|
||||
|
||||
} else {
|
||||
Logf("Found DeleteNamespace=false, skipping namespace deletion!")
|
||||
}
|
||||
|
||||
// Paranoia-- prevent reuse!
|
||||
f.Namespace = nil
|
||||
f.FederationNamespace = nil
|
||||
f.Client = nil
|
||||
}()
|
||||
|
||||
|
@ -375,6 +421,29 @@ func (f *Framework) CreateNamespace(baseName string, labels map[string]string) (
|
|||
return ns, err
|
||||
}
|
||||
|
||||
func (f *Framework) createFederationNamespace(baseName string) (*v1.Namespace, error) {
|
||||
clientset := f.FederationClientset_1_4
|
||||
namespaceObj := &v1.Namespace{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
GenerateName: fmt.Sprintf("e2e-tests-%v-", baseName),
|
||||
},
|
||||
}
|
||||
// Be robust about making the namespace creation call.
|
||||
var got *v1.Namespace
|
||||
if err := wait.PollImmediate(Poll, SingleCallTimeout, func() (bool, error) {
|
||||
var err error
|
||||
got, err = clientset.Core().Namespaces().Create(namespaceObj)
|
||||
if err != nil {
|
||||
Logf("Unexpected error while creating namespace: %v", err)
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return got, nil
|
||||
}
|
||||
|
||||
// WaitForPodTerminated waits for the pod to be terminated with the given reason.
|
||||
func (f *Framework) WaitForPodTerminated(podName, reason string) error {
|
||||
return waitForPodTerminatedInNamespace(f.Client, podName, reason, f.Namespace.Name)
|
||||
|
|
Loading…
Reference in New Issue