namespace.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /*
  2. Copyright 2014 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package apimachinery
  14. import (
  15. "context"
  16. "encoding/json"
  17. "fmt"
  18. "strings"
  19. "sync"
  20. "time"
  21. "k8s.io/api/core/v1"
  22. apierrors "k8s.io/apimachinery/pkg/api/errors"
  23. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  24. "k8s.io/apimachinery/pkg/util/intstr"
  25. "k8s.io/apimachinery/pkg/util/uuid"
  26. "k8s.io/apimachinery/pkg/util/wait"
  27. "k8s.io/kubernetes/test/e2e/framework"
  28. e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
  29. imageutils "k8s.io/kubernetes/test/utils/image"
  30. "github.com/onsi/ginkgo"
  31. "k8s.io/apimachinery/pkg/types"
  32. )
  33. func extinguish(f *framework.Framework, totalNS int, maxAllowedAfterDel int, maxSeconds int) {
  34. var err error
  35. ginkgo.By("Creating testing namespaces")
  36. wg := &sync.WaitGroup{}
  37. wg.Add(totalNS)
  38. for n := 0; n < totalNS; n++ {
  39. go func(n int) {
  40. defer wg.Done()
  41. defer ginkgo.GinkgoRecover()
  42. ns := fmt.Sprintf("nslifetest-%v", n)
  43. _, err = f.CreateNamespace(ns, nil)
  44. framework.ExpectNoError(err, "failed to create namespace: %s", ns)
  45. }(n)
  46. }
  47. wg.Wait()
  48. //Wait 10 seconds, then SEND delete requests for all the namespaces.
  49. ginkgo.By("Waiting 10 seconds")
  50. time.Sleep(time.Duration(10 * time.Second))
  51. deleteFilter := []string{"nslifetest"}
  52. deleted, err := framework.DeleteNamespaces(f.ClientSet, deleteFilter, nil /* skipFilter */)
  53. framework.ExpectNoError(err, "failed to delete namespace(s) containing: %s", deleteFilter)
  54. framework.ExpectEqual(len(deleted), totalNS)
  55. ginkgo.By("Waiting for namespaces to vanish")
  56. //Now POLL until all namespaces have been eradicated.
  57. framework.ExpectNoError(wait.Poll(2*time.Second, time.Duration(maxSeconds)*time.Second,
  58. func() (bool, error) {
  59. var cnt = 0
  60. nsList, err := f.ClientSet.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{})
  61. if err != nil {
  62. return false, err
  63. }
  64. for _, item := range nsList.Items {
  65. if strings.Contains(item.Name, "nslifetest") {
  66. cnt++
  67. }
  68. }
  69. if cnt > maxAllowedAfterDel {
  70. framework.Logf("Remaining namespaces : %v", cnt)
  71. return false, nil
  72. }
  73. return true, nil
  74. }))
  75. }
  76. func ensurePodsAreRemovedWhenNamespaceIsDeleted(f *framework.Framework) {
  77. ginkgo.By("Creating a test namespace")
  78. namespaceName := "nsdeletetest"
  79. namespace, err := f.CreateNamespace(namespaceName, nil)
  80. framework.ExpectNoError(err, "failed to create namespace: %s", namespaceName)
  81. ginkgo.By("Waiting for a default service account to be provisioned in namespace")
  82. err = framework.WaitForDefaultServiceAccountInNamespace(f.ClientSet, namespace.Name)
  83. framework.ExpectNoError(err, "failure while waiting for a default service account to be provisioned in namespace: %s", namespace.Name)
  84. ginkgo.By("Creating a pod in the namespace")
  85. podName := "test-pod"
  86. pod := &v1.Pod{
  87. ObjectMeta: metav1.ObjectMeta{
  88. Name: podName,
  89. },
  90. Spec: v1.PodSpec{
  91. Containers: []v1.Container{
  92. {
  93. Name: "nginx",
  94. Image: imageutils.GetPauseImageName(),
  95. },
  96. },
  97. },
  98. }
  99. pod, err = f.ClientSet.CoreV1().Pods(namespace.Name).Create(context.TODO(), pod, metav1.CreateOptions{})
  100. framework.ExpectNoError(err, "failed to create pod %s in namespace: %s", podName, namespace.Name)
  101. ginkgo.By("Waiting for the pod to have running status")
  102. framework.ExpectNoError(e2epod.WaitForPodRunningInNamespace(f.ClientSet, pod))
  103. ginkgo.By("Deleting the namespace")
  104. err = f.ClientSet.CoreV1().Namespaces().Delete(context.TODO(), namespace.Name, nil)
  105. framework.ExpectNoError(err, "failed to delete namespace: %s", namespace.Name)
  106. ginkgo.By("Waiting for the namespace to be removed.")
  107. maxWaitSeconds := int64(60) + *pod.Spec.TerminationGracePeriodSeconds
  108. framework.ExpectNoError(wait.Poll(1*time.Second, time.Duration(maxWaitSeconds)*time.Second,
  109. func() (bool, error) {
  110. _, err = f.ClientSet.CoreV1().Namespaces().Get(context.TODO(), namespace.Name, metav1.GetOptions{})
  111. if err != nil && apierrors.IsNotFound(err) {
  112. return true, nil
  113. }
  114. return false, nil
  115. }))
  116. ginkgo.By("Recreating the namespace")
  117. namespace, err = f.CreateNamespace(namespaceName, nil)
  118. framework.ExpectNoError(err, "failed to create namespace: %s", namespaceName)
  119. ginkgo.By("Verifying there are no pods in the namespace")
  120. _, err = f.ClientSet.CoreV1().Pods(namespace.Name).Get(context.TODO(), pod.Name, metav1.GetOptions{})
  121. framework.ExpectError(err, "failed to get pod %s in namespace: %s", pod.Name, namespace.Name)
  122. }
  123. func ensureServicesAreRemovedWhenNamespaceIsDeleted(f *framework.Framework) {
  124. var err error
  125. ginkgo.By("Creating a test namespace")
  126. namespaceName := "nsdeletetest"
  127. namespace, err := f.CreateNamespace(namespaceName, nil)
  128. framework.ExpectNoError(err, "failed to create namespace: %s", namespaceName)
  129. ginkgo.By("Waiting for a default service account to be provisioned in namespace")
  130. err = framework.WaitForDefaultServiceAccountInNamespace(f.ClientSet, namespace.Name)
  131. framework.ExpectNoError(err, "failure while waiting for a default service account to be provisioned in namespace: %s", namespace.Name)
  132. ginkgo.By("Creating a service in the namespace")
  133. serviceName := "test-service"
  134. labels := map[string]string{
  135. "foo": "bar",
  136. "baz": "blah",
  137. }
  138. service := &v1.Service{
  139. ObjectMeta: metav1.ObjectMeta{
  140. Name: serviceName,
  141. },
  142. Spec: v1.ServiceSpec{
  143. Selector: labels,
  144. Ports: []v1.ServicePort{{
  145. Port: 80,
  146. TargetPort: intstr.FromInt(80),
  147. }},
  148. },
  149. }
  150. service, err = f.ClientSet.CoreV1().Services(namespace.Name).Create(context.TODO(), service, metav1.CreateOptions{})
  151. framework.ExpectNoError(err, "failed to create service %s in namespace %s", serviceName, namespace.Name)
  152. ginkgo.By("Deleting the namespace")
  153. err = f.ClientSet.CoreV1().Namespaces().Delete(context.TODO(), namespace.Name, nil)
  154. framework.ExpectNoError(err, "failed to delete namespace: %s", namespace.Name)
  155. ginkgo.By("Waiting for the namespace to be removed.")
  156. maxWaitSeconds := int64(60)
  157. framework.ExpectNoError(wait.Poll(1*time.Second, time.Duration(maxWaitSeconds)*time.Second,
  158. func() (bool, error) {
  159. _, err = f.ClientSet.CoreV1().Namespaces().Get(context.TODO(), namespace.Name, metav1.GetOptions{})
  160. if err != nil && apierrors.IsNotFound(err) {
  161. return true, nil
  162. }
  163. return false, nil
  164. }))
  165. ginkgo.By("Recreating the namespace")
  166. namespace, err = f.CreateNamespace(namespaceName, nil)
  167. framework.ExpectNoError(err, "failed to create namespace: %s", namespaceName)
  168. ginkgo.By("Verifying there is no service in the namespace")
  169. _, err = f.ClientSet.CoreV1().Services(namespace.Name).Get(context.TODO(), service.Name, metav1.GetOptions{})
  170. framework.ExpectError(err, "failed to get service %s in namespace: %s", service.Name, namespace.Name)
  171. }
  172. // This test must run [Serial] due to the impact of running other parallel
  173. // tests can have on its performance. Each test that follows the common
  174. // test framework follows this pattern:
  175. // 1. Create a Namespace
  176. // 2. Do work that generates content in that namespace
  177. // 3. Delete a Namespace
  178. // Creation of a Namespace is non-trivial since it requires waiting for a
  179. // ServiceAccount to be generated.
  180. // Deletion of a Namespace is non-trivial and performance intensive since
  181. // its an orchestrated process. The controller that handles deletion must
  182. // query the namespace for all existing content, and then delete each piece
  183. // of content in turn. As the API surface grows to add more KIND objects
  184. // that could exist in a Namespace, the number of calls that the namespace
  185. // controller must orchestrate grows since it must LIST, DELETE (1x1) each
  186. // KIND.
  187. // There is work underway to improve this, but it's
  188. // most likely not going to get significantly better until etcd v3.
  189. // Going back to this test, this test generates 100 Namespace objects, and then
  190. // rapidly deletes all of them. This causes the NamespaceController to observe
  191. // and attempt to process a large number of deletes concurrently. In effect,
  192. // it's like running 100 traditional e2e tests in parallel. If the namespace
  193. // controller orchestrating deletes is slowed down deleting another test's
  194. // content then this test may fail. Since the goal of this test is to soak
  195. // Namespace creation, and soak Namespace deletion, its not appropriate to
  196. // further soak the cluster with other parallel Namespace deletion activities
  197. // that each have a variable amount of content in the associated Namespace.
  198. // When run in [Serial] this test appears to delete Namespace objects at a
  199. // rate of approximately 1 per second.
  200. var _ = SIGDescribe("Namespaces [Serial]", func() {
  201. f := framework.NewDefaultFramework("namespaces")
  202. /*
  203. Testname: namespace-deletion-removes-pods
  204. Description: Ensure that if a namespace is deleted then all pods are removed from that namespace.
  205. */
  206. framework.ConformanceIt("should ensure that all pods are removed when a namespace is deleted",
  207. func() { ensurePodsAreRemovedWhenNamespaceIsDeleted(f) })
  208. /*
  209. Testname: namespace-deletion-removes-services
  210. Description: Ensure that if a namespace is deleted then all services are removed from that namespace.
  211. */
  212. framework.ConformanceIt("should ensure that all services are removed when a namespace is deleted",
  213. func() { ensureServicesAreRemovedWhenNamespaceIsDeleted(f) })
  214. ginkgo.It("should delete fast enough (90 percent of 100 namespaces in 150 seconds)",
  215. func() { extinguish(f, 100, 10, 150) })
  216. // On hold until etcd3; see #7372
  217. ginkgo.It("should always delete fast (ALL of 100 namespaces in 150 seconds) [Feature:ComprehensiveNamespaceDraining]",
  218. func() { extinguish(f, 100, 0, 150) })
  219. /*
  220. Release : v1.18
  221. Testname: Namespace patching
  222. Description: A Namespace is created.
  223. The Namespace is patched.
  224. The Namespace and MUST now include the new Label.
  225. */
  226. framework.ConformanceIt("should patch a Namespace", func() {
  227. ginkgo.By("creating a Namespace")
  228. namespaceName := "nspatchtest-" + string(uuid.NewUUID())
  229. ns, err := f.CreateNamespace(namespaceName, nil)
  230. framework.ExpectNoError(err, "failed creating Namespace")
  231. namespaceName = ns.ObjectMeta.Name
  232. ginkgo.By("patching the Namespace")
  233. nspatch, err := json.Marshal(map[string]interface{}{
  234. "metadata": map[string]interface{}{
  235. "labels": map[string]string{"testLabel": "testValue"},
  236. },
  237. })
  238. framework.ExpectNoError(err, "failed to marshal JSON patch data")
  239. _, err = f.ClientSet.CoreV1().Namespaces().Patch(context.TODO(), namespaceName, types.StrategicMergePatchType, []byte(nspatch), metav1.PatchOptions{})
  240. framework.ExpectNoError(err, "failed to patch Namespace")
  241. ginkgo.By("get the Namespace and ensuring it has the label")
  242. namespace, err := f.ClientSet.CoreV1().Namespaces().Get(context.TODO(), namespaceName, metav1.GetOptions{})
  243. framework.ExpectNoError(err, "failed to get Namespace")
  244. framework.ExpectEqual(namespace.ObjectMeta.Labels["testLabel"], "testValue", "namespace not patched")
  245. })
  246. })