...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package crane
16
17 import (
18 "fmt"
19 "os"
20
21 "github.com/google/go-containerregistry/internal/windows"
22 v1 "github.com/google/go-containerregistry/pkg/v1"
23 "github.com/google/go-containerregistry/pkg/v1/mutate"
24 "github.com/google/go-containerregistry/pkg/v1/stream"
25 "github.com/google/go-containerregistry/pkg/v1/tarball"
26 "github.com/google/go-containerregistry/pkg/v1/types"
27 )
28
29 func isWindows(img v1.Image) (bool, error) {
30 cfg, err := img.ConfigFile()
31 if err != nil {
32 return false, err
33 }
34 return cfg != nil && cfg.OS == "windows", nil
35 }
36
37
38
39
40
41
42 func Append(base v1.Image, paths ...string) (v1.Image, error) {
43 if base == nil {
44 return nil, fmt.Errorf("invalid argument: base")
45 }
46
47 win, err := isWindows(base)
48 if err != nil {
49 return nil, fmt.Errorf("getting base image: %w", err)
50 }
51
52 baseMediaType, err := base.MediaType()
53
54 if err != nil {
55 return nil, fmt.Errorf("getting base image media type: %w", err)
56 }
57
58 layerType := types.DockerLayer
59
60 if baseMediaType == types.OCIManifestSchema1 {
61 layerType = types.OCILayer
62 }
63
64 layers := make([]v1.Layer, 0, len(paths))
65 for _, path := range paths {
66 layer, err := getLayer(path, layerType)
67 if err != nil {
68 return nil, fmt.Errorf("reading layer %q: %w", path, err)
69 }
70
71 if win {
72 layer, err = windows.Windows(layer)
73 if err != nil {
74 return nil, fmt.Errorf("converting %q for Windows: %w", path, err)
75 }
76 }
77
78 layers = append(layers, layer)
79 }
80
81 return mutate.AppendLayers(base, layers...)
82 }
83
84 func getLayer(path string, layerType types.MediaType) (v1.Layer, error) {
85 f, err := streamFile(path)
86 if err != nil {
87 return nil, err
88 }
89 if f != nil {
90 return stream.NewLayer(f, stream.WithMediaType(layerType)), nil
91 }
92
93 return tarball.LayerFromFile(path, tarball.WithMediaType(layerType))
94 }
95
96
97
98
99
100 func streamFile(path string) (*os.File, error) {
101 if path == "-" {
102 return os.Stdin, nil
103 }
104 fi, err := os.Stat(path)
105 if err != nil {
106 return nil, err
107 }
108
109 if !fi.Mode().IsRegular() {
110 return os.Open(path)
111 }
112
113 return nil, nil
114 }
115
View as plain text