From 7875732cb5a28b14ef55d2e09e69b7a9cf78688a Mon Sep 17 00:00:00 2001 From: Manuel de Brito Fontes Date: Thu, 27 Oct 2016 00:01:38 -0300 Subject: [PATCH] Add ingress class and info features --- README.md | 82 ++++++++++++++++++---- backends/nginx/Makefile | 2 +- backends/nginx/pkg/cmd/controller/nginx.go | 6 ++ pkg/ingress/controller/controller.go | 14 +++- pkg/ingress/controller/launch.go | 13 ++-- pkg/ingress/types.go | 5 +- 6 files changed, 99 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 57a395d..e36cdf6 100644 --- a/README.md +++ b/README.md @@ -5,20 +5,74 @@ # Ingress Controller -This project contains the boilerplate to spin up an Ingress controller. +This project contains the boilerplate to create an Ingress controller in order to avoid starting from scrach. See [Ingress controller documentation](https://github.com/kubernetes/contrib/blob/master/ingress/controllers/README.md) for details on how it works. -## DONE: - - SSL pass through - - avoid unnecessary overwrite of ssl certificates - - [Interface](https://github.com/aledbf/ingress-controller/blob/master/pkg/ingress/types.go#L40) - -## TODO: - - api docs - - example - - used directories - - on shutdown remove status IP - - finish [first implementation](https://github.com/aledbf/ingress-controller/tree/master/backends/nginx) (nginx) - - add ingress uuid (allow to group multiple controller in the same namespace - this is required to update the status IP in the leader) - - + +### Backends + - [NGINX](https://github.com/aledbf/ingress-controller/blob/master/backends/nginx) + + +### How I can use X as backend? + +Chek if the backend is available [here](https://github.com/aledbf/ingress-controller/blob/master/backends) + +Create a `main.go` file +``` +func main() { + // start a new nginx controller + ngx := newNGINXController() + // create a custom Ingress controller using NGINX as backend + ic := controller.NewIngressController(ngx) + // start the controller + ic.Start() + // wait + glog.Infof("shutting down Ingress controller...") +} +``` + +Implement the [Controller](https://github.com/aledbf/ingress-controller/blob/master/pkg/ingress/types.go#L40) interface +``` +type Controller interface { + // Start returns the command is executed to start the backend. + // The command must run in foreground. + Start() + // Stop stops the backend + Stop() error + // Restart reload the backend with the a configuration file returning + // the combined output of Stdout and Stderr + Restart(data []byte) ([]byte, error) + // Tests returns a commands that checks if the configuration file is valid + // Example: nginx -t -c + Test(file string) *exec.Cmd + // OnUpdate callback invoked from the sync queue https://github.com/aledbf/ingress-controller/blob/master/pkg/ingress/controller/controller.go#L355 + // when an update occurs. This is executed frequently because Ingress + // controllers watches changes in: + // - Ingresses: main work + // - Secrets: referenced from Ingress rules with TLS configured + // - ConfigMaps: where the controller reads custom configuration + // - Services: referenced from Ingress rules and required to obtain + // information about ports and annotations + // - Endpoints: referenced from Services and what the backend uses + // to route traffic + // + // ConfigMap content of --configmap + // Configuration returns the translation from Ingress rules containing + // information about all the upstreams (service endpoints ) "virtual" + // servers (FQDN) + // and all the locations inside each server. Each location contains + // information about all the annotations were configured + // https://github.com/aledbf/ingress-controller/blob/master/pkg/ingress/types.go#L48 + OnUpdate(*api.ConfigMap, Configuration) ([]byte, error) + // UpstreamDefaults returns the minimum settings required to configure the + // communication to upstream servers (endpoints) + UpstreamDefaults() defaults.Backend + // IsReloadRequired checks if the backend must be reloaded or not. + // The parameter contains the new rendered template + IsReloadRequired([]byte) bool + // Info returns information about the ingress controller + // This can include build version, repository, etc. + Info() string +} +``` \ No newline at end of file diff --git a/backends/nginx/Makefile b/backends/nginx/Makefile index 36ff93d..cd43581 100644 --- a/backends/nginx/Makefile +++ b/backends/nginx/Makefile @@ -13,7 +13,7 @@ ifndef COMMIT COMMIT := git-$(shell git rev-parse --short HEAD) endif -PKG := "github.com/aledbf/ingress-controller/backends/nginx" +PKG=github.com/aledbf/ingress-controller/backends/nginx build: clean CGO_ENABLED=0 GOOS=${GOOS} go build -a -installsuffix cgo \ diff --git a/backends/nginx/pkg/cmd/controller/nginx.go b/backends/nginx/pkg/cmd/controller/nginx.go index e2f4ebf..9eb6e04 100644 --- a/backends/nginx/pkg/cmd/controller/nginx.go +++ b/backends/nginx/pkg/cmd/controller/nginx.go @@ -30,6 +30,7 @@ import ( "github.com/aledbf/ingress-controller/backends/nginx/pkg/config" ngx_template "github.com/aledbf/ingress-controller/backends/nginx/pkg/template" + "github.com/aledbf/ingress-controller/backends/nginx/pkg/version" "k8s.io/kubernetes/pkg/api" ) @@ -165,6 +166,11 @@ func (n NGINXController) IsReloadRequired(data []byte) bool { return false } +// Info return build information +func (n NGINXController) Info() string { + return fmt.Sprintf("build version %v from repo %v commit %v", version.RELEASE, version.REPO, version.COMMIT) +} + // testTemplate checks if the NGINX configuration inside the byte array is valid // running the command "nginx -t" using a temporal file. func (n NGINXController) testTemplate(cfg []byte) error { diff --git a/pkg/ingress/controller/controller.go b/pkg/ingress/controller/controller.go index 69ec204..0531ed3 100644 --- a/pkg/ingress/controller/controller.go +++ b/pkg/ingress/controller/controller.go @@ -76,6 +76,8 @@ type Interface interface { Start() Stop() error + Info() string + healthz.HealthzChecker } @@ -337,6 +339,16 @@ func (ic GenericController) Check(_ *http.Request) error { return nil } +// Info returns information about the backend +func (ic GenericController) Info() string { + return ic.cfg.Backend.Info() +} + +// IngressClass returns information about the backend +func (ic GenericController) IngressClass() string { + return ic.cfg.IngressClass +} + // getSecret searchs for a secret in the local secrets Store func (ic *GenericController) getSecret(name string) (*api.Secret, error) { s, exists, err := ic.secrLister.Store.GetByKey(name) @@ -423,7 +435,7 @@ func (ic *GenericController) sync(key interface{}) error { glog.Errorf("unexpected failure restarting the backend: \n%v", string(out)) return err } - reloadOperations.WithLabelValues(ReloadOperations).Inc() + reloadOperations.WithLabelValues(ReloadOperations).Inc() return nil } diff --git a/pkg/ingress/controller/launch.go b/pkg/ingress/controller/launch.go index 512ed47..a270ca5 100644 --- a/pkg/ingress/controller/launch.go +++ b/pkg/ingress/controller/launch.go @@ -36,7 +36,7 @@ func NewIngressController(backend ingress.Controller) Interface { ingressClass = flags.String("ingress-class", "nginx", `Name of the ingress class to route through this controller.`) - nxgConfigMap = flags.String("config-map", "", + configMap = flags.String("configmap", "", `Name of the ConfigMap that containes the custom configuration to use`) publishSvc = flags.String("publish-service", "", @@ -80,7 +80,8 @@ func NewIngressController(backend ingress.Controller) Interface { flag.Set("logtostderr", "true") - //glog.Infof("Using build version %v from repo %v commit %v", version.RELEASE, version.REPO, version.COMMIT) + glog.Info(backend.Info()) + if *ingressClass != "" { glog.Infof("Watching for ingress class: %s", *ingressClass) } @@ -127,8 +128,8 @@ func NewIngressController(backend ingress.Controller) Interface { glog.Infof("service %v validated as source of Ingress status", *publishSvc) } - if *nxgConfigMap != "" { - _, _, err = k8s.ParseNameNS(*nxgConfigMap) + if *configMap != "" { + _, _, err = k8s.ParseNameNS(*configMap) if err != nil { glog.Fatalf("configmap error: %v", err) } @@ -143,7 +144,7 @@ func NewIngressController(backend ingress.Controller) Interface { DefaultService: *defaultSvc, IngressClass: *ingressClass, Namespace: *watchNamespace, - ConfigMapName: *nxgConfigMap, + ConfigMapName: *configMap, TCPConfigMapName: *tcpConfigMapName, UDPConfigMapName: *udpConfigMapName, DefaultSSLCertificate: *defSSLCertificate, @@ -165,7 +166,7 @@ func registerHandlers(enableProfiling bool, port int, ic Interface) { mux.HandleFunc("/build", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) - //fmt.Fprintf(w, "build version %v from repo %v commit %v", version.RELEASE, version.REPO, version.COMMIT) + fmt.Fprintf(w, ic.Info()) }) mux.HandleFunc("/stop", func(w http.ResponseWriter, r *http.Request) { diff --git a/pkg/ingress/types.go b/pkg/ingress/types.go index 0526693..c934e87 100644 --- a/pkg/ingress/types.go +++ b/pkg/ingress/types.go @@ -61,7 +61,7 @@ type Controller interface { // - Endpoints: referenced from Services and what the backend uses // to route traffic // - // ConfigMap content of --config-map + // ConfigMap content of --configmap // Configuration returns the translation from Ingress rules containing // information about all the upstreams (service endpoints ) "virtual" // servers (FQDN) @@ -75,6 +75,9 @@ type Controller interface { // IsReloadRequired checks if the backend must be reloaded or not. // The parameter contains the new rendered template IsReloadRequired([]byte) bool + // Info returns information about the ingress controller + // This can include build version, repository, etc. + Info() string } // Configuration describes