Remove GenericController and add tests
This commit is contained in:
parent
1701bfc334
commit
86f39d9deb
39 changed files with 1131 additions and 1325 deletions
64
cmd/nginx/flag_test.go
Normal file
64
cmd/nginx/flag_test.go
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// resetForTesting clears all flag state and sets the usage function as directed.
|
||||
// After calling resetForTesting, parse errors in flag handling will not
|
||||
// exit the program.
|
||||
// Extracted from https://github.com/golang/go/blob/master/src/flag/export_test.go
|
||||
func resetForTesting(usage func()) {
|
||||
flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ContinueOnError)
|
||||
flag.Usage = usage
|
||||
}
|
||||
|
||||
func TestMandatoryFlag(t *testing.T) {
|
||||
_, _, err := parseFlags()
|
||||
if err == nil {
|
||||
t.Fatalf("expected and error about default backend service")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaults(t *testing.T) {
|
||||
resetForTesting(func() { t.Fatal("bad parse") })
|
||||
|
||||
oldArgs := os.Args
|
||||
defer func() { os.Args = oldArgs }()
|
||||
os.Args = []string{"cmd", "--default-backend-service", "namespace/test", "--http-port", "0", "--https-port", "0"}
|
||||
|
||||
showVersion, conf, err := parseFlags()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error parsing default flags: %v", err)
|
||||
}
|
||||
|
||||
if showVersion {
|
||||
t.Fatal("expected false but true was returned for flag show-version")
|
||||
}
|
||||
|
||||
if conf == nil {
|
||||
t.Fatal("expected a configuration but nil returned")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetupSSLProxy(t *testing.T) {
|
||||
// TODO
|
||||
}
|
||||
191
cmd/nginx/flags.go
Normal file
191
cmd/nginx/flags.go
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
|
||||
"k8s.io/ingress-nginx/pkg/ingress/controller"
|
||||
ngx_config "k8s.io/ingress-nginx/pkg/ingress/controller/config"
|
||||
ing_net "k8s.io/ingress-nginx/pkg/net"
|
||||
)
|
||||
|
||||
const (
|
||||
defIngressClass = "nginx"
|
||||
)
|
||||
|
||||
func parseFlags() (bool, *controller.Configuration, error) {
|
||||
var (
|
||||
flags = pflag.NewFlagSet("", pflag.ExitOnError)
|
||||
|
||||
apiserverHost = flags.String("apiserver-host", "", "The address of the Kubernetes Apiserver "+
|
||||
"to connect to in the format of protocol://address:port, e.g., "+
|
||||
"http://localhost:8080. If not specified, the assumption is that the binary runs inside a "+
|
||||
"Kubernetes cluster and local discovery is attempted.")
|
||||
kubeConfigFile = flags.String("kubeconfig", "", "Path to kubeconfig file with authorization and master location information.")
|
||||
|
||||
defaultSvc = flags.String("default-backend-service", "",
|
||||
`Service used to serve a 404 page for the default backend. Takes the form
|
||||
namespace/name. The controller uses the first node port of this Service for
|
||||
the default backend.`)
|
||||
|
||||
ingressClass = flags.String("ingress-class", "",
|
||||
`Name of the ingress class to route through this controller.`)
|
||||
|
||||
configMap = flags.String("configmap", "",
|
||||
`Name of the ConfigMap that contains the custom configuration to use`)
|
||||
|
||||
publishSvc = flags.String("publish-service", "",
|
||||
`Service fronting the ingress controllers. Takes the form
|
||||
namespace/name. The controller will set the endpoint records on the
|
||||
ingress objects to reflect those on the service.`)
|
||||
|
||||
tcpConfigMapName = flags.String("tcp-services-configmap", "",
|
||||
`Name of the ConfigMap that contains the definition of the TCP services to expose.
|
||||
The key in the map indicates the external port to be used. The value is the name of the
|
||||
service with the format namespace/serviceName and the port of the service could be a
|
||||
number of the name of the port.
|
||||
The ports 80 and 443 are not allowed as external ports. This ports are reserved for the backend`)
|
||||
|
||||
udpConfigMapName = flags.String("udp-services-configmap", "",
|
||||
`Name of the ConfigMap that contains the definition of the UDP services to expose.
|
||||
The key in the map indicates the external port to be used. The value is the name of the
|
||||
service with the format namespace/serviceName and the port of the service could be a
|
||||
number of the name of the port.`)
|
||||
|
||||
resyncPeriod = flags.Duration("sync-period", 600*time.Second,
|
||||
`Relist and confirm cloud resources this often. Default is 10 minutes`)
|
||||
|
||||
watchNamespace = flags.String("watch-namespace", apiv1.NamespaceAll,
|
||||
`Namespace to watch for Ingress. Default is to watch all namespaces`)
|
||||
|
||||
profiling = flags.Bool("profiling", true, `Enable profiling via web interface host:port/debug/pprof/`)
|
||||
|
||||
defSSLCertificate = flags.String("default-ssl-certificate", "", `Name of the secret
|
||||
that contains a SSL certificate to be used as default for a HTTPS catch-all server`)
|
||||
|
||||
defHealthzURL = flags.String("health-check-path", "/healthz", `Defines
|
||||
the URL to be used as health check inside in the default server in NGINX.`)
|
||||
|
||||
updateStatus = flags.Bool("update-status", true, `Indicates if the
|
||||
ingress controller should update the Ingress status IP/hostname. Default is true`)
|
||||
|
||||
electionID = flags.String("election-id", "ingress-controller-leader", `Election id to use for status update.`)
|
||||
|
||||
forceIsolation = flags.Bool("force-namespace-isolation", false,
|
||||
`Force namespace isolation. This flag is required to avoid the reference of secrets or
|
||||
configmaps located in a different namespace than the specified in the flag --watch-namespace.`)
|
||||
|
||||
disableNodeList = flags.Bool("disable-node-list", false,
|
||||
`Disable querying nodes. If --force-namespace-isolation is true, this should also be set.`)
|
||||
|
||||
updateStatusOnShutdown = flags.Bool("update-status-on-shutdown", true, `Indicates if the
|
||||
ingress controller should update the Ingress status IP/hostname when the controller
|
||||
is being stopped. Default is true`)
|
||||
|
||||
sortBackends = flags.Bool("sort-backends", false,
|
||||
`Defines if backends and it's endpoints should be sorted`)
|
||||
|
||||
useNodeInternalIP = flags.Bool("report-node-internal-ip-address", false,
|
||||
`Defines if the nodes IP address to be returned in the ingress status should be the internal instead of the external IP address`)
|
||||
|
||||
showVersion = flags.Bool("version", false,
|
||||
`Shows release information about the NGINX Ingress controller`)
|
||||
|
||||
enableSSLPassthrough = flags.Bool("enable-ssl-passthrough", false, `Enable SSL passthrough feature. Default is disabled`)
|
||||
|
||||
httpPort = flags.Int("http-port", 80, `Indicates the port to use for HTTP traffic`)
|
||||
httpsPort = flags.Int("https-port", 443, `Indicates the port to use for HTTPS traffic`)
|
||||
statusPort = flags.Int("status-port", 18080, `Indicates the TCP port to use for exposing the nginx status page`)
|
||||
sslProxyPort = flags.Int("ssl-passtrough-proxy-port", 442, `Default port to use internally for SSL when SSL Passthgough is enabled`)
|
||||
defServerPort = flags.Int("default-server-port", 8181, `Default port to use for exposing the default server (catch all)`)
|
||||
healthzPort = flags.Int("healthz-port", 10254, "port for healthz endpoint.")
|
||||
)
|
||||
|
||||
flag.Set("logtostderr", "true")
|
||||
|
||||
flags.AddGoFlagSet(flag.CommandLine)
|
||||
flags.Parse(os.Args)
|
||||
flag.Set("logtostderr", "true")
|
||||
|
||||
// Workaround for this issue:
|
||||
// https://github.com/kubernetes/kubernetes/issues/17162
|
||||
flag.CommandLine.Parse([]string{})
|
||||
|
||||
if *showVersion {
|
||||
return true, nil, nil
|
||||
}
|
||||
|
||||
if *defaultSvc == "" {
|
||||
return false, nil, fmt.Errorf("Please specify --default-backend-service")
|
||||
}
|
||||
|
||||
if *ingressClass != "" {
|
||||
glog.Infof("Watching for ingress class: %s", *ingressClass)
|
||||
|
||||
if *ingressClass != defIngressClass {
|
||||
glog.Warningf("only Ingress with class \"%v\" will be processed by this ingress controller", *ingressClass)
|
||||
}
|
||||
}
|
||||
|
||||
// check port collisions
|
||||
if !ing_net.IsPortAvailable(*httpPort) {
|
||||
return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --http-port", *httpPort)
|
||||
}
|
||||
|
||||
if !ing_net.IsPortAvailable(*httpsPort) {
|
||||
return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --https-port", *httpsPort)
|
||||
}
|
||||
|
||||
if !ing_net.IsPortAvailable(*statusPort) {
|
||||
return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --status-port", *statusPort)
|
||||
}
|
||||
|
||||
if !ing_net.IsPortAvailable(*defServerPort) {
|
||||
return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --default-server-port", *defServerPort)
|
||||
}
|
||||
|
||||
if *enableSSLPassthrough && !ing_net.IsPortAvailable(*sslProxyPort) {
|
||||
return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --ssl-passtrough-proxy-port", *sslProxyPort)
|
||||
}
|
||||
|
||||
config := &controller.Configuration{
|
||||
APIServerHost: *apiserverHost,
|
||||
KubeConfigFile: *kubeConfigFile,
|
||||
UpdateStatus: *updateStatus,
|
||||
ElectionID: *electionID,
|
||||
EnableProfiling: *profiling,
|
||||
EnableSSLPassthrough: *enableSSLPassthrough,
|
||||
ResyncPeriod: *resyncPeriod,
|
||||
DefaultService: *defaultSvc,
|
||||
IngressClass: *ingressClass,
|
||||
Namespace: *watchNamespace,
|
||||
ConfigMapName: *configMap,
|
||||
TCPConfigMapName: *tcpConfigMapName,
|
||||
UDPConfigMapName: *udpConfigMapName,
|
||||
DefaultSSLCertificate: *defSSLCertificate,
|
||||
DefaultHealthzURL: *defHealthzURL,
|
||||
PublishService: *publishSvc,
|
||||
ForceNamespaceIsolation: *forceIsolation,
|
||||
DisableNodeList: *disableNodeList,
|
||||
UpdateStatusOnShutdown: *updateStatusOnShutdown,
|
||||
SortBackends: *sortBackends,
|
||||
UseNodeInternalIP: *useNodeInternalIP,
|
||||
ListenPorts: &ngx_config.ListenPorts{
|
||||
Default: *defServerPort,
|
||||
Health: *healthzPort,
|
||||
HTTP: *httpPort,
|
||||
HTTPS: *httpsPort,
|
||||
SSLProxy: *sslProxyPort,
|
||||
Status: *statusPort,
|
||||
},
|
||||
}
|
||||
|
||||
return false, config, nil
|
||||
}
|
||||
|
|
@ -17,29 +17,125 @@ limitations under the License.
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/pprof"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"k8s.io/ingress-nginx/pkg/nginx/controller"
|
||||
|
||||
proxyproto "github.com/armon/go-proxyproto"
|
||||
"github.com/golang/glog"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apiserver/pkg/server/healthz"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
|
||||
"k8s.io/ingress-nginx/pkg/ingress"
|
||||
"k8s.io/ingress-nginx/pkg/ingress/controller"
|
||||
"k8s.io/ingress-nginx/pkg/k8s"
|
||||
"k8s.io/ingress-nginx/pkg/net/ssl"
|
||||
"k8s.io/ingress-nginx/version"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// start a new nginx controller
|
||||
ngx := controller.NewNGINXController()
|
||||
fmt.Println(version.String())
|
||||
|
||||
showVersion, conf, err := parseFlags()
|
||||
if showVersion {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
glog.Fatal(err)
|
||||
}
|
||||
|
||||
kubeClient, err := createApiserverClient(conf.APIServerHost, conf.KubeConfigFile)
|
||||
if err != nil {
|
||||
handleFatalInitError(err)
|
||||
}
|
||||
|
||||
ns, name, err := k8s.ParseNameNS(conf.DefaultService)
|
||||
if err != nil {
|
||||
glog.Fatalf("invalid format for service %v: %v", conf.DefaultService, err)
|
||||
}
|
||||
|
||||
_, err = kubeClient.Core().Services(ns).Get(name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "cannot get services in the namespace") {
|
||||
glog.Fatalf("✖ It seems the cluster it is running with Authorization enabled (like RBAC) and there is no permissions for the ingress controller. Please check the configuration")
|
||||
}
|
||||
glog.Fatalf("no service with name %v found: %v", conf.DefaultService, err)
|
||||
}
|
||||
glog.Infof("validated %v as the default backend", conf.DefaultService)
|
||||
|
||||
if conf.PublishService != "" {
|
||||
ns, name, err := k8s.ParseNameNS(conf.PublishService)
|
||||
if err != nil {
|
||||
glog.Fatalf("invalid service format: %v", err)
|
||||
}
|
||||
|
||||
svc, err := kubeClient.CoreV1().Services(ns).Get(name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
glog.Fatalf("unexpected error getting information about service %v: %v", conf.PublishService, err)
|
||||
}
|
||||
|
||||
if len(svc.Status.LoadBalancer.Ingress) == 0 {
|
||||
if len(svc.Spec.ExternalIPs) > 0 {
|
||||
glog.Infof("service %v validated as assigned with externalIP", conf.PublishService)
|
||||
} else {
|
||||
// We could poll here, but we instead just exit and rely on k8s to restart us
|
||||
glog.Fatalf("service %s does not (yet) have ingress points", conf.PublishService)
|
||||
}
|
||||
} else {
|
||||
glog.Infof("service %v validated as source of Ingress status", conf.PublishService)
|
||||
}
|
||||
}
|
||||
|
||||
if conf.Namespace != "" {
|
||||
_, err = kubeClient.CoreV1().Namespaces().Get(conf.Namespace, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
glog.Fatalf("no watchNamespace with name %v found: %v", conf.Namespace, err)
|
||||
}
|
||||
}
|
||||
|
||||
if conf.ResyncPeriod.Seconds() < 10 {
|
||||
glog.Fatalf("resync period (%vs) is too low", conf.ResyncPeriod.Seconds())
|
||||
}
|
||||
|
||||
// create directory that will contains the SSL Certificates
|
||||
err = os.MkdirAll(ingress.DefaultSSLDirectory, 0655)
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to mkdir SSL directory: %v", err)
|
||||
}
|
||||
// create the default SSL certificate (dummy)
|
||||
sha, pem := createDefaultSSLCertificate()
|
||||
conf.FakeCertificatePath = pem
|
||||
conf.FakeCertificateSHA = sha
|
||||
|
||||
conf.Client = kubeClient
|
||||
conf.DefaultIngressClass = defIngressClass
|
||||
|
||||
ngx := controller.NewNGINXController(conf)
|
||||
|
||||
if conf.EnableSSLPassthrough {
|
||||
setupSSLProxy(conf.ListenPorts.HTTPS, conf.ListenPorts.SSLProxy, ngx)
|
||||
}
|
||||
|
||||
go handleSigterm(ngx)
|
||||
// start the controller
|
||||
|
||||
mux := http.NewServeMux()
|
||||
go registerHandlers(conf.EnableProfiling, conf.ListenPorts.Health, ngx, mux)
|
||||
|
||||
ngx.Start()
|
||||
// wait
|
||||
glog.Infof("shutting down Ingress controller...")
|
||||
for {
|
||||
glog.Infof("Handled quit, awaiting pod deletion")
|
||||
time.Sleep(30 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
func handleSigterm(ngx *controller.NGINXController) {
|
||||
|
|
@ -54,6 +150,176 @@ func handleSigterm(ngx *controller.NGINXController) {
|
|||
exitCode = 1
|
||||
}
|
||||
|
||||
glog.Infof("Handled quit, awaiting pod deletion")
|
||||
time.Sleep(10 * time.Second)
|
||||
|
||||
glog.Infof("Exiting with %v", exitCode)
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
|
||||
func setupSSLProxy(sslPort, proxyPort int, n *controller.NGINXController) {
|
||||
glog.Info("starting TLS proxy for SSL passthrough")
|
||||
n.Proxy = &controller.TCPProxy{
|
||||
Default: &controller.TCPServer{
|
||||
Hostname: "localhost",
|
||||
IP: "127.0.0.1",
|
||||
Port: proxyPort,
|
||||
ProxyProtocol: true,
|
||||
},
|
||||
}
|
||||
|
||||
listener, err := net.Listen("tcp", fmt.Sprintf(":%v", sslPort))
|
||||
if err != nil {
|
||||
glog.Fatalf("%v", err)
|
||||
}
|
||||
|
||||
proxyList := &proxyproto.Listener{Listener: listener}
|
||||
|
||||
// start goroutine that accepts tcp connections in port 443
|
||||
go func() {
|
||||
for {
|
||||
var conn net.Conn
|
||||
var err error
|
||||
|
||||
if n.IsProxyProtocolEnabled {
|
||||
// we need to wrap the listener in order to decode
|
||||
// proxy protocol before handling the connection
|
||||
conn, err = proxyList.Accept()
|
||||
} else {
|
||||
conn, err = listener.Accept()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
glog.Warningf("unexpected error accepting tcp connection: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
glog.V(3).Infof("remote address %s to local %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||
go n.Proxy.Handle(conn)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// createApiserverClient creates new Kubernetes Apiserver client. When kubeconfig or apiserverHost param is empty
|
||||
// the function assumes that it is running inside a Kubernetes cluster and attempts to
|
||||
// discover the Apiserver. Otherwise, it connects to the Apiserver specified.
|
||||
//
|
||||
// apiserverHost param is in the format of protocol://address:port/pathPrefix, e.g.http://localhost:8001.
|
||||
// kubeConfig location of kubeconfig file
|
||||
func createApiserverClient(apiserverHost string, kubeConfig string) (*kubernetes.Clientset, error) {
|
||||
cfg, err := buildConfigFromFlags(apiserverHost, kubeConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfg.QPS = defaultQPS
|
||||
cfg.Burst = defaultBurst
|
||||
cfg.ContentType = "application/vnd.kubernetes.protobuf"
|
||||
|
||||
glog.Infof("Creating API client for %s", cfg.Host)
|
||||
|
||||
client, err := kubernetes.NewForConfig(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v, err := client.Discovery().ServerVersion()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
glog.Infof("Running in Kubernetes Cluster version v%v.%v (%v) - git (%v) commit %v - platform %v",
|
||||
v.Major, v.Minor, v.GitVersion, v.GitTreeState, v.GitCommit, v.Platform)
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
const (
|
||||
// High enough QPS to fit all expected use cases. QPS=0 is not set here, because
|
||||
// client code is overriding it.
|
||||
defaultQPS = 1e6
|
||||
// High enough Burst to fit all expected use cases. Burst=0 is not set here, because
|
||||
// client code is overriding it.
|
||||
defaultBurst = 1e6
|
||||
|
||||
fakeCertificate = "default-fake-certificate"
|
||||
)
|
||||
|
||||
// buildConfigFromFlags builds REST config based on master URL and kubeconfig path.
|
||||
// If both of them are empty then in cluster config is used.
|
||||
func buildConfigFromFlags(masterURL, kubeconfigPath string) (*rest.Config, error) {
|
||||
if kubeconfigPath == "" && masterURL == "" {
|
||||
kubeconfig, err := rest.InClusterConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return kubeconfig, nil
|
||||
}
|
||||
|
||||
return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
|
||||
&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeconfigPath},
|
||||
&clientcmd.ConfigOverrides{
|
||||
ClusterInfo: clientcmdapi.Cluster{
|
||||
Server: masterURL,
|
||||
},
|
||||
}).ClientConfig()
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles fatal init error that prevents server from doing any work. Prints verbose error
|
||||
* message and quits the server.
|
||||
*/
|
||||
func handleFatalInitError(err error) {
|
||||
glog.Fatalf("Error while initializing connection to Kubernetes apiserver. "+
|
||||
"This most likely means that the cluster is misconfigured (e.g., it has "+
|
||||
"invalid apiserver certificates or service accounts configuration). Reason: %s\n"+
|
||||
"Refer to the troubleshooting guide for more information: "+
|
||||
"https://github.com/kubernetes/ingress-nginx/blob/master/docs/troubleshooting.md", err)
|
||||
}
|
||||
|
||||
func registerHandlers(enableProfiling bool, port int, ic *controller.NGINXController, mux *http.ServeMux) {
|
||||
// expose health check endpoint (/healthz)
|
||||
healthz.InstallHandler(mux,
|
||||
healthz.PingHealthz,
|
||||
ic,
|
||||
)
|
||||
|
||||
mux.Handle("/metrics", promhttp.Handler())
|
||||
|
||||
mux.HandleFunc("/build", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
b, _ := json.Marshal(version.String())
|
||||
w.Write(b)
|
||||
})
|
||||
|
||||
mux.HandleFunc("/stop", func(w http.ResponseWriter, r *http.Request) {
|
||||
err := syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
|
||||
if err != nil {
|
||||
glog.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
if enableProfiling {
|
||||
mux.HandleFunc("/debug/pprof/", pprof.Index)
|
||||
mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
|
||||
mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
|
||||
mux.HandleFunc("/debug/pprof/trace", pprof.Trace)
|
||||
}
|
||||
|
||||
server := &http.Server{
|
||||
Addr: fmt.Sprintf(":%v", port),
|
||||
Handler: mux,
|
||||
}
|
||||
glog.Fatal(server.ListenAndServe())
|
||||
}
|
||||
|
||||
func createDefaultSSLCertificate() (string, string) {
|
||||
defCert, defKey := ssl.GetFakeSSLCert()
|
||||
c, err := ssl.AddOrUpdateCertAndKey(fakeCertificate, defCert, defKey, []byte{})
|
||||
if err != nil {
|
||||
glog.Fatalf("Error generating self signed certificate: %v", err)
|
||||
}
|
||||
|
||||
return c.PemSHA, c.PemFileName
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue