Skip to content

Commit 1084d59

Browse files
Merge pull request #958 from shajmakh/introspect-features
e2e: manager: add features introspection
2 parents cf2b5f3 + 8ff79d9 commit 1084d59

32 files changed

+603
-30
lines changed

.github/workflows/e2e-tools.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ jobs:
4343
4444
- name: Build tools
4545
run: |
46-
make build-tools binary-nrovalidate
46+
make build-tools binary-nrovalidate bin/mkginkgolabelfilter binary
4747
4848
- name: Create K8s Kind Cluster
4949
run: |

.github/workflows/support-tools.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Build support tools binaries
2+
3+
on:
4+
workflow_dispatch:
5+
6+
defaults:
7+
run:
8+
shell: bash
9+
10+
jobs:
11+
setup:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: checkout sources
15+
uses: actions/checkout@v3
16+
with:
17+
fetch-depth: 0
18+
19+
- name: setup golang
20+
uses: actions/setup-go@v2
21+
id: go
22+
with:
23+
go-version: 1.22.4
24+
25+
build:
26+
needs: [setup]
27+
runs-on: ubuntu-latest
28+
steps:
29+
- name: checkout sources
30+
uses: actions/checkout@v3
31+
with:
32+
fetch-depth: 0
33+
34+
- name: build tools' binaries
35+
run: |
36+
make bin/mkginkgolabelfilter
37+
make bin/catkubeletconfmap
38+
39+
- name: release the binaries
40+
uses: ncipollo/release-action@v1
41+
with:
42+
artifacts: bin/*
43+
tag: support-tools

Makefile

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ goversion:
386386
build-tools: goversion bin/buildhelper bin/envsubst bin/lsplatform
387387

388388
.PHONY: build-tools-all
389-
build-tools-all: goversion bin/buildhelper bin/envsubst bin/lsplatform bin/catkubeletconfmap bin/watchnrtattr
389+
build-tools-all: goversion bin/buildhelper bin/envsubst bin/lsplatform bin/catkubeletconfmap bin/watchnrtattr bin/mkginkgolabelfilter
390390

391391
bin/buildhelper:
392392
@go build -o bin/buildhelper tools/buildhelper/buildhelper.go
@@ -398,11 +398,16 @@ bin/lsplatform:
398398
@go build -o bin/lsplatform tools/lsplatform/lsplatform.go
399399

400400
bin/catkubeletconfmap:
401-
@go build -o bin/catkubeletconfmap tools/catkubeletconfmap/catkubeletconfmap.go
401+
LDFLAGS="-static"
402+
CGO_ENABLED=0 go build -o bin/catkubeletconfmap -ldflags "$$LDFLAGS" tools/catkubeletconfmap/catkubeletconfmap.go
402403

403404
bin/watchnrtattr:
404405
@go build -o bin/watchnrtattr tools/watchnrtattr/watchnrtattr.go
405406

407+
bin/mkginkgolabelfilter:
408+
LDFLAGS="-static"
409+
@go build -o bin/mkginkgolabelfilter -ldflags "$$LDFLAGS" tools/mkginkgolabelfilter/mkginkgolabelfilter.go
410+
406411
verify-generated: bundle generate
407412
@echo "Verifying that all code is committed after updating deps and formatting and generating code"
408413
hack/verify-generated.sh

doc/features/README.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
Features introspection in e2e tests
2+
======================================
3+
4+
**Goal**
5+
6+
Provide a way to identify the active features for every supported operator version.
7+
8+
**Design**
9+
10+
- Provide the possibility to group a set of tests that verify a common feature using ginkgo Label("feature:<topic>").
11+
A Topic should describe the main feature being tested or the unique effect of the test on the cluster. For instance:
12+
`feature:schedrst`: indicates that the test is expected to restart the schedular, be it a pod restart or a complete removal of the scheduler and recreation.
13+
`feature:rtetols`: indicates that the test is testing the new feature RTE tolerations, which involves specific non-default configuration on the operator CRs hence functional effects.
14+
`feature:unsched`: indicates that the test workload is anticipated to be un-schedulable for any reason for example: insufficient resources (pod is pending), TAE (failed)..
15+
`feature:wlplacement`: indicates that the test challenges the scheduler to place a workload on a node. This is a common label for most of the functional tests.
16+
- Rules for creating a new topic
17+
- A topic should point out briefly the new feature being tested or the unique effect of the test on the cluster
18+
- The topic should be lowercase
19+
- For composite topics use `_` between the words, e.g no_nrt
20+
- Should not consist of any of `&|!,()/`
21+
- Define the list of supported features for each version.
22+
- Allow the user to list the supported features by adding new flag, `-inspect-features` which if passed the numaresources-operator binary on the controller pod will list the active features for the deployed version of the operator.
23+
- For automated bugs' scenarios that their fix is not back-ported to all versions use keywords tags that briefly describes the bug's main check.
24+
25+
**List active features**
26+
27+
Once the operator is installed, perform the following on the controller manager pod:
28+
29+
```azure
30+
oc exec -it numaresources-controller-manager-95dd55c6-k6428 -n openshift-numaresources -- /bin/numaresources-operator --inspect-features
31+
```
32+
33+
Example output:
34+
```
35+
{"active":["config","nonreg","hostlevel","resacct","cache","stall","rmsched","rtetols","overhead","wlplacement","unsched","nonrt","taint","nodelabel","byres","tmpol"]}
36+
```
37+
38+
**Use case example: run tests for supported features only**
39+
40+
To build the filter label query of the supported features on a specific version, a binary called `mkginkgolabelfilter` exists in `releases/support-tools` which expects a JSON input showing the supported features from the operator controller pod as follows:
41+
42+
To use the helper tool perform the following:
43+
44+
```
45+
# curl -L -o mkginkgolabelfilter https://github.com/openshift-kni/numaresources-operator/releases/download/support-tools/mkginkgolabelfilter
46+
# chmod 755 mkginkgolabelfilter
47+
# ./mkginkgolabelfilter # This will wait to read the input which should be the output of the --inspect-features above
48+
{"active":["config","nonreg","hostlevel","resacct","cache","stall","rmsched","rtetols","overhead","wlplacement","unsched","nonrt","taint","nodelabel","byres","tmpol"]}
49+
feature: consistAny {config,nonreg,hostlevel,resacct,cache,stall,rmsched,rtetols,overhead,wlplacement,unsched,nonrt,taint,nodelabel,byres,tmpol}
50+
```
51+
52+
Then later in the podman command of running the tests use `--filter-label` with the output of the tool to run tests of supported features only.

internal/api/features/_topics.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"active": [
3+
"config",
4+
"nonreg",
5+
"hostlevel",
6+
"resacct",
7+
"cache",
8+
"stall",
9+
"schedrst",
10+
"rtetols",
11+
"overhead",
12+
"wlplacement",
13+
"unsched",
14+
"nonrt",
15+
"taint",
16+
"nodelabel",
17+
"byres",
18+
"tmpol"
19+
]
20+
}

internal/api/features/topics.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*
14+
* Copyright 2024 Red Hat, Inc.
15+
*/
16+
17+
package features
18+
19+
import (
20+
_ "embed"
21+
"encoding/json"
22+
)
23+
24+
//go:embed _topics.json
25+
var topicsData string
26+
27+
func GetTopics() TopicInfo {
28+
var tp TopicInfo
29+
_ = json.Unmarshal([]byte(topicsData), &tp)
30+
return tp
31+
}

internal/api/features/topics_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
Copyright 2024.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package features
18+
19+
import (
20+
"strings"
21+
"testing"
22+
23+
"k8s.io/utils/strings/slices"
24+
)
25+
26+
func TestGetTopics(t *testing.T) {
27+
type testcase struct {
28+
name string
29+
topicsList string
30+
isPositive bool
31+
}
32+
testcases := []testcase{
33+
{
34+
name: "with list of well known topics that every release operator must support",
35+
topicsList: "config,nonreg,hostlevel,resacct,cache,stall,schedrst,overhead,wlplacement,unsched,taint,nodelabel,byres,tmpol",
36+
isPositive: true,
37+
},
38+
{
39+
name: "with inactive topics included",
40+
topicsList: "config,nonreg,hostlevel,notfound,cache",
41+
isPositive: false,
42+
},
43+
}
44+
45+
actual := GetTopics()
46+
for _, tc := range testcases {
47+
topicsStr := strings.TrimSpace(tc.topicsList)
48+
topics := strings.Split(topicsStr, ",")
49+
tp := findMissingTopics(actual.Active, topics)
50+
51+
if len(tp) > 0 && tc.isPositive {
52+
t.Errorf("expected to include topic(s) %v but it didn't, list found: %v", tp, actual.Active)
53+
}
54+
55+
if len(tp) == 0 && !tc.isPositive {
56+
t.Errorf("active topics included unsupported topic(s) %v, list found: %v", tp, actual.Active)
57+
}
58+
}
59+
}
60+
61+
func findMissingTopics(agianstList, sublist []string) []string {
62+
missing := []string{}
63+
for _, el := range sublist {
64+
if !slices.Contains(agianstList, el) {
65+
missing = append(missing, el)
66+
}
67+
}
68+
return missing
69+
}

internal/api/features/types.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*
14+
* Copyright 2024 Red Hat, Inc.
15+
*/
16+
17+
package features
18+
19+
import (
20+
"fmt"
21+
22+
goversion "github.com/aquasecurity/go-version/pkg/version"
23+
)
24+
25+
const (
26+
Version = "v4.17.0"
27+
)
28+
29+
type Metadata struct {
30+
// semantic versioning vX.Y.Z, e.g. v1.0.0
31+
Version string `json:"version"`
32+
}
33+
34+
type TopicInfo struct {
35+
Metadata Metadata `json:"metadata"`
36+
// unsorted list of topics active (supported)
37+
Active []string `json:"active"`
38+
}
39+
40+
func NewTopicInfo() TopicInfo {
41+
return TopicInfo{
42+
Metadata: Metadata{
43+
Version: Version,
44+
},
45+
}
46+
}
47+
48+
func (tp TopicInfo) Validate() error {
49+
if tp.Metadata.Version == "" {
50+
return fmt.Errorf("metadata: missing version")
51+
}
52+
if _, err := goversion.Parse(tp.Metadata.Version); err != nil {
53+
return fmt.Errorf("metadata: malformed version: %w", err)
54+
}
55+
if len(tp.Active) == 0 {
56+
return fmt.Errorf("missing active topics")
57+
}
58+
return nil
59+
}

0 commit comments

Comments
 (0)