GitOps for k8s
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

images.go 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. package update
  2. import (
  3. "fmt"
  4. "strings"
  5. "github.com/go-kit/kit/log"
  6. "github.com/pkg/errors"
  7. glob "github.com/ryanuber/go-glob"
  8. "github.com/weaveworks/flux/cluster"
  9. fluxerr "github.com/weaveworks/flux/errors"
  10. "github.com/weaveworks/flux/image"
  11. "github.com/weaveworks/flux/registry"
  12. )
  13. type infoMap map[image.CanonicalName][]image.Info
  14. type ImageMap struct {
  15. images infoMap
  16. }
  17. // LatestImage returns the latest releasable image for a repository
  18. // for which the tag matches a given pattern. A releasable image is
  19. // one that is not tagged "latest". (Assumes the available images are
  20. // in descending order of latestness.) If no such image exists,
  21. // returns a zero value and `false`, and the caller can decide whether
  22. // that's an error or not.
  23. func (m ImageMap) LatestImage(repo image.Name, tagGlob string) (image.Info, bool) {
  24. for _, available := range m.images[repo.CanonicalName()] {
  25. tag := available.ID.Tag
  26. // Ignore latest if and only if it's not what the user wants.
  27. if !strings.EqualFold(tagGlob, "latest") && strings.EqualFold(tag, "latest") {
  28. continue
  29. }
  30. if glob.Glob(tagGlob, tag) {
  31. var im image.Info
  32. im = available
  33. im.ID = repo.ToRef(tag)
  34. return im, true
  35. }
  36. }
  37. return image.Info{}, false
  38. }
  39. // Available returns image.Info entries for all the images in the
  40. // named image repository.
  41. func (m ImageMap) Available(repo image.Name) []image.Info {
  42. if canon, ok := m.images[repo.CanonicalName()]; ok {
  43. infos := make([]image.Info, len(canon))
  44. for i := range canon {
  45. infos[i] = canon[i]
  46. infos[i].ID = repo.ToRef(infos[i].ID.Tag)
  47. }
  48. return infos
  49. }
  50. return nil
  51. }
  52. // collectUpdateImages is a convenient shim to
  53. // `CollectAvailableImages`.
  54. func collectUpdateImages(registry registry.Registry, updateable []*ControllerUpdate, logger log.Logger) (ImageMap, error) {
  55. var servicesToCheck []cluster.Controller
  56. for _, update := range updateable {
  57. servicesToCheck = append(servicesToCheck, update.Controller)
  58. }
  59. return CollectAvailableImages(registry, servicesToCheck, logger)
  60. }
  61. // CollectAvailableImages finds all the known image metadata for
  62. // containers in the controllers given.
  63. func CollectAvailableImages(reg registry.Registry, services []cluster.Controller, logger log.Logger) (ImageMap, error) {
  64. images := infoMap{}
  65. for _, service := range services {
  66. for _, container := range service.ContainersOrNil() {
  67. images[container.Image.CanonicalName()] = nil
  68. }
  69. }
  70. for name := range images {
  71. imageRepo, err := reg.GetRepository(name.Name)
  72. if err != nil {
  73. // Not an error if missing. Use empty images.
  74. if !fluxerr.IsMissing(err) {
  75. logger.Log("err", errors.Wrapf(err, "fetching image metadata for %s", name))
  76. continue
  77. }
  78. }
  79. images[name] = imageRepo
  80. }
  81. return ImageMap{images}, nil
  82. }
  83. // Create a map of images. It will check that each image exists.
  84. func exactImages(reg registry.Registry, images []image.Ref) (ImageMap, error) {
  85. m := infoMap{}
  86. for _, id := range images {
  87. // We must check that the exact images requested actually exist. Otherwise we risk pushing invalid images to git.
  88. exist, err := imageExists(reg, id)
  89. if err != nil {
  90. return ImageMap{}, errors.Wrap(image.ErrInvalidImageID, err.Error())
  91. }
  92. if !exist {
  93. return ImageMap{}, errors.Wrap(image.ErrInvalidImageID, fmt.Sprintf("image %q does not exist", id))
  94. }
  95. m[id.CanonicalName()] = []image.Info{{ID: id}}
  96. }
  97. return ImageMap{m}, nil
  98. }
  99. // Checks whether the given image exists in the repository.
  100. // Return true if exist, false otherwise
  101. func imageExists(reg registry.Registry, imageID image.Ref) (bool, error) {
  102. _, err := reg.GetImage(imageID)
  103. if err != nil {
  104. return false, nil
  105. }
  106. return true, nil
  107. }