You've already forked haproxy-ingress
mirror of
https://github.com/encounter/haproxy-ingress.git
synced 2026-03-30 11:12:55 -07:00
170 lines
5.1 KiB
Go
170 lines
5.1 KiB
Go
/*
|
|
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 controller
|
|
|
|
import (
|
|
"bytes"
|
|
"github.com/golang/glog"
|
|
"github.com/jcmoraisjr/haproxy-ingress/pkg/version"
|
|
"github.com/spf13/pflag"
|
|
"io/ioutil"
|
|
api "k8s.io/client-go/pkg/api/v1"
|
|
"k8s.io/ingress/core/pkg/ingress"
|
|
"k8s.io/ingress/core/pkg/ingress/controller"
|
|
"k8s.io/ingress/core/pkg/ingress/defaults"
|
|
"net/http"
|
|
"os"
|
|
"os/exec"
|
|
)
|
|
|
|
// HAProxyController has internal data of a HAProxyController instance
|
|
type HAProxyController struct {
|
|
controller *controller.GenericController
|
|
configMap *api.ConfigMap
|
|
storeLister *ingress.StoreLister
|
|
command string
|
|
reloadStrategy *string
|
|
configFile string
|
|
template *template
|
|
}
|
|
|
|
// NewHAProxyController constructor
|
|
func NewHAProxyController() *HAProxyController {
|
|
return &HAProxyController{}
|
|
}
|
|
|
|
// Info provides controller name and repository infos
|
|
func (haproxy *HAProxyController) Info() *ingress.BackendInfo {
|
|
return &ingress.BackendInfo{
|
|
Name: "HAProxy",
|
|
Release: version.RELEASE,
|
|
Build: version.COMMIT,
|
|
Repository: version.REPO,
|
|
}
|
|
}
|
|
|
|
// Start starts the controller
|
|
func (haproxy *HAProxyController) Start() {
|
|
haproxy.controller = controller.NewIngressController(haproxy)
|
|
haproxy.controller.Start()
|
|
}
|
|
|
|
// Stop shutdown the controller process
|
|
func (haproxy *HAProxyController) Stop() error {
|
|
err := haproxy.controller.Stop()
|
|
return err
|
|
}
|
|
|
|
// Name provides the complete name of the controller
|
|
func (haproxy *HAProxyController) Name() string {
|
|
return "HAProxy Ingress Controller"
|
|
}
|
|
|
|
// DefaultIngressClass returns the ingress class name
|
|
func (haproxy *HAProxyController) DefaultIngressClass() string {
|
|
return "haproxy"
|
|
}
|
|
|
|
// Check health check implementation
|
|
func (haproxy *HAProxyController) Check(_ *http.Request) error {
|
|
return nil
|
|
}
|
|
|
|
// SetListers give access to the store listers
|
|
func (haproxy *HAProxyController) SetListers(lister ingress.StoreLister) {
|
|
haproxy.storeLister = &lister
|
|
}
|
|
|
|
// ConfigureFlags allow to configure more flags before the parsing of
|
|
// command line arguments
|
|
func (haproxy *HAProxyController) ConfigureFlags(flags *pflag.FlagSet) {
|
|
haproxy.reloadStrategy = flags.String("reload-strategy", "native",
|
|
`Name of the reload strategy. Options are: native (default) or multibinder`)
|
|
ingressClass := flags.Lookup("ingress-class")
|
|
if ingressClass != nil {
|
|
ingressClass.Value.Set("haproxy")
|
|
ingressClass.DefValue = "haproxy"
|
|
}
|
|
}
|
|
|
|
// OverrideFlags allows controller to override command line parameter flags
|
|
func (haproxy *HAProxyController) OverrideFlags(flags *pflag.FlagSet) {
|
|
if *haproxy.reloadStrategy == "native" {
|
|
haproxy.configFile = "/etc/haproxy/haproxy.cfg"
|
|
haproxy.template = newTemplate("haproxy.tmpl", "/etc/haproxy/template/haproxy.tmpl")
|
|
} else if *haproxy.reloadStrategy == "multibinder" {
|
|
haproxy.configFile = "/etc/haproxy/haproxy.cfg.erb"
|
|
haproxy.template = newTemplate("haproxy.cfg.erb.tmpl", "/etc/haproxy/haproxy.cfg.erb.tmpl")
|
|
} else {
|
|
glog.Fatalf("Unsupported reload strategy: %v", *haproxy.reloadStrategy)
|
|
}
|
|
haproxy.command = "/haproxy-reload.sh"
|
|
}
|
|
|
|
// SetConfig receives the ConfigMap the user has configured
|
|
func (haproxy *HAProxyController) SetConfig(configMap *api.ConfigMap) {
|
|
haproxy.configMap = configMap
|
|
}
|
|
|
|
// BackendDefaults defines default values to the ingress core
|
|
func (haproxy *HAProxyController) BackendDefaults() defaults.Backend {
|
|
return newHAProxyConfig(haproxy).Backend
|
|
}
|
|
|
|
// OnUpdate regenerate the configuration file of the backend
|
|
func (haproxy *HAProxyController) OnUpdate(cfg ingress.Configuration) ([]byte, error) {
|
|
data, err := haproxy.template.execute(newControllerConfig(&cfg, haproxy))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return data, nil
|
|
}
|
|
|
|
// Reload reload the backend if the configuration file has changed
|
|
func (haproxy *HAProxyController) Reload(data []byte) ([]byte, bool, error) {
|
|
if !haproxy.configChanged(data) {
|
|
return nil, false, nil
|
|
}
|
|
// TODO missing HAProxy validation before overwrite and try to reload
|
|
err := ioutil.WriteFile(haproxy.configFile, data, 0644)
|
|
if err != nil {
|
|
return nil, false, err
|
|
}
|
|
out, err := haproxy.reloadHaproxy()
|
|
if len(out) > 0 {
|
|
glog.Infof("HAProxy output:\n%v", string(out))
|
|
}
|
|
return out, true, err
|
|
}
|
|
|
|
func (haproxy *HAProxyController) configChanged(data []byte) bool {
|
|
if _, err := os.Stat(haproxy.configFile); os.IsNotExist(err) {
|
|
return true
|
|
}
|
|
cfg, err := ioutil.ReadFile(haproxy.configFile)
|
|
if err != nil {
|
|
glog.Warningf("error reading haproxy config: %v")
|
|
return false
|
|
}
|
|
return !bytes.Equal(cfg, data)
|
|
}
|
|
|
|
func (haproxy *HAProxyController) reloadHaproxy() ([]byte, error) {
|
|
out, err := exec.Command(haproxy.command, *haproxy.reloadStrategy, haproxy.configFile).CombinedOutput()
|
|
return out, err
|
|
}
|