PageRenderTime 26ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/k8s.io/kubernetes/pkg/registry/deployment/etcd/etcd_test.go

https://gitlab.com/admin-github-cloud/bootkube
Go | 384 lines | 325 code | 32 blank | 27 comment | 56 complexity | 47e7a537f0ac5212145c6d1aeaac231d MD5 | raw file
  1. /*
  2. Copyright 2015 The Kubernetes Authors All rights reserved.
  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 etcd
  14. import (
  15. "reflect"
  16. "testing"
  17. "k8s.io/kubernetes/pkg/api"
  18. "k8s.io/kubernetes/pkg/api/errors"
  19. storeerr "k8s.io/kubernetes/pkg/api/errors/storage"
  20. "k8s.io/kubernetes/pkg/api/rest"
  21. "k8s.io/kubernetes/pkg/api/unversioned"
  22. "k8s.io/kubernetes/pkg/apis/extensions"
  23. "k8s.io/kubernetes/pkg/fields"
  24. "k8s.io/kubernetes/pkg/labels"
  25. "k8s.io/kubernetes/pkg/registry/generic"
  26. "k8s.io/kubernetes/pkg/registry/registrytest"
  27. "k8s.io/kubernetes/pkg/runtime"
  28. "k8s.io/kubernetes/pkg/storage/etcd/etcdtest"
  29. etcdtesting "k8s.io/kubernetes/pkg/storage/etcd/testing"
  30. "k8s.io/kubernetes/pkg/util/diff"
  31. "k8s.io/kubernetes/pkg/util/intstr"
  32. )
  33. const defaultReplicas = 100
  34. func newStorage(t *testing.T) (*DeploymentStorage, *etcdtesting.EtcdTestServer) {
  35. etcdStorage, server := registrytest.NewEtcdStorage(t, extensions.GroupName)
  36. restOptions := generic.RESTOptions{Storage: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1}
  37. deploymentStorage := NewStorage(restOptions)
  38. return &deploymentStorage, server
  39. }
  40. var namespace = "foo-namespace"
  41. var name = "foo-deployment"
  42. func validNewDeployment() *extensions.Deployment {
  43. return &extensions.Deployment{
  44. ObjectMeta: api.ObjectMeta{
  45. Name: name,
  46. Namespace: namespace,
  47. },
  48. Spec: extensions.DeploymentSpec{
  49. Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"a": "b"}},
  50. Strategy: extensions.DeploymentStrategy{
  51. Type: extensions.RollingUpdateDeploymentStrategyType,
  52. RollingUpdate: &extensions.RollingUpdateDeployment{
  53. MaxSurge: intstr.FromInt(1),
  54. MaxUnavailable: intstr.FromInt(1),
  55. },
  56. },
  57. Template: api.PodTemplateSpec{
  58. ObjectMeta: api.ObjectMeta{
  59. Labels: map[string]string{"a": "b"},
  60. },
  61. Spec: api.PodSpec{
  62. Containers: []api.Container{
  63. {
  64. Name: "test",
  65. Image: "test_image",
  66. ImagePullPolicy: api.PullIfNotPresent,
  67. },
  68. },
  69. RestartPolicy: api.RestartPolicyAlways,
  70. DNSPolicy: api.DNSClusterFirst,
  71. },
  72. },
  73. Replicas: 7,
  74. },
  75. Status: extensions.DeploymentStatus{
  76. Replicas: 5,
  77. },
  78. }
  79. }
  80. var validDeployment = *validNewDeployment()
  81. func TestCreate(t *testing.T) {
  82. storage, server := newStorage(t)
  83. defer server.Terminate(t)
  84. test := registrytest.New(t, storage.Deployment.Store)
  85. deployment := validNewDeployment()
  86. deployment.ObjectMeta = api.ObjectMeta{}
  87. test.TestCreate(
  88. // valid
  89. deployment,
  90. // invalid (invalid selector)
  91. &extensions.Deployment{
  92. Spec: extensions.DeploymentSpec{
  93. Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{}},
  94. Template: validDeployment.Spec.Template,
  95. },
  96. },
  97. )
  98. }
  99. func TestUpdate(t *testing.T) {
  100. storage, server := newStorage(t)
  101. defer server.Terminate(t)
  102. test := registrytest.New(t, storage.Deployment.Store)
  103. test.TestUpdate(
  104. // valid
  105. validNewDeployment(),
  106. // updateFunc
  107. func(obj runtime.Object) runtime.Object {
  108. object := obj.(*extensions.Deployment)
  109. object.Spec.Template.Spec.NodeSelector = map[string]string{"c": "d"}
  110. return object
  111. },
  112. // invalid updateFunc
  113. func(obj runtime.Object) runtime.Object {
  114. object := obj.(*extensions.Deployment)
  115. object.Name = ""
  116. return object
  117. },
  118. func(obj runtime.Object) runtime.Object {
  119. object := obj.(*extensions.Deployment)
  120. object.Spec.Template.Spec.RestartPolicy = api.RestartPolicyOnFailure
  121. return object
  122. },
  123. func(obj runtime.Object) runtime.Object {
  124. object := obj.(*extensions.Deployment)
  125. object.Spec.Selector = &unversioned.LabelSelector{MatchLabels: map[string]string{}}
  126. return object
  127. },
  128. )
  129. }
  130. func TestDelete(t *testing.T) {
  131. storage, server := newStorage(t)
  132. defer server.Terminate(t)
  133. test := registrytest.New(t, storage.Deployment.Store)
  134. test.TestDelete(validNewDeployment())
  135. }
  136. func TestGet(t *testing.T) {
  137. storage, server := newStorage(t)
  138. defer server.Terminate(t)
  139. test := registrytest.New(t, storage.Deployment.Store)
  140. test.TestGet(validNewDeployment())
  141. }
  142. func TestList(t *testing.T) {
  143. storage, server := newStorage(t)
  144. defer server.Terminate(t)
  145. test := registrytest.New(t, storage.Deployment.Store)
  146. test.TestList(validNewDeployment())
  147. }
  148. func TestWatch(t *testing.T) {
  149. storage, server := newStorage(t)
  150. defer server.Terminate(t)
  151. test := registrytest.New(t, storage.Deployment.Store)
  152. test.TestWatch(
  153. validNewDeployment(),
  154. // matching labels
  155. []labels.Set{},
  156. // not matching labels
  157. []labels.Set{
  158. {"a": "c"},
  159. {"foo": "bar"},
  160. },
  161. // matching fields
  162. []fields.Set{
  163. {"metadata.name": name},
  164. },
  165. // not matchin fields
  166. []fields.Set{
  167. {"metadata.name": "bar"},
  168. {"name": name},
  169. },
  170. )
  171. }
  172. func TestScaleGet(t *testing.T) {
  173. storage, server := newStorage(t)
  174. defer server.Terminate(t)
  175. var deployment extensions.Deployment
  176. ctx := api.WithNamespace(api.NewContext(), namespace)
  177. key := etcdtest.AddPrefix("/deployments/" + namespace + "/" + name)
  178. if err := storage.Deployment.Storage.Create(ctx, key, &validDeployment, &deployment, 0); err != nil {
  179. t.Fatalf("error setting new deployment (key: %s) %v: %v", key, validDeployment, err)
  180. }
  181. want := &extensions.Scale{
  182. ObjectMeta: api.ObjectMeta{
  183. Name: name,
  184. Namespace: namespace,
  185. UID: deployment.UID,
  186. ResourceVersion: deployment.ResourceVersion,
  187. CreationTimestamp: deployment.CreationTimestamp,
  188. },
  189. Spec: extensions.ScaleSpec{
  190. Replicas: validDeployment.Spec.Replicas,
  191. },
  192. Status: extensions.ScaleStatus{
  193. Replicas: validDeployment.Status.Replicas,
  194. Selector: validDeployment.Spec.Selector,
  195. },
  196. }
  197. obj, err := storage.Scale.Get(ctx, name)
  198. if err != nil {
  199. t.Fatalf("error fetching scale for %s: %v", name, err)
  200. }
  201. got := obj.(*extensions.Scale)
  202. if !api.Semantic.DeepEqual(want, got) {
  203. t.Errorf("unexpected scale: %s", diff.ObjectDiff(want, got))
  204. }
  205. }
  206. func TestScaleUpdate(t *testing.T) {
  207. storage, server := newStorage(t)
  208. defer server.Terminate(t)
  209. var deployment extensions.Deployment
  210. ctx := api.WithNamespace(api.NewContext(), namespace)
  211. key := etcdtest.AddPrefix("/deployments/" + namespace + "/" + name)
  212. if err := storage.Deployment.Storage.Create(ctx, key, &validDeployment, &deployment, 0); err != nil {
  213. t.Fatalf("error setting new deployment (key: %s) %v: %v", key, validDeployment, err)
  214. }
  215. replicas := int32(12)
  216. update := extensions.Scale{
  217. ObjectMeta: api.ObjectMeta{Name: name, Namespace: namespace},
  218. Spec: extensions.ScaleSpec{
  219. Replicas: replicas,
  220. },
  221. }
  222. if _, _, err := storage.Scale.Update(ctx, update.Name, rest.DefaultUpdatedObjectInfo(&update, api.Scheme)); err != nil {
  223. t.Fatalf("error updating scale %v: %v", update, err)
  224. }
  225. obj, err := storage.Scale.Get(ctx, name)
  226. if err != nil {
  227. t.Fatalf("error fetching scale for %s: %v", name, err)
  228. }
  229. scale := obj.(*extensions.Scale)
  230. if scale.Spec.Replicas != replicas {
  231. t.Errorf("wrong replicas count expected: %d got: %d", replicas, deployment.Spec.Replicas)
  232. }
  233. update.ResourceVersion = deployment.ResourceVersion
  234. update.Spec.Replicas = 15
  235. if _, _, err = storage.Scale.Update(ctx, update.Name, rest.DefaultUpdatedObjectInfo(&update, api.Scheme)); err != nil && !errors.IsConflict(err) {
  236. t.Fatalf("unexpected error, expecting an update conflict but got %v", err)
  237. }
  238. }
  239. func TestStatusUpdate(t *testing.T) {
  240. storage, server := newStorage(t)
  241. defer server.Terminate(t)
  242. ctx := api.WithNamespace(api.NewContext(), namespace)
  243. key := etcdtest.AddPrefix("/deployments/" + namespace + "/" + name)
  244. if err := storage.Deployment.Storage.Create(ctx, key, &validDeployment, nil, 0); err != nil {
  245. t.Fatalf("unexpected error: %v", err)
  246. }
  247. update := extensions.Deployment{
  248. ObjectMeta: validDeployment.ObjectMeta,
  249. Spec: extensions.DeploymentSpec{
  250. Replicas: defaultReplicas,
  251. },
  252. Status: extensions.DeploymentStatus{
  253. Replicas: defaultReplicas,
  254. },
  255. }
  256. if _, _, err := storage.Status.Update(ctx, update.Name, rest.DefaultUpdatedObjectInfo(&update, api.Scheme)); err != nil {
  257. t.Fatalf("unexpected error: %v", err)
  258. }
  259. obj, err := storage.Deployment.Get(ctx, name)
  260. if err != nil {
  261. t.Fatalf("unexpected error: %v", err)
  262. }
  263. deployment := obj.(*extensions.Deployment)
  264. if deployment.Spec.Replicas != 7 {
  265. t.Errorf("we expected .spec.replicas to not be updated but it was updated to %v", deployment.Spec.Replicas)
  266. }
  267. if deployment.Status.Replicas != defaultReplicas {
  268. t.Errorf("we expected .status.replicas to be updated to %d but it was %v", defaultReplicas, deployment.Status.Replicas)
  269. }
  270. }
  271. func TestEtcdCreateDeploymentRollback(t *testing.T) {
  272. ctx := api.WithNamespace(api.NewContext(), namespace)
  273. testCases := map[string]struct {
  274. rollback extensions.DeploymentRollback
  275. errOK func(error) bool
  276. }{
  277. "normal": {
  278. rollback: extensions.DeploymentRollback{
  279. Name: name,
  280. UpdatedAnnotations: map[string]string{},
  281. RollbackTo: extensions.RollbackConfig{Revision: 1},
  282. },
  283. errOK: func(err error) bool { return err == nil },
  284. },
  285. "noAnnotation": {
  286. rollback: extensions.DeploymentRollback{
  287. Name: name,
  288. RollbackTo: extensions.RollbackConfig{Revision: 1},
  289. },
  290. errOK: func(err error) bool { return err == nil },
  291. },
  292. "noName": {
  293. rollback: extensions.DeploymentRollback{
  294. UpdatedAnnotations: map[string]string{},
  295. RollbackTo: extensions.RollbackConfig{Revision: 1},
  296. },
  297. errOK: func(err error) bool { return err != nil },
  298. },
  299. }
  300. for k, test := range testCases {
  301. storage, server := newStorage(t)
  302. rollbackStorage := storage.Rollback
  303. key, _ := storage.Deployment.KeyFunc(ctx, name)
  304. key = etcdtest.AddPrefix(key)
  305. if _, err := storage.Deployment.Create(ctx, validNewDeployment()); err != nil {
  306. t.Fatalf("%s: unexpected error: %v", k, err)
  307. }
  308. if _, err := rollbackStorage.Create(ctx, &test.rollback); !test.errOK(err) {
  309. t.Errorf("%s: unexpected error: %v", k, err)
  310. } else if err == nil {
  311. // If rollback succeeded, verify Rollback field of deployment
  312. d, err := storage.Deployment.Get(ctx, validNewDeployment().ObjectMeta.Name)
  313. if err != nil {
  314. t.Errorf("%s: unexpected error: %v", k, err)
  315. } else if !reflect.DeepEqual(*d.(*extensions.Deployment).Spec.RollbackTo, test.rollback.RollbackTo) {
  316. t.Errorf("%s: expected: %v, got: %v", k, *d.(*extensions.Deployment).Spec.RollbackTo, test.rollback.RollbackTo)
  317. }
  318. }
  319. server.Terminate(t)
  320. }
  321. }
  322. // Ensure that when a deploymentRollback is created for a deployment that has already been deleted
  323. // by the API server, API server returns not-found error.
  324. func TestEtcdCreateDeploymentRollbackNoDeployment(t *testing.T) {
  325. storage, server := newStorage(t)
  326. defer server.Terminate(t)
  327. rollbackStorage := storage.Rollback
  328. ctx := api.WithNamespace(api.NewContext(), namespace)
  329. key, _ := storage.Deployment.KeyFunc(ctx, name)
  330. key = etcdtest.AddPrefix(key)
  331. _, err := rollbackStorage.Create(ctx, &extensions.DeploymentRollback{
  332. Name: name,
  333. UpdatedAnnotations: map[string]string{},
  334. RollbackTo: extensions.RollbackConfig{Revision: 1},
  335. })
  336. if err == nil {
  337. t.Fatalf("Expected not-found-error but got nothing")
  338. }
  339. if !errors.IsNotFound(storeerr.InterpretGetError(err, extensions.Resource("deployments"), name)) {
  340. t.Fatalf("Unexpected error returned: %#v", err)
  341. }
  342. _, err = storage.Deployment.Get(ctx, name)
  343. if err == nil {
  344. t.Fatalf("Expected not-found-error but got nothing")
  345. }
  346. if !errors.IsNotFound(storeerr.InterpretGetError(err, extensions.Resource("deployments"), name)) {
  347. t.Fatalf("Unexpected error: %v", err)
  348. }
  349. }