-
Notifications
You must be signed in to change notification settings - Fork 129
/
push.go
156 lines (135 loc) · 4.94 KB
/
push.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
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
// Copyright (c) Contributors to the Apptainer project, established as
// Apptainer a Series of LF Projects LLC.
// For website terms of use, trademark policy, privacy policy and other
// project policies see https://lfprojects.org/policies
// Copyright (c) 2020, Control Command Inc. All rights reserved.
// Copyright (c) 2018-2020, Sylabs Inc. All rights reserved.
// This software is licensed under a 3-clause BSD license. Please consult the
// LICENSE.md file distributed with the sources of this project regarding your
// rights to use or distribute this software.
package cli
import (
"fmt"
"github.com/apptainer/apptainer/docs"
"github.com/apptainer/apptainer/internal/app/apptainer"
"github.com/apptainer/apptainer/internal/pkg/client/oras"
"github.com/apptainer/apptainer/internal/pkg/remote/endpoint"
"github.com/apptainer/apptainer/internal/pkg/util/uri"
"github.com/apptainer/apptainer/pkg/cmdline"
"github.com/apptainer/apptainer/pkg/sylog"
"github.com/spf13/cobra"
)
var (
// PushLibraryURI holds the base URI to a Sylabs library API instance
PushLibraryURI string
// unsignedPush when true will allow pushing a unsigned container
unsignedPush bool
// pushDescription holds a description to be set against a library container
pushDescription string
)
// --library
var pushLibraryURIFlag = cmdline.Flag{
ID: "pushLibraryURIFlag",
Value: &PushLibraryURI,
DefaultValue: "",
Name: "library",
Usage: "the library to push to",
EnvKeys: []string{"LIBRARY"},
}
// -U|--allow-unsigned
var pushAllowUnsignedFlag = cmdline.Flag{
ID: "pushAllowUnsignedFlag",
Value: &unsignedPush,
DefaultValue: false,
Name: "allow-unsigned",
ShortHand: "U",
Usage: "do not require a signed container image",
EnvKeys: []string{"ALLOW_UNSIGNED"},
}
// -D|--description
var pushDescriptionFlag = cmdline.Flag{
ID: "pushDescriptionFlag",
Value: &pushDescription,
DefaultValue: "",
Name: "description",
ShortHand: "D",
Usage: "description for container image (library:// only)",
}
func init() {
addCmdInit(func(cmdManager *cmdline.CommandManager) {
cmdManager.RegisterCmd(PushCmd)
cmdManager.RegisterFlagForCmd(&pushLibraryURIFlag, PushCmd)
cmdManager.RegisterFlagForCmd(&pushAllowUnsignedFlag, PushCmd)
cmdManager.RegisterFlagForCmd(&pushDescriptionFlag, PushCmd)
cmdManager.RegisterFlagForCmd(&commonNoHTTPSFlag, PushCmd)
cmdManager.RegisterFlagForCmd(&dockerHostFlag, PushCmd)
cmdManager.RegisterFlagForCmd(&dockerUsernameFlag, PushCmd)
cmdManager.RegisterFlagForCmd(&dockerPasswordFlag, PushCmd)
})
}
// PushCmd apptainer push
var PushCmd = &cobra.Command{
DisableFlagsInUseLine: true,
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
file, dest := args[0], args[1]
transport, ref := uri.Split(dest)
if transport == "" {
sylog.Fatalf("bad uri %s", dest)
}
switch transport {
case LibraryProtocol: // Handle pushing to a library
lc, err := getLibraryClientConfig(PushLibraryURI)
if err != nil {
sylog.Fatalf("Unable to get library client configuration: %v", err)
}
// Push to library requires a valid authToken
if lc.AuthToken == "" {
sylog.Fatalf("Cannot push image to library: %v", remoteWarning)
}
co, err := getKeyserverClientOpts("", endpoint.KeyserverVerifyOp)
if err != nil {
sylog.Fatalf("Unable to get keyserver client configuration: %v", err)
}
feURL, err := currentRemoteEndpoint.GetURL()
if err != nil {
sylog.Fatalf("Unable to find remote web URI %v", err)
}
pushSpec := apptainer.LibraryPushSpec{
SourceFile: file,
DestRef: dest,
Description: pushDescription,
AllowUnsigned: unsignedPush,
FrontendURI: feURL,
}
err = apptainer.LibraryPush(cmd.Context(), pushSpec, lc, co)
if err == apptainer.ErrLibraryUnsigned {
fmt.Printf("TIP: You can push unsigned images with 'apptainer push -U %s'.\n", file)
fmt.Printf("TIP: Learn how to sign your own containers by using 'apptainer help sign'\n\n")
sylog.Fatalf("Unable to upload container: unable to verify signature")
} else if err != nil {
sylog.Fatalf("Unable to push image to library: %v", err)
}
case OrasProtocol:
if cmd.Flag(pushDescriptionFlag.Name).Changed {
sylog.Warningf("Description is not supported for push to oras. Ignoring it.")
}
ociAuth, err := makeDockerCredentials(cmd)
if err != nil {
sylog.Fatalf("Unable to make docker oci credentials: %s", err)
}
if err := oras.UploadImage(cmd.Context(), file, ref, ociAuth, noHTTPS); err != nil {
sylog.Fatalf("Unable to push image to oci registry: %v", err)
}
sylog.Infof("Upload complete")
case "":
sylog.Fatalf("Transport type URI required but not supplied")
default:
sylog.Fatalf("Unsupported transport type: %s", transport)
}
},
Use: docs.PushUse,
Short: docs.PushShort,
Long: docs.PushLong,
Example: docs.PushExample,
}