diff --git a/conformance/apis/v1/conformancereport.go b/conformance/apis/v1/conformancereport.go index dcea92dffc..7f4f4d5325 100644 --- a/conformance/apis/v1/conformancereport.go +++ b/conformance/apis/v1/conformancereport.go @@ -50,10 +50,6 @@ type ConformanceReport struct { // SucceededProvisionalTests is a list of the names of the provisional tests that // have been successfully run. SucceededProvisionalTests []string `json:"succeededProvisionalTests,omitempty"` - - // InferredSupportedFeatures indicates whether the supported features were - // automatically detected by the conformance suite. - InferredSupportedFeatures bool `json:"inferredSupportedFeatures"` } // Implementation provides metadata information on the downstream diff --git a/conformance/utils/suite/suite.go b/conformance/utils/suite/suite.go index f1164fa2fe..5b30598886 100644 --- a/conformance/utils/suite/suite.go +++ b/conformance/utils/suite/suite.go @@ -84,7 +84,7 @@ type ConformanceTestSuite struct { // If SupportedFeatures are automatically determined from GWC Status. // This will be required to report in future iterations as the passing // will be determined based on this. - isInferredSupportedFeatures bool + supportedFeaturesSource supportedFeaturesSource // mode is the operating mode of the implementation. // The default value for it is "default". @@ -188,24 +188,37 @@ const ( undefinedKeyword = "UNDEFINED" ) +// SupportedFeaturesSource represents the source from which supported features are derived. +// It is used to distinguish between them being inferred from GWC Status or manually +// supplied for the conformance report. +type supportedFeaturesSource string + +const ( + supportedFeaturesSourceManual supportedFeaturesSource = "Manual" + supportedFeaturesSourceInferred supportedFeaturesSource = "Inferred" +) + // NewConformanceTestSuite is a helper to use for creating a new ConformanceTestSuite. func NewConformanceTestSuite(options ConformanceOptions) (*ConformanceTestSuite, error) { supportedFeatures := options.SupportedFeatures.Difference(options.ExemptFeatures) - isInferred := false - switch { - case options.EnableAllSupportedFeatures: + source := supportedFeaturesSourceManual + if options.EnableAllSupportedFeatures { supportedFeatures = features.SetsToNamesSet(features.AllFeatures) - case shouldInferSupportedFeatures(&options): + } else if shouldInferSupportedFeatures(&options) { var err error supportedFeatures, err = fetchSupportedFeatures(options.Client, options.GatewayClassName) if err != nil { - return nil, fmt.Errorf("Cannot infer supported features: %w", err) + return nil, fmt.Errorf("cannot infer supported features: %w", err) + } + + if hasMeshFeatures(supportedFeatures) { + return nil, fmt.Errorf("mesh features should not be populated in GatewayClass") } - isInferred = true + source = supportedFeaturesSourceInferred } // If features were not inferred from Status, it's a GWC issue. - if isInferred && supportedFeatures.Len() == 0 { + if source == supportedFeaturesSourceInferred && supportedFeatures.Len() == 0 { return nil, fmt.Errorf("no supported features were determined for test suite") } @@ -273,7 +286,7 @@ func NewConformanceTestSuite(options ConformanceOptions) (*ConformanceTestSuite, mode: mode, apiVersion: apiVersion, apiChannel: apiChannel, - isInferredSupportedFeatures: isInferred, + supportedFeaturesSource: source, Hook: options.Hook, } @@ -394,10 +407,6 @@ func (suite *ConformanceTestSuite) Setup(t *testing.T, tests []ConformanceTest) } } -func (suite *ConformanceTestSuite) IsInferredSupportedFeatures() bool { - return suite.isInferredSupportedFeatures -} - func (suite *ConformanceTestSuite) setClientsetForTest(test ConformanceTest) error { featureNames := []string{} for _, v := range test.Features { @@ -552,7 +561,6 @@ func (suite *ConformanceTestSuite) Report() (*confv1.ConformanceReport, error) { GatewayAPIChannel: suite.apiChannel, ProfileReports: profileReports.list(), SucceededProvisionalTests: succeededProvisionalTests, - InferredSupportedFeatures: suite.IsInferredSupportedFeatures(), }, nil } @@ -610,8 +618,6 @@ func shouldInferSupportedFeatures(opts *ConformanceOptions) bool { return !opts.EnableAllSupportedFeatures && opts.SupportedFeatures.Len() == 0 && opts.ExemptFeatures.Len() == 0 && - opts.ConformanceProfiles.Len() == 0 && - len(opts.SkipTests) == 0 && opts.RunTest == "" } @@ -645,3 +651,7 @@ func getAPIVersionAndChannel(crds []apiextensionsv1.CustomResourceDefinition) (v return version, channel, nil } + +func hasMeshFeatures(f FeaturesSet) bool { + return f.HasAny(features.SetsToNamesSet(features.MeshCoreFeatures, features.MeshExtendedFeatures).UnsortedList()...) +} diff --git a/conformance/utils/suite/suite_test.go b/conformance/utils/suite/suite_test.go index ccb259adb0..311da616a2 100644 --- a/conformance/utils/suite/suite_test.go +++ b/conformance/utils/suite/suite_test.go @@ -280,7 +280,6 @@ func TestSuiteReport(t *testing.T) { coreProvisionalTest.ShortName, extendedProvisionalTest.ShortName, }, - InferredSupportedFeatures: true, }, }, { @@ -390,7 +389,6 @@ func TestSuiteReport(t *testing.T) { }, }, }, - InferredSupportedFeatures: true, }, }, } @@ -434,33 +432,37 @@ func TestInferSupportedFeatures(t *testing.T) { exemptFeatures FeaturesSet ConformanceProfile sets.Set[ConformanceProfileName] expectedFeatures FeaturesSet - expectedIsInferred bool + expectedSource supportedFeaturesSource }{ { - name: "properly infer supported features", - expectedFeatures: namesToFeatureSet(statusFeatureNames), - expectedIsInferred: true, + name: "properly infer supported features", + expectedFeatures: namesToFeatureSet(statusFeatureNames), + expectedSource: supportedFeaturesSourceInferred, }, { name: "no features", supportedFeatures: sets.New[features.FeatureName]("Gateway"), expectedFeatures: sets.New[features.FeatureName]("Gateway"), + expectedSource: supportedFeaturesSourceManual, }, { name: "remove exempt features", supportedFeatures: sets.New[features.FeatureName]("Gateway", "HTTPRoute"), exemptFeatures: sets.New[features.FeatureName]("HTTPRoute"), expectedFeatures: sets.New[features.FeatureName]("Gateway"), + expectedSource: supportedFeaturesSourceManual, }, { name: "allow all features", allowAllFeatures: true, expectedFeatures: features.SetsToNamesSet(features.AllFeatures), + expectedSource: supportedFeaturesSourceManual, }, { name: "supports conformance profile - core", ConformanceProfile: sets.New(GatewayHTTPConformanceProfileName), - expectedFeatures: namesToFeatureSet([]string{"Gateway", "HTTPRoute", "ReferenceGrant"}), + expectedFeatures: namesToFeatureSet(statusFeatureNames), + expectedSource: supportedFeaturesSourceInferred, }, } @@ -512,8 +514,8 @@ func TestInferSupportedFeatures(t *testing.T) { t.Fatalf("error initializing conformance suite: %v", err) } - if cSuite.IsInferredSupportedFeatures() != tc.expectedIsInferred { - t.Errorf("InferredSupportedFeatures mismatch: got %v, want %v", cSuite.IsInferredSupportedFeatures(), tc.expectedIsInferred) + if cSuite.supportedFeaturesSource != tc.expectedSource { + t.Errorf("InferredSupportedFeatures mismatch: got %v, want %v", cSuite.supportedFeaturesSource, tc.expectedSource) } if equal := cSuite.SupportedFeatures.Equal(tc.expectedFeatures); !equal { @@ -523,6 +525,55 @@ func TestInferSupportedFeatures(t *testing.T) { } } +func TestGWCPublishedMeshFeatures(t *testing.T) { + gwcName := "ochopintre" + gwc := &gatewayv1.GatewayClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: gwcName, + }, + Spec: gatewayv1.GatewayClassSpec{ + ControllerName: "example.com/gateway-controller", + }, + Status: gatewayv1.GatewayClassStatus{ + Conditions: []metav1.Condition{ + { + Type: string(gatewayv1.GatewayConditionAccepted), + Status: metav1.ConditionTrue, + Reason: "Accepted", + Message: "GatewayClass is accepted and ready for use", + }, + }, + SupportedFeatures: featureNamesToSet([]string{ + string(features.SupportGateway), + string(features.SupportGatewayStaticAddresses), + string(features.SupportMeshClusterIPMatching), + string(features.SupportMeshConsumerRoute), + }), + }, + } + scheme := runtime.NewScheme() + scheme.AddKnownTypes(gatewayv1.SchemeGroupVersion, &gatewayv1.GatewayClass{}) + fakeClient := fake.NewClientBuilder(). + WithScheme(scheme). + WithObjects(gwc). + WithLists(&apiextensionsv1.CustomResourceDefinitionList{}). + Build() + + gatewayv1.Install(fakeClient.Scheme()) + apiextensionsv1.AddToScheme(fakeClient.Scheme()) + + options := ConformanceOptions{ + AllowCRDsMismatch: true, + GatewayClassName: gwcName, + Client: fakeClient, + } + + _, err := NewConformanceTestSuite(options) + if err == nil { + t.Fatalf("expected an error but got nil") + } +} + func featureNamesToSet(set []string) []gatewayv1.SupportedFeature { var features []gatewayv1.SupportedFeature for _, feature := range set {