Skip to content

Commit

Permalink
connectivity: Introduce feature requirements
Browse files Browse the repository at this point in the history
This commit introduces a new function to the connectivity test framework
to specify feature requirements for certain tests. All tests requiring
the L7 proxy are updated to use the new requirements framework to skip
those tests if the L7 proxy is not available.

Signed-off-by: Sebastian Wicki <sebastian@isovalent.com>
  • Loading branch information
gandro committed Jul 28, 2022
1 parent 2705087 commit 38605c4
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 1 deletion.
49 changes: 49 additions & 0 deletions connectivity/check/features.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,55 @@ func (s FeatureStatus) String() string {
// FeatureSet contains the status
type FeatureSet map[Feature]FeatureStatus

// MatchRequirements returns true if the FeatureSet fs satisfies all the
// requirements in reqs
func (fs FeatureSet) MatchRequirements(reqs ...FeatureRequirement) bool {
for _, req := range reqs {
status := fs[req.feature]
if req.requiresEnabled && (req.enabled != status.Enabled) {
return false
}
if req.requiresMode && (req.mode != status.Mode) {
return false
}
}

// empty requirement list matches any feature set
return len(reqs) == 0
}

// FeatureRequirement defines a test requirement. A given FeatureSet may or
// may not satisfy this requirement
type FeatureRequirement struct {
feature Feature

requiresEnabled bool
enabled bool

requiresMode bool
mode string
}

// RequireFeatureEnabled constructs a FeatureRequirement which expects the
// feature to be enabled
func RequireFeatureEnabled(feature Feature) FeatureRequirement {
return FeatureRequirement{
feature: feature,
requiresEnabled: true,
enabled: true,
}
}

// RequireFeatureMode constructs a FeatureRequirement which expects the feature
// to be in the given mode
func RequireFeatureMode(feature Feature, mode string) FeatureRequirement {
return FeatureRequirement{
feature: feature,
requiresMode: true,
mode: mode,
}
}

func parseBoolStatus(s string) bool {
switch s {
case "Enabled", "enabled", "True", "true":
Expand Down
18 changes: 17 additions & 1 deletion connectivity/check/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ type Test struct {
// True if the Test is marked as failed.
failed bool

// requirements is a list of required Cilium features which need to match
// for this test to be run
requirements []FeatureRequirement

// Scenarios registered to this test.
scenarios map[Scenario][]*Action

Expand Down Expand Up @@ -103,10 +107,15 @@ func (t *Test) skip(s Scenario) {
t.Logf("[-] Skipping Scenario [%s]", t.scenarioName(s))
}

// willRun returns false if all of the Test's Scenarios will be skipped.
// willRun returns false if all of the Test's Scenarios will be skipped, or
// if any of its FeatureRequirements does not match
func (t *Test) willRun() bool {
var sc int

if !t.Context().features.MatchRequirements(t.requirements...) {
return false
}

for s := range t.scenarios {
if !t.Context().params.testEnabled(t.scenarioName(s)) {
sc++
Expand Down Expand Up @@ -238,6 +247,13 @@ func (t *Test) WithScenarios(sl ...Scenario) *Test {
return t
}

// WithFeatureRequirements adds FeatureRequirements to Test, all of which
// must be satisfied in order for the test to be run
func (t *Test) WithFeatureRequirements(reqs ...FeatureRequirement) *Test {
t.requirements = append(t.requirements, reqs...)
return t
}

// NewAction creates a new Action. s must be the Scenario the Action is created
// for, name should be a visually-distinguishable name, src is the execution
// Pod of the action, and dst is the network target the Action will connect to.
Expand Down
4 changes: 4 additions & 0 deletions connectivity/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ func Run(ctx context.Context, ct *check.ConnectivityTest) error {

// Test L7 HTTP introspection using an ingress policy on echo pods.
ct.NewTest("echo-ingress-l7").
WithFeatureRequirements(check.RequireFeatureEnabled(check.FeatureL7Proxy)).
WithPolicy(echoIngressL7HTTPPolicyYAML). // L7 allow policy with HTTP introspection
WithScenarios(
tests.PodToPodWithEndpoints(),
Expand All @@ -215,6 +216,7 @@ func Run(ctx context.Context, ct *check.ConnectivityTest) error {

// Test L7 HTTP introspection using an egress policy on the clients.
ct.NewTest("client-egress-l7").
WithFeatureRequirements(check.RequireFeatureEnabled(check.FeatureL7Proxy)).
WithPolicy(clientEgressOnlyDNSPolicyYAML). // DNS resolution only
WithPolicy(clientEgressL7HTTPPolicyYAML). // L7 allow policy with HTTP introspection
WithScenarios(
Expand Down Expand Up @@ -242,6 +244,7 @@ func Run(ctx context.Context, ct *check.ConnectivityTest) error {

// Only allow UDP:53 to kube-dns, no DNS proxy enabled.
ct.NewTest("dns-only").WithPolicy(clientEgressOnlyDNSPolicyYAML).
WithFeatureRequirements(check.RequireFeatureEnabled(check.FeatureL7Proxy)).
WithScenarios(
tests.PodToPod(), // connects to other Pods directly, no DNS
tests.PodToWorld(), // resolves one.one.one.one
Expand All @@ -252,6 +255,7 @@ func Run(ctx context.Context, ct *check.ConnectivityTest) error {

// This policy only allows port 80 to "one.one.one.one". DNS proxy enabled.
ct.NewTest("to-fqdns").WithPolicy(clientEgressToFQDNsCiliumIOPolicyYAML).
WithFeatureRequirements(check.RequireFeatureEnabled(check.FeatureL7Proxy)).
WithScenarios(
tests.PodToWorld(),
).
Expand Down

0 comments on commit 38605c4

Please sign in to comment.