common_test.go 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. /*
  2. Copyright 2018 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 config
  14. import (
  15. "fmt"
  16. "testing"
  17. "github.com/lithammer/dedent"
  18. "k8s.io/apimachinery/pkg/runtime/schema"
  19. kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
  20. "k8s.io/kubernetes/cmd/kubeadm/app/constants"
  21. kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
  22. )
  23. const KubeadmGroupName = "kubeadm.k8s.io"
  24. func TestValidateSupportedVersion(t *testing.T) {
  25. tests := []struct {
  26. gv schema.GroupVersion
  27. allowDeprecated bool
  28. expectedErr bool
  29. }{
  30. {
  31. gv: schema.GroupVersion{
  32. Group: KubeadmGroupName,
  33. Version: "v1alpha1",
  34. },
  35. expectedErr: true,
  36. },
  37. {
  38. gv: schema.GroupVersion{
  39. Group: KubeadmGroupName,
  40. Version: "v1alpha2",
  41. },
  42. expectedErr: true,
  43. },
  44. {
  45. gv: schema.GroupVersion{
  46. Group: KubeadmGroupName,
  47. Version: "v1alpha3",
  48. },
  49. expectedErr: true,
  50. },
  51. {
  52. gv: schema.GroupVersion{
  53. Group: KubeadmGroupName,
  54. Version: "v1alpha3",
  55. },
  56. allowDeprecated: true,
  57. expectedErr: true,
  58. },
  59. {
  60. gv: schema.GroupVersion{
  61. Group: KubeadmGroupName,
  62. Version: "v1beta1",
  63. },
  64. allowDeprecated: true,
  65. },
  66. {
  67. gv: schema.GroupVersion{
  68. Group: KubeadmGroupName,
  69. Version: "v1beta1",
  70. },
  71. },
  72. {
  73. gv: schema.GroupVersion{
  74. Group: KubeadmGroupName,
  75. Version: "v1beta2",
  76. },
  77. },
  78. {
  79. gv: schema.GroupVersion{
  80. Group: "foo.k8s.io",
  81. Version: "v1",
  82. },
  83. },
  84. }
  85. for _, rt := range tests {
  86. t.Run(fmt.Sprintf("%s/allowDeprecated:%t", rt.gv, rt.allowDeprecated), func(t *testing.T) {
  87. err := validateSupportedVersion(rt.gv, rt.allowDeprecated)
  88. if rt.expectedErr && err == nil {
  89. t.Error("unexpected success")
  90. } else if !rt.expectedErr && err != nil {
  91. t.Errorf("unexpected failure: %v", err)
  92. }
  93. })
  94. }
  95. }
  96. func TestLowercaseSANs(t *testing.T) {
  97. tests := []struct {
  98. name string
  99. in []string
  100. out []string
  101. }{
  102. {
  103. name: "empty struct",
  104. },
  105. {
  106. name: "already lowercase",
  107. in: []string{"example.k8s.io"},
  108. out: []string{"example.k8s.io"},
  109. },
  110. {
  111. name: "ip addresses and uppercase",
  112. in: []string{"EXAMPLE.k8s.io", "10.100.0.1"},
  113. out: []string{"example.k8s.io", "10.100.0.1"},
  114. },
  115. {
  116. name: "punycode and uppercase",
  117. in: []string{"xn--7gq663byk9a.xn--fiqz9s", "ANOTHEREXAMPLE.k8s.io"},
  118. out: []string{"xn--7gq663byk9a.xn--fiqz9s", "anotherexample.k8s.io"},
  119. },
  120. }
  121. for _, test := range tests {
  122. t.Run(test.name, func(t *testing.T) {
  123. cfg := &kubeadmapiv1beta2.ClusterConfiguration{
  124. APIServer: kubeadmapiv1beta2.APIServer{
  125. CertSANs: test.in,
  126. },
  127. }
  128. LowercaseSANs(cfg.APIServer.CertSANs)
  129. if len(cfg.APIServer.CertSANs) != len(test.out) {
  130. t.Fatalf("expected %d elements, got %d", len(test.out), len(cfg.APIServer.CertSANs))
  131. }
  132. for i, expected := range test.out {
  133. if cfg.APIServer.CertSANs[i] != expected {
  134. t.Errorf("expected element %d to be %q, got %q", i, expected, cfg.APIServer.CertSANs[i])
  135. }
  136. }
  137. })
  138. }
  139. }
  140. func TestVerifyAPIServerBindAddress(t *testing.T) {
  141. tests := []struct {
  142. name string
  143. address string
  144. expectedError bool
  145. }{
  146. {
  147. name: "valid address: IPV4",
  148. address: "192.168.0.1",
  149. },
  150. {
  151. name: "valid address: IPV6",
  152. address: "2001:db8:85a3::8a2e:370:7334",
  153. },
  154. {
  155. name: "valid address 127.0.0.1",
  156. address: "127.0.0.1",
  157. expectedError: false,
  158. },
  159. {
  160. name: "invalid address: not a global unicast 0.0.0.0",
  161. address: "0.0.0.0",
  162. expectedError: true,
  163. },
  164. {
  165. name: "invalid address: not a global unicast ::",
  166. address: "::",
  167. expectedError: true,
  168. },
  169. {
  170. name: "invalid address: cannot parse IPV4",
  171. address: "255.255.255.255.255",
  172. expectedError: true,
  173. },
  174. {
  175. name: "invalid address: cannot parse IPV6",
  176. address: "2a00:800::2a00:800:10102a00",
  177. expectedError: true,
  178. },
  179. }
  180. for _, test := range tests {
  181. t.Run(test.name, func(t *testing.T) {
  182. if err := VerifyAPIServerBindAddress(test.address); (err != nil) != test.expectedError {
  183. t.Errorf("expected error: %v, got %v, error: %v", test.expectedError, (err != nil), err)
  184. }
  185. })
  186. }
  187. }
  188. func TestMigrateOldConfigFromFile(t *testing.T) {
  189. tests := []struct {
  190. desc string
  191. oldCfg string
  192. expectedKinds []string
  193. expectErr bool
  194. }{
  195. {
  196. desc: "empty file produces empty result",
  197. oldCfg: "",
  198. expectErr: false,
  199. },
  200. {
  201. desc: "bad config produces error",
  202. oldCfg: dedent.Dedent(`
  203. apiVersion: kubeadm.k8s.io/v1beta1
  204. `),
  205. expectErr: true,
  206. },
  207. {
  208. desc: "InitConfiguration only gets migrated",
  209. oldCfg: dedent.Dedent(`
  210. apiVersion: kubeadm.k8s.io/v1beta1
  211. kind: InitConfiguration
  212. `),
  213. expectedKinds: []string{
  214. constants.InitConfigurationKind,
  215. constants.ClusterConfigurationKind,
  216. },
  217. expectErr: false,
  218. },
  219. {
  220. desc: "ClusterConfiguration only gets migrated",
  221. oldCfg: dedent.Dedent(`
  222. apiVersion: kubeadm.k8s.io/v1beta1
  223. kind: ClusterConfiguration
  224. `),
  225. expectedKinds: []string{
  226. constants.InitConfigurationKind,
  227. constants.ClusterConfigurationKind,
  228. },
  229. expectErr: false,
  230. },
  231. {
  232. desc: "JoinConfiguration only gets migrated",
  233. oldCfg: dedent.Dedent(`
  234. apiVersion: kubeadm.k8s.io/v1beta1
  235. kind: JoinConfiguration
  236. discovery:
  237. bootstrapToken:
  238. token: abcdef.0123456789abcdef
  239. apiServerEndpoint: kube-apiserver:6443
  240. unsafeSkipCAVerification: true
  241. `),
  242. expectedKinds: []string{
  243. constants.JoinConfigurationKind,
  244. },
  245. expectErr: false,
  246. },
  247. {
  248. desc: "Init + Cluster Configurations are migrated",
  249. oldCfg: dedent.Dedent(`
  250. apiVersion: kubeadm.k8s.io/v1beta1
  251. kind: InitConfiguration
  252. ---
  253. apiVersion: kubeadm.k8s.io/v1beta1
  254. kind: ClusterConfiguration
  255. `),
  256. expectedKinds: []string{
  257. constants.InitConfigurationKind,
  258. constants.ClusterConfigurationKind,
  259. },
  260. expectErr: false,
  261. },
  262. {
  263. desc: "Init + Join Configurations are migrated",
  264. oldCfg: dedent.Dedent(`
  265. apiVersion: kubeadm.k8s.io/v1beta1
  266. kind: InitConfiguration
  267. ---
  268. apiVersion: kubeadm.k8s.io/v1beta1
  269. kind: JoinConfiguration
  270. discovery:
  271. bootstrapToken:
  272. token: abcdef.0123456789abcdef
  273. apiServerEndpoint: kube-apiserver:6443
  274. unsafeSkipCAVerification: true
  275. `),
  276. expectedKinds: []string{
  277. constants.InitConfigurationKind,
  278. constants.ClusterConfigurationKind,
  279. constants.JoinConfigurationKind,
  280. },
  281. expectErr: false,
  282. },
  283. {
  284. desc: "Cluster + Join Configurations are migrated",
  285. oldCfg: dedent.Dedent(`
  286. apiVersion: kubeadm.k8s.io/v1beta1
  287. kind: ClusterConfiguration
  288. ---
  289. apiVersion: kubeadm.k8s.io/v1beta1
  290. kind: JoinConfiguration
  291. discovery:
  292. bootstrapToken:
  293. token: abcdef.0123456789abcdef
  294. apiServerEndpoint: kube-apiserver:6443
  295. unsafeSkipCAVerification: true
  296. `),
  297. expectedKinds: []string{
  298. constants.InitConfigurationKind,
  299. constants.ClusterConfigurationKind,
  300. constants.JoinConfigurationKind,
  301. },
  302. expectErr: false,
  303. },
  304. {
  305. desc: "Init + Cluster + Join Configurations are migrated",
  306. oldCfg: dedent.Dedent(`
  307. apiVersion: kubeadm.k8s.io/v1beta1
  308. kind: InitConfiguration
  309. ---
  310. apiVersion: kubeadm.k8s.io/v1beta1
  311. kind: ClusterConfiguration
  312. ---
  313. apiVersion: kubeadm.k8s.io/v1beta1
  314. kind: JoinConfiguration
  315. discovery:
  316. bootstrapToken:
  317. token: abcdef.0123456789abcdef
  318. apiServerEndpoint: kube-apiserver:6443
  319. unsafeSkipCAVerification: true
  320. `),
  321. expectedKinds: []string{
  322. constants.InitConfigurationKind,
  323. constants.ClusterConfigurationKind,
  324. constants.JoinConfigurationKind,
  325. },
  326. expectErr: false,
  327. },
  328. {
  329. desc: "component configs are not migrated",
  330. oldCfg: dedent.Dedent(`
  331. apiVersion: kubeadm.k8s.io/v1beta1
  332. kind: InitConfiguration
  333. ---
  334. apiVersion: kubeadm.k8s.io/v1beta1
  335. kind: ClusterConfiguration
  336. ---
  337. apiVersion: kubeadm.k8s.io/v1beta1
  338. kind: JoinConfiguration
  339. discovery:
  340. bootstrapToken:
  341. token: abcdef.0123456789abcdef
  342. apiServerEndpoint: kube-apiserver:6443
  343. unsafeSkipCAVerification: true
  344. ---
  345. apiVersion: kubeproxy.config.k8s.io/v1alpha1
  346. kind: KubeProxyConfiguration
  347. ---
  348. apiVersion: kubelet.config.k8s.io/v1beta1
  349. kind: KubeletConfiguration
  350. `),
  351. expectedKinds: []string{
  352. constants.InitConfigurationKind,
  353. constants.ClusterConfigurationKind,
  354. constants.JoinConfigurationKind,
  355. },
  356. expectErr: false,
  357. },
  358. }
  359. for _, test := range tests {
  360. t.Run(test.desc, func(t *testing.T) {
  361. b, err := MigrateOldConfig([]byte(test.oldCfg))
  362. if test.expectErr {
  363. if err == nil {
  364. t.Fatalf("unexpected success:\n%s", b)
  365. }
  366. } else {
  367. if err != nil {
  368. t.Fatalf("unexpected failure: %v", err)
  369. }
  370. gvks, err := kubeadmutil.GroupVersionKindsFromBytes(b)
  371. if err != nil {
  372. t.Fatalf("unexpected error returned by GroupVersionKindsFromBytes: %v", err)
  373. }
  374. if len(gvks) != len(test.expectedKinds) {
  375. t.Fatalf("length mismatch between resulting gvks and expected kinds:\n\tlen(gvks)=%d\n\tlen(expectedKinds)=%d",
  376. len(gvks), len(test.expectedKinds))
  377. }
  378. for _, expectedKind := range test.expectedKinds {
  379. if !kubeadmutil.GroupVersionKindsHasKind(gvks, expectedKind) {
  380. t.Fatalf("migration failed to produce config kind: %s", expectedKind)
  381. }
  382. }
  383. }
  384. })
  385. }
  386. }