Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chore: Define dedicated types for DBMode and RouterFlavor #5092

Merged
merged 8 commits into from
Nov 9, 2023
2 changes: 2 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ linters-settings:
alias: gateway${1}
- pkg: github.com/kong/kubernetes-ingress-controller/v2/pkg/apis/configuration/(v[\w\d]+)
alias: kong${1}
- pkg: github.com/kong/kubernetes-ingress-controller/v3/internal/dataplane/config
alias: dpconf
forbidigo:
exclude-godoc-examples: false
forbid:
Expand Down
8 changes: 4 additions & 4 deletions internal/clients/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import (
"golang.org/x/exp/maps"

"github.com/kong/kubernetes-ingress-controller/v3/internal/adminapi"
dpconf "github.com/kong/kubernetes-ingress-controller/v3/internal/dataplane/config"
"github.com/kong/kubernetes-ingress-controller/v3/internal/util"
"github.com/kong/kubernetes-ingress-controller/v3/internal/util/clock"
dataplaneutil "github.com/kong/kubernetes-ingress-controller/v3/internal/util/dataplane"
)

// DefaultReadinessReconciliationInterval is the interval at which the manager will run readiness reconciliation loop.
Expand Down Expand Up @@ -50,7 +50,7 @@ type AdminAPIClientsManager struct {
discoveredAdminAPIsNotifyChan chan []adminapi.DiscoveredAdminAPI
gatewayClientsChangesSubscribers []chan struct{}

dbMode string
dbMode dpconf.DBMode

ctx context.Context
onceNotifyLoopRunning sync.Once
Expand Down Expand Up @@ -90,7 +90,7 @@ func WithReadinessReconciliationTicker(ticker Ticker) AdminAPIClientsManagerOpti
}

// WithDBMode allows to set the DBMode of the Kong gateway instances behind the admin API service.
func (c *AdminAPIClientsManager) WithDBMode(dbMode string) *AdminAPIClientsManager {
func (c *AdminAPIClientsManager) WithDBMode(dbMode dpconf.DBMode) *AdminAPIClientsManager {
c.dbMode = dbMode
return c
}
Expand Down Expand Up @@ -194,7 +194,7 @@ func (c *AdminAPIClientsManager) GatewayClientsToConfigure() []*adminapi.Client
defer c.lock.RUnlock()
readyGatewayClients := lo.Values(c.readyGatewayClients)
// With DB-less mode, we should send the configuration to ALL gateway instances.
if dataplaneutil.IsDBLessMode(c.dbMode) {
if c.dbMode.IsDBLessMode() {
return readyGatewayClients
}
// When a gateway is DB-backed, we return a random client
Expand Down
4 changes: 3 additions & 1 deletion internal/dataplane/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package dataplane

import (
"context"

dpconf "github.com/kong/kubernetes-ingress-controller/v3/internal/dataplane/config"
)

// -----------------------------------------------------------------------------
Expand All @@ -24,7 +26,7 @@ const (
type Client interface {
// DBMode informs the caller which DB mode the data-plane has employed
// (e.g. "off" (dbless) or "postgres").
DBMode() string
DBMode() dpconf.DBMode

// Update the data-plane by parsing the current configuring and applying
// it to the backend API.
Expand Down
31 changes: 31 additions & 0 deletions internal/dataplane/config/dbmode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package config

import "fmt"

type DBMode string

const (
DBModeOff DBMode = "off"
DBModePostgres DBMode = "postgres"
)

func NewDBMode(mode string) (DBMode, error) {
switch mode {
case "", string(DBModeOff):
return DBModeOff, nil
case string(DBModePostgres):
return DBModePostgres, nil
}
return "", fmt.Errorf("unsupported db mode: %q", mode)
}

// IsDBLessMode can be used to detect the proxy mode (db or dbless).
func (m DBMode) IsDBLessMode() bool {
return m == "" || m == DBModeOff
}

// DBBacked returns true if the gateway is DB backed.
// reverse of IsDBLessMode for readability.
func (m DBMode) DBBacked() bool {
return !m.IsDBLessMode()
}
13 changes: 13 additions & 0 deletions internal/dataplane/config/router.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package config

type RouterFlavor string

const (
RouterFlavorTraditional RouterFlavor = "traditional"
RouterFlavorTraditionalCompatible RouterFlavor = "traditional_compatible"
RouterFlavorExpressions RouterFlavor = "expressions"
)

func ShouldEnableExpressionRoutes(rf RouterFlavor) bool {
return rf == RouterFlavorExpressions
}
12 changes: 6 additions & 6 deletions internal/dataplane/kong_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (

"github.com/kong/kubernetes-ingress-controller/v3/internal/adminapi"
"github.com/kong/kubernetes-ingress-controller/v3/internal/clients"
dpconf "github.com/kong/kubernetes-ingress-controller/v3/internal/dataplane/config"
"github.com/kong/kubernetes-ingress-controller/v3/internal/dataplane/configfetcher"
"github.com/kong/kubernetes-ingress-controller/v3/internal/dataplane/deckgen"
"github.com/kong/kubernetes-ingress-controller/v3/internal/dataplane/failures"
Expand All @@ -34,7 +35,6 @@ import (
"github.com/kong/kubernetes-ingress-controller/v3/internal/metrics"
"github.com/kong/kubernetes-ingress-controller/v3/internal/store"
"github.com/kong/kubernetes-ingress-controller/v3/internal/util"
dataplaneutil "github.com/kong/kubernetes-ingress-controller/v3/internal/util/dataplane"
k8sobj "github.com/kong/kubernetes-ingress-controller/v3/internal/util/kubernetes/object"
"github.com/kong/kubernetes-ingress-controller/v3/internal/util/kubernetes/object/status"
)
Expand Down Expand Up @@ -75,7 +75,7 @@ type KongClient struct {
kongConfig sendconfig.Config

// dbmode indicates the current database mode of the backend Kong Admin API
dbmode string
dbmode dpconf.DBMode

// lock is used to ensure threadsafety of the KongClient object
lock sync.RWMutex
Expand Down Expand Up @@ -150,7 +150,7 @@ func NewKongClient(
diagnostic util.ConfigDumpDiagnostic,
kongConfig sendconfig.Config,
eventRecorder record.EventRecorder,
dbMode string,
dbMode dpconf.DBMode,
clientsProvider clients.AdminAPIClientsProvider,
updateStrategyResolver sendconfig.UpdateStrategyResolver,
configChangeDetector sendconfig.ConfigurationChangeDetector,
Expand Down Expand Up @@ -368,7 +368,7 @@ func (c *KongClient) KubernetesObjectConfigurationStatus(obj client.Object) k8so
// -----------------------------------------------------------------------------

// DBMode indicates which database the Kong Gateway is using.
func (c *KongClient) DBMode() string {
func (c *KongClient) DBMode() dpconf.DBMode {
c.lock.RLock()
defer c.lock.RUnlock()
return c.dbmode
Expand All @@ -382,7 +382,7 @@ func (c *KongClient) Update(ctx context.Context) error {
defer c.lock.Unlock()

// If Kong is running in dbless mode, we can fetch and store the last good configuration.
if dataplaneutil.IsDBLessMode(c.dbmode) {
if c.dbmode.IsDBLessMode() {
// Fetch the last valid configuration from the proxy only in case there is no valid
// configuration already stored in memory. This can happen when KIC restarts and there
// already is a Kong Proxy with a valid configuration loaded.
Expand Down Expand Up @@ -478,7 +478,7 @@ func (c *KongClient) sendOutToGatewayClients(
// since only ONE gateway client is chosen to send requests and store SHA of latest configurations,
// we should propagate the SHA from the chosen client to other clients
// as well as they will pick the configuration from the shared database.
if dataplaneutil.DBBacked(c.dbmode) &&
if c.dbmode.DBBacked() &&
len(gatewayClients) > 1 {
for _, client := range gatewayClients {
client.SetLastConfigSHA([]byte(shas[0]))
Expand Down
9 changes: 4 additions & 5 deletions internal/dataplane/kong_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (

"github.com/kong/kubernetes-ingress-controller/v3/internal/adminapi"
"github.com/kong/kubernetes-ingress-controller/v3/internal/clients"
dpconf "github.com/kong/kubernetes-ingress-controller/v3/internal/dataplane/config"
"github.com/kong/kubernetes-ingress-controller/v3/internal/dataplane/configfetcher"
"github.com/kong/kubernetes-ingress-controller/v3/internal/dataplane/deckgen"
"github.com/kong/kubernetes-ingress-controller/v3/internal/dataplane/failures"
Expand All @@ -38,7 +39,6 @@ import (
"github.com/kong/kubernetes-ingress-controller/v3/internal/metrics"
"github.com/kong/kubernetes-ingress-controller/v3/internal/store"
"github.com/kong/kubernetes-ingress-controller/v3/internal/util"
dataplaneutil "github.com/kong/kubernetes-ingress-controller/v3/internal/util/dataplane"
"github.com/kong/kubernetes-ingress-controller/v3/internal/versions"
"github.com/kong/kubernetes-ingress-controller/v3/test/mocks"
)
Expand Down Expand Up @@ -144,7 +144,7 @@ var (
type mockGatewayClientsProvider struct {
gatewayClients []*adminapi.Client
konnectClient *adminapi.KonnectClient
dbMode string
dbMode dpconf.DBMode
}

func (p mockGatewayClientsProvider) KonnectClient() *adminapi.KonnectClient {
Expand All @@ -156,7 +156,7 @@ func (p mockGatewayClientsProvider) GatewayClients() []*adminapi.Client {
}

func (p mockGatewayClientsProvider) GatewayClientsToConfigure() []*adminapi.Client {
if dataplaneutil.IsDBLessMode(p.dbMode) {
if p.dbMode.IsDBLessMode() {
return p.gatewayClients
}
if len(p.gatewayClients) == 0 {
Expand Down Expand Up @@ -681,7 +681,6 @@ func setupTestKongClient(
timeout := time.Second
diagnostic := util.ConfigDumpDiagnostic{}
config := sendconfig.Config{}
dbMode := "off"

if eventRecorder == nil {
eventRecorder = mocks.NewEventRecorder()
Expand All @@ -693,7 +692,7 @@ func setupTestKongClient(
diagnostic,
config,
eventRecorder,
dbMode,
dpconf.DBModeOff,
clientsProvider,
updateStrategyResolver,
configChangeDetector,
Expand Down
6 changes: 3 additions & 3 deletions internal/dataplane/synchronizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (

"github.com/go-logr/logr"

dataplaneutil "github.com/kong/kubernetes-ingress-controller/v3/internal/util/dataplane"
dpconf "github.com/kong/kubernetes-ingress-controller/v3/internal/dataplane/config"
)

// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -42,7 +42,7 @@ type Synchronizer struct {

// dataplane client to send updates to the Kong Admin API
dataplaneClient Client
dbMode string
dbMode dpconf.DBMode

// server configuration, flow control, channels and utility attributes
stagger time.Duration
Expand Down Expand Up @@ -140,7 +140,7 @@ func (p *Synchronizer) IsReady() bool {
defer p.lock.RUnlock()
// If the proxy is has no database, it is only ready after a successful sync
// Otherwise, it has no configuration loaded
if dataplaneutil.IsDBLessMode(p.dbMode) {
if p.dbMode.IsDBLessMode() {
return p.configApplied
}
// If the proxy has a database, it is ready immediately
Expand Down
13 changes: 9 additions & 4 deletions internal/dataplane/synchronizer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"

dpconf "github.com/kong/kubernetes-ingress-controller/v3/internal/dataplane/config"
)

const testSynchronizerTick = time.Millisecond * 10
Expand All @@ -22,7 +24,7 @@ func TestSynchronizer(t *testing.T) {
}

t.Log("setting up a fake dataplane client to test the synchronizer")
c := &fakeDataplaneClient{dbmode: "postgres"}
c := &fakeDataplaneClient{dbmode: dpconf.DBModePostgres}

t.Log("configuring the dataplane synchronizer")
ctx, cancel := context.WithCancel(context.Background())
Expand Down Expand Up @@ -90,7 +92,10 @@ func TestSynchronizer(t *testing.T) {
}

func TestSynchronizer_IsReadyDoesntBlockWhenDataPlaneIsBlocked(t *testing.T) {
for _, dbMode := range []string{"off", "postgres"} {
for _, dbMode := range []dpconf.DBMode{
dpconf.DBModeOff,
dpconf.DBModePostgres,
} {
dbMode := dbMode
t.Run(fmt.Sprintf("dbmode=%s", dbMode), func(t *testing.T) {
c := &fakeDataplaneClient{dbmode: dbMode, t: t}
Expand Down Expand Up @@ -126,14 +131,14 @@ func TestSynchronizer_IsReadyDoesntBlockWhenDataPlaneIsBlocked(t *testing.T) {
// fakeDataplaneClient fakes the dataplane.Client interface so that we can
// unit test the dataplane.Synchronizer.
type fakeDataplaneClient struct {
dbmode string
dbmode dpconf.DBMode
updateCount atomic.Uint64
lock sync.RWMutex
clientCallBlockDuration time.Duration
t *testing.T
}

func (c *fakeDataplaneClient) DBMode() string {
func (c *fakeDataplaneClient) DBMode() dpconf.DBMode {
c.lock.RLock()
defer c.lock.RUnlock()
if c.clientCallBlockDuration > 0 {
Expand Down
26 changes: 4 additions & 22 deletions internal/dataplane/translator/translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/kong/kubernetes-ingress-controller/v3/internal/annotations"
dpconf "github.com/kong/kubernetes-ingress-controller/v3/internal/dataplane/config"
"github.com/kong/kubernetes-ingress-controller/v3/internal/dataplane/failures"
"github.com/kong/kubernetes-ingress-controller/v3/internal/dataplane/kongstate"
"github.com/kong/kubernetes-ingress-controller/v3/internal/gatewayapi"
Expand All @@ -34,13 +35,7 @@ import (
// Translator - Public Constants and Package Variables
// -----------------------------------------------------------------------------

const (
KindGateway = gatewayapi.Kind("Gateway")

// kongRouterFlavorExpressions is the value used in router_flavor of kong configuration
// to enable expression based router of kong.
kongRouterFlavorExpressions = "expressions"
)
const KindGateway = gatewayapi.Kind("Gateway")

// -----------------------------------------------------------------------------
// Translator - Public Types
Expand All @@ -65,31 +60,18 @@ type FeatureFlags struct {
}

func NewFeatureFlags(
logger logr.Logger,
featureGates featuregates.FeatureGates,
routerFlavor string,
routerFlavor dpconf.RouterFlavor,
updateStatusFlag bool,
) FeatureFlags {
return FeatureFlags{
ReportConfiguredKubernetesObjects: updateStatusFlag,
ExpressionRoutes: shouldEnableTranslatorExpressionRoutes(logger, routerFlavor),
ExpressionRoutes: dpconf.ShouldEnableExpressionRoutes(routerFlavor),
FillIDs: featureGates.Enabled(featuregates.FillIDsFeature),
RewriteURIs: featureGates.Enabled(featuregates.RewriteURIsFeature),
}
}

func shouldEnableTranslatorExpressionRoutes(
logger logr.Logger,
routerFlavor string,
) bool {
if routerFlavor != kongRouterFlavorExpressions {
logger.V(util.InfoLevel).Info("Gateway is running with non-expression router flavor", "flavor", routerFlavor)
return false
}
logger.V(util.InfoLevel).Info("The expression routes mode enabled")
return true
}

// LicenseGetter is an interface for getting the Kong Enterprise license.
type LicenseGetter interface {
// GetLicense returns an optional license.
Expand Down
Loading