cache.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. // Copyright (c) Tailscale Inc & contributors
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. package main
  4. import (
  5. "encoding/json"
  6. "os"
  7. )
  8. // Cache contains cached information about the last time this tool was run.
  9. //
  10. // This is serialized to a JSON file that should NOT be checked into git.
  11. // It should be managed with either CI cache tools or stored locally somehow. The
  12. // exact mechanism is irrelevant as long as it is consistent.
  13. //
  14. // This allows gitops-pusher to detect external ACL changes. I'm not sure what to
  15. // call this problem, so I've been calling it the "three version problem" in my
  16. // notes. The basic problem is that at any given time we only have two versions
  17. // of the ACL file at any given point. In order to check if there has been
  18. // tampering of the ACL files in the admin panel, we need to have a _third_ version
  19. // to compare against.
  20. //
  21. // In this case I am not storing the old ACL entirely (though that could be a
  22. // reasonable thing to add in the future), but only its sha256sum. This allows
  23. // us to detect if the shasum in control matches the shasum we expect, and if that
  24. // expectation fails, then we can react accordingly.
  25. type Cache struct {
  26. PrevETag string // Stores the previous ETag of the ACL to allow
  27. }
  28. // Save persists the cache to a given file.
  29. func (c *Cache) Save(fname string) error {
  30. os.Remove(fname)
  31. fout, err := os.Create(fname)
  32. if err != nil {
  33. return err
  34. }
  35. defer fout.Close()
  36. return json.NewEncoder(fout).Encode(c)
  37. }
  38. // LoadCache loads the cache from a given file.
  39. func LoadCache(fname string) (*Cache, error) {
  40. var result Cache
  41. fin, err := os.Open(fname)
  42. if err != nil {
  43. return nil, err
  44. }
  45. defer fin.Close()
  46. err = json.NewDecoder(fin).Decode(&result)
  47. if err != nil {
  48. return nil, err
  49. }
  50. return &result, nil
  51. }
  52. // Shuck removes the first and last character of a string, analogous to
  53. // shucking off the husk of an ear of corn.
  54. func Shuck(s string) string {
  55. return s[1 : len(s)-1]
  56. }