fsstore_test.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. /*
  2. Copyright 2017 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 store
  14. import (
  15. "fmt"
  16. "io/ioutil"
  17. "path/filepath"
  18. "reflect"
  19. "testing"
  20. "time"
  21. "github.com/davecgh/go-spew/spew"
  22. apiv1 "k8s.io/api/core/v1"
  23. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  24. "k8s.io/apimachinery/pkg/types"
  25. "k8s.io/kubelet/config/v1beta1"
  26. kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
  27. "k8s.io/kubernetes/pkg/kubelet/apis/config/scheme"
  28. "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint"
  29. utilcodec "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec"
  30. utilfiles "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/files"
  31. utiltest "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/test"
  32. utilfs "k8s.io/kubernetes/pkg/util/filesystem"
  33. )
  34. var testdir string
  35. func init() {
  36. tmp, err := ioutil.TempDir("", "fsstore-test")
  37. if err != nil {
  38. panic(err)
  39. }
  40. testdir = tmp
  41. }
  42. func newInitializedFakeFsStore() (*fsStore, error) {
  43. // Test with the default filesystem, the fake filesystem has an issue caused by afero: https://github.com/spf13/afero/issues/141
  44. // The default filesystem also behaves more like production, so we should probably not mock the filesystem for unit tests.
  45. fs := utilfs.DefaultFs{}
  46. tmpdir, err := fs.TempDir(testdir, "store-")
  47. if err != nil {
  48. return nil, err
  49. }
  50. store := NewFsStore(fs, tmpdir)
  51. if err := store.Initialize(); err != nil {
  52. return nil, err
  53. }
  54. return store.(*fsStore), nil
  55. }
  56. func TestFsStoreInitialize(t *testing.T) {
  57. store, err := newInitializedFakeFsStore()
  58. if err != nil {
  59. t.Fatalf("fsStore.Initialize() failed with error: %v", err)
  60. }
  61. // check that store.dir exists
  62. if _, err := store.fs.Stat(store.dir); err != nil {
  63. t.Fatalf("expect %q to exist, but stat failed with error: %v", store.dir, err)
  64. }
  65. // check that meta dir exists
  66. if _, err := store.fs.Stat(store.metaPath("")); err != nil {
  67. t.Fatalf("expect %q to exist, but stat failed with error: %v", store.metaPath(""), err)
  68. }
  69. // check that checkpoints dir exists
  70. if _, err := store.fs.Stat(filepath.Join(store.dir, checkpointsDir)); err != nil {
  71. t.Fatalf("expect %q to exist, but stat failed with error: %v", filepath.Join(store.dir, checkpointsDir), err)
  72. }
  73. // check that assignedFile exists
  74. if _, err := store.fs.Stat(store.metaPath(assignedFile)); err != nil {
  75. t.Fatalf("expect %q to exist, but stat failed with error: %v", store.metaPath(assignedFile), err)
  76. }
  77. // check that lastKnownGoodFile exists
  78. if _, err := store.fs.Stat(store.metaPath(lastKnownGoodFile)); err != nil {
  79. t.Fatalf("expect %q to exist, but stat failed with error: %v", store.metaPath(lastKnownGoodFile), err)
  80. }
  81. }
  82. func TestFsStoreExists(t *testing.T) {
  83. store, err := newInitializedFakeFsStore()
  84. if err != nil {
  85. t.Fatalf("error constructing store: %v", err)
  86. }
  87. // checkpoint a payload
  88. const (
  89. uid = "uid"
  90. resourceVersion = "1"
  91. )
  92. p, err := checkpoint.NewConfigMapPayload(&apiv1.ConfigMap{ObjectMeta: metav1.ObjectMeta{UID: uid, ResourceVersion: resourceVersion}})
  93. if err != nil {
  94. t.Fatalf("could not construct Payload, error: %v", err)
  95. }
  96. if err := store.Save(p); err != nil {
  97. t.Fatalf("unexpected error: %v", err)
  98. }
  99. cases := []struct {
  100. desc string
  101. uid types.UID
  102. resourceVersion string
  103. expect bool
  104. err string
  105. }{
  106. {"exists", uid, resourceVersion, true, ""},
  107. {"does not exist", "bogus-uid", "bogus-resourceVersion", false, ""},
  108. {"ambiguous UID", "", "bogus-resourceVersion", false, "empty UID is ambiguous"},
  109. {"ambiguous ResourceVersion", "bogus-uid", "", false, "empty ResourceVersion is ambiguous"},
  110. }
  111. for _, c := range cases {
  112. t.Run(c.desc, func(t *testing.T) {
  113. source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{
  114. ConfigMap: &apiv1.ConfigMapNodeConfigSource{
  115. Name: "name",
  116. Namespace: "namespace",
  117. UID: c.uid,
  118. ResourceVersion: c.resourceVersion,
  119. KubeletConfigKey: "kubelet",
  120. }})
  121. if err != nil {
  122. t.Fatalf("unexpected error: %v", err)
  123. }
  124. ok, err := store.Exists(source)
  125. utiltest.ExpectError(t, err, c.err)
  126. if err != nil {
  127. return
  128. }
  129. if c.expect != ok {
  130. t.Errorf("expect %t but got %t", c.expect, ok)
  131. }
  132. })
  133. }
  134. }
  135. func TestFsStoreSave(t *testing.T) {
  136. store, err := newInitializedFakeFsStore()
  137. if err != nil {
  138. t.Fatalf("error constructing store: %v", err)
  139. }
  140. nameTooLong := func() string {
  141. s := ""
  142. for i := 0; i < 256; i++ {
  143. s += "a"
  144. }
  145. return s
  146. }()
  147. const (
  148. uid = "uid"
  149. resourceVersion = "1"
  150. )
  151. cases := []struct {
  152. desc string
  153. uid types.UID
  154. resourceVersion string
  155. files map[string]string
  156. err string
  157. }{
  158. {"valid payload", uid, resourceVersion, map[string]string{"foo": "foocontent", "bar": "barcontent"}, ""},
  159. {"empty key name", uid, resourceVersion, map[string]string{"": "foocontent"}, "must not be empty"},
  160. {"key name is not a base file name (foo/bar)", uid, resourceVersion, map[string]string{"foo/bar": "foocontent"}, "only base names are allowed"},
  161. {"key name is not a base file name (/foo)", uid, resourceVersion, map[string]string{"/bar": "foocontent"}, "only base names are allowed"},
  162. {"used .", uid, resourceVersion, map[string]string{".": "foocontent"}, "may not be '.' or '..'"},
  163. {"used ..", uid, resourceVersion, map[string]string{"..": "foocontent"}, "may not be '.' or '..'"},
  164. {"length violation", uid, resourceVersion, map[string]string{nameTooLong: "foocontent"}, "must be less than 255 characters"},
  165. }
  166. for _, c := range cases {
  167. t.Run(c.desc, func(t *testing.T) {
  168. // construct the payload
  169. p, err := checkpoint.NewConfigMapPayload(&apiv1.ConfigMap{
  170. ObjectMeta: metav1.ObjectMeta{UID: c.uid, ResourceVersion: c.resourceVersion},
  171. Data: c.files,
  172. })
  173. // if no error, save the payload, otherwise skip straight to error handler
  174. if err == nil {
  175. err = store.Save(p)
  176. }
  177. utiltest.ExpectError(t, err, c.err)
  178. if err != nil {
  179. return
  180. }
  181. // read the saved checkpoint
  182. m, err := mapFromCheckpoint(store, p.UID(), p.ResourceVersion())
  183. if err != nil {
  184. t.Fatalf("error loading checkpoint to map: %v", err)
  185. }
  186. // compare our expectation to what got saved
  187. expect := p.Files()
  188. if !reflect.DeepEqual(expect, m) {
  189. t.Errorf("expect %v, but got %v", expect, m)
  190. }
  191. })
  192. }
  193. }
  194. func TestFsStoreLoad(t *testing.T) {
  195. store, err := newInitializedFakeFsStore()
  196. if err != nil {
  197. t.Fatalf("error constructing store: %v", err)
  198. }
  199. // encode a kubelet configuration that has all defaults set
  200. expect, err := newKubeletConfiguration()
  201. if err != nil {
  202. t.Fatalf("error constructing KubeletConfiguration: %v", err)
  203. }
  204. data, err := utilcodec.EncodeKubeletConfig(expect, v1beta1.SchemeGroupVersion)
  205. if err != nil {
  206. t.Fatalf("error encoding KubeletConfiguration: %v", err)
  207. }
  208. // construct a payload that contains the kubeletconfig
  209. const (
  210. uid = "uid"
  211. resourceVersion = "1"
  212. kubeletKey = "kubelet"
  213. )
  214. p, err := checkpoint.NewConfigMapPayload(&apiv1.ConfigMap{
  215. ObjectMeta: metav1.ObjectMeta{UID: types.UID(uid), ResourceVersion: resourceVersion},
  216. Data: map[string]string{
  217. kubeletKey: string(data),
  218. },
  219. })
  220. if err != nil {
  221. t.Fatalf("error constructing payload: %v", err)
  222. }
  223. // save the payload
  224. err = store.Save(p)
  225. if err != nil {
  226. t.Fatalf("error saving payload: %v", err)
  227. }
  228. cases := []struct {
  229. desc string
  230. uid types.UID
  231. resourceVersion string
  232. err string
  233. }{
  234. {"checkpoint exists", uid, resourceVersion, ""},
  235. {"checkpoint does not exist", "bogus-uid", "bogus-resourceVersion", "no checkpoint for source"},
  236. {"ambiguous UID", "", "bogus-resourceVersion", "empty UID is ambiguous"},
  237. {"ambiguous ResourceVersion", "bogus-uid", "", "empty ResourceVersion is ambiguous"},
  238. }
  239. for _, c := range cases {
  240. t.Run(c.desc, func(t *testing.T) {
  241. source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{
  242. ConfigMap: &apiv1.ConfigMapNodeConfigSource{
  243. Name: "name",
  244. Namespace: "namespace",
  245. UID: c.uid,
  246. ResourceVersion: c.resourceVersion,
  247. KubeletConfigKey: kubeletKey,
  248. }})
  249. if err != nil {
  250. t.Fatalf("unexpected error: %v", err)
  251. }
  252. loaded, err := store.Load(source)
  253. utiltest.ExpectError(t, err, c.err)
  254. if err != nil {
  255. return
  256. }
  257. if !reflect.DeepEqual(expect, loaded) {
  258. t.Errorf("expect %#v, but got %#v", expect, loaded)
  259. }
  260. })
  261. }
  262. }
  263. func TestFsStoreAssignedModified(t *testing.T) {
  264. store, err := newInitializedFakeFsStore()
  265. if err != nil {
  266. t.Fatalf("error constructing store: %v", err)
  267. }
  268. // create an empty assigned file, this is good enough for testing
  269. saveTestSourceFile(t, store, assignedFile, nil)
  270. // round the current time to the nearest second because some file systems do not support sub-second precision.
  271. now := time.Now().Round(time.Second)
  272. // set the timestamps to the current time, so we can compare to result of store.AssignedModified
  273. err = store.fs.Chtimes(store.metaPath(assignedFile), now, now)
  274. if err != nil {
  275. t.Fatalf("could not change timestamps, error: %v", err)
  276. }
  277. modTime, err := store.AssignedModified()
  278. if err != nil {
  279. t.Fatalf("unable to determine modification time of assigned config source, error: %v", err)
  280. }
  281. if !now.Equal(modTime) {
  282. t.Errorf("expect %q but got %q", now.Format(time.RFC3339), modTime.Format(time.RFC3339))
  283. }
  284. }
  285. func TestFsStoreAssigned(t *testing.T) {
  286. store, err := newInitializedFakeFsStore()
  287. if err != nil {
  288. t.Fatalf("error constructing store: %v", err)
  289. }
  290. source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{
  291. ConfigMap: &apiv1.ConfigMapNodeConfigSource{
  292. Name: "name",
  293. Namespace: "namespace",
  294. UID: "uid",
  295. KubeletConfigKey: "kubelet",
  296. }})
  297. if err != nil {
  298. t.Fatalf("unexpected error: %v", err)
  299. }
  300. cases := []struct {
  301. desc string
  302. expect checkpoint.RemoteConfigSource
  303. err string
  304. }{
  305. {"default source", nil, ""},
  306. {"non-default source", source, ""},
  307. }
  308. for _, c := range cases {
  309. t.Run(c.desc, func(t *testing.T) {
  310. // save the last known good source
  311. saveTestSourceFile(t, store, assignedFile, c.expect)
  312. // load last-known-good and compare to expected result
  313. source, err := store.Assigned()
  314. utiltest.ExpectError(t, err, c.err)
  315. if err != nil {
  316. return
  317. }
  318. if !checkpoint.EqualRemoteConfigSources(c.expect, source) {
  319. t.Errorf("case %q, expect %q but got %q", spew.Sdump(c.expect), spew.Sdump(c.expect), spew.Sdump(source))
  320. }
  321. })
  322. }
  323. }
  324. func TestFsStoreLastKnownGood(t *testing.T) {
  325. store, err := newInitializedFakeFsStore()
  326. if err != nil {
  327. t.Fatalf("error constructing store: %v", err)
  328. }
  329. source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{
  330. ConfigMap: &apiv1.ConfigMapNodeConfigSource{
  331. Name: "name",
  332. Namespace: "namespace",
  333. UID: "uid",
  334. KubeletConfigKey: "kubelet",
  335. }})
  336. if err != nil {
  337. t.Fatalf("unexpected error: %v", err)
  338. }
  339. cases := []struct {
  340. desc string
  341. expect checkpoint.RemoteConfigSource
  342. err string
  343. }{
  344. {"default source", nil, ""},
  345. {"non-default source", source, ""},
  346. }
  347. for _, c := range cases {
  348. t.Run(c.desc, func(t *testing.T) {
  349. // save the last known good source
  350. saveTestSourceFile(t, store, lastKnownGoodFile, c.expect)
  351. // load last-known-good and compare to expected result
  352. source, err := store.LastKnownGood()
  353. utiltest.ExpectError(t, err, c.err)
  354. if err != nil {
  355. return
  356. }
  357. if !checkpoint.EqualRemoteConfigSources(c.expect, source) {
  358. t.Errorf("case %q, expect %q but got %q", spew.Sdump(c.expect), spew.Sdump(c.expect), spew.Sdump(source))
  359. }
  360. })
  361. }
  362. }
  363. func TestFsStoreSetAssigned(t *testing.T) {
  364. store, err := newInitializedFakeFsStore()
  365. if err != nil {
  366. t.Fatalf("error constructing store: %v", err)
  367. }
  368. cases := []struct {
  369. desc string
  370. source *apiv1.NodeConfigSource
  371. expect string
  372. err string
  373. }{
  374. {
  375. desc: "nil source",
  376. expect: "", // empty file
  377. },
  378. {
  379. desc: "non-nil source",
  380. source: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
  381. Name: "name",
  382. Namespace: "namespace",
  383. UID: "uid",
  384. ResourceVersion: "1",
  385. KubeletConfigKey: "kubelet",
  386. }},
  387. expect: `apiVersion: kubelet.config.k8s.io/v1beta1
  388. kind: SerializedNodeConfigSource
  389. source:
  390. configMap:
  391. kubeletConfigKey: kubelet
  392. name: name
  393. namespace: namespace
  394. resourceVersion: "1"
  395. uid: uid
  396. `,
  397. },
  398. {
  399. desc: "missing UID",
  400. source: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
  401. Name: "name",
  402. Namespace: "namespace",
  403. ResourceVersion: "1",
  404. KubeletConfigKey: "kubelet",
  405. }},
  406. err: "failed to write RemoteConfigSource, empty UID is ambiguous",
  407. },
  408. {
  409. desc: "missing ResourceVersion",
  410. source: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
  411. Name: "name",
  412. Namespace: "namespace",
  413. UID: "uid",
  414. KubeletConfigKey: "kubelet",
  415. }},
  416. err: "failed to write RemoteConfigSource, empty ResourceVersion is ambiguous",
  417. },
  418. }
  419. for _, c := range cases {
  420. t.Run(c.desc, func(t *testing.T) {
  421. var source checkpoint.RemoteConfigSource
  422. if c.source != nil {
  423. s, _, err := checkpoint.NewRemoteConfigSource(c.source)
  424. if err != nil {
  425. t.Fatalf("unexpected error: %v", err)
  426. }
  427. source = s
  428. }
  429. // save the assigned source
  430. err = store.SetAssigned(source)
  431. utiltest.ExpectError(t, err, c.err)
  432. if err != nil {
  433. return
  434. }
  435. // check that the source saved as we would expect
  436. data := readTestSourceFile(t, store, assignedFile)
  437. if c.expect != string(data) {
  438. t.Errorf("expect assigned source file to contain %q, but got %q", c.expect, string(data))
  439. }
  440. })
  441. }
  442. }
  443. func TestFsStoreSetLastKnownGood(t *testing.T) {
  444. store, err := newInitializedFakeFsStore()
  445. if err != nil {
  446. t.Fatalf("error constructing store: %v", err)
  447. }
  448. cases := []struct {
  449. desc string
  450. source *apiv1.NodeConfigSource
  451. expect string
  452. err string
  453. }{
  454. {
  455. desc: "nil source",
  456. expect: "", // empty file
  457. },
  458. {
  459. desc: "non-nil source",
  460. source: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
  461. Name: "name",
  462. Namespace: "namespace",
  463. UID: "uid",
  464. ResourceVersion: "1",
  465. KubeletConfigKey: "kubelet",
  466. }},
  467. expect: `apiVersion: kubelet.config.k8s.io/v1beta1
  468. kind: SerializedNodeConfigSource
  469. source:
  470. configMap:
  471. kubeletConfigKey: kubelet
  472. name: name
  473. namespace: namespace
  474. resourceVersion: "1"
  475. uid: uid
  476. `,
  477. },
  478. {
  479. desc: "missing UID",
  480. source: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
  481. Name: "name",
  482. Namespace: "namespace",
  483. ResourceVersion: "1",
  484. KubeletConfigKey: "kubelet",
  485. }},
  486. err: "failed to write RemoteConfigSource, empty UID is ambiguous",
  487. },
  488. {
  489. desc: "missing ResourceVersion",
  490. source: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
  491. Name: "name",
  492. Namespace: "namespace",
  493. UID: "uid",
  494. KubeletConfigKey: "kubelet",
  495. }},
  496. err: "failed to write RemoteConfigSource, empty ResourceVersion is ambiguous",
  497. },
  498. }
  499. for _, c := range cases {
  500. t.Run(c.desc, func(t *testing.T) {
  501. var source checkpoint.RemoteConfigSource
  502. if c.source != nil {
  503. s, _, err := checkpoint.NewRemoteConfigSource(c.source)
  504. if err != nil {
  505. t.Fatalf("unexpected error: %v", err)
  506. }
  507. source = s
  508. }
  509. // save the assigned source
  510. err = store.SetLastKnownGood(source)
  511. utiltest.ExpectError(t, err, c.err)
  512. if err != nil {
  513. return
  514. }
  515. // check that the source saved as we would expect
  516. data := readTestSourceFile(t, store, lastKnownGoodFile)
  517. if c.expect != string(data) {
  518. t.Errorf("expect assigned source file to contain %q, but got %q", c.expect, string(data))
  519. }
  520. })
  521. }
  522. }
  523. func TestFsStoreReset(t *testing.T) {
  524. store, err := newInitializedFakeFsStore()
  525. if err != nil {
  526. t.Fatalf("error constructing store: %v", err)
  527. }
  528. source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
  529. Name: "name",
  530. Namespace: "namespace",
  531. UID: "uid",
  532. KubeletConfigKey: "kubelet",
  533. }})
  534. if err != nil {
  535. t.Fatalf("unexpected error: %v", err)
  536. }
  537. otherSource, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
  538. Name: "other-name",
  539. Namespace: "namespace",
  540. UID: "other-uid",
  541. KubeletConfigKey: "kubelet",
  542. }})
  543. if err != nil {
  544. t.Fatalf("unexpected error: %v", err)
  545. }
  546. cases := []struct {
  547. desc string
  548. assigned checkpoint.RemoteConfigSource
  549. lastKnownGood checkpoint.RemoteConfigSource
  550. updated bool
  551. }{
  552. {"nil -> nil", nil, nil, false},
  553. {"source -> nil", source, nil, true},
  554. {"nil -> source", nil, source, false},
  555. {"source -> source", source, source, true},
  556. {"source -> otherSource", source, otherSource, true},
  557. {"otherSource -> source", otherSource, source, true},
  558. }
  559. for _, c := range cases {
  560. t.Run(c.desc, func(t *testing.T) {
  561. // manually save the sources to their respective files
  562. saveTestSourceFile(t, store, assignedFile, c.assigned)
  563. saveTestSourceFile(t, store, lastKnownGoodFile, c.lastKnownGood)
  564. // reset
  565. updated, err := store.Reset()
  566. if err != nil {
  567. t.Fatalf("unexpected error: %v", err)
  568. }
  569. // make sure the files were emptied
  570. if size := testSourceFileSize(t, store, assignedFile); size > 0 {
  571. t.Errorf("case %q, expect source file %q to be empty but got %d bytes", c.desc, assignedFile, size)
  572. }
  573. if size := testSourceFileSize(t, store, lastKnownGoodFile); size > 0 {
  574. t.Errorf("case %q, expect source file %q to be empty but got %d bytes", c.desc, lastKnownGoodFile, size)
  575. }
  576. // make sure Assigned() and LastKnownGood() both return nil
  577. assigned, err := store.Assigned()
  578. if err != nil {
  579. t.Fatalf("unexpected error: %v", err)
  580. }
  581. lastKnownGood, err := store.LastKnownGood()
  582. if err != nil {
  583. t.Fatalf("unexpected error: %v", err)
  584. }
  585. if assigned != nil || lastKnownGood != nil {
  586. t.Errorf("case %q, expect nil for assigned and last-known-good checkpoints, but still have %q and %q, respectively",
  587. c.desc, assigned, lastKnownGood)
  588. }
  589. if c.updated != updated {
  590. t.Errorf("case %q, expect reset to return %t, but got %t", c.desc, c.updated, updated)
  591. }
  592. })
  593. }
  594. }
  595. func mapFromCheckpoint(store *fsStore, uid, resourceVersion string) (map[string]string, error) {
  596. files, err := store.fs.ReadDir(store.checkpointPath(uid, resourceVersion))
  597. if err != nil {
  598. return nil, err
  599. }
  600. m := map[string]string{}
  601. for _, f := range files {
  602. // expect no subdirs, only regular files
  603. if !f.Mode().IsRegular() {
  604. return nil, fmt.Errorf("expect only regular files in checkpoint dir %q", uid)
  605. }
  606. // read the file contents and build the map
  607. data, err := store.fs.ReadFile(filepath.Join(store.checkpointPath(uid, resourceVersion), f.Name()))
  608. if err != nil {
  609. return nil, err
  610. }
  611. m[f.Name()] = string(data)
  612. }
  613. return m, nil
  614. }
  615. func readTestSourceFile(t *testing.T, store *fsStore, relPath string) []byte {
  616. data, err := store.fs.ReadFile(store.metaPath(relPath))
  617. if err != nil {
  618. t.Fatalf("unable to read test source file, error: %v", err)
  619. }
  620. return data
  621. }
  622. func saveTestSourceFile(t *testing.T, store *fsStore, relPath string, source checkpoint.RemoteConfigSource) {
  623. if source != nil {
  624. data, err := source.Encode()
  625. if err != nil {
  626. t.Fatalf("unable to save test source file, error: %v", err)
  627. }
  628. err = utilfiles.ReplaceFile(store.fs, store.metaPath(relPath), data)
  629. if err != nil {
  630. t.Fatalf("unable to save test source file, error: %v", err)
  631. }
  632. } else {
  633. err := utilfiles.ReplaceFile(store.fs, store.metaPath(relPath), []byte{})
  634. if err != nil {
  635. t.Fatalf("unable to save test source file, error: %v", err)
  636. }
  637. }
  638. }
  639. func testSourceFileSize(t *testing.T, store *fsStore, relPath string) int64 {
  640. info, err := store.fs.Stat(store.metaPath(relPath))
  641. if err != nil {
  642. t.Fatalf("unexpected error: %v", err)
  643. }
  644. return info.Size()
  645. }
  646. // newKubeletConfiguration will create a new KubeletConfiguration with default values set
  647. func newKubeletConfiguration() (*kubeletconfig.KubeletConfiguration, error) {
  648. s, _, err := scheme.NewSchemeAndCodecs()
  649. if err != nil {
  650. return nil, err
  651. }
  652. versioned := &v1beta1.KubeletConfiguration{}
  653. s.Default(versioned)
  654. config := &kubeletconfig.KubeletConfiguration{}
  655. if err := s.Convert(versioned, config, nil); err != nil {
  656. return nil, err
  657. }
  658. return config, nil
  659. }