forked from openshift/origin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
router.go
283 lines (243 loc) · 9 KB
/
router.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
278
279
280
281
282
283
package router
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"
kutil "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"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 an OpenShift router
This command helps to setup an OpenShift router to take edge traffic and balance it to
your application. With no arguments, the command will check for an existing router
service called 'router' and perform some diagnostics to ensure the router is properly
configured and functioning.
If a router does not exist with the given name, the --create flag can be passed to
create a deployment configuration and service that will run the router. If you are
running your router in production, you should pass --replicas=2 or higher to ensure
you have failover protection.
Examples:
Check the default router ("router"):
$ %[1]s %[2]s
See what the router would look like if created:
$ %[1]s %[2]s -o json
Create a router if it does not exist:
$ %[1]s %[2]s router-west --create --replicas=2
Use a different router image and see the router configuration:
$ %[1]s %[2]s region-west -o yaml --images=myrepo/somerouter:mytag
ALPHA: This command is currently being actively developed. It is intended to simplify
the tasks of setting up routers in a new installation.
`
type config struct {
Type string
ImageTemplate variable.ImageTemplate
Ports string
Replicas int
Labels string
Create bool
Credentials string
}
const defaultLabel = "router=<name>"
func NewCmdRouter(f *clientcmd.Factory, parentName, name string, out io.Writer) *cobra.Command {
cfg := &config{
ImageTemplate: variable.NewDefaultImageTemplate(),
Labels: defaultLabel,
Ports: "80:80,443:443",
Replicas: 1,
}
cmd := &cobra.Command{
Use: fmt.Sprintf("%s [<name>]", name),
Short: "Install and check OpenShift routers",
Long: fmt.Sprintf(longDesc, parentName, name),
Run: func(cmd *cobra.Command, args []string) {
var name string
switch len(args) {
case 0:
name = "router"
case 1:
name = args[0]
default:
glog.Fatalf("You may pass zero or one arguments to provide a name for the router")
}
ports, err := app.ContainerPortsFromString(cfg.Ports)
if err != nil {
glog.Fatal(err)
}
label := map[string]string{"router": name}
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 router %q: %v", name, err)
}
generate = true
}
}
if generate {
if !cfg.Create && !output {
glog.Fatalf("Router %q does not exist (no service). Pass --create to install.", name)
}
// create new router
if len(cfg.Credentials) == 0 {
glog.Fatalf("You must specify a .kubeconfig file path containing credentials for connecting the router to the master with --credentials")
}
clientConfigLoadingRules := &kclientcmd.ClientConfigLoadingRules{ExplicitPath: cfg.Credentials, Precedence: []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,
}
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: &kapi.PodTemplateSpec{
ObjectMeta: kapi.ObjectMeta{Labels: label},
Spec: kapi.PodSpec{
Containers: []kapi.Container{
{
Name: "router",
Image: image,
Ports: ports,
Env: env.List(),
LivenessProbe: &kapi.Probe{
Handler: kapi.Handler{
TCPSocket: &kapi.TCPSocketAction{
Port: kutil.IntOrString{
IntVal: ports[0].ContainerPort,
},
},
},
},
},
},
},
},
},
},
},
}
objects = app.AddServices(objects)
// TODO: label all created objects with the same label - router=<name>
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, "Router %q service exists\n", name)
},
}
cmd.Flags().StringVar(&cfg.Type, "type", "haproxy-router", "The type of router 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 router 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 images for the router 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 router pod. The default is set for HAProxy.")
cmd.Flags().IntVar(&cfg.Replicas, "replicas", cfg.Replicas, "The replication factor of the router; commonly 2 when high availability is desired.")
cmd.Flags().StringVar(&cfg.Labels, "labels", cfg.Labels, "A set of labels to uniquely identify the router and its components.")
cmd.Flags().BoolVar(&cfg.Create, "create", cfg.Create, "Create the router if it does not exist.")
cmd.Flags().StringVar(&cfg.Credentials, "credentials", "", "Path to a .kubeconfig file that will contain the credentials the router should use to contact the master.")
cmdutil.AddPrinterFlags(cmd)
return cmd
}
/*
// Example with generation - this does not have port metadata so its slightly less
// clear to end users.
registry, imageNamespace, imageName, tag, err := imageapi.SplitDockerPullSpec(image)
if err != nil {
glog.Fatalf("The image value %q is not valid: %v", image, err)
}
image := &app.ImageRef{
Namespace: imageNamespace,
Name: imageName,
Registry: registry,
Tag: tag,
}
pipeline, err := app.NewImagePipeline(name, image)
if err != nil {
glog.Fatalf("Unable to set up an image for the router: %v", err)
}
if err := pipeline.NeedsDeployment(nil); err != nil {
glog.Fatalf("Unable to set up a deployment for the router: %v", err)
}
objects, err := pipeline.Objects(app.NewAcceptFirst())
if err != nil {
glog.Fatalf("Unable to configure objects for deployment: %v", err)
}
objects = app.AddServices(objects)
*/