describe_test.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  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 kubectl
  14. import (
  15. "bytes"
  16. "encoding/json"
  17. "fmt"
  18. "reflect"
  19. "strings"
  20. "testing"
  21. "time"
  22. "k8s.io/kubernetes/federation/apis/federation"
  23. fed_fake "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset/fake"
  24. "k8s.io/kubernetes/pkg/api"
  25. "k8s.io/kubernetes/pkg/api/resource"
  26. "k8s.io/kubernetes/pkg/api/unversioned"
  27. "k8s.io/kubernetes/pkg/apis/extensions"
  28. "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
  29. client "k8s.io/kubernetes/pkg/client/unversioned"
  30. "k8s.io/kubernetes/pkg/client/unversioned/testclient"
  31. )
  32. type describeClient struct {
  33. T *testing.T
  34. Namespace string
  35. Err error
  36. client.Interface
  37. }
  38. func TestDescribePod(t *testing.T) {
  39. fake := testclient.NewSimpleFake(&api.Pod{
  40. ObjectMeta: api.ObjectMeta{
  41. Name: "bar",
  42. Namespace: "foo",
  43. },
  44. })
  45. c := &describeClient{T: t, Namespace: "foo", Interface: fake}
  46. d := PodDescriber{c}
  47. out, err := d.Describe("foo", "bar", DescriberSettings{ShowEvents: true})
  48. if err != nil {
  49. t.Errorf("unexpected error: %v", err)
  50. }
  51. if !strings.Contains(out, "bar") || !strings.Contains(out, "Status:") {
  52. t.Errorf("unexpected out: %s", out)
  53. }
  54. }
  55. func TestDescribePodTolerations(t *testing.T) {
  56. podTolerations := []api.Toleration{{Key: "key1", Value: "value1"},
  57. {Key: "key2", Value: "value2"}}
  58. pt, _ := json.Marshal(podTolerations)
  59. fake := testclient.NewSimpleFake(&api.Pod{
  60. ObjectMeta: api.ObjectMeta{
  61. Name: "bar",
  62. Namespace: "foo",
  63. Annotations: map[string]string{
  64. api.TolerationsAnnotationKey: string(pt),
  65. },
  66. },
  67. })
  68. c := &describeClient{T: t, Namespace: "foo", Interface: fake}
  69. d := PodDescriber{c}
  70. out, err := d.Describe("foo", "bar", DescriberSettings{})
  71. if err != nil {
  72. t.Errorf("unexpected error: %v", err)
  73. }
  74. if !strings.Contains(out, "key1=value1") || !strings.Contains(out, "key2=value2") || !strings.Contains(out, "Tolerations:") {
  75. t.Errorf("unexpected out: %s", out)
  76. }
  77. }
  78. func TestDescribeService(t *testing.T) {
  79. fake := testclient.NewSimpleFake(&api.Service{
  80. ObjectMeta: api.ObjectMeta{
  81. Name: "bar",
  82. Namespace: "foo",
  83. },
  84. })
  85. c := &describeClient{T: t, Namespace: "foo", Interface: fake}
  86. d := ServiceDescriber{c}
  87. out, err := d.Describe("foo", "bar", DescriberSettings{ShowEvents: true})
  88. if err != nil {
  89. t.Errorf("unexpected error: %v", err)
  90. }
  91. if !strings.Contains(out, "Labels:") || !strings.Contains(out, "bar") {
  92. t.Errorf("unexpected out: %s", out)
  93. }
  94. }
  95. func TestPodDescribeResultsSorted(t *testing.T) {
  96. // Arrange
  97. fake := testclient.NewSimpleFake(&api.EventList{
  98. Items: []api.Event{
  99. {
  100. Source: api.EventSource{Component: "kubelet"},
  101. Message: "Item 1",
  102. FirstTimestamp: unversioned.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)),
  103. LastTimestamp: unversioned.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)),
  104. Count: 1,
  105. Type: api.EventTypeNormal,
  106. },
  107. {
  108. Source: api.EventSource{Component: "scheduler"},
  109. Message: "Item 2",
  110. FirstTimestamp: unversioned.NewTime(time.Date(1987, time.June, 17, 0, 0, 0, 0, time.UTC)),
  111. LastTimestamp: unversioned.NewTime(time.Date(1987, time.June, 17, 0, 0, 0, 0, time.UTC)),
  112. Count: 1,
  113. Type: api.EventTypeNormal,
  114. },
  115. {
  116. Source: api.EventSource{Component: "kubelet"},
  117. Message: "Item 3",
  118. FirstTimestamp: unversioned.NewTime(time.Date(2002, time.December, 25, 0, 0, 0, 0, time.UTC)),
  119. LastTimestamp: unversioned.NewTime(time.Date(2002, time.December, 25, 0, 0, 0, 0, time.UTC)),
  120. Count: 1,
  121. Type: api.EventTypeNormal,
  122. },
  123. },
  124. })
  125. c := &describeClient{T: t, Namespace: "foo", Interface: fake}
  126. d := PodDescriber{c}
  127. // Act
  128. out, err := d.Describe("foo", "bar", DescriberSettings{ShowEvents: true})
  129. // Assert
  130. if err != nil {
  131. t.Errorf("unexpected error: %v", err)
  132. }
  133. VerifyDatesInOrder(out, "\n" /* rowDelimiter */, "\t" /* columnDelimiter */, t)
  134. }
  135. func TestDescribeContainers(t *testing.T) {
  136. testCases := []struct {
  137. container api.Container
  138. status api.ContainerStatus
  139. expectedElements []string
  140. }{
  141. // Running state.
  142. {
  143. container: api.Container{Name: "test", Image: "image"},
  144. status: api.ContainerStatus{
  145. Name: "test",
  146. State: api.ContainerState{
  147. Running: &api.ContainerStateRunning{
  148. StartedAt: unversioned.NewTime(time.Now()),
  149. },
  150. },
  151. Ready: true,
  152. RestartCount: 7,
  153. },
  154. expectedElements: []string{"test", "State", "Running", "Ready", "True", "Restart Count", "7", "Image", "image", "Started"},
  155. },
  156. // Waiting state.
  157. {
  158. container: api.Container{Name: "test", Image: "image"},
  159. status: api.ContainerStatus{
  160. Name: "test",
  161. State: api.ContainerState{
  162. Waiting: &api.ContainerStateWaiting{
  163. Reason: "potato",
  164. },
  165. },
  166. Ready: true,
  167. RestartCount: 7,
  168. },
  169. expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "Reason", "potato"},
  170. },
  171. // Terminated state.
  172. {
  173. container: api.Container{Name: "test", Image: "image"},
  174. status: api.ContainerStatus{
  175. Name: "test",
  176. State: api.ContainerState{
  177. Terminated: &api.ContainerStateTerminated{
  178. StartedAt: unversioned.NewTime(time.Now()),
  179. FinishedAt: unversioned.NewTime(time.Now()),
  180. Reason: "potato",
  181. ExitCode: 2,
  182. },
  183. },
  184. Ready: true,
  185. RestartCount: 7,
  186. },
  187. expectedElements: []string{"test", "State", "Terminated", "Ready", "True", "Restart Count", "7", "Image", "image", "Reason", "potato", "Started", "Finished", "Exit Code", "2"},
  188. },
  189. // Last Terminated
  190. {
  191. container: api.Container{Name: "test", Image: "image"},
  192. status: api.ContainerStatus{
  193. Name: "test",
  194. State: api.ContainerState{
  195. Running: &api.ContainerStateRunning{
  196. StartedAt: unversioned.NewTime(time.Now()),
  197. },
  198. },
  199. LastTerminationState: api.ContainerState{
  200. Terminated: &api.ContainerStateTerminated{
  201. StartedAt: unversioned.NewTime(time.Now().Add(time.Second * 3)),
  202. FinishedAt: unversioned.NewTime(time.Now()),
  203. Reason: "crashing",
  204. ExitCode: 3,
  205. },
  206. },
  207. Ready: true,
  208. RestartCount: 7,
  209. },
  210. expectedElements: []string{"test", "State", "Terminated", "Ready", "True", "Restart Count", "7", "Image", "image", "Started", "Finished", "Exit Code", "2", "crashing", "3"},
  211. },
  212. // No state defaults to waiting.
  213. {
  214. container: api.Container{Name: "test", Image: "image"},
  215. status: api.ContainerStatus{
  216. Name: "test",
  217. Ready: true,
  218. RestartCount: 7,
  219. },
  220. expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image"},
  221. },
  222. // Env
  223. {
  224. container: api.Container{Name: "test", Image: "image", Env: []api.EnvVar{{Name: "envname", Value: "xyz"}}},
  225. status: api.ContainerStatus{
  226. Name: "test",
  227. Ready: true,
  228. RestartCount: 7,
  229. },
  230. expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz"},
  231. },
  232. // Command
  233. {
  234. container: api.Container{Name: "test", Image: "image", Command: []string{"sleep", "1000"}},
  235. status: api.ContainerStatus{
  236. Name: "test",
  237. Ready: true,
  238. RestartCount: 7,
  239. },
  240. expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "sleep", "1000"},
  241. },
  242. // Args
  243. {
  244. container: api.Container{Name: "test", Image: "image", Args: []string{"time", "1000"}},
  245. status: api.ContainerStatus{
  246. Name: "test",
  247. Ready: true,
  248. RestartCount: 7,
  249. },
  250. expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "time", "1000"},
  251. },
  252. // Using limits.
  253. {
  254. container: api.Container{
  255. Name: "test",
  256. Image: "image",
  257. Resources: api.ResourceRequirements{
  258. Limits: api.ResourceList{
  259. api.ResourceName(api.ResourceCPU): resource.MustParse("1000"),
  260. api.ResourceName(api.ResourceMemory): resource.MustParse("4G"),
  261. api.ResourceName(api.ResourceStorage): resource.MustParse("20G"),
  262. },
  263. },
  264. },
  265. status: api.ContainerStatus{
  266. Name: "test",
  267. Ready: true,
  268. RestartCount: 7,
  269. },
  270. expectedElements: []string{"cpu", "1k", "memory", "4G", "storage", "20G"},
  271. },
  272. // Using requests.
  273. {
  274. container: api.Container{
  275. Name: "test",
  276. Image: "image",
  277. Resources: api.ResourceRequirements{
  278. Requests: api.ResourceList{
  279. api.ResourceName(api.ResourceCPU): resource.MustParse("1000"),
  280. api.ResourceName(api.ResourceMemory): resource.MustParse("4G"),
  281. api.ResourceName(api.ResourceStorage): resource.MustParse("20G"),
  282. },
  283. },
  284. },
  285. expectedElements: []string{"cpu", "1k", "memory", "4G", "storage", "20G"},
  286. },
  287. }
  288. for i, testCase := range testCases {
  289. out := new(bytes.Buffer)
  290. pod := api.Pod{
  291. Spec: api.PodSpec{
  292. Containers: []api.Container{testCase.container},
  293. },
  294. Status: api.PodStatus{
  295. ContainerStatuses: []api.ContainerStatus{testCase.status},
  296. },
  297. }
  298. describeContainers("Containers", pod.Spec.Containers, pod.Status.ContainerStatuses, EnvValueRetriever(&pod), out, "")
  299. output := out.String()
  300. for _, expected := range testCase.expectedElements {
  301. if !strings.Contains(output, expected) {
  302. t.Errorf("Test case %d: expected to find %q in output: %q", i, expected, output)
  303. }
  304. }
  305. }
  306. }
  307. func TestDescribers(t *testing.T) {
  308. first := &api.Event{}
  309. second := &api.Pod{}
  310. var third *api.Pod
  311. testErr := fmt.Errorf("test")
  312. d := Describers{}
  313. d.Add(
  314. func(e *api.Event, p *api.Pod) (string, error) {
  315. if e != first {
  316. t.Errorf("first argument not equal: %#v", e)
  317. }
  318. if p != second {
  319. t.Errorf("second argument not equal: %#v", p)
  320. }
  321. return "test", testErr
  322. },
  323. )
  324. if out, err := d.DescribeObject(first, second); out != "test" || err != testErr {
  325. t.Errorf("unexpected result: %s %v", out, err)
  326. }
  327. if out, err := d.DescribeObject(first, second, third); out != "" || err == nil {
  328. t.Errorf("unexpected result: %s %v", out, err)
  329. } else {
  330. if noDescriber, ok := err.(ErrNoDescriber); ok {
  331. if !reflect.DeepEqual(noDescriber.Types, []string{"*api.Event", "*api.Pod", "*api.Pod"}) {
  332. t.Errorf("unexpected describer: %v", err)
  333. }
  334. } else {
  335. t.Errorf("unexpected error type: %v", err)
  336. }
  337. }
  338. d.Add(
  339. func(e *api.Event) (string, error) {
  340. if e != first {
  341. t.Errorf("first argument not equal: %#v", e)
  342. }
  343. return "simpler", testErr
  344. },
  345. )
  346. if out, err := d.DescribeObject(first); out != "simpler" || err != testErr {
  347. t.Errorf("unexpected result: %s %v", out, err)
  348. }
  349. }
  350. func TestDefaultDescribers(t *testing.T) {
  351. out, err := DefaultObjectDescriber.DescribeObject(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}})
  352. if err != nil {
  353. t.Fatalf("unexpected error: %v", err)
  354. }
  355. if !strings.Contains(out, "foo") {
  356. t.Errorf("unexpected output: %s", out)
  357. }
  358. out, err = DefaultObjectDescriber.DescribeObject(&api.Service{ObjectMeta: api.ObjectMeta{Name: "foo"}})
  359. if err != nil {
  360. t.Fatalf("unexpected error: %v", err)
  361. }
  362. if !strings.Contains(out, "foo") {
  363. t.Errorf("unexpected output: %s", out)
  364. }
  365. out, err = DefaultObjectDescriber.DescribeObject(&api.ReplicationController{ObjectMeta: api.ObjectMeta{Name: "foo"}})
  366. if err != nil {
  367. t.Fatalf("unexpected error: %v", err)
  368. }
  369. if !strings.Contains(out, "foo") {
  370. t.Errorf("unexpected output: %s", out)
  371. }
  372. out, err = DefaultObjectDescriber.DescribeObject(&api.Node{ObjectMeta: api.ObjectMeta{Name: "foo"}})
  373. if err != nil {
  374. t.Fatalf("unexpected error: %v", err)
  375. }
  376. if !strings.Contains(out, "foo") {
  377. t.Errorf("unexpected output: %s", out)
  378. }
  379. }
  380. func TestGetPodsTotalRequests(t *testing.T) {
  381. testCases := []struct {
  382. pods *api.PodList
  383. expectedReqs, expectedLimits map[api.ResourceName]resource.Quantity
  384. }{
  385. {
  386. pods: &api.PodList{
  387. Items: []api.Pod{
  388. {
  389. Spec: api.PodSpec{
  390. Containers: []api.Container{
  391. {
  392. Resources: api.ResourceRequirements{
  393. Requests: api.ResourceList{
  394. api.ResourceName(api.ResourceCPU): resource.MustParse("1"),
  395. api.ResourceName(api.ResourceMemory): resource.MustParse("300Mi"),
  396. api.ResourceName(api.ResourceStorage): resource.MustParse("1G"),
  397. },
  398. },
  399. },
  400. {
  401. Resources: api.ResourceRequirements{
  402. Requests: api.ResourceList{
  403. api.ResourceName(api.ResourceCPU): resource.MustParse("90m"),
  404. api.ResourceName(api.ResourceMemory): resource.MustParse("120Mi"),
  405. api.ResourceName(api.ResourceStorage): resource.MustParse("200M"),
  406. },
  407. },
  408. },
  409. },
  410. },
  411. },
  412. {
  413. Spec: api.PodSpec{
  414. Containers: []api.Container{
  415. {
  416. Resources: api.ResourceRequirements{
  417. Requests: api.ResourceList{
  418. api.ResourceName(api.ResourceCPU): resource.MustParse("60m"),
  419. api.ResourceName(api.ResourceMemory): resource.MustParse("43Mi"),
  420. api.ResourceName(api.ResourceStorage): resource.MustParse("500M"),
  421. },
  422. },
  423. },
  424. {
  425. Resources: api.ResourceRequirements{
  426. Requests: api.ResourceList{
  427. api.ResourceName(api.ResourceCPU): resource.MustParse("34m"),
  428. api.ResourceName(api.ResourceMemory): resource.MustParse("83Mi"),
  429. api.ResourceName(api.ResourceStorage): resource.MustParse("700M"),
  430. },
  431. },
  432. },
  433. },
  434. },
  435. },
  436. },
  437. },
  438. expectedReqs: map[api.ResourceName]resource.Quantity{
  439. api.ResourceName(api.ResourceCPU): resource.MustParse("1.184"),
  440. api.ResourceName(api.ResourceMemory): resource.MustParse("546Mi"),
  441. api.ResourceName(api.ResourceStorage): resource.MustParse("2.4G"),
  442. },
  443. },
  444. }
  445. for _, testCase := range testCases {
  446. reqs, _, err := getPodsTotalRequestsAndLimits(testCase.pods)
  447. if err != nil {
  448. t.Errorf("Unexpected error %v", err)
  449. }
  450. if !api.Semantic.DeepEqual(reqs, testCase.expectedReqs) {
  451. t.Errorf("Expected %v, got %v", testCase.expectedReqs, reqs)
  452. }
  453. }
  454. }
  455. func TestPersistentVolumeDescriber(t *testing.T) {
  456. tests := map[string]*api.PersistentVolume{
  457. "hostpath": {
  458. Spec: api.PersistentVolumeSpec{
  459. PersistentVolumeSource: api.PersistentVolumeSource{
  460. HostPath: &api.HostPathVolumeSource{},
  461. },
  462. },
  463. },
  464. "gce": {
  465. Spec: api.PersistentVolumeSpec{
  466. PersistentVolumeSource: api.PersistentVolumeSource{
  467. GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{},
  468. },
  469. },
  470. },
  471. "ebs": {
  472. Spec: api.PersistentVolumeSpec{
  473. PersistentVolumeSource: api.PersistentVolumeSource{
  474. AWSElasticBlockStore: &api.AWSElasticBlockStoreVolumeSource{},
  475. },
  476. },
  477. },
  478. "nfs": {
  479. Spec: api.PersistentVolumeSpec{
  480. PersistentVolumeSource: api.PersistentVolumeSource{
  481. NFS: &api.NFSVolumeSource{},
  482. },
  483. },
  484. },
  485. "iscsi": {
  486. Spec: api.PersistentVolumeSpec{
  487. PersistentVolumeSource: api.PersistentVolumeSource{
  488. ISCSI: &api.ISCSIVolumeSource{},
  489. },
  490. },
  491. },
  492. "gluster": {
  493. Spec: api.PersistentVolumeSpec{
  494. PersistentVolumeSource: api.PersistentVolumeSource{
  495. Glusterfs: &api.GlusterfsVolumeSource{},
  496. },
  497. },
  498. },
  499. "rbd": {
  500. Spec: api.PersistentVolumeSpec{
  501. PersistentVolumeSource: api.PersistentVolumeSource{
  502. RBD: &api.RBDVolumeSource{},
  503. },
  504. },
  505. },
  506. "quobyte": {
  507. Spec: api.PersistentVolumeSpec{
  508. PersistentVolumeSource: api.PersistentVolumeSource{
  509. Quobyte: &api.QuobyteVolumeSource{},
  510. },
  511. },
  512. },
  513. }
  514. for name, pv := range tests {
  515. fake := testclient.NewSimpleFake(pv)
  516. c := PersistentVolumeDescriber{fake}
  517. str, err := c.Describe("foo", "bar", DescriberSettings{ShowEvents: true})
  518. if err != nil {
  519. t.Errorf("Unexpected error for test %s: %v", name, err)
  520. }
  521. if str == "" {
  522. t.Errorf("Unexpected empty string for test %s. Expected PV Describer output", name)
  523. }
  524. }
  525. }
  526. func TestDescribeDeployment(t *testing.T) {
  527. fake := fake.NewSimpleClientset(&extensions.Deployment{
  528. ObjectMeta: api.ObjectMeta{
  529. Name: "bar",
  530. Namespace: "foo",
  531. },
  532. Spec: extensions.DeploymentSpec{
  533. Template: api.PodTemplateSpec{},
  534. },
  535. })
  536. d := DeploymentDescriber{fake}
  537. out, err := d.Describe("foo", "bar", DescriberSettings{ShowEvents: true})
  538. if err != nil {
  539. t.Errorf("unexpected error: %v", err)
  540. }
  541. if !strings.Contains(out, "bar") || !strings.Contains(out, "foo") {
  542. t.Errorf("unexpected out: %s", out)
  543. }
  544. }
  545. func TestDescribeCluster(t *testing.T) {
  546. cluster := federation.Cluster{
  547. ObjectMeta: api.ObjectMeta{
  548. Name: "foo",
  549. ResourceVersion: "4",
  550. Labels: map[string]string{
  551. "name": "foo",
  552. },
  553. },
  554. Spec: federation.ClusterSpec{
  555. ServerAddressByClientCIDRs: []federation.ServerAddressByClientCIDR{
  556. {
  557. ClientCIDR: "0.0.0.0/0",
  558. ServerAddress: "localhost:8888",
  559. },
  560. },
  561. },
  562. Status: federation.ClusterStatus{
  563. Conditions: []federation.ClusterCondition{
  564. {Type: federation.ClusterReady, Status: api.ConditionTrue},
  565. },
  566. },
  567. }
  568. fake := fed_fake.NewSimpleClientset(&cluster)
  569. d := ClusterDescriber{Interface: fake}
  570. out, err := d.Describe("any", "foo", DescriberSettings{ShowEvents: true})
  571. if err != nil {
  572. t.Errorf("unexpected error: %v", err)
  573. }
  574. if !strings.Contains(out, "foo") {
  575. t.Errorf("unexpected out: %s", out)
  576. }
  577. }
  578. func TestDescribeEvents(t *testing.T) {
  579. events := &api.EventList{
  580. Items: []api.Event{
  581. {
  582. ObjectMeta: api.ObjectMeta{
  583. Namespace: "foo",
  584. },
  585. Source: api.EventSource{Component: "kubelet"},
  586. Message: "Item 1",
  587. FirstTimestamp: unversioned.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)),
  588. LastTimestamp: unversioned.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)),
  589. Count: 1,
  590. Type: api.EventTypeNormal,
  591. },
  592. },
  593. }
  594. m := map[string]Describer{
  595. "DaemonSetDescriber": &DaemonSetDescriber{
  596. testclient.NewSimpleFake(&extensions.DaemonSet{
  597. ObjectMeta: api.ObjectMeta{
  598. Name: "bar",
  599. Namespace: "foo",
  600. },
  601. }, events),
  602. },
  603. "DeploymentDescriber": &DeploymentDescriber{
  604. fake.NewSimpleClientset(&extensions.Deployment{
  605. ObjectMeta: api.ObjectMeta{
  606. Name: "bar",
  607. Namespace: "foo",
  608. },
  609. }, events),
  610. },
  611. "EndpointsDescriber": &EndpointsDescriber{
  612. testclient.NewSimpleFake(&api.Endpoints{
  613. ObjectMeta: api.ObjectMeta{
  614. Name: "bar",
  615. Namespace: "foo",
  616. },
  617. }, events),
  618. },
  619. // TODO(jchaloup): add tests for:
  620. // - HorizontalPodAutoscalerDescriber
  621. // - IngressDescriber
  622. // - JobDescriber
  623. "NodeDescriber": &NodeDescriber{
  624. testclient.NewSimpleFake(&api.Node{
  625. ObjectMeta: api.ObjectMeta{
  626. Name: "bar",
  627. Namespace: "foo",
  628. SelfLink: "url/url/url",
  629. },
  630. }, events),
  631. },
  632. "PersistentVolumeDescriber": &PersistentVolumeDescriber{
  633. testclient.NewSimpleFake(&api.PersistentVolume{
  634. ObjectMeta: api.ObjectMeta{
  635. Name: "bar",
  636. Namespace: "foo",
  637. SelfLink: "url/url/url",
  638. },
  639. }, events),
  640. },
  641. "PodDescriber": &PodDescriber{
  642. testclient.NewSimpleFake(&api.Pod{
  643. ObjectMeta: api.ObjectMeta{
  644. Name: "bar",
  645. Namespace: "foo",
  646. SelfLink: "url/url/url",
  647. },
  648. }, events),
  649. },
  650. "ReplicaSetDescriber": &ReplicaSetDescriber{
  651. testclient.NewSimpleFake(&extensions.ReplicaSet{
  652. ObjectMeta: api.ObjectMeta{
  653. Name: "bar",
  654. Namespace: "foo",
  655. },
  656. }, events),
  657. },
  658. "ReplicationControllerDescriber": &ReplicationControllerDescriber{
  659. testclient.NewSimpleFake(&api.ReplicationController{
  660. ObjectMeta: api.ObjectMeta{
  661. Name: "bar",
  662. Namespace: "foo",
  663. },
  664. }, events),
  665. },
  666. "Service": &ServiceDescriber{
  667. testclient.NewSimpleFake(&api.Service{
  668. ObjectMeta: api.ObjectMeta{
  669. Name: "bar",
  670. Namespace: "foo",
  671. },
  672. }, events),
  673. },
  674. }
  675. for name, d := range m {
  676. out, err := d.Describe("foo", "bar", DescriberSettings{ShowEvents: true})
  677. if err != nil {
  678. t.Errorf("unexpected error for %q: %v", name, err)
  679. }
  680. if !strings.Contains(out, "bar") {
  681. t.Errorf("unexpected out for %q: %s", name, out)
  682. }
  683. if !strings.Contains(out, "Events:") {
  684. t.Errorf("events not found for %q when ShowEvents=true: %s", name, out)
  685. }
  686. out, err = d.Describe("foo", "bar", DescriberSettings{ShowEvents: false})
  687. if err != nil {
  688. t.Errorf("unexpected error for %q: %s", name, err)
  689. }
  690. if !strings.Contains(out, "bar") {
  691. t.Errorf("unexpected out for %q: %s", name, out)
  692. }
  693. if strings.Contains(out, "Events:") {
  694. t.Errorf("events found for %q when ShowEvents=false: %s", name, out)
  695. }
  696. }
  697. }