transformers.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. Copyright 2020 Docker Compose CLI 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 bridge
  14. import (
  15. "context"
  16. "fmt"
  17. "os"
  18. "path/filepath"
  19. "github.com/docker/cli/cli/command"
  20. "github.com/moby/go-archive"
  21. "github.com/moby/moby/api/types/image"
  22. "github.com/moby/moby/client"
  23. )
  24. const (
  25. TransformerLabel = "com.docker.compose.bridge"
  26. DefaultTransformerImage = "docker/compose-bridge-kubernetes"
  27. templatesPath = "/templates"
  28. )
  29. type CreateTransformerOptions struct {
  30. Dest string
  31. From string
  32. }
  33. func CreateTransformer(ctx context.Context, dockerCli command.Cli, options CreateTransformerOptions) error {
  34. if options.From == "" {
  35. options.From = DefaultTransformerImage
  36. }
  37. out, err := filepath.Abs(options.Dest)
  38. if err != nil {
  39. return err
  40. }
  41. if _, err := os.Stat(out); err == nil {
  42. return fmt.Errorf("output folder %s already exists", out)
  43. }
  44. tmpl := filepath.Join(out, "templates")
  45. err = os.MkdirAll(tmpl, 0o744)
  46. if err != nil && !os.IsExist(err) {
  47. return fmt.Errorf("cannot create output folder: %w", err)
  48. }
  49. if err := command.ValidateOutputPath(out); err != nil {
  50. return err
  51. }
  52. created, err := dockerCli.Client().ContainerCreate(ctx, client.ContainerCreateOptions{
  53. Image: options.From,
  54. })
  55. defer func() {
  56. _, _ = dockerCli.Client().ContainerRemove(context.Background(), created.ID, client.ContainerRemoveOptions{
  57. Force: true,
  58. })
  59. }()
  60. if err != nil {
  61. return err
  62. }
  63. resp, err := dockerCli.Client().CopyFromContainer(ctx, created.ID, client.CopyFromContainerOptions{
  64. SourcePath: templatesPath,
  65. })
  66. if err != nil {
  67. return err
  68. }
  69. defer func() {
  70. _ = resp.Content.Close()
  71. }()
  72. srcInfo := archive.CopyInfo{
  73. Path: templatesPath,
  74. Exists: true,
  75. IsDir: resp.Stat.Mode.IsDir(),
  76. }
  77. preArchive := resp.Content
  78. if srcInfo.RebaseName != "" {
  79. _, srcBase := archive.SplitPathDirEntry(srcInfo.Path)
  80. preArchive = archive.RebaseArchiveEntries(resp.Content, srcBase, srcInfo.RebaseName)
  81. }
  82. if err := archive.CopyTo(preArchive, srcInfo, out); err != nil {
  83. return err
  84. }
  85. dockerfile := `FROM docker/compose-bridge-transformer
  86. LABEL com.docker.compose.bridge=transformation
  87. COPY templates /templates
  88. `
  89. if err := os.WriteFile(filepath.Join(out, "Dockerfile"), []byte(dockerfile), 0o700); err != nil {
  90. return err
  91. }
  92. _, err = fmt.Fprintf(dockerCli.Out(), "Transformer created in %q\n", out)
  93. return err
  94. }
  95. func ListTransformers(ctx context.Context, dockerCli command.Cli) ([]image.Summary, error) {
  96. res, err := dockerCli.Client().ImageList(ctx, client.ImageListOptions{
  97. Filters: make(client.Filters).Add("label", fmt.Sprintf("%s=%s", TransformerLabel, "transformation")),
  98. })
  99. if err != nil {
  100. return nil, err
  101. }
  102. return res.Items, nil
  103. }