run_test.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  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 cmd
  14. import (
  15. "bytes"
  16. "fmt"
  17. "io/ioutil"
  18. "net/http"
  19. "os"
  20. "reflect"
  21. "testing"
  22. "github.com/spf13/cobra"
  23. "k8s.io/kubernetes/pkg/api"
  24. "k8s.io/kubernetes/pkg/api/testapi"
  25. "k8s.io/kubernetes/pkg/client/restclient"
  26. "k8s.io/kubernetes/pkg/client/unversioned/fake"
  27. cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
  28. "k8s.io/kubernetes/pkg/runtime"
  29. "k8s.io/kubernetes/pkg/util/intstr"
  30. )
  31. func TestGetRestartPolicy(t *testing.T) {
  32. tests := []struct {
  33. input string
  34. interactive bool
  35. expected api.RestartPolicy
  36. expectErr bool
  37. }{
  38. {
  39. input: "",
  40. expected: api.RestartPolicyAlways,
  41. },
  42. {
  43. input: "",
  44. interactive: true,
  45. expected: api.RestartPolicyOnFailure,
  46. },
  47. {
  48. input: string(api.RestartPolicyAlways),
  49. interactive: true,
  50. expected: api.RestartPolicyAlways,
  51. },
  52. {
  53. input: string(api.RestartPolicyNever),
  54. interactive: true,
  55. expected: api.RestartPolicyNever,
  56. },
  57. {
  58. input: string(api.RestartPolicyAlways),
  59. expected: api.RestartPolicyAlways,
  60. },
  61. {
  62. input: string(api.RestartPolicyNever),
  63. expected: api.RestartPolicyNever,
  64. },
  65. {
  66. input: "foo",
  67. expectErr: true,
  68. },
  69. }
  70. for _, test := range tests {
  71. cmd := &cobra.Command{}
  72. cmd.Flags().String("restart", "", "dummy restart flag")
  73. cmd.Flags().Lookup("restart").Value.Set(test.input)
  74. policy, err := getRestartPolicy(cmd, test.interactive)
  75. if test.expectErr && err == nil {
  76. t.Error("unexpected non-error")
  77. }
  78. if !test.expectErr && err != nil {
  79. t.Errorf("unexpected error: %v", err)
  80. }
  81. if !test.expectErr && policy != test.expected {
  82. t.Errorf("expected: %s, saw: %s (%s:%v)", test.expected, policy, test.input, test.interactive)
  83. }
  84. }
  85. }
  86. func TestGetEnv(t *testing.T) {
  87. test := struct {
  88. input []string
  89. expected []string
  90. }{
  91. input: []string{"a=b", "c=d"},
  92. expected: []string{"a=b", "c=d"},
  93. }
  94. cmd := &cobra.Command{}
  95. cmd.Flags().StringSlice("env", test.input, "")
  96. envStrings := cmdutil.GetFlagStringSlice(cmd, "env")
  97. if len(envStrings) != 2 || !reflect.DeepEqual(envStrings, test.expected) {
  98. t.Errorf("expected: %s, saw: %s", test.expected, envStrings)
  99. }
  100. }
  101. func TestRunArgsFollowDashRules(t *testing.T) {
  102. _, _, rc := testData()
  103. tests := []struct {
  104. args []string
  105. argsLenAtDash int
  106. expectError bool
  107. name string
  108. }{
  109. {
  110. args: []string{},
  111. argsLenAtDash: -1,
  112. expectError: true,
  113. name: "empty",
  114. },
  115. {
  116. args: []string{"foo"},
  117. argsLenAtDash: -1,
  118. expectError: false,
  119. name: "no cmd",
  120. },
  121. {
  122. args: []string{"foo", "sleep"},
  123. argsLenAtDash: -1,
  124. expectError: false,
  125. name: "cmd no dash",
  126. },
  127. {
  128. args: []string{"foo", "sleep"},
  129. argsLenAtDash: 1,
  130. expectError: false,
  131. name: "cmd has dash",
  132. },
  133. {
  134. args: []string{"foo", "sleep"},
  135. argsLenAtDash: 0,
  136. expectError: true,
  137. name: "no name",
  138. },
  139. }
  140. for _, test := range tests {
  141. f, tf, codec, ns := NewAPIFactory()
  142. tf.Client = &fake.RESTClient{
  143. NegotiatedSerializer: ns,
  144. Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
  145. return &http.Response{StatusCode: 201, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil
  146. }),
  147. }
  148. tf.Namespace = "test"
  149. tf.ClientConfig = &restclient.Config{}
  150. cmd := NewCmdRun(f, os.Stdin, os.Stdout, os.Stderr)
  151. cmd.Flags().Set("image", "nginx")
  152. cmd.Flags().Set("generator", "run/v1")
  153. err := Run(f, os.Stdin, os.Stdout, os.Stderr, cmd, test.args, test.argsLenAtDash)
  154. if test.expectError && err == nil {
  155. t.Errorf("unexpected non-error (%s)", test.name)
  156. }
  157. if !test.expectError && err != nil {
  158. t.Errorf("unexpected error: %v (%s)", err, test.name)
  159. }
  160. }
  161. }
  162. func TestGenerateService(t *testing.T) {
  163. tests := []struct {
  164. port string
  165. args []string
  166. serviceGenerator string
  167. params map[string]interface{}
  168. expectErr bool
  169. name string
  170. service api.Service
  171. expectPOST bool
  172. }{
  173. {
  174. port: "80",
  175. args: []string{"foo"},
  176. serviceGenerator: "service/v2",
  177. params: map[string]interface{}{
  178. "name": "foo",
  179. },
  180. expectErr: false,
  181. name: "basic",
  182. service: api.Service{
  183. ObjectMeta: api.ObjectMeta{
  184. Name: "foo",
  185. },
  186. Spec: api.ServiceSpec{
  187. Ports: []api.ServicePort{
  188. {
  189. Port: 80,
  190. Protocol: "TCP",
  191. TargetPort: intstr.FromInt(80),
  192. },
  193. },
  194. Selector: map[string]string{
  195. "run": "foo",
  196. },
  197. Type: api.ServiceTypeClusterIP,
  198. SessionAffinity: api.ServiceAffinityNone,
  199. },
  200. },
  201. expectPOST: true,
  202. },
  203. {
  204. port: "80",
  205. args: []string{"foo"},
  206. serviceGenerator: "service/v2",
  207. params: map[string]interface{}{
  208. "name": "foo",
  209. "labels": "app=bar",
  210. },
  211. expectErr: false,
  212. name: "custom labels",
  213. service: api.Service{
  214. ObjectMeta: api.ObjectMeta{
  215. Name: "foo",
  216. Labels: map[string]string{"app": "bar"},
  217. },
  218. Spec: api.ServiceSpec{
  219. Ports: []api.ServicePort{
  220. {
  221. Port: 80,
  222. Protocol: "TCP",
  223. TargetPort: intstr.FromInt(80),
  224. },
  225. },
  226. Selector: map[string]string{
  227. "app": "bar",
  228. },
  229. Type: api.ServiceTypeClusterIP,
  230. SessionAffinity: api.ServiceAffinityNone,
  231. },
  232. },
  233. expectPOST: true,
  234. },
  235. {
  236. expectErr: true,
  237. name: "missing port",
  238. expectPOST: false,
  239. },
  240. {
  241. port: "80",
  242. args: []string{"foo"},
  243. serviceGenerator: "service/v2",
  244. params: map[string]interface{}{
  245. "name": "foo",
  246. },
  247. expectErr: false,
  248. name: "dry-run",
  249. expectPOST: false,
  250. },
  251. }
  252. for _, test := range tests {
  253. sawPOST := false
  254. f, tf, codec, ns := NewAPIFactory()
  255. tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}
  256. tf.Printer = &testPrinter{}
  257. tf.Client = &fake.RESTClient{
  258. NegotiatedSerializer: ns,
  259. Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
  260. switch p, m := req.URL.Path, req.Method; {
  261. case test.expectPOST && m == "POST" && p == "/namespaces/namespace/services":
  262. sawPOST = true
  263. body := objBody(codec, &test.service)
  264. data, err := ioutil.ReadAll(req.Body)
  265. if err != nil {
  266. t.Errorf("unexpected error: %v", err)
  267. t.FailNow()
  268. }
  269. defer req.Body.Close()
  270. svc := &api.Service{}
  271. if err := runtime.DecodeInto(codec, data, svc); err != nil {
  272. t.Errorf("unexpected error: %v", err)
  273. t.FailNow()
  274. }
  275. // Copy things that are defaulted by the system
  276. test.service.Annotations = svc.Annotations
  277. if !reflect.DeepEqual(&test.service, svc) {
  278. t.Errorf("expected:\n%v\nsaw:\n%v\n", &test.service, svc)
  279. }
  280. return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil
  281. default:
  282. // Ensures no GET is performed when deleting by name
  283. t.Errorf("%s: unexpected request: %s %#v\n%#v", test.name, req.Method, req.URL, req)
  284. return nil, fmt.Errorf("unexpected request")
  285. }
  286. }),
  287. }
  288. cmd := &cobra.Command{}
  289. cmd.Flags().Bool(cmdutil.ApplyAnnotationsFlag, false, "")
  290. cmd.Flags().Bool("record", false, "Record current kubectl command in the resource annotation. If set to false, do not record the command. If set to true, record the command. If not set, default to updating the existing annotation value only if one already exists.")
  291. cmdutil.AddPrinterFlags(cmd)
  292. cmdutil.AddInclude3rdPartyFlags(cmd)
  293. addRunFlags(cmd)
  294. if !test.expectPOST {
  295. cmd.Flags().Set("dry-run", "true")
  296. }
  297. if len(test.port) > 0 {
  298. cmd.Flags().Set("port", test.port)
  299. test.params["port"] = test.port
  300. }
  301. buff := &bytes.Buffer{}
  302. err := generateService(f, cmd, test.args, test.serviceGenerator, test.params, "namespace", buff)
  303. if test.expectErr {
  304. if err == nil {
  305. t.Error("unexpected non-error")
  306. }
  307. continue
  308. }
  309. if err != nil {
  310. t.Errorf("unexpected error: %v", err)
  311. }
  312. if test.expectPOST != sawPOST {
  313. t.Errorf("expectPost: %v, sawPost: %v", test.expectPOST, sawPOST)
  314. }
  315. }
  316. }