forked from openshift/origin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
template.go
186 lines (152 loc) · 6.03 KB
/
template.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
package router
import (
"errors"
"fmt"
"strconv"
"time"
"github.com/golang/glog"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
ktypes "k8s.io/kubernetes/pkg/types"
"github.com/openshift/origin/pkg/cmd/util"
"github.com/openshift/origin/pkg/cmd/util/clientcmd"
"github.com/openshift/origin/pkg/router/controller"
"github.com/openshift/origin/pkg/util/proc"
"github.com/openshift/origin/pkg/version"
templateplugin "github.com/openshift/origin/plugins/router/template"
)
const (
routerLong = `
Start a router
This command launches a router connected to your cluster master. The router listens for routes and endpoints
created by users and keeps a local router configuration up to date with those changes.
You may customize the router by providing your own --template and --reload scripts.
You may restrict the set of routes exposed to a single project (with --namespace), projects your client has
access to with a set of labels (--project-labels), namespaces matching a label (--namespace-labels), or all
namespaces (no argument). You can limit the routes to those matching a --labels or --fields selector. Note
that you must have a cluster-wide administrative role to view all namespaces.`
)
type TemplateRouterOptions struct {
Config *clientcmd.Config
TemplateRouter
RouterStats
RouterSelection
}
type TemplateRouter struct {
WorkingDir string
TemplateFile string
ReloadScript string
ReloadInterval time.Duration
DefaultCertificate string
RouterService *ktypes.NamespacedName
}
func (o *TemplateRouter) Bind(flag *pflag.FlagSet) {
flag.StringVar(&o.WorkingDir, "working-dir", "/var/lib/containers/router", "The working directory for the router plugin")
flag.StringVar(&o.DefaultCertificate, "default-certificate", util.Env("DEFAULT_CERTIFICATE", ""), "A path to default certificate to use for routes that don't expose a TLS server cert; in PEM format")
flag.StringVar(&o.TemplateFile, "template", util.Env("TEMPLATE_FILE", ""), "The path to the template file to use")
flag.StringVar(&o.ReloadScript, "reload", util.Env("RELOAD_SCRIPT", ""), "The path to the reload script to use")
interval := util.Env("RELOAD_INTERVAL", "0s")
var err error
o.ReloadInterval, err = time.ParseDuration(interval)
if err != nil {
glog.Warningf("Invalid RELOAD_INTERVAL %q, ignoring ...", interval)
o.ReloadInterval = time.Duration(0 * time.Second)
}
flag.DurationVar(&o.ReloadInterval, "interval", o.ReloadInterval, "Controls how often router reloads are invoked. Mutiple router reload requests are coalesced for the duration of this interval since the last reload time.")
}
type RouterStats struct {
StatsPortString string
StatsPassword string
StatsUsername string
StatsPort int
}
func (o *RouterStats) Bind(flag *pflag.FlagSet) {
flag.StringVar(&o.StatsPortString, "stats-port", util.Env("STATS_PORT", ""), "If the underlying router implementation can provide statistics this is a hint to expose it on this port.")
flag.StringVar(&o.StatsPassword, "stats-password", util.Env("STATS_PASSWORD", ""), "If the underlying router implementation can provide statistics this is the requested password for auth.")
flag.StringVar(&o.StatsUsername, "stats-user", util.Env("STATS_USERNAME", ""), "If the underlying router implementation can provide statistics this is the requested username for auth.")
}
// NewCommndTemplateRouter provides CLI handler for the template router backend
func NewCommandTemplateRouter(name string) *cobra.Command {
options := &TemplateRouterOptions{
Config: clientcmd.NewConfig(),
}
options.Config.FromFile = true
cmd := &cobra.Command{
Use: fmt.Sprintf("%s%s", name, clientcmd.ConfigSyntax),
Short: "Start a router",
Long: routerLong,
Run: func(c *cobra.Command, args []string) {
options.RouterSelection.Namespace = cmdutil.GetFlagString(c, "namespace")
cmdutil.CheckErr(options.Complete())
cmdutil.CheckErr(options.Validate())
cmdutil.CheckErr(options.Run())
},
}
cmd.AddCommand(version.NewVersionCommand(name, false))
flag := cmd.Flags()
options.Config.Bind(flag)
options.TemplateRouter.Bind(flag)
options.RouterStats.Bind(flag)
options.RouterSelection.Bind(flag)
return cmd
}
func (o *TemplateRouterOptions) Complete() error {
routerSvcName := util.Env("ROUTER_SERVICE_NAME", "")
routerSvcNamespace := util.Env("ROUTER_SERVICE_NAMESPACE", "")
if len(routerSvcName) > 0 {
if len(routerSvcNamespace) == 0 {
return fmt.Errorf("ROUTER_SERVICE_NAMESPACE is required when ROUTER_SERVICE_NAME is specified")
}
o.RouterService = &ktypes.NamespacedName{
Namespace: routerSvcNamespace,
Name: routerSvcName,
}
}
if len(o.StatsPortString) > 0 {
statsPort, err := strconv.Atoi(o.StatsPortString)
if err != nil {
return fmt.Errorf("stat port is not valid: %v", err)
}
o.StatsPort = statsPort
}
return o.RouterSelection.Complete()
}
func (o *TemplateRouterOptions) Validate() error {
if len(o.TemplateFile) == 0 {
return errors.New("template file must be specified")
}
if len(o.ReloadScript) == 0 {
return errors.New("reload script must be specified")
}
return nil
}
// Run launches a template router using the provided options. It never exits.
func (o *TemplateRouterOptions) Run() error {
pluginCfg := templateplugin.TemplatePluginConfig{
WorkingDir: o.WorkingDir,
TemplatePath: o.TemplateFile,
ReloadScriptPath: o.ReloadScript,
ReloadInterval: o.ReloadInterval,
DefaultCertificate: o.DefaultCertificate,
StatsPort: o.StatsPort,
StatsUsername: o.StatsUsername,
StatsPassword: o.StatsPassword,
PeerService: o.RouterService,
IncludeUDP: o.RouterSelection.IncludeUDP,
}
templatePlugin, err := templateplugin.NewTemplatePlugin(pluginCfg)
if err != nil {
return err
}
plugin := controller.NewUniqueHost(templatePlugin, o.RouteSelectionFunc())
oc, kc, err := o.Config.Clients()
if err != nil {
return err
}
factory := o.RouterSelection.NewFactory(oc, kc)
controller := factory.Create(plugin)
controller.Run()
proc.StartReaper()
select {}
}