Skip to content

Commit

Permalink
MEDIUM: change backend management
Browse files Browse the repository at this point in the history
This commit aims to prevent all reloads issues about false comparisons between a request backend and the one inside the configuration file. This situation occurs because of different reasons from CN or CP.
  • Loading branch information
ivanmatmati committed Jan 21, 2025
1 parent 0574902 commit 280a8e4
Show file tree
Hide file tree
Showing 16 changed files with 466 additions and 264 deletions.
29 changes: 11 additions & 18 deletions pkg/annotations/cfgSnippetHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,40 +14,33 @@ type ConfigSnippetHandler struct{}

func (h ConfigSnippetHandler) Update(k store.K8s, api haproxy.HAProxy, ann Annotations) (err error) {
// We get the configmap configsnippet value
configmapCfgSnippetValue, errConfigmapCfgSnippet := getConfigmapConfigSnippet(k.BackendsWithNoConfigSnippets, api)
if errConfigmapCfgSnippet != nil {
return errConfigmapCfgSnippet
}
configmapCfgSnippetValue := getConfigmapConfigSnippet(k.BackendsWithNoConfigSnippets, api)
// We pass the configmap config snippet value to be inserted at top of the comment section for every config snippet section
return updateConfigSnippet(api, configmapCfgSnippetValue)
}

func getConfigmapConfigSnippet(backendsWithNoConfigSnippets map[string]struct{}, api api.HAProxyClient) (configmapCfgSnippetValue []string, err error) {
func getConfigmapConfigSnippet(backendsWithNoConfigSnippets map[string]struct{}, api api.HAProxyClient) []string {
// configmap config snippet if any.
configmapCfgSnippetValue = []string{}
configmapCfgSnippetValue := []string{}
// configmap config snippet will be hold in special backend 'configmap' with origin 'configmap'
if configmapCfgSnippet := cfgSnippet.backends["configmap"]["configmap"]; configmapCfgSnippet != nil &&
configmapCfgSnippet.status != store.DELETED &&
!configmapCfgSnippet.disabled {
configmapCfgSnippetValue = configmapCfgSnippet.value
// if any existing and enabled configmap configsnippet then add a special insertion for every existing backend
// to replicate everywhere the configmap insertion.
if backends, errGet := api.BackendsGet(); errGet == nil {
for _, backend := range backends {
if _, ok := backendsWithNoConfigSnippets[backend.Name]; ok {
continue
}
if _, ok := cfgSnippet.backends[backend.Name]; !ok {
cfgSnippet.backends[backend.Name] = map[string]*cfgData{
"configmap-insertion": {status: store.ADDED},
}
for _, backend := range api.BackendsGet() {
if _, ok := backendsWithNoConfigSnippets[backend.Name]; ok {
continue
}
if _, ok := cfgSnippet.backends[backend.Name]; !ok {
cfgSnippet.backends[backend.Name] = map[string]*cfgData{
"configmap-insertion": {status: store.ADDED},
}
}
} else {
err = errGet
}
}
return
return configmapCfgSnippetValue
}

func updateConfigSnippet(api api.HAProxyClient, configmapCfgSnippetValue []string) (err error) {
Expand Down
7 changes: 5 additions & 2 deletions pkg/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ func (c *HAProxyController) updateHAProxy() {
c.setToReady()
}

err = c.haproxy.APICommitTransaction()
err = c.haproxy.APIFinalCommitTransaction()
if err != nil {
logger.Error("unable to Sync HAProxy configuration !!")
logger.Error(err)
Expand All @@ -196,6 +196,8 @@ func (c *HAProxyController) updateHAProxy() {
c.updateHAProxy()
return
}
// If any error not from config snippet then pop the previous state of backends
logger.Error(c.haproxy.PopPreviousBackends())
return
}

Expand All @@ -213,7 +215,8 @@ func (c *HAProxyController) updateHAProxy() {
}

c.clean(false)

// If transaction succeeds thenpush backends state for any future recover.
logger.Error(c.haproxy.PushPreviousBackends())
logger.Trace("HAProxy config sync ended")
}

Expand Down
9 changes: 3 additions & 6 deletions pkg/gateways/gateways.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,16 +203,13 @@ func (gm GatewayManagerImpl) manageTCPRoutes() {
}

// If not called on the route, the afferent backend will be automatically deleted.
errBackendCreate := gm.haproxyClient.BackendCreateIfNotExist(
gm.haproxyClient.BackendCreateIfNotExist(
models.Backend{
Name: getBackendName(*tcproute),
Mode: "tcp",
DefaultServer: &models.DefaultServer{ServerParams: models.ServerParams{Check: "enabled"}},
})
if errBackendCreate != nil {
logger.Error(errBackendCreate)
continue
}

_, backendExists := gm.backends[tcpRouteBackendName]
instance.ReloadIf(!backendExists, "modification in backend for tcproute '%s/%s'", tcproute.Namespace, tcproute.Name)
gm.backends[tcpRouteBackendName] = struct{}{}
Expand Down Expand Up @@ -369,7 +366,7 @@ func (gm GatewayManagerImpl) isNamespaceGranted(namespace string, backendRef sto
// addServersToRoute adds all the servers from the backendrefs from tcproute according validation rules.
func (gm GatewayManagerImpl) addServersToRoute(route store.TCPRoute) (reload bool, err error) {
backendName := getBackendName(route)
gm.haproxyClient.BackendServerDeleteAll(backendName)
_ = gm.haproxyClient.BackendServerDeleteAll(backendName)
i := 0
var servers []string
defer func() {
Expand Down
18 changes: 7 additions & 11 deletions pkg/handler/https.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,8 @@ func (handler HTTPS) Update(k store.K8s, h haproxy.HAProxy, a annotations.Annota
}
// ssl-passthrough
_, errFtSSL := h.FrontendGet(h.FrontSSL)
_, errBdSSL := h.BackendGet(h.BackSSL)
if haproxy.SSLPassthrough {
if errFtSSL != nil || errBdSSL != nil {
if errFtSSL != nil || !h.BackendExists(h.BackSSL) {
logger.Error(handler.enableSSLPassthrough(h))
instance.Reload("SSLPassthrough enabled")
}
Expand Down Expand Up @@ -223,13 +222,13 @@ func (handler HTTPS) enableSSLPassthrough(h haproxy.HAProxy) (err error) {
}
// Create backend for proxy chaining (chaining
// ssl-passthrough frontend to ssl-offload backend)
h.BackendCreatePermanently(models.Backend{
Name: h.BackSSL,
Mode: "tcp",
})
var errors utils.Errors
errors.Add(
h.BackendCreate(models.Backend{
Name: h.BackSSL,
Mode: "tcp",
}),
h.BackendServerCreate(h.BackSSL, models.Server{
h.BackendServerCreateOrUpdate(h.BackSSL, models.Server{
Name: h.FrontHTTPS,
Address: "unix@" + handler.unixSocketPath(h),
ServerParams: models.ServerParams{SendProxyV2: "enabled"},
Expand All @@ -248,10 +247,7 @@ func (handler HTTPS) disableSSLPassthrough(h haproxy.HAProxy) (err error) {
return err
}
h.DeleteFTRules(h.FrontSSL)
err = h.BackendDelete(h.BackSSL)
if err != nil {
return err
}
h.BackendDelete(h.BackSSL)
if err = handler.toggleSSLPassthrough(false, h); err != nil {
return err
}
Expand Down
15 changes: 7 additions & 8 deletions pkg/handler/pprof.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,14 @@ type Pprof struct{}

func (handler Pprof) Update(k store.K8s, h haproxy.HAProxy, a annotations.Annotations) (err error) {
k.BackendsWithNoConfigSnippets[pprofBackend] = struct{}{}
_, err = h.BackendGet(pprofBackend)
if err != nil {
err = h.BackendCreatePermanently(models.Backend{

if !h.BackendExists(pprofBackend) {
h.BackendCreatePermanently(models.Backend{
Name: pprofBackend,
Mode: "http",
})
if err != nil {
return
}
err = h.BackendServerCreate(pprofBackend, models.Server{

err = h.BackendServerCreateOrUpdate(pprofBackend, models.Server{
Name: pprofBackend,
Address: fmt.Sprintf("127.0.0.1:%d", h.Env.ControllerPort),
})
Expand All @@ -49,6 +47,7 @@ func (handler Pprof) Update(k store.K8s, h haproxy.HAProxy, a annotations.Annota
}
logger.Debug("pprof backend created")
}

err = route.AddHostPathRoute(route.Route{
BackendName: pprofBackend,
Path: &store.IngressPath{
Expand All @@ -59,6 +58,6 @@ func (handler Pprof) Update(k store.K8s, h haproxy.HAProxy, a annotations.Annota
if err != nil {
return
}
// instance.Reload("pprof backend created")

return
}
3 changes: 1 addition & 2 deletions pkg/handler/prometheus.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ func (handler PrometheusEndpoint) Update(k store.K8s, h haproxy.HAProxy, a annot

status := store.EMPTY
var secret *store.Secret
_, errBackend := h.BackendGet(prometheusBackendName)
backendExists := errBackend == nil
backendExists := h.BackendExists(prometheusBackendName)

annSecret := annotations.String("prometheus-endpoint-auth-secret", k.ConfigMaps.Main.Annotations)
var secretExists, secretChanged, userListChanged bool
Expand Down
10 changes: 1 addition & 9 deletions pkg/handler/refresh.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package handler
import (
"github.com/haproxytech/kubernetes-ingress/pkg/annotations"
"github.com/haproxytech/kubernetes-ingress/pkg/haproxy"
"github.com/haproxytech/kubernetes-ingress/pkg/haproxy/instance"
"github.com/haproxytech/kubernetes-ingress/pkg/store"
)

Expand All @@ -38,13 +37,6 @@ func (handler Refresh) Update(k store.K8s, h haproxy.HAProxy, a annotations.Anno
h.RefreshRules(h.HAProxyClient)
// Maps
h.RefreshMaps(h.HAProxyClient)
// Backends
deleted, err := h.RefreshBackends()
instance.ReloadIf(len(deleted) > 0, "some backends are deleted")
logger.Error(err)
for _, backend := range deleted {
logger.Debugf("Backend '%s' deleted", backend)
annotations.RemoveBackendCfgSnippet(backend)
}

return
}
35 changes: 34 additions & 1 deletion pkg/haproxy/api/acl.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
package api

import "github.com/haproxytech/client-native/v5/models"
import (
"fmt"

"github.com/haproxytech/client-native/v5/models"
)

func (c *clientNative) ACLsGet(parentType, parentName string, aclName ...string) (models.Acls, error) {
configuration, err := c.nativeAPI.Configuration()
if err != nil {
return nil, err
}

if parentType == "backend" {
backend, exists := c.backends[parentName]
if !exists {
return nil, fmt.Errorf("can't get acls for unexisting backend %s : %w", parentName, ErrNotFound)
}
return backend.ACLList, nil
}

_, acls, err := configuration.GetACLs(parentType, parentName, c.activeTransaction, aclName...)
if err != nil {
return nil, err
Expand Down Expand Up @@ -39,6 +52,17 @@ func (c *clientNative) ACLDeleteAll(parentType string, parentName string) error
if err != nil {
return err
}

if parentType == "backend" {
backend, exists := c.backends[parentName]
if !exists {
return fmt.Errorf("can't delete acls for unexisting backend %s : %w", parentName, ErrNotFound)
}
backend.ACLList = nil
c.backends[parentName] = backend
return nil
}

_, acls, errGet := configuration.GetACLs(parentType, parentName, c.activeTransaction)
if errGet != nil {
return errGet
Expand All @@ -58,6 +82,15 @@ func (c *clientNative) ACLCreate(parentType string, parentName string, data *mod
if err != nil {
return err
}
if parentType == "backend" {
backend, exists := c.backends[parentName]
if !exists {
return fmt.Errorf("can't create acl for unexisting backend %s : %w", parentName, ErrNotFound)
}
backend.ACLList = append(backend.ACLList, data)
c.backends[parentName] = backend
return nil
}
return configuration.CreateACL(parentType, parentName, data, c.activeTransaction, 0)
}

Expand Down
Loading

0 comments on commit 280a8e4

Please sign in to comment.