-
Notifications
You must be signed in to change notification settings - Fork 69
Expand file tree
/
Copy pathcontents.go
More file actions
166 lines (132 loc) · 4.16 KB
/
Copy pathcontents.go
File metadata and controls
166 lines (132 loc) · 4.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// Copyright 2020 VMware, Inc.
// SPDX-License-Identifier: Apache-2.0
package bundle
import (
"fmt"
"os"
"path/filepath"
"strings"
regname "github.com/google/go-containerregistry/pkg/name"
regv1 "github.com/google/go-containerregistry/pkg/v1"
regremote "github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/vmware-tanzu/carvel-imgpkg/pkg/imgpkg/internal/util"
"github.com/vmware-tanzu/carvel-imgpkg/pkg/imgpkg/plainimage"
"github.com/vmware-tanzu/carvel-imgpkg/pkg/imgpkg/registry"
)
const (
ImgpkgDir = ".imgpkg"
BundlesDir = "bundles"
ImagesLockFile = "images.yml"
)
type Contents struct {
paths []string
excludedPaths []string
preservePermissions bool
}
//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . ImagesMetadataWriter
type ImagesMetadataWriter interface {
ImagesMetadata
WriteImage(regname.Reference, regv1.Image, chan regv1.Update) error
WriteTag(ref regname.Tag, taggagle regremote.Taggable) error
CloneWithLogger(logger util.ProgressLogger) registry.Registry
}
// NewContents creates Contents struct
func NewContents(paths []string, excludedPaths []string, preservePermissions bool) Contents {
return Contents{paths: paths, excludedPaths: excludedPaths, preservePermissions: preservePermissions}
}
// Push the contents of the bundle to the registry as an OCI Image with one or more tags
func (b Contents) Push(uploadRefs []regname.Tag, labels map[string]string, registry ImagesMetadataWriter, logger Logger) (string, error) {
err := b.validate()
if err != nil {
return "", err
}
if labels == nil {
labels = map[string]string{}
}
labels[BundleConfigLabel] = "true"
return plainimage.NewContents(b.paths, b.excludedPaths, b.preservePermissions).Push(uploadRefs, labels, registry, logger)
}
// PresentsAsBundle checks if the provided folders have the needed structure to be a bundle
func (b Contents) PresentsAsBundle() (bool, error) {
imgpkgDirs, err := b.findImgpkgDirs()
if err != nil {
return false, err
}
err = b.validateImgpkgDirs(imgpkgDirs)
if _, ok := err.(bundleValidationError); ok {
return false, nil
}
if err != nil {
return false, err
}
return true, nil
}
func (b Contents) validate() error {
imgpkgDirs, err := b.findImgpkgDirs()
if err != nil {
return err
}
err = b.validateImgpkgDirs(imgpkgDirs)
if err != nil {
return err
}
return nil
}
func (b *Contents) findImgpkgDirs() ([]string, error) {
var bundlePaths []string
for _, path := range b.paths {
err := filepath.Walk(path, func(currPath string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if filepath.Base(currPath) != ImgpkgDir {
return nil
}
currPath, err = filepath.Abs(currPath)
if err != nil {
return err
}
bundlePaths = append(bundlePaths, currPath)
return nil
})
if err != nil {
return []string{}, err
}
}
return bundlePaths, nil
}
func (b Contents) validateImgpkgDirs(imgpkgDirs []string) error {
if len(imgpkgDirs) != 1 {
imgpkgPath := filepath.Join(ImgpkgDir, ImagesLockFile)
msg := fmt.Sprintf("This directory is not a bundle. It is missing %s", imgpkgPath)
if len(imgpkgDirs) > 0 {
msg = fmt.Sprintf("This directory contains multiple bundle definitions. Only a single instance of %s can be provided and instead these were provided %s", imgpkgPath, strings.Join(imgpkgDirs, ", "))
}
return bundleValidationError{msg}
}
// make sure it is a child of one input dir
path := imgpkgDirs[0]
for _, flagPath := range b.paths {
flagPath, err := filepath.Abs(flagPath)
if err != nil {
return err
}
if filepath.Dir(path) == flagPath {
imgpkgPath := filepath.Join(path, ImagesLockFile)
if _, err := os.Stat(imgpkgPath); os.IsNotExist(err) {
msg := fmt.Sprintf("The bundle expected .imgpkg/images.yml to exist, but it wasn't found in the path %s", imgpkgPath)
return bundleValidationError{msg}
}
return nil
}
}
msg := fmt.Sprintf("Expected '%s' directory, to be a direct child of one of: %s; was %s",
ImgpkgDir, strings.Join(b.paths, ", "), path)
return bundleValidationError{msg}
}
type bundleValidationError struct {
msg string
}
func (b bundleValidationError) Error() string {
return b.msg
}