Skip to content

Commit a7f822d

Browse files
Merge pull request #21457 from smarterclayton/mirror_stdin
cli: Teach `oc image mirror` to accept a file from stdin
2 parents 6e1990f + 0ceedc2 commit a7f822d

File tree

6 files changed

+57
-34
lines changed

6 files changed

+57
-34
lines changed

contrib/completions/bash/oc

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contrib/completions/zsh/oc

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/oc/cli/image/extract/extract.go

+2-27
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,10 @@ import (
1414
"strconv"
1515
"strings"
1616

17-
"github.com/docker/distribution/registry/api/errcode"
18-
1917
"github.com/golang/glog"
2018
"github.com/spf13/cobra"
2119

2220
"github.com/docker/distribution"
23-
registryapiv2 "github.com/docker/distribution/registry/api/v2"
2421
dockerarchive "github.com/docker/docker/pkg/archive"
2522
digest "github.com/opencontainers/go-digest"
2623

@@ -256,28 +253,6 @@ func parseMappings(images, paths []string, requireEmpty bool) ([]Mapping, error)
256253
return mappings, nil
257254
}
258255

259-
type imageNotFound struct {
260-
msg string
261-
err error
262-
}
263-
264-
func IsImageNotFound(err error) bool {
265-
switch t := err.(type) {
266-
case errcode.Errors:
267-
return len(t) == 1 && IsImageNotFound(t[0])
268-
case errcode.Error:
269-
return t.Code == registryapiv2.ErrorCodeManifestUnknown
270-
case *imageNotFound:
271-
return true
272-
default:
273-
return false
274-
}
275-
}
276-
277-
func (e *imageNotFound) Error() string {
278-
return e.msg
279-
}
280-
281256
func (o *Options) Complete(cmd *cobra.Command, args []string) error {
282257
if err := o.FilterOptions.Complete(cmd.Flags()); err != nil {
283258
return err
@@ -334,14 +309,14 @@ func (o *Options) Run() error {
334309

335310
srcManifest, srcDigest, location, err := imagemanifest.FirstManifest(ctx, from, repo, o.FilterOptions.Include)
336311
if err != nil {
337-
if IsImageNotFound(err) {
312+
if imagemanifest.IsImageNotFound(err) {
338313
var msg string
339314
if len(o.Mappings) == 1 {
340315
msg = "image does not exist"
341316
} else {
342317
msg = fmt.Sprintf("image %q does not exist", from)
343318
}
344-
return &imageNotFound{msg: msg, err: err}
319+
return imagemanifest.NewImageNotFound(msg, err)
345320
}
346321
return fmt.Errorf("unable to read image %s: %v", from, err)
347322
}

pkg/oc/cli/image/manifest/errors.go

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package manifest
2+
3+
import (
4+
"github.com/docker/distribution/registry/api/errcode"
5+
registryapiv2 "github.com/docker/distribution/registry/api/v2"
6+
)
7+
8+
type imageNotFound struct {
9+
msg string
10+
err error
11+
}
12+
13+
func NewImageNotFound(msg string, err error) error {
14+
return &imageNotFound{msg: msg, err: err}
15+
}
16+
17+
func IsImageNotFound(err error) bool {
18+
switch t := err.(type) {
19+
case errcode.Errors:
20+
return len(t) == 1 && IsImageNotFound(t[0])
21+
case errcode.Error:
22+
return t.Code == registryapiv2.ErrorCodeManifestUnknown
23+
case *imageNotFound:
24+
return true
25+
default:
26+
return false
27+
}
28+
}
29+
30+
func (e *imageNotFound) Error() string {
31+
return e.msg
32+
}

pkg/oc/cli/image/mirror/mappings.go

+10-6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package mirror
33
import (
44
"bufio"
55
"fmt"
6+
"io"
67
"os"
78
"strings"
89
"sync"
@@ -104,14 +105,17 @@ func parseArgs(args []string, overlap map[string]string) ([]Mapping, error) {
104105
return mappings, nil
105106
}
106107

107-
func parseFile(filename string, overlap map[string]string) ([]Mapping, error) {
108+
func parseFile(filename string, overlap map[string]string, in io.Reader) ([]Mapping, error) {
108109
var fileMappings []Mapping
109-
f, err := os.Open(filename)
110-
if err != nil {
111-
return nil, err
110+
if filename != "-" {
111+
f, err := os.Open(filename)
112+
if err != nil {
113+
return nil, err
114+
}
115+
defer f.Close()
116+
in = f
112117
}
113-
defer f.Close()
114-
s := bufio.NewScanner(f)
118+
s := bufio.NewScanner(in)
115119
lineNumber := 0
116120
for s.Scan() {
117121
line := s.Text()

pkg/oc/cli/image/mirror/mirror.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ type MirrorImageOptions struct {
8585
Insecure bool
8686
SkipMount bool
8787
SkipMultipleScopes bool
88+
SkipMissing bool
8889
Force bool
8990

9091
MaxRegistry int
@@ -127,6 +128,7 @@ func NewCmdMirrorImage(name string, streams genericclioptions.IOStreams) *cobra.
127128

128129
flag.BoolVar(&o.DryRun, "dry-run", o.DryRun, "Print the actions that would be taken and exit without writing to the destinations.")
129130
flag.BoolVar(&o.Insecure, "insecure", o.Insecure, "Allow push and pull operations to registries to be made over HTTP")
131+
flag.BoolVar(&o.SkipMissing, "skip-missing", o.SkipMissing, "If an input image is not found, skip them.")
130132
flag.BoolVar(&o.SkipMount, "skip-mount", o.SkipMount, "Always push layers instead of cross-mounting them")
131133
flag.BoolVar(&o.SkipMultipleScopes, "skip-multiple-scopes", o.SkipMultipleScopes, "Some registries do not support multiple scopes passed to the registry login.")
132134
flag.BoolVar(&o.Force, "force", o.Force, "Attempt to write all layers and manifests even if they exist in the remote repository.")
@@ -151,7 +153,7 @@ func (o *MirrorImageOptions) Complete(cmd *cobra.Command, args []string) error {
151153
return err
152154
}
153155
for _, filename := range o.Filenames {
154-
mappings, err := parseFile(filename, overlap)
156+
mappings, err := parseFile(filename, overlap, o.In)
155157
if err != nil {
156158
return err
157159
}
@@ -364,6 +366,12 @@ func (o *MirrorImageOptions) plan() (*plan, error) {
364366
w.Parallel(func() {
365367
desc, err := srcRepo.Tags(ctx).Get(ctx, srcTag)
366368
if err != nil {
369+
if o.SkipMissing && imagemanifest.IsImageNotFound(err) {
370+
ref := src.ref
371+
ref.Tag = srcTag
372+
fmt.Fprintf(o.ErrOut, "warning: Image %s does not exist and will not be mirrored\n", ref)
373+
return
374+
}
367375
plan.AddError(retrieverError{src: src.ref, err: fmt.Errorf("unable to retrieve source image %s by tag %s: %v", src.ref, srcTag, err)})
368376
return
369377
}

0 commit comments

Comments
 (0)