-
Notifications
You must be signed in to change notification settings - Fork 0
/
image-clone.go
90 lines (77 loc) · 2.61 KB
/
image-clone.go
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
package main
import (
"fmt"
"os"
"strings"
"github.com/docker/cli/cli/config"
"github.com/docker/cli/cli/config/types"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/remote"
)
func RegistryLogin(registry, username, password string) error {
reg, err := name.NewRegistry(registry)
if err != nil {
return err
}
serverAddress := reg.Name()
if username == "" && password == "" {
return fmt.Errorf("username and password required")
}
cf, err := config.Load(os.Getenv("DOCKER_CONFIG"))
if err != nil {
return fmt.Errorf("unable to load config: %s", err)
}
creds := cf.GetCredentialsStore(serverAddress)
if serverAddress == name.DefaultRegistry {
serverAddress = authn.DefaultAuthKey
}
if err := creds.Store(types.AuthConfig{
ServerAddress: serverAddress,
Username: username,
Password: password,
}); err != nil {
return fmt.Errorf("unable to store credentials: %s", err)
}
if err := cf.Save(); err != nil {
return fmt.Errorf("unable to save config: %s", err)
}
return nil
}
func ImageBackup(registry, repository, src string) (string, error) {
ref, err := name.ParseReference(src)
if err != nil {
return "", fmt.Errorf("unable to parse source ref: %s", err)
}
tag, err := name.NewTag(src)
if err != nil {
return "", fmt.Errorf("unable to parse tag: %s", err)
}
desc, err := remote.Get(ref, remote.WithAuthFromKeychain(authn.DefaultKeychain))
if err != nil {
return "", fmt.Errorf("unable to access remote image: %s", err)
}
img, err := desc.Image()
if err != nil {
return "", fmt.Errorf("failed to get image: %s", err)
}
newName := rename(ref, tag, registry, repository)
newRef, err := name.ParseReference(newName)
if err != nil {
return "", fmt.Errorf("unable to parse new ref: %s", err)
}
return newRef.Name(), remote.Write(newRef, img, remote.WithAuthFromKeychain(authn.DefaultKeychain))
}
func ImageBackedUp(repository, image string) bool {
return strings.Contains(image, repository)
}
func rename(source name.Reference, tag name.Tag, registry, repository string) string {
var destination string
nameWithoutRegistry := strings.ReplaceAll(source.Context().Name(), source.Context().RegistryStr(), "")
nameWithoutNestedRepository := strings.ReplaceAll(nameWithoutRegistry, "/", "-")
destination = fmt.Sprintf("%s/%s/%s:%s", registry, repository, nameWithoutNestedRepository[1:], tag.TagStr())
if strings.Contains(registry, "index.docker.io/v1") || registry == "" {
destination = repository + "/" + nameWithoutNestedRepository[1:] + ":" + tag.TagStr()
}
return destination
}