set_selector_test.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. /*
  2. Copyright 2016 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 set
  14. import (
  15. "reflect"
  16. "strings"
  17. "testing"
  18. "github.com/stretchr/testify/assert"
  19. batchv1 "k8s.io/api/batch/v1"
  20. "k8s.io/api/core/v1"
  21. extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
  22. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  23. "k8s.io/apimachinery/pkg/runtime"
  24. "k8s.io/cli-runtime/pkg/genericclioptions"
  25. "k8s.io/cli-runtime/pkg/printers"
  26. "k8s.io/cli-runtime/pkg/resource"
  27. )
  28. func TestUpdateSelectorForObjectTypes(t *testing.T) {
  29. before := metav1.LabelSelector{MatchLabels: map[string]string{"fee": "true"},
  30. MatchExpressions: []metav1.LabelSelectorRequirement{
  31. {
  32. Key: "foo",
  33. Operator: metav1.LabelSelectorOpIn,
  34. Values: []string{"on", "yes"},
  35. },
  36. }}
  37. rc := v1.ReplicationController{}
  38. ser := v1.Service{}
  39. dep := extensionsv1beta1.Deployment{Spec: extensionsv1beta1.DeploymentSpec{Selector: &before}}
  40. ds := extensionsv1beta1.DaemonSet{Spec: extensionsv1beta1.DaemonSetSpec{Selector: &before}}
  41. rs := extensionsv1beta1.ReplicaSet{Spec: extensionsv1beta1.ReplicaSetSpec{Selector: &before}}
  42. job := batchv1.Job{Spec: batchv1.JobSpec{Selector: &before}}
  43. pvc := v1.PersistentVolumeClaim{Spec: v1.PersistentVolumeClaimSpec{Selector: &before}}
  44. sa := v1.ServiceAccount{}
  45. type args struct {
  46. obj runtime.Object
  47. selector metav1.LabelSelector
  48. }
  49. tests := []struct {
  50. name string
  51. args args
  52. wantErr bool
  53. }{
  54. {name: "rc",
  55. args: args{
  56. obj: &rc,
  57. selector: metav1.LabelSelector{},
  58. },
  59. wantErr: true,
  60. },
  61. {name: "ser",
  62. args: args{
  63. obj: &ser,
  64. selector: metav1.LabelSelector{},
  65. },
  66. wantErr: false,
  67. },
  68. {name: "dep",
  69. args: args{
  70. obj: &dep,
  71. selector: metav1.LabelSelector{},
  72. },
  73. wantErr: true,
  74. },
  75. {name: "ds",
  76. args: args{
  77. obj: &ds,
  78. selector: metav1.LabelSelector{},
  79. },
  80. wantErr: true,
  81. },
  82. {name: "rs",
  83. args: args{
  84. obj: &rs,
  85. selector: metav1.LabelSelector{},
  86. },
  87. wantErr: true,
  88. },
  89. {name: "job",
  90. args: args{
  91. obj: &job,
  92. selector: metav1.LabelSelector{},
  93. },
  94. wantErr: true,
  95. },
  96. {name: "pvc - no updates",
  97. args: args{
  98. obj: &pvc,
  99. selector: metav1.LabelSelector{},
  100. },
  101. wantErr: true,
  102. },
  103. {name: "sa - no selector",
  104. args: args{
  105. obj: &sa,
  106. selector: metav1.LabelSelector{},
  107. },
  108. wantErr: true,
  109. },
  110. }
  111. for _, tt := range tests {
  112. if err := updateSelectorForObject(tt.args.obj, tt.args.selector); (err != nil) != tt.wantErr {
  113. t.Errorf("%q. updateSelectorForObject() error = %v, wantErr %v", tt.name, err, tt.wantErr)
  114. }
  115. }
  116. }
  117. func TestUpdateNewSelectorValuesForObject(t *testing.T) {
  118. ser := v1.Service{}
  119. type args struct {
  120. obj runtime.Object
  121. selector metav1.LabelSelector
  122. }
  123. tests := []struct {
  124. name string
  125. args args
  126. wantErr bool
  127. }{
  128. {name: "empty",
  129. args: args{
  130. obj: &ser,
  131. selector: metav1.LabelSelector{
  132. MatchLabels: map[string]string{},
  133. MatchExpressions: []metav1.LabelSelectorRequirement{},
  134. },
  135. },
  136. wantErr: false,
  137. },
  138. {name: "label-only",
  139. args: args{
  140. obj: &ser,
  141. selector: metav1.LabelSelector{
  142. MatchLabels: map[string]string{"b": "u"},
  143. MatchExpressions: []metav1.LabelSelectorRequirement{},
  144. },
  145. },
  146. wantErr: false,
  147. },
  148. }
  149. for _, tt := range tests {
  150. if err := updateSelectorForObject(tt.args.obj, tt.args.selector); (err != nil) != tt.wantErr {
  151. t.Errorf("%q. updateSelectorForObject() error = %v, wantErr %v", tt.name, err, tt.wantErr)
  152. }
  153. assert.EqualValues(t, tt.args.selector.MatchLabels, ser.Spec.Selector, tt.name)
  154. }
  155. }
  156. func TestUpdateOldSelectorValuesForObject(t *testing.T) {
  157. ser := v1.Service{Spec: v1.ServiceSpec{Selector: map[string]string{"fee": "true"}}}
  158. type args struct {
  159. obj runtime.Object
  160. selector metav1.LabelSelector
  161. }
  162. tests := []struct {
  163. name string
  164. args args
  165. wantErr bool
  166. }{
  167. {name: "empty",
  168. args: args{
  169. obj: &ser,
  170. selector: metav1.LabelSelector{
  171. MatchLabels: map[string]string{},
  172. MatchExpressions: []metav1.LabelSelectorRequirement{},
  173. },
  174. },
  175. wantErr: false,
  176. },
  177. {name: "label-only",
  178. args: args{
  179. obj: &ser,
  180. selector: metav1.LabelSelector{
  181. MatchLabels: map[string]string{"fee": "false", "x": "y"},
  182. MatchExpressions: []metav1.LabelSelectorRequirement{},
  183. },
  184. },
  185. wantErr: false,
  186. },
  187. {name: "expr-only - err",
  188. args: args{
  189. obj: &ser,
  190. selector: metav1.LabelSelector{
  191. MatchLabels: map[string]string{},
  192. MatchExpressions: []metav1.LabelSelectorRequirement{
  193. {
  194. Key: "a",
  195. Operator: "In",
  196. Values: []string{"x", "y"},
  197. },
  198. },
  199. },
  200. },
  201. wantErr: true,
  202. },
  203. {name: "both - err",
  204. args: args{
  205. obj: &ser,
  206. selector: metav1.LabelSelector{
  207. MatchLabels: map[string]string{"b": "u"},
  208. MatchExpressions: []metav1.LabelSelectorRequirement{
  209. {
  210. Key: "a",
  211. Operator: "In",
  212. Values: []string{"x", "y"},
  213. },
  214. },
  215. },
  216. },
  217. wantErr: true,
  218. },
  219. }
  220. for _, tt := range tests {
  221. err := updateSelectorForObject(tt.args.obj, tt.args.selector)
  222. if (err != nil) != tt.wantErr {
  223. t.Errorf("%q. updateSelectorForObject() error = %v, wantErr %v", tt.name, err, tt.wantErr)
  224. } else if !tt.wantErr {
  225. assert.EqualValues(t, tt.args.selector.MatchLabels, ser.Spec.Selector, tt.name)
  226. }
  227. }
  228. }
  229. func TestGetResourcesAndSelector(t *testing.T) {
  230. type args struct {
  231. args []string
  232. }
  233. tests := []struct {
  234. name string
  235. args args
  236. wantResources []string
  237. wantSelector *metav1.LabelSelector
  238. wantErr bool
  239. }{
  240. {
  241. name: "basic match",
  242. args: args{args: []string{"rc/foo", "healthy=true"}},
  243. wantResources: []string{"rc/foo"},
  244. wantErr: false,
  245. wantSelector: &metav1.LabelSelector{
  246. MatchLabels: map[string]string{"healthy": "true"},
  247. MatchExpressions: []metav1.LabelSelectorRequirement{},
  248. },
  249. },
  250. {
  251. name: "basic expression",
  252. args: args{args: []string{"rc/foo", "buildType notin (debug, test)"}},
  253. wantResources: []string{"rc/foo"},
  254. wantErr: false,
  255. wantSelector: &metav1.LabelSelector{
  256. MatchLabels: map[string]string{},
  257. MatchExpressions: []metav1.LabelSelectorRequirement{
  258. {
  259. Key: "buildType",
  260. Operator: "NotIn",
  261. Values: []string{"debug", "test"},
  262. },
  263. },
  264. },
  265. },
  266. {
  267. name: "selector error",
  268. args: args{args: []string{"rc/foo", "buildType notthis (debug, test)"}},
  269. wantResources: []string{"rc/foo"},
  270. wantErr: true,
  271. wantSelector: &metav1.LabelSelector{
  272. MatchLabels: map[string]string{},
  273. MatchExpressions: []metav1.LabelSelectorRequirement{},
  274. },
  275. },
  276. {
  277. name: "no resource and selector",
  278. args: args{args: []string{}},
  279. wantResources: []string{},
  280. wantErr: false,
  281. wantSelector: nil,
  282. },
  283. }
  284. for _, tt := range tests {
  285. gotResources, gotSelector, err := getResourcesAndSelector(tt.args.args)
  286. if err != nil {
  287. if !tt.wantErr {
  288. t.Errorf("%q. getResourcesAndSelector() error = %v, wantErr %v", tt.name, err, tt.wantErr)
  289. }
  290. continue
  291. }
  292. if !reflect.DeepEqual(gotResources, tt.wantResources) {
  293. t.Errorf("%q. getResourcesAndSelector() gotResources = %v, want %v", tt.name, gotResources, tt.wantResources)
  294. }
  295. if !reflect.DeepEqual(gotSelector, tt.wantSelector) {
  296. t.Errorf("%q. getResourcesAndSelector() gotSelector = %v, want %v", tt.name, gotSelector, tt.wantSelector)
  297. }
  298. }
  299. }
  300. func TestSelectorTest(t *testing.T) {
  301. info := &resource.Info{
  302. Object: &v1.Service{
  303. TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Service"},
  304. ObjectMeta: metav1.ObjectMeta{Namespace: "some-ns", Name: "cassandra"},
  305. },
  306. }
  307. labelToSet, err := metav1.ParseToLabelSelector("environment=qa")
  308. if err != nil {
  309. t.Fatal(err)
  310. }
  311. iostreams, _, buf, _ := genericclioptions.NewTestIOStreams()
  312. o := &SetSelectorOptions{
  313. selector: labelToSet,
  314. ResourceFinder: genericclioptions.NewSimpleFakeResourceFinder(info),
  315. Recorder: genericclioptions.NoopRecorder{},
  316. PrintObj: (&printers.NamePrinter{}).PrintObj,
  317. IOStreams: iostreams,
  318. }
  319. if err := o.RunSelector(); err != nil {
  320. t.Fatal(err)
  321. }
  322. if !strings.Contains(buf.String(), "service/cassandra") {
  323. t.Errorf("did not set selector: %s", buf.String())
  324. }
  325. }