-
Notifications
You must be signed in to change notification settings - Fork 594
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(diag): expose fallback configuration diagnostics (#6159)
Expose fallback configuration generation diagnostics data via the `GET /debug/config/fallback` endpoint.
- Loading branch information
Showing
14 changed files
with
607 additions
and
153 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package fallback | ||
|
||
import ( | ||
"github.com/samber/lo" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
) | ||
|
||
// GeneratedCacheMetadata contains metadata generated during the fallback process. | ||
type GeneratedCacheMetadata struct { | ||
// BrokenObjects are objects that were reported as broken by the Kong Admin API. | ||
BrokenObjects []ObjectHash | ||
// ExcludedObjects are objects that were excluded from the fallback configuration as they were broken or either of their | ||
// dependencies was broken. | ||
ExcludedObjects []AffectedCacheObjectMetadata | ||
// BackfilledObjects are objects that were backfilled from the last valid cache state as they were broken or either of | ||
// their dependencies was broken. | ||
BackfilledObjects []AffectedCacheObjectMetadata | ||
} | ||
|
||
// GeneratedCacheMetadataCollector is a collector for cache metadata generated during the fallback process. | ||
// It's primarily used to deduplicate the metadata and make it easier to work with. | ||
type GeneratedCacheMetadataCollector struct { | ||
brokenObjects []ObjectHash | ||
excludedObjects map[ObjectHash]AffectedCacheObjectMetadata | ||
backfilledObjects map[ObjectHash]AffectedCacheObjectMetadata | ||
} | ||
|
||
// AffectedCacheObjectMetadata contains an object and a list of objects that caused it to be excluded or backfilled | ||
// during the fallback process. | ||
type AffectedCacheObjectMetadata struct { | ||
Object client.Object | ||
CausingObjects []ObjectHash | ||
} | ||
|
||
// NewGenerateCacheMetadataCollector creates a new GeneratedCacheMetadataCollector instance. | ||
func NewGenerateCacheMetadataCollector(brokenObjects ...ObjectHash) *GeneratedCacheMetadataCollector { | ||
return &GeneratedCacheMetadataCollector{ | ||
brokenObjects: brokenObjects, | ||
excludedObjects: make(map[ObjectHash]AffectedCacheObjectMetadata), | ||
backfilledObjects: make(map[ObjectHash]AffectedCacheObjectMetadata), | ||
} | ||
} | ||
|
||
// CollectExcluded collects an excluded object (an object that was excluded from the fallback configuration as it was | ||
// broken or one of its dependencies was broken). | ||
func (m *GeneratedCacheMetadataCollector) CollectExcluded(excluded client.Object, causing ObjectHash) { | ||
objHash := GetObjectHash(excluded) | ||
if existingEntry, ok := m.excludedObjects[objHash]; ok { | ||
existingEntry.CausingObjects = append(existingEntry.CausingObjects, causing) | ||
m.excludedObjects[objHash] = existingEntry | ||
} else { | ||
m.excludedObjects[objHash] = AffectedCacheObjectMetadata{Object: excluded, CausingObjects: []ObjectHash{causing}} | ||
} | ||
} | ||
|
||
// CollectBackfilled collects a backfilled object (an object that was backfilled from the last valid cache state as that or | ||
// one of its dependencies was broken). | ||
func (m *GeneratedCacheMetadataCollector) CollectBackfilled(backfilled client.Object, causing ObjectHash) { | ||
objHash := GetObjectHash(backfilled) | ||
if existingEntry, ok := m.backfilledObjects[objHash]; ok { | ||
existingEntry.CausingObjects = append(existingEntry.CausingObjects, causing) | ||
m.backfilledObjects[objHash] = existingEntry | ||
} else { | ||
m.backfilledObjects[objHash] = AffectedCacheObjectMetadata{Object: backfilled, CausingObjects: []ObjectHash{causing}} | ||
} | ||
} | ||
|
||
// Metadata generates the final cache metadata from the collected data. | ||
func (m *GeneratedCacheMetadataCollector) Metadata() GeneratedCacheMetadata { | ||
return GeneratedCacheMetadata{ | ||
BrokenObjects: m.brokenObjects, | ||
ExcludedObjects: lo.Values(m.excludedObjects), | ||
BackfilledObjects: lo.Values(m.backfilledObjects), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
package fallback_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
|
||
"github.com/kong/kubernetes-ingress-controller/v3/internal/dataplane/fallback" | ||
) | ||
|
||
func TestGeneratedCacheMetadataCollector(t *testing.T) { | ||
excluded1 := testService(t, "excluded-1") | ||
excluded2 := testService(t, "excluded-2") | ||
backfilled1 := testService(t, "backfilled-1") | ||
backfilled2 := testService(t, "backfilled-2") | ||
causing1 := testService(t, "causing-1") | ||
causing2 := testService(t, "causing-2") | ||
|
||
t.Run("only excluded", func(t *testing.T) { | ||
c := fallback.NewGenerateCacheMetadataCollector( | ||
fallback.GetObjectHash(causing1), | ||
fallback.GetObjectHash(causing2), | ||
) | ||
c.CollectExcluded(excluded1, fallback.GetObjectHash(causing1)) | ||
c.CollectExcluded(excluded2, fallback.GetObjectHash(causing1)) | ||
c.CollectExcluded(excluded2, fallback.GetObjectHash(causing2)) // Duplicate with another causing object. | ||
|
||
meta := c.Metadata() | ||
require.ElementsMatch(t, []fallback.ObjectHash{ | ||
fallback.GetObjectHash(causing1), | ||
fallback.GetObjectHash(causing2), | ||
}, | ||
meta.BrokenObjects, | ||
) | ||
require.ElementsMatch(t, []fallback.AffectedCacheObjectMetadata{ | ||
{ | ||
Object: excluded1, | ||
CausingObjects: []fallback.ObjectHash{fallback.GetObjectHash(causing1)}, | ||
}, | ||
{ | ||
Object: excluded2, | ||
CausingObjects: []fallback.ObjectHash{fallback.GetObjectHash(causing1), fallback.GetObjectHash(causing2)}, | ||
}, | ||
}, | ||
meta.ExcludedObjects, | ||
) | ||
}) | ||
|
||
t.Run("excluded and backfilled", func(t *testing.T) { | ||
c := fallback.NewGenerateCacheMetadataCollector( | ||
fallback.GetObjectHash(causing1), | ||
fallback.GetObjectHash(causing2), | ||
) | ||
c.CollectExcluded(excluded1, fallback.GetObjectHash(causing1)) | ||
c.CollectExcluded(excluded2, fallback.GetObjectHash(causing1)) | ||
c.CollectExcluded(excluded2, fallback.GetObjectHash(causing2)) // Duplicate with another causing object. | ||
|
||
c.CollectBackfilled(backfilled1, fallback.GetObjectHash(causing1)) | ||
c.CollectBackfilled(backfilled2, fallback.GetObjectHash(causing1)) | ||
c.CollectBackfilled(backfilled2, fallback.GetObjectHash(causing2)) // Duplicate with another causing object. | ||
|
||
meta := c.Metadata() | ||
require.ElementsMatch(t, []fallback.ObjectHash{ | ||
fallback.GetObjectHash(causing1), | ||
fallback.GetObjectHash(causing2), | ||
}, | ||
meta.BrokenObjects, | ||
) | ||
require.ElementsMatch(t, []fallback.AffectedCacheObjectMetadata{ | ||
{ | ||
Object: excluded1, | ||
CausingObjects: []fallback.ObjectHash{fallback.GetObjectHash(causing1)}, | ||
}, | ||
{ | ||
Object: excluded2, | ||
CausingObjects: []fallback.ObjectHash{fallback.GetObjectHash(causing1), fallback.GetObjectHash(causing2)}, | ||
}, | ||
}, | ||
meta.ExcludedObjects, | ||
) | ||
require.ElementsMatch(t, []fallback.AffectedCacheObjectMetadata{ | ||
{ | ||
Object: backfilled1, | ||
CausingObjects: []fallback.ObjectHash{fallback.GetObjectHash(causing1)}, | ||
}, | ||
{ | ||
Object: backfilled2, | ||
CausingObjects: []fallback.ObjectHash{fallback.GetObjectHash(causing1), fallback.GetObjectHash(causing2)}, | ||
}, | ||
}, | ||
meta.BackfilledObjects, | ||
) | ||
}) | ||
} |
Oops, something went wrong.