forked from projectatomic/atomic-enterprise
-
Notifications
You must be signed in to change notification settings - Fork 0
/
registry.go
277 lines (238 loc) · 9.34 KB
/
registry.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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
package registry
import (
"fmt"
"io"
"os"
"strings"
kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
kclient "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
kclientcmd "github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/golang/glog"
"github.com/spf13/cobra"
"github.com/openshift/origin/pkg/cmd/util/clientcmd"
"github.com/openshift/origin/pkg/cmd/util/variable"
configcmd "github.com/openshift/origin/pkg/config/cmd"
dapi "github.com/openshift/origin/pkg/deploy/api"
"github.com/openshift/origin/pkg/generate/app"
)
const longDesc = `
Install or configure a Docker registry for OpenShift
This command sets up a Docker registry integrated with OpenShift to provide notifications when
images are pushed. With no arguments, the command will check for the existing registry service
called 'docker-registry' and perform some diagnostics to ensure the registry is properly
configured and functioning.
If a registry service does not exist, the --create flag can be passed to
create a deployment configuration and service that will run the registry.
To run a highly available registry, you should be using a remote storage mechanism like an
object store (several are supported by the Docker registry). The default Docker registry image
is configured to accept configuration as environment variables - refer to the config file in
that image for more on setting up alternative storage. Once you've made those changes, you can
pass --replicas=2 or higher to ensure you have failover protection. The default registry setup
uses a local volume and the data will be lost if you delete the running pod.
Examples:
Check the default Docker registry ("docker-registry"):
$ %[1]s %[2]s
See what the registry would look like if created:
$ %[1]s %[2]s -o json
Create a registry if it does not exist with two replicas:
$ %[1]s %[2]s --create --replicas=2
Use a different registry image and see the registry configuration:
$ %[1]s %[2]s -o yaml --images=myrepo/docker-registry:mytag
ALPHA: This command is currently being actively developed. It is intended to simplify
the tasks of setting up a Docker registry in a new installation. Some configuration
beyond this command is still required to make your registry permanent.
`
type config struct {
Type string
ImageTemplate variable.ImageTemplate
Ports string
Replicas int
Labels string
Volume string
HostMount string
Create bool
Credentials string
// TODO: accept environment values.
}
const defaultLabel = "docker-registry=default"
func NewCmdRegistry(f *clientcmd.Factory, parentName, name string, out io.Writer) *cobra.Command {
cfg := &config{
ImageTemplate: variable.NewDefaultImageTemplate(),
Labels: defaultLabel,
Ports: "5000",
Volume: "/registry",
Replicas: 1,
}
cmd := &cobra.Command{
Use: name,
Short: "Install and check OpenShift Docker registry",
Long: fmt.Sprintf(longDesc, parentName, name),
Run: func(cmd *cobra.Command, args []string) {
var name string
switch len(args) {
case 0:
name = "docker-registry"
default:
glog.Fatalf("No arguments are allowed to this command")
}
ports, err := app.ContainerPortsFromString(cfg.Ports)
if err != nil {
glog.Fatal(err)
}
label := map[string]string{
"docker-registry": "default",
}
if cfg.Labels != defaultLabel {
valid, remove, err := app.LabelsFromSpec(strings.Split(cfg.Labels, ","))
if err != nil {
glog.Fatal(err)
}
if len(remove) > 0 {
glog.Fatalf("You may not pass negative labels in %q", cfg.Labels)
}
label = valid
}
image := cfg.ImageTemplate.ExpandOrDie(cfg.Type)
namespace, err := f.OpenShiftClientConfig.Namespace()
if err != nil {
glog.Fatalf("Error getting client: %v", err)
}
_, kClient, err := f.Clients()
if err != nil {
glog.Fatalf("Error getting client: %v", err)
}
p, output, err := cmdutil.PrinterForCommand(cmd)
if err != nil {
glog.Fatalf("Unable to configure printer: %v", err)
}
generate := output
if !generate {
_, err = kClient.Services(namespace).Get(name)
if err != nil {
if !errors.IsNotFound(err) {
glog.Fatalf("Can't check for existing docker-registry %q: %v", name, err)
}
generate = true
}
}
if generate {
if !cfg.Create && !output {
glog.Fatalf("Docker-registry %q does not exist (no service). Pass --create to install.", name)
}
// create new registry
if len(cfg.Credentials) == 0 {
glog.Fatalf("You must specify a .kubeconfig file path containing credentials for connecting the registry to the master with --credentials")
}
clientConfigLoadingRules := &kclientcmd.ClientConfigLoadingRules{cfg.Credentials, []string{}}
credentials, err := clientConfigLoadingRules.Load()
if err != nil {
glog.Fatalf("The provided credentials %q could not be loaded: %v", cfg.Credentials, err)
}
config, err := kclientcmd.NewDefaultClientConfig(*credentials, &kclientcmd.ConfigOverrides{}).ClientConfig()
if err != nil {
glog.Fatalf("The provided credentials %q could not be used: %v", cfg.Credentials, err)
}
if err := kclient.LoadTLSFiles(config); err != nil {
glog.Fatalf("The provided credentials %q could not load certificate info: %v", cfg.Credentials, err)
}
insecure := "false"
if config.Insecure {
insecure = "true"
}
env := app.Environment{
"OPENSHIFT_MASTER": config.Host,
"OPENSHIFT_CA_DATA": string(config.CAData),
"OPENSHIFT_KEY_DATA": string(config.KeyData),
"OPENSHIFT_CERT_DATA": string(config.CertData),
"OPENSHIFT_INSECURE": insecure,
}
mountHost := len(cfg.HostMount) > 0
podTemplate := &kapi.PodTemplateSpec{
ObjectMeta: kapi.ObjectMeta{Labels: label},
Spec: kapi.PodSpec{
Containers: []kapi.Container{
{
Name: "registry",
Image: image,
Ports: ports,
Env: env.List(),
VolumeMounts: []kapi.VolumeMount{
{
Name: "registry-storage",
MountPath: cfg.Volume,
},
},
Privileged: mountHost,
},
},
Volumes: []kapi.Volume{
{
Name: "registry-storage",
VolumeSource: kapi.VolumeSource{},
},
},
},
}
if mountHost {
podTemplate.Spec.Volumes[0].HostPath = &kapi.HostPathVolumeSource{Path: cfg.HostMount}
} else {
podTemplate.Spec.Volumes[0].EmptyDir = &kapi.EmptyDirVolumeSource{}
}
objects := []runtime.Object{
&dapi.DeploymentConfig{
ObjectMeta: kapi.ObjectMeta{
Name: name,
Labels: label,
},
Triggers: []dapi.DeploymentTriggerPolicy{
{Type: dapi.DeploymentTriggerOnConfigChange},
},
Template: dapi.DeploymentTemplate{
Strategy: dapi.DeploymentStrategy{
Type: dapi.DeploymentStrategyTypeRecreate,
},
ControllerTemplate: kapi.ReplicationControllerSpec{
Replicas: cfg.Replicas,
Selector: label,
Template: podTemplate,
},
},
},
}
objects = app.AddServices(objects)
// TODO: label all created objects with the same label
list := &kapi.List{Items: objects}
if output {
if err := p.PrintObj(list, out); err != nil {
glog.Fatalf("Unable to print object: %v", err)
}
return
}
bulk := configcmd.Bulk{
Factory: f.Factory,
After: configcmd.NewPrintNameOrErrorAfter(out, os.Stderr),
}
if errs := bulk.Create(list, namespace); len(errs) != 0 {
os.Exit(1)
}
return
}
fmt.Fprintf(out, "Docker registry %q service exists\n", name)
},
}
cmd.Flags().StringVar(&cfg.Type, "type", "docker-registry", "The registry image to use - if you specify --images this flag may be ignored.")
cmd.Flags().StringVar(&cfg.ImageTemplate.Format, "images", cfg.ImageTemplate.Format, "The image to base this registry on - ${component} will be replaced with --type")
cmd.Flags().BoolVar(&cfg.ImageTemplate.Latest, "latest-images", cfg.ImageTemplate.Latest, "If true, attempt to use the latest image for the registry instead of the latest release.")
cmd.Flags().StringVar(&cfg.Ports, "ports", cfg.Ports, "A comma delimited list of ports or port pairs to expose on the registry pod. The default is set for 5000.")
cmd.Flags().IntVar(&cfg.Replicas, "replicas", cfg.Replicas, "The replication factor of the registry; commonly 2 when high availability is desired.")
cmd.Flags().StringVar(&cfg.Labels, "labels", cfg.Labels, "A set of labels to uniquely identify the registry and its components.")
cmd.Flags().StringVar(&cfg.Volume, "volume", cfg.Volume, "The volume path to use for registry storage; defaults to /registry which is the default for origin-docker-registry.")
cmd.Flags().StringVar(&cfg.HostMount, "mount-host", cfg.HostMount, "If set, the registry volume will be created as a host-mount at this path.")
cmd.Flags().BoolVar(&cfg.Create, "create", cfg.Create, "Create the registry if it does not exist.")
cmd.Flags().StringVar(&cfg.Credentials, "credentials", "", "Path to a .kubeconfig file that will contain the credentials the registry should use to contact the master.")
cmdutil.AddPrinterFlags(cmd)
return cmd
}