main.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "os"
  6. "path/filepath"
  7. resource "github.com/concourse/registry-image-resource"
  8. color "github.com/fatih/color"
  9. "github.com/google/go-containerregistry/pkg/name"
  10. "github.com/google/go-containerregistry/pkg/v1"
  11. "github.com/google/go-containerregistry/pkg/v1/remote"
  12. "github.com/google/go-containerregistry/pkg/v1/tarball"
  13. "github.com/sirupsen/logrus"
  14. )
  15. type InRequest struct {
  16. Source resource.Source `json:"source"`
  17. Params resource.GetParams `json:"params"`
  18. Version resource.Version `json:"version"`
  19. }
  20. type InResponse struct {
  21. Version resource.Version `json:"version"`
  22. Metadata []resource.MetadataField `json:"metadata"`
  23. }
  24. type ImageMetadata struct {
  25. Env []string `json:"env"`
  26. User string `json:"user"`
  27. }
  28. func main() {
  29. logrus.SetOutput(os.Stderr)
  30. logrus.SetFormatter(&logrus.TextFormatter{
  31. ForceColors: true,
  32. })
  33. color.NoColor = false
  34. var req InRequest
  35. err := json.NewDecoder(os.Stdin).Decode(&req)
  36. if err != nil {
  37. logrus.Errorf("invalid payload: %s", err)
  38. os.Exit(1)
  39. return
  40. }
  41. if req.Source.Debug {
  42. logrus.SetLevel(logrus.DebugLevel)
  43. }
  44. if len(os.Args) < 2 {
  45. logrus.Errorf("destination path not specified")
  46. os.Exit(1)
  47. return
  48. }
  49. dest := os.Args[1]
  50. ref := req.Source.Repository + "@" + req.Version.Digest
  51. n, err := name.ParseReference(ref, name.WeakValidation)
  52. if err != nil {
  53. logrus.Errorf("failed to resolve name: %s", err)
  54. os.Exit(1)
  55. return
  56. }
  57. fmt.Fprintf(os.Stderr, "fetching %s@%s\n", color.GreenString(req.Source.Repository), color.YellowString(req.Version.Digest))
  58. image, err := remote.Image(n)
  59. if err != nil {
  60. logrus.Errorf("failed to locate remote image: %s", err)
  61. os.Exit(1)
  62. return
  63. }
  64. switch req.Params.Format() {
  65. case "oci":
  66. ociFormat(dest, req, image)
  67. case "rootfs":
  68. rootfsFormat(dest, req, image)
  69. }
  70. json.NewEncoder(os.Stdout).Encode(InResponse{
  71. Version: req.Version,
  72. Metadata: []resource.MetadataField{},
  73. })
  74. }
  75. func ociFormat(dest string, req InRequest, image v1.Image) {
  76. tag, err := name.NewTag(req.Source.Repository+":"+req.Source.Tag(), name.WeakValidation)
  77. if err != nil {
  78. logrus.Errorf("failed to construct tag reference: %s", err)
  79. os.Exit(1)
  80. return
  81. }
  82. err = tarball.WriteToFile(filepath.Join(dest, "image.tar"), tag, image, nil)
  83. if err != nil {
  84. logrus.Errorf("failed to write OCI image: %s", err)
  85. os.Exit(1)
  86. return
  87. }
  88. }
  89. func rootfsFormat(dest string, req InRequest, image v1.Image) {
  90. err := unpackImage(filepath.Join(dest, "rootfs"), image, req.Source.Debug)
  91. if err != nil {
  92. logrus.Errorf("failed to extract image: %s", err)
  93. os.Exit(1)
  94. return
  95. }
  96. cfg, err := image.ConfigFile()
  97. if err != nil {
  98. logrus.Errorf("failed to inspect image config: %s", err)
  99. os.Exit(1)
  100. return
  101. }
  102. meta, err := os.Create(filepath.Join(dest, "metadata.json"))
  103. if err != nil {
  104. logrus.Errorf("failed to create image metadata: %s", err)
  105. os.Exit(1)
  106. return
  107. }
  108. err = json.NewEncoder(meta).Encode(ImageMetadata{
  109. Env: cfg.ContainerConfig.Env,
  110. User: cfg.ContainerConfig.User,
  111. })
  112. if err != nil {
  113. logrus.Errorf("failed to write image metadata: %s", err)
  114. os.Exit(1)
  115. return
  116. }
  117. err = meta.Close()
  118. if err != nil {
  119. logrus.Errorf("failed to close image metadata file: %s", err)
  120. os.Exit(1)
  121. return
  122. }
  123. }