├── internal ├── cli │ └── cli_test.go ├── log │ ├── log_test.go │ ├── custom_handler_test.go │ ├── multi_handler_test.go │ └── multi_handler.go ├── results │ ├── archiver_test.go │ ├── html_test.go │ ├── rhconnect_test.go │ ├── html │ │ ├── results.html │ │ └── README.md │ ├── doc.go │ ├── doc_test.go │ └── html.go ├── datautil │ ├── data_util.go │ └── data_util_test.go ├── crclient │ └── crclient_test.go └── clientsholder │ ├── command_test.go │ ├── clientsholder_test.go │ └── ocpclient_test.go ├── .checkmake ├── pkg ├── certsuite │ └── certsuite_test.go ├── checksdb │ ├── checksdb_test.go │ └── checksgroup_test.go ├── collector │ └── collector_test.go ├── autodiscover │ ├── autodiscover_nads_test.go │ ├── autodiscover_scales_test.go │ ├── constants_test.go │ ├── autodiscover_debug.go │ ├── autodiscover_debug_test.go │ ├── autodiscover_service_accounts_test.go │ ├── autodiscover_clusteroperators.go │ ├── autodiscover_nads.go │ ├── constants.go │ ├── autodiscover_resources.go │ ├── autodiscover_networkpolicies.go │ ├── autodiscover_sriov_test.go │ ├── autodiscover_service_accounts.go │ ├── autodiscover_pdbs.go │ ├── autodiscover_services.go │ ├── autodiscover_events.go │ ├── autodiscover_clusteroperators_test.go │ ├── autodiscover_networkpolicies_test.go │ ├── autodiscover_pv.go │ ├── autodiscover_resources_test.go │ ├── autodiscover_events_test.go │ ├── autodiscover_pdbs_test.go │ └── autodiscover_services_accounts_test.go ├── postmortem │ ├── postmortem_test.go │ └── postmortem.go ├── configuration │ ├── utils_test.go │ ├── configuration_test.go │ ├── testdata │ │ └── tnf_test_config.yml │ ├── doc.go │ ├── doc_test.go │ ├── config_test.go │ └── utils.go ├── junit │ ├── doc.go │ └── doc_test.go ├── provider │ ├── doc.go │ ├── doc_test.go │ ├── scale_object.go │ ├── events.go │ ├── events_test.go │ ├── statefulsets.go │ ├── scale_object_test.go │ ├── nodes_test.go │ ├── deployments.go │ └── catalogsources_test.go ├── versions │ └── versions.go ├── arrayhelper │ └── arrayhelper.go └── labels │ └── labels.go ├── webserver ├── webserver_test.go ├── logs.js ├── toast.js └── submit.js ├── tests ├── identifiers │ ├── doclinks_test.go │ ├── exceptions_test.go │ ├── remediation_test.go │ ├── doc.go │ ├── doc_test.go │ └── identifiers_test.go ├── platform │ ├── operatingsystem │ │ ├── testdata │ │ │ └── versionMapTest.txt │ │ └── operatingsystem.go │ ├── clusteroperator │ │ ├── clusteroperator.go │ │ └── clusteroperator_test.go │ ├── suite_test.go │ ├── bootparams │ │ └── bootparams_test.go │ ├── doc.go │ └── doc_test.go ├── operator │ ├── openapi │ │ ├── openapi.go │ │ └── openapi_test.go │ ├── suite_test.go │ ├── doc.go │ ├── doc_test.go │ ├── catalogsource │ │ ├── catalogsource.go │ │ └── catalogsource_test.go │ └── access │ │ ├── access.go │ │ └── access_test.go ├── common │ ├── env_test.go │ ├── constant_test.go │ ├── doc.go │ ├── doc_test.go │ ├── constant.go │ └── env.go ├── networking │ ├── suite_test.go │ ├── doc.go │ ├── doc_test.go │ └── netutil │ │ └── netutil_test.go ├── performance │ └── suite_test.go ├── lifecycle │ ├── scaling │ │ ├── statefulset_scaling_test.go │ │ ├── crd_scaling_test.go │ │ └── scaling_helper.go │ ├── doc.go │ ├── doc_test.go │ ├── volumes │ │ └── volumes.go │ └── ownerreference │ │ ├── ownerreference.go │ │ └── ownerreference_test.go ├── doc.go ├── doc_test.go ├── accesscontrol │ ├── doc.go │ ├── doc_test.go │ ├── namespace │ │ └── namespace_test.go │ └── pidshelper.go ├── observability │ ├── doc.go │ └── doc_test.go ├── certification │ ├── doc.go │ ├── doc_test.go │ └── suite_test.go └── manageability │ └── suite_test.go ├── cmd └── certsuite │ ├── generate │ ├── catalog │ │ └── testdata │ │ │ └── testFile1.txt │ ├── feedback │ │ └── feedback_test.go │ └── generate.go │ ├── claim │ ├── compare │ │ ├── testdata │ │ │ ├── invalid.json │ │ │ └── diff2_same_claims.txt │ │ ├── versions │ │ │ └── versions.go │ │ ├── configurations │ │ │ └── configurations.go │ │ └── nodes │ │ │ └── nodes.go │ ├── claim.go │ └── show │ │ ├── show.go │ │ ├── failures │ │ ├── types_test.go │ │ └── types.go │ │ └── csv │ │ └── cnf-type.json │ ├── upload │ ├── upload.go │ └── results_spreadsheet │ │ ├── const.go │ │ └── drive_utils.go │ ├── check │ └── check.go │ ├── version │ └── version.go │ ├── pkg │ └── claim │ │ └── claim_test.go │ └── main.go ├── script ├── get-claim-version.sh ├── get-git-release.sh ├── get-git-previous-release.sh ├── create-missing-test-files.sh ├── create-version-files.sh └── exec-container.sh ├── version.json ├── .github ├── actions │ ├── documentation │ │ ├── entrypoint.sh │ │ ├── action.yml │ │ └── Dockerfile │ ├── install-yaml-dep │ │ └── action.yml │ ├── free-disk-space │ │ └── action.yml │ ├── setup │ │ └── action.yml │ ├── setup-docker-storage │ │ └── action.yml │ ├── setup-partner-cluster │ │ └── action.yml │ └── slack-webhook-sender │ │ └── action.yml └── workflows │ ├── do-not-merge.yaml │ ├── doc-publish.yml │ ├── merge.yaml │ ├── upload-release-assets.yaml │ ├── preflight.yml │ └── update-rhcos-mapping.yml ├── docs ├── assets │ └── images │ │ ├── htmlpage.png │ │ ├── tests-flow-charts │ │ ├── lifecycle-crd-scaling.png │ │ └── lifecycle-deployment-scaling.png │ │ └── overview.drawio ├── exception.md ├── reference.md ├── data-collection.md ├── workload-developers.md ├── cluster-deploy │ └── kustomization.yaml ├── developers.md ├── runtime-env.md ├── test-spec.md └── index.md ├── _typos.toml ├── .yamllint.yml ├── .gitignore ├── config └── certsuite_config.yml └── mkdocs.yml /internal/cli/cli_test.go: -------------------------------------------------------------------------------- 1 | package cli 2 | -------------------------------------------------------------------------------- /internal/log/log_test.go: -------------------------------------------------------------------------------- 1 | package log 2 | -------------------------------------------------------------------------------- /.checkmake: -------------------------------------------------------------------------------- 1 | [maxbodylength] 2 | disabled = true 3 | -------------------------------------------------------------------------------- /internal/log/custom_handler_test.go: -------------------------------------------------------------------------------- 1 | package log 2 | -------------------------------------------------------------------------------- /internal/log/multi_handler_test.go: -------------------------------------------------------------------------------- 1 | package log 2 | -------------------------------------------------------------------------------- /internal/results/archiver_test.go: -------------------------------------------------------------------------------- 1 | package results 2 | -------------------------------------------------------------------------------- /internal/results/html_test.go: -------------------------------------------------------------------------------- 1 | package results 2 | -------------------------------------------------------------------------------- /pkg/certsuite/certsuite_test.go: -------------------------------------------------------------------------------- 1 | package certsuite 2 | -------------------------------------------------------------------------------- /pkg/checksdb/checksdb_test.go: -------------------------------------------------------------------------------- 1 | package checksdb 2 | -------------------------------------------------------------------------------- /pkg/checksdb/checksgroup_test.go: -------------------------------------------------------------------------------- 1 | package checksdb 2 | -------------------------------------------------------------------------------- /pkg/collector/collector_test.go: -------------------------------------------------------------------------------- 1 | package collector 2 | -------------------------------------------------------------------------------- /webserver/webserver_test.go: -------------------------------------------------------------------------------- 1 | package webserver 2 | -------------------------------------------------------------------------------- /internal/results/rhconnect_test.go: -------------------------------------------------------------------------------- 1 | package results 2 | -------------------------------------------------------------------------------- /tests/identifiers/doclinks_test.go: -------------------------------------------------------------------------------- 1 | package identifiers 2 | -------------------------------------------------------------------------------- /pkg/autodiscover/autodiscover_nads_test.go: -------------------------------------------------------------------------------- 1 | package autodiscover 2 | -------------------------------------------------------------------------------- /cmd/certsuite/generate/catalog/testdata/testFile1.txt: -------------------------------------------------------------------------------- 1 | testing file 2 | -------------------------------------------------------------------------------- /cmd/certsuite/generate/feedback/feedback_test.go: -------------------------------------------------------------------------------- 1 | package feedback 2 | -------------------------------------------------------------------------------- /pkg/autodiscover/autodiscover_scales_test.go: -------------------------------------------------------------------------------- 1 | package autodiscover 2 | -------------------------------------------------------------------------------- /cmd/certsuite/claim/compare/testdata/invalid.json: -------------------------------------------------------------------------------- 1 | Text content, not unmarshalable as json. -------------------------------------------------------------------------------- /script/get-claim-version.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #set -x 3 | 4 | jq .claimFormat Moved Permanently. 2 | 3 | -------------------------------------------------------------------------------- /docs/assets/images/htmlpage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhat-best-practices-for-k8s/certsuite/HEAD/docs/assets/images/htmlpage.png -------------------------------------------------------------------------------- /script/get-git-release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #set -x 3 | 4 | GIT_RELEASE=$(comm -12 all-releases.txt release-tag.txt) 5 | echo "$GIT_RELEASE" 6 | -------------------------------------------------------------------------------- /internal/results/html/README.md: -------------------------------------------------------------------------------- 1 | # HTML parser page 2 | 3 | The HTML parser page (results.html) will be copied here when building 4 | the CNF test executable 5 | -------------------------------------------------------------------------------- /tests/platform/operatingsystem/testdata/versionMapTest.txt: -------------------------------------------------------------------------------- 1 | 4.9.21 / 49.84.202202081504-0 2 | 4.9.25 / 49.84.202203112054-0 3 | 4.10.14 / 410.84.202205031645-0 4 | -------------------------------------------------------------------------------- /script/get-git-previous-release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #set -x 3 | 4 | GIT_PREVIOUS_RELEASE=$(comm -12 all-releases.txt latest-release-tag.txt) 5 | echo "$GIT_PREVIOUS_RELEASE" 6 | -------------------------------------------------------------------------------- /docs/assets/images/tests-flow-charts/lifecycle-crd-scaling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhat-best-practices-for-k8s/certsuite/HEAD/docs/assets/images/tests-flow-charts/lifecycle-crd-scaling.png -------------------------------------------------------------------------------- /.github/actions/documentation/action.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: 'Deploy to GitHub Pages' 3 | description: 'Publish Markdown docs as GitHub Pages static site' 4 | runs: 5 | using: 'docker' 6 | image: 'Dockerfile' 7 | -------------------------------------------------------------------------------- /docs/assets/images/tests-flow-charts/lifecycle-deployment-scaling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhat-best-practices-for-k8s/certsuite/HEAD/docs/assets/images/tests-flow-charts/lifecycle-deployment-scaling.png -------------------------------------------------------------------------------- /_typos.toml: -------------------------------------------------------------------------------- 1 | [default.extend-words] 2 | iif = "iif" 3 | ono = "ono" 4 | 5 | [files] 6 | extend-exclude = ["depends-on.json", "go.mod", "results.html", "cmd/certsuite/claim/compare/testdata", "docs/assets/images/*.svg", "*.js"] 7 | -------------------------------------------------------------------------------- /.yamllint.yml: -------------------------------------------------------------------------------- 1 | extends: default 2 | rules: 3 | line-length: 4 | max: 180 5 | level: warning 6 | trailing-spaces: 7 | level: warning 8 | brackets: 9 | level: warning 10 | empty-lines: 11 | level: warning 12 | no_warnings: true 13 | -------------------------------------------------------------------------------- /internal/datautil/data_util.go: -------------------------------------------------------------------------------- 1 | package datautil 2 | 3 | func IsMapSubset[K, V comparable](m, s map[K]V) bool { 4 | if len(s) > len(m) { 5 | return false 6 | } 7 | for ks, vs := range s { 8 | if vm, found := m[ks]; !found || vm != vs { 9 | return false 10 | } 11 | } 12 | return true 13 | } 14 | -------------------------------------------------------------------------------- /docs/exception.md: -------------------------------------------------------------------------------- 1 | 2 | # Exception Process 3 | 4 | There may exist some test cases which needs to fail always. The exception raised by the failed tests is published to Red Hat website for that partner. 5 | 6 | [CATALOG](https://github.com/redhat-best-practices-for-k8s/certsuite/blob/main/CATALOG.md) provides the details of such exception. 7 | -------------------------------------------------------------------------------- /script/create-missing-test-files.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | for folder in certsuite internal pkg; do 3 | echo "./$folder" 4 | find ./$folder -name "*.go" | grep -v "_test.go" | grep -v "_moq.go" | sed 's/.go//g' | xargs -I{} sh -c \ 5 | " 6 | echo {} 7 | if ! test -f '{}_test.go'; then 8 | sed '/^package/q' {}.go >{}_test.go 9 | fi 10 | " 11 | done 12 | rm -f {}_test.go 13 | -------------------------------------------------------------------------------- /docs/reference.md: -------------------------------------------------------------------------------- 1 | # Helpful Links 2 | 3 | - [Contribution Guidelines](https://github.com/redhat-best-practices-for-k8s/certsuite/blob/main/CONTRIBUTING.md) 4 | - [CATALOG](https://github.com/redhat-best-practices-for-k8s/certsuite/blob/main/CATALOG.md) 5 | - [Best Practices Document v1.3](https://connect.redhat.com/sites/default/files/2022-05/Cloud%20Native%20Network%20Function%20Requirements%201-3.pdf) 6 | -------------------------------------------------------------------------------- /webserver/logs.js: -------------------------------------------------------------------------------- 1 | import '@rhds/elements/rh-code-block/rh-code-block.js'; 2 | 3 | const socket = new WebSocket('ws://localhost:8084/logstream'); 4 | const code = document 5 | .getElementById('logs') 6 | .querySelector('rh-code-block'); 7 | code.textContent = ''; 8 | // Handle incoming log messages 9 | socket.addEventListener('message', function (event) { 10 | code.innerHTML += event.data + '\n'; 11 | }); -------------------------------------------------------------------------------- /script/create-version-files.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #set -x 3 | 4 | GIT_COMMIT=$(git rev-list -1 HEAD) 5 | 6 | curl -s https://api.github.com/repos/redhat-best-practices-for-k8s/certsuite/releases | jq -r ".[].tag_name" | sort >all-releases.txt 7 | git tag --points-at HEAD | sort >release-tag.txt 8 | git tag --no-contains "${GIT_COMMIT}" | tail -n1 | sort >latest-release-tag.txt 9 | 10 | echo "$GIT_COMMIT" 11 | -------------------------------------------------------------------------------- /.github/actions/install-yaml-dep/action.yml: -------------------------------------------------------------------------------- 1 | name: install-yaml-dep 2 | description: 'Install a yaml dependency.' 3 | 4 | runs: 5 | using: 'composite' 6 | steps: 7 | - name: Install yaml dependency 8 | shell: bash 9 | run: | 10 | python3 -m venv .venv 11 | source .venv/bin/activate 12 | python3 -m pip install --require-hashes -r .github/workflows/frozen-requirements-pre-main.txt 13 | -------------------------------------------------------------------------------- /.github/actions/documentation/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM registry.access.redhat.com/ubi9/python-39:9.7@sha256:8b817c728990c39e8e9a40a5b9ec0fc1ed78656b8cf052b1c06a88373ad1bde8 2 | 3 | # Pin versions in pip. 4 | # hadolint ignore=DL3013 5 | COPY frozen-requirements.txt frozen-requirements.txt 6 | RUN pip install --no-cache-dir --require-hashes -r frozen-requirements.txt 7 | 8 | COPY entrypoint.sh /entrypoint.sh 9 | 10 | ENTRYPOINT ["/entrypoint.sh"] 11 | -------------------------------------------------------------------------------- /cmd/certsuite/upload/upload.go: -------------------------------------------------------------------------------- 1 | package upload 2 | 3 | import ( 4 | resultsspreadsheet "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/upload/results_spreadsheet" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | var ( 9 | upload = &cobra.Command{ 10 | Use: "upload", 11 | Short: "upload tool for various test suite assets", 12 | } 13 | ) 14 | 15 | func NewCommand() *cobra.Command { 16 | upload.AddCommand(resultsspreadsheet.NewCommand()) 17 | 18 | return upload 19 | } 20 | -------------------------------------------------------------------------------- /.github/actions/free-disk-space/action.yml: -------------------------------------------------------------------------------- 1 | name: 'Free Disk Space' 2 | description: 'Frees up disk space on Ubuntu runners by removing unnecessary packages and files' 3 | runs: 4 | using: "composite" 5 | steps: 6 | - name: Free Disk Space (Ubuntu) 7 | uses: jlumbroso/free-disk-space@main 8 | with: 9 | tool-cache: false 10 | large-packages: true 11 | android: true 12 | dotnet: true 13 | haskell: true 14 | docker-images: true 15 | swap-storage: false 16 | 17 | -------------------------------------------------------------------------------- /cmd/certsuite/claim/claim.go: -------------------------------------------------------------------------------- 1 | package claim 2 | 3 | import ( 4 | "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/claim/compare" 5 | "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/claim/show" 6 | "github.com/spf13/cobra" 7 | ) 8 | 9 | var ( 10 | claimCommand = &cobra.Command{ 11 | Use: "claim", 12 | Short: "Help tools for working with claim files.", 13 | } 14 | ) 15 | 16 | func NewCommand() *cobra.Command { 17 | claimCommand.AddCommand(compare.NewCommand()) 18 | claimCommand.AddCommand(show.NewCommand()) 19 | 20 | return claimCommand 21 | } 22 | -------------------------------------------------------------------------------- /cmd/certsuite/claim/show/show.go: -------------------------------------------------------------------------------- 1 | package show 2 | 3 | import ( 4 | "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/claim/show/csv" 5 | "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/claim/show/failures" 6 | "github.com/spf13/cobra" 7 | ) 8 | 9 | var ( 10 | showCommand = &cobra.Command{ 11 | Use: "show", 12 | Short: "Shows information from a claim file.", 13 | } 14 | ) 15 | 16 | func NewCommand() *cobra.Command { 17 | showCommand.AddCommand(failures.NewCommand()) 18 | showCommand.AddCommand(csv.NewCommand()) 19 | return showCommand 20 | } 21 | -------------------------------------------------------------------------------- /.github/workflows/do-not-merge.yaml: -------------------------------------------------------------------------------- 1 | name: Do Not Merge 2 | 3 | on: 4 | pull_request: 5 | types: [synchronize, opened, reopened, labeled, unlabeled] 6 | 7 | permissions: 8 | contents: read 9 | 10 | jobs: 11 | do-not-merge: 12 | if: ${{ contains(github.event.*.labels.*.name, 'do not merge') }} 13 | name: Prevent Merging 14 | runs-on: ubuntu-24.04 15 | steps: 16 | - name: Check for label 17 | run: | 18 | echo "Pull request is labeled as 'do not merge'" 19 | echo "This workflow fails so that the pull request cannot be merged" 20 | exit 1 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | catalog.json 3 | claim.json 4 | certsuite/certsuite.log 5 | .idea 6 | vendor 7 | *.test 8 | redhat-best-practices-for-k8s_junit.xml 9 | cover.out 10 | cover.out.tmp 11 | certsuite/certsuite-tests_junit.xml 12 | certsuite_junit.xml 13 | certsuitetests-junit.xml 14 | setup_junit.xml 15 | validation_junit.xml 16 | .vscode 17 | jsontest-cli 18 | test-out.json 19 | certsuite/results.html 20 | redhat-best-practices-for-k8s 21 | certsuite/claimjson.js 22 | 23 | temp/ 24 | /certsuite 25 | /all-releases.txt 26 | /latest-release-tag.txt 27 | /release-tag.txt 28 | 29 | credentials.json 30 | token.json -------------------------------------------------------------------------------- /cmd/certsuite/check/check.go: -------------------------------------------------------------------------------- 1 | package check 2 | 3 | import ( 4 | imagecert "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/check/image_cert_status" 5 | "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/check/results" 6 | "github.com/spf13/cobra" 7 | ) 8 | 9 | var ( 10 | checkCmd = &cobra.Command{ 11 | Use: "check", 12 | Short: "check the status of certsuite resources or artifacts.", 13 | } 14 | ) 15 | 16 | func NewCommand() *cobra.Command { 17 | checkCmd.AddCommand(imagecert.NewCommand()) 18 | checkCmd.AddCommand(results.NewCommand()) 19 | 20 | return checkCmd 21 | } 22 | -------------------------------------------------------------------------------- /script/exec-container.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # proof of concept bash script to execute any commands in running pods 3 | set -x 4 | NAMESPACE=$1 5 | POD_NAME=$2 6 | COMMAND=$3 7 | NODE_NAME=$(oc get pods -n "$NAMESPACE" "$POD_NAME" --no-headers=true -ocustom-columns=node:.spec.nodeName) 8 | CONTAINER_ID=$(oc get pods -ojsonpath=\{.status.containerStatuses[0].containerID\} -n "$NAMESPACE" "$POD_NAME" | awk -F "//" '{print $2}') 9 | CONTAINER_PID=$(oc debug node/"$NODE_NAME" -- chroot /host crictl inspect --output go-template --template '{{.info.pid}}' "$CONTAINER_ID" 2>/dev/null) 10 | oc debug node/"$NODE_NAME" -- nsenter nsenter -t "$CONTAINER_PID" -n "$COMMAND" 11 | -------------------------------------------------------------------------------- /tests/operator/openapi/openapi.go: -------------------------------------------------------------------------------- 1 | package openapi 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/redhat-best-practices-for-k8s/certsuite/pkg/testhelper" 7 | apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 8 | ) 9 | 10 | func IsCRDDefinedWithOpenAPI3Schema(crd *apiextv1.CustomResourceDefinition) bool { 11 | for _, version := range crd.Spec.Versions { 12 | crdSchema := version.Schema.String() 13 | 14 | containsOpenAPIV3SchemaSubstr := strings.Contains(strings.ToLower(crdSchema), 15 | strings.ToLower(testhelper.OpenAPIV3Schema)) 16 | 17 | if containsOpenAPIV3SchemaSubstr { 18 | return true 19 | } 20 | } 21 | 22 | return false 23 | } 24 | -------------------------------------------------------------------------------- /tests/platform/clusteroperator/clusteroperator.go: -------------------------------------------------------------------------------- 1 | package clusteroperator 2 | 3 | import ( 4 | configv1 "github.com/openshift/api/config/v1" 5 | "github.com/redhat-best-practices-for-k8s/certsuite/internal/log" 6 | ) 7 | 8 | func IsClusterOperatorAvailable(co *configv1.ClusterOperator) bool { 9 | // Loop through the conditions, looking for the 'Available' state. 10 | for _, condition := range co.Status.Conditions { 11 | if condition.Type == configv1.OperatorAvailable { 12 | log.Info("ClusterOperator %q is in an 'Available' state", co.Name) 13 | return true 14 | } 15 | } 16 | 17 | log.Info("ClusterOperator %q is not in an 'Available' state", co.Name) 18 | return false 19 | } 20 | -------------------------------------------------------------------------------- /cmd/certsuite/version/version.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/redhat-best-practices-for-k8s/certsuite/pkg/versions" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | var ( 11 | versionCmd = &cobra.Command{ 12 | Use: "version", 13 | Short: "Show the Red Hat Best Practices Test Suite for Kubernetes version", 14 | RunE: showVersion, 15 | } 16 | ) 17 | 18 | func showVersion(cmd *cobra.Command, _ []string) error { 19 | fmt.Printf("Certsuite version: %s\n", versions.GitVersion()) 20 | fmt.Printf("Claim file version: %s\n", versions.ClaimFormatVersion) 21 | 22 | return nil 23 | } 24 | 25 | func NewCommand() *cobra.Command { 26 | return versionCmd 27 | } 28 | -------------------------------------------------------------------------------- /docs/data-collection.md: -------------------------------------------------------------------------------- 1 | # Share Test Suite Results with Red Hat 2 | 3 | Your test suite results can be collected and stored in our 4 | [Collector](https://github.com/redhat-best-practices-for-k8s/collector) database. 5 | 6 | ## What information is shared 7 | 8 | * Only partner name and pass/fail/skip status per test case is stored 9 | * Protected by password, partners can access only the data they have submitted. 10 | Red Hat team can access data from all partners. 11 | 12 | ## Why should I store my data in the Collector? 13 | 14 | * Keep track of your test suite results over time. 15 | * Contribute to our statistics and analysis, 16 | to improve Red Hat best practices test suite for Kubernetes. 17 | -------------------------------------------------------------------------------- /.github/workflows/doc-publish.yml: -------------------------------------------------------------------------------- 1 | # documentation publish 2 | --- 3 | name: doc-publish 4 | on: 5 | push: 6 | branches: 7 | - master 8 | - main 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | deploy: 14 | runs-on: ubuntu-24.04 15 | permissions: 16 | contents: write 17 | steps: 18 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 19 | - name: generate site 20 | uses: ./.github/actions/documentation 21 | 22 | - name: Deploy 23 | uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0 24 | with: 25 | github_token: ${{ secrets.GITHUB_TOKEN }} 26 | publish_dir: ./site 27 | -------------------------------------------------------------------------------- /.github/actions/setup/action.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: initial-setup-resources 3 | description: A shared action that removes a lot of copied 4 | tasks from steps in our CI 5 | 6 | runs: 7 | using: 'composite' 8 | steps: 9 | - name: Write temporary docker file 10 | run: | 11 | mkdir -p $GITHUB_WORKSPACE/.docker 12 | touch ${PFLT_DOCKERCONFIG} 13 | echo '{ "auths": {} }' >> ${PFLT_DOCKERCONFIG} 14 | shell: bash 15 | 16 | - name: Set up Go 17 | uses: actions/setup-go@v6 18 | with: 19 | go-version-file: go.mod 20 | cache: false 21 | 22 | - name: Disable default go problem matcher 23 | run: echo "::remove-matcher owner=go::" 24 | shell: bash 25 | -------------------------------------------------------------------------------- /cmd/certsuite/upload/results_spreadsheet/const.go: -------------------------------------------------------------------------------- 1 | package resultsspreadsheet 2 | 3 | const ( 4 | ConclusionSheetName = "conclusions" 5 | RawResultsSheetName = "raw results" 6 | SingleWorkloadResultsSheetName = "results" 7 | 8 | categoryConclusionsCol = "Category" 9 | workloadVersionConclusionsCol = "Workload Version" 10 | ocpVersionConclusionsCol = "OCP Version" 11 | WorkloadNameConclusionsCol = "Workload Name" 12 | ResultsConclusionsCol = "Results" 13 | 14 | workloadNameRawResultsCol = "CNFName" 15 | workloadTypeRawResultsCol = "CNFType" 16 | operatorVersionRawResultsCol = "OperatorVersion" 17 | 18 | nextStepAIIfFailSingleWorkloadSheetCol = "Next Step AI If Fail" 19 | conclusionIndividualSingleWorkloadSheetCol = "Owner/TechLead Conclusion" 20 | 21 | cellContentLimit = 50000 22 | ) 23 | -------------------------------------------------------------------------------- /tests/common/env_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package common 18 | -------------------------------------------------------------------------------- /tests/common/constant_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package common 18 | -------------------------------------------------------------------------------- /tests/operator/suite_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package operator 18 | -------------------------------------------------------------------------------- /tests/platform/suite_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package platform 18 | -------------------------------------------------------------------------------- /pkg/autodiscover/constants_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2022 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | package autodiscover 17 | -------------------------------------------------------------------------------- /pkg/postmortem/postmortem_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package postmortem 18 | -------------------------------------------------------------------------------- /tests/networking/suite_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package networking 18 | -------------------------------------------------------------------------------- /internal/crclient/crclient_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2022 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package crclient 18 | -------------------------------------------------------------------------------- /pkg/autodiscover/autodiscover_debug.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2022 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | package autodiscover 17 | -------------------------------------------------------------------------------- /pkg/configuration/utils_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2023 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package configuration 18 | -------------------------------------------------------------------------------- /tests/performance/suite_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package performance 18 | -------------------------------------------------------------------------------- /internal/clientsholder/command_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2022 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package clientsholder 18 | -------------------------------------------------------------------------------- /pkg/autodiscover/autodiscover_debug_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2022 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | package autodiscover 17 | -------------------------------------------------------------------------------- /tests/identifiers/exceptions_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package identifiers 18 | -------------------------------------------------------------------------------- /tests/identifiers/remediation_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package identifiers 18 | -------------------------------------------------------------------------------- /pkg/configuration/configuration_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2022 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package configuration 18 | -------------------------------------------------------------------------------- /tests/platform/bootparams/bootparams_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package bootparams 18 | -------------------------------------------------------------------------------- /internal/clientsholder/clientsholder_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2022 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package clientsholder 18 | -------------------------------------------------------------------------------- /internal/clientsholder/ocpclient_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2022 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package clientsholder_test 18 | -------------------------------------------------------------------------------- /pkg/autodiscover/autodiscover_service_accounts_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | package autodiscover 17 | -------------------------------------------------------------------------------- /pkg/configuration/testdata/tnf_test_config.yml: -------------------------------------------------------------------------------- 1 | targetNameSpaces: 2 | - name: tnf 3 | - name: test2 4 | podsUnderTestLabels: 5 | - "test: pod" 6 | - "cnf: pod" 7 | - "cnf/test: pod1" 8 | - "cnf/testEmpty:" 9 | operatorsUnderTestLabels: 10 | - "test: operator" 11 | - "cnf/test: operator1" 12 | - "cnf: operator" 13 | - "cnf/testEmpty:" 14 | targetCrdFilters: 15 | - nameSuffix: "group1.test.com" 16 | - nameSuffix: "group2.test.com" 17 | acceptedKernelTaints: 18 | - module: "taint1" 19 | - module: "taint2" 20 | skipScalingTestDeployments: 21 | - name: "deployment1" 22 | namespace: "tnf" 23 | skipScalingTestStatefulSetNames: 24 | - name: "statefulset1" 25 | namespace: "tnf" 26 | validProtocolNames: 27 | - "http3" 28 | - "sctp" 29 | ServicesIgnoreList: 30 | - "hazelcast-platform-controller-manager-service" 31 | - "hazelcast-platform-webhook-service" 32 | -------------------------------------------------------------------------------- /tests/lifecycle/scaling/statefulset_scaling_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package scaling 18 | -------------------------------------------------------------------------------- /cmd/certsuite/generate/generate.go: -------------------------------------------------------------------------------- 1 | package generate 2 | 3 | import ( 4 | "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/generate/catalog" 5 | "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/generate/config" 6 | "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/generate/feedback" 7 | qecoverage "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/generate/qe_coverage" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | var ( 12 | generate = &cobra.Command{ 13 | Use: "generate", 14 | Short: "generator tool for various test suite assets", 15 | } 16 | ) 17 | 18 | func NewCommand() *cobra.Command { 19 | generate.AddCommand(catalog.NewCommand()) 20 | generate.AddCommand(feedback.NewCommand()) 21 | generate.AddCommand(config.NewCommand()) 22 | generate.AddCommand(qecoverage.NewCommand()) 23 | 24 | return generate 25 | } 26 | -------------------------------------------------------------------------------- /pkg/autodiscover/autodiscover_clusteroperators.go: -------------------------------------------------------------------------------- 1 | package autodiscover 2 | 3 | import ( 4 | "context" 5 | 6 | configv1 "github.com/openshift/api/config/v1" 7 | clientconfigv1 "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1" 8 | "github.com/redhat-best-practices-for-k8s/certsuite/internal/log" 9 | k8serrors "k8s.io/apimachinery/pkg/api/errors" 10 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 11 | ) 12 | 13 | func findClusterOperators(client clientconfigv1.ClusterOperatorInterface) ([]configv1.ClusterOperator, error) { 14 | clusterOperators, err := client.List(context.TODO(), metav1.ListOptions{}) 15 | if err != nil && !k8serrors.IsNotFound(err) { 16 | return nil, err 17 | } 18 | 19 | if k8serrors.IsNotFound(err) { 20 | log.Debug("ClusterOperator CR not found in the cluster") 21 | return nil, nil 22 | } 23 | 24 | return clusterOperators.Items, nil 25 | } 26 | -------------------------------------------------------------------------------- /tests/lifecycle/scaling/crd_scaling_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | //nolint:dupl 18 | 19 | package scaling 20 | -------------------------------------------------------------------------------- /tests/identifiers/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package identifiers contains TNF test identifiers. 19 | */ 20 | package identifiers 21 | -------------------------------------------------------------------------------- /.github/actions/setup-docker-storage/action.yml: -------------------------------------------------------------------------------- 1 | name: 'Setup Docker Storage' 2 | description: 'Configures Docker to use /mnt/docker-storage instead of /var/lib/docker' 3 | runs: 4 | using: "composite" 5 | steps: 6 | - name: Create docker/daemon.json if it does not exist 7 | shell: bash 8 | run: | 9 | if [ ! -f /etc/docker/daemon.json ]; then 10 | echo '{}' | sudo tee /etc/docker/daemon.json 11 | fi 12 | 13 | - name: Make docker to use /mnt (sdb) for storage 14 | shell: bash 15 | run: | 16 | df -h 17 | lsblk 18 | sudo mkdir /mnt/docker-storage 19 | sudo jq '. +={"data-root" : "/mnt/docker-storage"}' < /etc/docker/daemon.json > /tmp/docker-daemon.json 20 | sudo cp /tmp/docker-daemon.json /etc/docker/daemon.json 21 | cat /etc/docker/daemon.json 22 | sudo systemctl restart docker 23 | sudo ls -la /mnt/docker-storage 24 | 25 | -------------------------------------------------------------------------------- /tests/identifiers/doc_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package identifiers contains TNF test identifiers. 19 | */ 20 | package identifiers 21 | -------------------------------------------------------------------------------- /internal/results/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package results contains a Codec to convert JUnit results to claim Results. 19 | */ 20 | package results 21 | -------------------------------------------------------------------------------- /tests/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package suite provides the entrypoint for running CNFCERT tests and producing a claim file. 19 | */ 20 | package suite 21 | -------------------------------------------------------------------------------- /tests/operator/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package operator provides CNFCERT tests used to validate operator CNF facets. 19 | */ 20 | package operator 21 | -------------------------------------------------------------------------------- /internal/results/doc_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package results contains a Codec to convert JUnit results to claim Results. 19 | */ 20 | package results 21 | -------------------------------------------------------------------------------- /tests/doc_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package suite provides the entrypoint for running CNFCERT tests and producing a claim file. 19 | */ 20 | package suite 21 | -------------------------------------------------------------------------------- /tests/operator/doc_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package operator provides CNFCERT tests used to validate operator CNF facets. 19 | */ 20 | package operator 21 | -------------------------------------------------------------------------------- /pkg/junit/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2022 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package junit provides utility conversion methods for encoding JUnit XML results to generic JSON. 19 | */ 20 | package junit 21 | -------------------------------------------------------------------------------- /pkg/junit/doc_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2022 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package junit provides utility conversion methods for encoding JUnit XML results to generic JSON. 19 | */ 20 | package junit 21 | -------------------------------------------------------------------------------- /tests/common/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package common contains constants, structures and utility function shared 19 | by multiple test suites. 20 | */ 21 | package common 22 | -------------------------------------------------------------------------------- /tests/common/doc_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package common contains constants, structures and utility function shared 19 | by multiple test suites. 20 | */ 21 | package common 22 | -------------------------------------------------------------------------------- /tests/networking/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package networking contains tests that check connectivity and networking config 19 | related best practices. 20 | */ 21 | package networking 22 | -------------------------------------------------------------------------------- /tests/networking/doc_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package networking contains tests that check connectivity and networking config 19 | related best practices. 20 | */ 21 | package networking 22 | -------------------------------------------------------------------------------- /tests/accesscontrol/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package accesscontrol contains tests related to pod privilege, role-binding, 19 | namespace, host resource etc. 20 | */ 21 | package accesscontrol 22 | -------------------------------------------------------------------------------- /tests/lifecycle/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package lifecycle contains k8s resource lifecycle related tests, such as pod 19 | scheduling, scaling, termination etc. 20 | */ 21 | package lifecycle 22 | -------------------------------------------------------------------------------- /tests/accesscontrol/doc_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package accesscontrol contains tests related to pod privilege, role-binding, 19 | namespace, host resource etc. 20 | */ 21 | package accesscontrol 22 | -------------------------------------------------------------------------------- /tests/lifecycle/doc_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package lifecycle contains k8s resource lifecycle related tests, such as pod 19 | scheduling, scaling, termination etc. 20 | */ 21 | package lifecycle 22 | -------------------------------------------------------------------------------- /pkg/configuration/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2022 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | // package configuration includes the definition of test suite configuration 18 | // and the functions necessary to process the configuration 19 | package configuration 20 | -------------------------------------------------------------------------------- /tests/platform/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package platform contains tests related to platform alteration such as kernel 19 | taint, boot param, huge page config, base image etc 20 | */ 21 | package platform 22 | -------------------------------------------------------------------------------- /pkg/configuration/doc_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2022 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | // package configuration includes the definition of test suite configuration 18 | // and the functions necessary to process the configuration 19 | package configuration 20 | -------------------------------------------------------------------------------- /tests/platform/doc_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package platform contains tests related to platform alteration such as kernel 19 | taint, boot param, huge page config, base image etc 20 | */ 21 | package platform 22 | -------------------------------------------------------------------------------- /tests/observability/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package observability contains tests related to the observability of the 19 | CNF workloads under test, such as logging, status reporting etc 20 | */ 21 | package observability 22 | -------------------------------------------------------------------------------- /tests/certification/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package certification contains tests that retrieve results from other 19 | affiliated certification project through an API query, e.g. CVP and OVP 20 | */ 21 | package certification 22 | -------------------------------------------------------------------------------- /tests/observability/doc_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package observability contains tests related to the observability of the 19 | CNF workloads under test, such as logging, status reporting etc 20 | */ 21 | package observability 22 | -------------------------------------------------------------------------------- /tests/certification/doc_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | /* 18 | Package certification contains tests that retrieve results from other 19 | affiliated certification project through an API query, e.g. CVP and OVP 20 | */ 21 | package certification 22 | -------------------------------------------------------------------------------- /pkg/autodiscover/autodiscover_nads.go: -------------------------------------------------------------------------------- 1 | package autodiscover 2 | 3 | import ( 4 | "context" 5 | 6 | nadClient "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" 7 | "github.com/redhat-best-practices-for-k8s/certsuite/internal/clientsholder" 8 | kerrors "k8s.io/apimachinery/pkg/api/errors" 9 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 10 | ) 11 | 12 | func getNetworkAttachmentDefinitions(client *clientsholder.ClientsHolder, namespaces []string) ([]nadClient.NetworkAttachmentDefinition, error) { 13 | var nadList []nadClient.NetworkAttachmentDefinition 14 | 15 | for _, ns := range namespaces { 16 | nad, err := client.CNCFNetworkingClient.K8sCniCncfIoV1().NetworkAttachmentDefinitions(ns).List(context.TODO(), metav1.ListOptions{}) 17 | if err != nil && !kerrors.IsNotFound(err) { 18 | return nil, err 19 | } 20 | 21 | // Append the list of networkAttachmentDefinitions to the nadList slice 22 | nadList = append(nadList, nad.Items...) 23 | } 24 | 25 | return nadList, nil 26 | } 27 | -------------------------------------------------------------------------------- /pkg/autodiscover/constants.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | package autodiscover 17 | 18 | const ( 19 | probeHelperPodsLabelName = "redhat-best-practices-for-k8s.com/app" 20 | probeHelperPodsLabelValue = "certsuite-probe" 21 | csvNameWithNamespaceFormatStr = "%s, ns=%s" 22 | ) 23 | -------------------------------------------------------------------------------- /pkg/provider/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2022 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | // provider package is responsible for providing data needed by tests 18 | // it's considered as a shim layer between tests and autodiscovery/configuration 19 | // package 20 | // test code is not supposed to import autodiscover/configuration packages 21 | package provider 22 | -------------------------------------------------------------------------------- /pkg/provider/doc_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2022 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | // provider package is responsible for providing data needed by tests 18 | // it's considered as a shim layer between tests and autodiscovery/configuration 19 | // package 20 | // test code is not supposed to import autodiscover/configuration packages 21 | package provider 22 | -------------------------------------------------------------------------------- /pkg/provider/scale_object.go: -------------------------------------------------------------------------------- 1 | package provider 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/redhat-best-practices-for-k8s/certsuite/internal/log" 7 | "github.com/redhat-best-practices-for-k8s/certsuite/pkg/autodiscover" 8 | 9 | "k8s.io/apimachinery/pkg/runtime/schema" 10 | "k8s.io/client-go/scale" 11 | 12 | scalingv1 "k8s.io/api/autoscaling/v1" 13 | ) 14 | 15 | type CrScale struct { 16 | *scalingv1.Scale 17 | } 18 | 19 | func (crScale CrScale) IsScaleObjectReady() bool { 20 | replicas := (crScale.Spec.Replicas) 21 | log.Info("replicas is %d status replica is %d", replicas, crScale.Status.Replicas) 22 | return crScale.Status.Replicas == replicas 23 | } 24 | 25 | func (crScale CrScale) ToString() string { 26 | return fmt.Sprintf("cr: %s ns: %s", 27 | crScale.Name, 28 | crScale.Namespace, 29 | ) 30 | } 31 | func GetUpdatedCrObject(sg scale.ScalesGetter, namespace, name string, groupResourceSchema schema.GroupResource) (*CrScale, error) { 32 | result, err := autodiscover.FindCrObjectByNameByNamespace(sg, namespace, name, groupResourceSchema) 33 | return &CrScale{ 34 | result, 35 | }, err 36 | } 37 | -------------------------------------------------------------------------------- /tests/operator/catalogsource/catalogsource.go: -------------------------------------------------------------------------------- 1 | package catalogsource 2 | 3 | import ( 4 | olmpkgv1 "github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/apis/operators/v1" 5 | "github.com/redhat-best-practices-for-k8s/certsuite/internal/log" 6 | ) 7 | 8 | func SkipPMBasedOnChannel(channels []olmpkgv1.PackageChannel, csvName string) bool { 9 | // This logic is in place because it is possible for an operator to pull from a multiple package manifests. 10 | skipPMBasedOnChannel := true 11 | for c := range channels { 12 | log.Debug("Comparing channel currentCSV %q with current CSV %q", channels[c].CurrentCSV, csvName) 13 | log.Debug("Number of channel entries %d", len(channels[c].Entries)) 14 | for _, entry := range channels[c].Entries { 15 | log.Debug("Comparing entry name %q with current CSV %q", entry.Name, csvName) 16 | 17 | if entry.Name == csvName { 18 | log.Debug("Skipping package manifest based on channel entry %q", entry.Name) 19 | skipPMBasedOnChannel = false 20 | break 21 | } 22 | } 23 | 24 | if !skipPMBasedOnChannel { 25 | break 26 | } 27 | } 28 | 29 | return skipPMBasedOnChannel 30 | } 31 | -------------------------------------------------------------------------------- /docs/workload-developers.md: -------------------------------------------------------------------------------- 1 | 2 | # Workload Guidelines for developers 3 | 4 | Developers of Kubernetes workloads, particularly those targeting 5 | [certification with Red Hat on OpenShift](https://redhat-connect.gitbook.io/openshift-badges/badges/cloud-native-network-functions-cnf), 6 | can use this suite to test the interaction of their workload with OpenShift. If interested in certification 7 | please contact [Red Hat](https://redhat-connect.gitbook.io/red-hat-partner-connect-general-guide/managing-your-account/getting-help/technology-partner-success-desk). 8 | 9 | **Requirements** 10 | 11 | - [OpenShift 4.10 installation](https://docs.openshift.com/container-platform/4.10/welcome/index.html) to run the workload 12 | - At least one extra machine to host the test suite 13 | 14 | ## To add private test cases 15 | 16 | Refer this documentation 17 | https://github.com/redhat-best-practices-for-k8s/cnfextensions 18 | 19 | **Reference** 20 | 21 | [certsuite-sample-workload](https://github.com/redhat-best-practices-for-k8s/certsuite-sample-workload) repository provides sample example to model the test setup. 22 | -------------------------------------------------------------------------------- /pkg/configuration/config_test.go: -------------------------------------------------------------------------------- 1 | package configuration_test 2 | 3 | import ( 4 | "testing" 5 | 6 | configuration "github.com/redhat-best-practices-for-k8s/certsuite/pkg/configuration" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | const ( 11 | filePath = "testdata/tnf_test_config.yml" 12 | nsLength = 2 13 | ns1 = "tnf" 14 | ns2 = "test2" 15 | crds = 2 16 | crdSuffix1 = "group1.test.com" 17 | crdSuffix2 = "group2.test.com" 18 | ) 19 | 20 | func TestLoadConfiguration(t *testing.T) { 21 | env, err := configuration.LoadConfiguration(filePath) 22 | assert.Nil(t, err) 23 | // check if targetNameSpaces section is parsed properly 24 | assert.Equal(t, nsLength, len(env.TargetNameSpaces)) 25 | ns := configuration.Namespace{Name: ns1} 26 | assert.Contains(t, env.TargetNameSpaces, ns) 27 | ns.Name = ns2 28 | assert.Contains(t, env.TargetNameSpaces, ns) 29 | // check if targetCrdFilters section is parsed properly 30 | assert.Equal(t, crds, len(env.CrdFilters)) 31 | crd1 := configuration.CrdFilter{NameSuffix: crdSuffix1} 32 | assert.Contains(t, env.CrdFilters, crd1) 33 | crd2 := configuration.CrdFilter{NameSuffix: crdSuffix2} 34 | assert.Contains(t, env.CrdFilters, crd2) 35 | } 36 | -------------------------------------------------------------------------------- /cmd/certsuite/pkg/claim/claim_test.go: -------------------------------------------------------------------------------- 1 | package claim 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestIsClaimFormatVersionSupported(t *testing.T) { 10 | testCases := []struct { 11 | claimFormatVersion string 12 | expectedError string 13 | }{ 14 | // Invalid version strings 15 | { 16 | claimFormatVersion: "", 17 | expectedError: `claim file version "" is not valid: invalid semantic version`, 18 | }, 19 | { 20 | claimFormatVersion: "v0.v0.2", 21 | expectedError: `claim file version "v0.v0.2" is not valid: invalid semantic version`, 22 | }, 23 | { 24 | claimFormatVersion: "v0.0.0", 25 | expectedError: "claim format version v0.0.0 is not supported. Supported version is v0.5.0", 26 | }, 27 | { 28 | claimFormatVersion: "v0.0.1", 29 | expectedError: "claim format version v0.0.1 is not supported. Supported version is v0.5.0", 30 | }, 31 | { 32 | claimFormatVersion: "v0.5.0", 33 | expectedError: "", 34 | }, 35 | } 36 | 37 | for _, tc := range testCases { 38 | err := CheckVersion(tc.claimFormatVersion) 39 | if err != nil { 40 | assert.Equal(t, tc.expectedError, err.Error()) 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /tests/operator/access/access.go: -------------------------------------------------------------------------------- 1 | package access 2 | 3 | import ( 4 | "github.com/operator-framework/api/pkg/operators/v1alpha1" 5 | ) 6 | 7 | func PermissionsHaveBadRule(clusterPermissions []v1alpha1.StrategyDeploymentPermissions) bool { 8 | badRuleFound := false 9 | for permissionIndex := range clusterPermissions { 10 | permission := &clusterPermissions[permissionIndex] 11 | for ruleIndex := range permission.Rules { 12 | rule := &permission.Rules[ruleIndex] 13 | 14 | // Check whether the rule is for the security api group. 15 | securityGroupFound := false 16 | for _, group := range rule.APIGroups { 17 | if group == "*" || group == "security.openshift.io" { 18 | securityGroupFound = true 19 | break 20 | } 21 | } 22 | 23 | if !securityGroupFound { 24 | continue 25 | } 26 | 27 | // Now check whether it grants some access to securitycontextconstraint resources. 28 | for _, resource := range rule.Resources { 29 | if resource == "*" || resource == "securitycontextconstraints" { 30 | // Keep reviewing other permissions' rules so we can log all the failing ones in the claim file. 31 | badRuleFound = true 32 | break 33 | } 34 | } 35 | } 36 | } 37 | 38 | return badRuleFound 39 | } 40 | -------------------------------------------------------------------------------- /cmd/certsuite/claim/show/failures/types_test.go: -------------------------------------------------------------------------------- 1 | package failures 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestAddField(t *testing.T) { 10 | spec := ObjectSpec{} 11 | spec.AddField("key1", "value1") 12 | assert.Len(t, spec.Fields, 1) 13 | } 14 | 15 | func TestMarshalJSON(t *testing.T) { 16 | testCases := []struct { 17 | key string 18 | value string 19 | expectedJSON string 20 | clearFields bool 21 | }{ 22 | { 23 | key: "key1", 24 | value: "value1", 25 | expectedJSON: `{"key1":"value1"}`, 26 | clearFields: false, 27 | }, 28 | { 29 | key: "key1", 30 | value: "value1", 31 | expectedJSON: `{}`, 32 | clearFields: true, 33 | }, 34 | } 35 | 36 | for _, tc := range testCases { 37 | spec := ObjectSpec{} 38 | spec.AddField(tc.key, tc.value) 39 | 40 | if tc.clearFields { 41 | spec.Fields = nil 42 | result, err := spec.MarshalJSON() 43 | assert.Nil(t, err) 44 | assert.Equal(t, tc.expectedJSON, string(result)) 45 | } else { 46 | result, err := spec.MarshalJSON() 47 | assert.Nil(t, err) 48 | assert.Len(t, spec.Fields, 1) 49 | assert.Equal(t, tc.expectedJSON, string(result)) 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /pkg/provider/events.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package provider 18 | 19 | import ( 20 | "fmt" 21 | 22 | corev1 "k8s.io/api/core/v1" 23 | ) 24 | 25 | type Event struct { 26 | *corev1.Event 27 | } 28 | 29 | func NewEvent(aEvent *corev1.Event) (out Event) { 30 | out.Event = aEvent 31 | return out 32 | } 33 | func (e *Event) String() string { 34 | return fmt.Sprintf("timestamp=%s involved object=%s reason=%s message=%s", e.CreationTimestamp.Time, e.InvolvedObject, e.Reason, e.Message) 35 | } 36 | -------------------------------------------------------------------------------- /.github/workflows/merge.yaml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | pull_request: 5 | types: [ closed ] 6 | 7 | permissions: 8 | contents: read 9 | 10 | jobs: 11 | do-not-merge: 12 | if: ${{ contains(github.event.*.labels.*.name, 'do not merge') }} 13 | name: Prevent Merging 14 | runs-on: ubuntu-24.04 15 | steps: 16 | - name: Check for label 17 | run: | 18 | echo "Pull request is labeled as 'do not merge'" 19 | echo "This workflow fails so that the pull request cannot be merged" 20 | exit 1 21 | build: 22 | if: github.event.pull_request.merged == true 23 | name: Run Tests 24 | runs-on: ubuntu-24.04 25 | steps: 26 | - name: Check out code 27 | uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 28 | 29 | - name: Set up Go 30 | uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 31 | with: 32 | go-version-file: go.mod 33 | 34 | - name: Run Tests 35 | run: make test 36 | env: 37 | SHELL: /bin/bash 38 | 39 | close_job: 40 | if: github.event.pull_request.merged == false 41 | runs-on: ubuntu-24.04 42 | steps: 43 | - run: | 44 | echo PR #${{ github.event.number }} has been closed without being merged 45 | -------------------------------------------------------------------------------- /pkg/autodiscover/autodiscover_resources.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package autodiscover 18 | 19 | import ( 20 | "context" 21 | 22 | corev1 "k8s.io/api/core/v1" 23 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | corev1client "k8s.io/client-go/kubernetes/typed/core/v1" 25 | ) 26 | 27 | func getResourceQuotas(oc corev1client.CoreV1Interface) ([]corev1.ResourceQuota, error) { 28 | rql, err := oc.ResourceQuotas("").List(context.TODO(), metav1.ListOptions{}) 29 | if err != nil { 30 | return nil, err 31 | } 32 | return rql.Items, nil 33 | } 34 | -------------------------------------------------------------------------------- /tests/operator/catalogsource/catalogsource_test.go: -------------------------------------------------------------------------------- 1 | package catalogsource 2 | 3 | import ( 4 | "testing" 5 | 6 | olmpkgv1 "github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/apis/operators/v1" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestSkipPMBasedOnChannel(t *testing.T) { 11 | testCases := []struct { 12 | testChannels []olmpkgv1.PackageChannel 13 | testCSVName string 14 | expected bool 15 | }{ 16 | { // Test Case #1 - Do not skip package manifest based on channel entry 17 | testChannels: []olmpkgv1.PackageChannel{ 18 | { 19 | CurrentCSV: "test-csv.v1.0.0", 20 | Entries: []olmpkgv1.ChannelEntry{ 21 | { 22 | Name: "test-csv.v1.0.0", 23 | }, 24 | }, 25 | }, 26 | }, 27 | testCSVName: "test-csv.v1.0.0", 28 | expected: false, 29 | }, 30 | { // Test Case #2 - Skip package manifest based on channel entry 31 | testChannels: []olmpkgv1.PackageChannel{ 32 | { 33 | CurrentCSV: "test-csv.v1.0.0", 34 | Entries: []olmpkgv1.ChannelEntry{ 35 | { 36 | Name: "test-csv.v1.0.0", 37 | }, 38 | }, 39 | }, 40 | }, 41 | testCSVName: "test-csv.v1.0.1", 42 | expected: true, 43 | }, 44 | } 45 | 46 | for _, tc := range testCases { 47 | assert.Equal(t, tc.expected, SkipPMBasedOnChannel(tc.testChannels, tc.testCSVName)) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /pkg/autodiscover/autodiscover_networkpolicies.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022-2023 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package autodiscover 18 | 19 | import ( 20 | "context" 21 | 22 | networkingv1 "k8s.io/api/networking/v1" 23 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | networkingv1client "k8s.io/client-go/kubernetes/typed/networking/v1" 25 | ) 26 | 27 | func getNetworkPolicies(oc networkingv1client.NetworkingV1Interface) ([]networkingv1.NetworkPolicy, error) { 28 | nps, err := oc.NetworkPolicies("").List(context.TODO(), metav1.ListOptions{}) 29 | if err != nil { 30 | return nil, err 31 | } 32 | return nps.Items, nil 33 | } 34 | -------------------------------------------------------------------------------- /.github/workflows/upload-release-assets.yaml: -------------------------------------------------------------------------------- 1 | name: Upload release assets 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | permissions: 8 | contents: write 9 | 10 | jobs: 11 | upload-release-assets: 12 | name: Upload release assets 13 | runs-on: ubuntu-24.04 14 | steps: 15 | - name: Check out code 16 | uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 17 | 18 | - name: Set up Go 19 | uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 20 | with: 21 | go-version-file: go.mod 22 | 23 | - name: Build Certsuite binary (x86_64) 24 | env: 25 | SHELL: /bin/bash 26 | run: | 27 | make build 28 | tar -cvzf certsuite-${GITHUB_REF_NAME}-x86_64.tar.gz certsuite 29 | rm certsuite 30 | 31 | - name: Build Certsuite binary (ARM 64) 32 | env: 33 | SHELL: /bin/bash 34 | run: | 35 | make build-darwin-arm64 36 | tar -cvzf certsuite-${GITHUB_REF_NAME}-arm64.tar.gz certsuite 37 | rm certsuite 38 | 39 | - name: Upload Certsuite binaries 40 | env: 41 | SHELL: /bin/bash 42 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 43 | run: gh release upload ${GITHUB_REF_NAME} certsuite-${GITHUB_REF_NAME}-x86_64.tar.gz certsuite-${GITHUB_REF_NAME}-arm64.tar.gz 44 | -------------------------------------------------------------------------------- /internal/log/multi_handler.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "context" 5 | "log/slog" 6 | ) 7 | 8 | type MultiHandler struct { 9 | handlers []slog.Handler 10 | } 11 | 12 | func NewMultiHandler(handlers ...slog.Handler) *MultiHandler { 13 | return &MultiHandler{ 14 | handlers: handlers, 15 | } 16 | } 17 | 18 | func (h *MultiHandler) Enabled(ctx context.Context, level slog.Level) bool { 19 | for i := range h.handlers { 20 | if h.handlers[i].Enabled(ctx, level) { 21 | return true 22 | } 23 | } 24 | 25 | return false 26 | } 27 | 28 | //nolint:gocritic 29 | func (h *MultiHandler) Handle(ctx context.Context, r slog.Record) error { 30 | for i := range h.handlers { 31 | if err := h.handlers[i].Handle(ctx, r.Clone()); err != nil { 32 | return err 33 | } 34 | } 35 | 36 | return nil 37 | } 38 | 39 | func (h *MultiHandler) WithAttrs(attrs []slog.Attr) slog.Handler { 40 | handlersWithAttrs := make([]slog.Handler, len(h.handlers)) 41 | for i := range h.handlers { 42 | handlersWithAttrs[i] = h.handlers[i].WithAttrs(attrs) 43 | } 44 | return NewMultiHandler(handlersWithAttrs...) 45 | } 46 | 47 | func (h *MultiHandler) WithGroup(name string) slog.Handler { 48 | handlersWithGroup := make([]slog.Handler, len(h.handlers)) 49 | for i := range h.handlers { 50 | handlersWithGroup[i] = h.handlers[i].WithGroup(name) 51 | } 52 | return NewMultiHandler(handlersWithGroup...) 53 | } 54 | -------------------------------------------------------------------------------- /docs/cluster-deploy/kustomization.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: kustomize.config.k8s.io/v1beta1 3 | kind: Kustomization 4 | 5 | resources: 6 | - certsuite.yaml 7 | # Uncomment the next line (namespace transformer) to deploy all the certsuite related 8 | # resources in a different namespace. 9 | # namespace: my-custom-ns-name 10 | 11 | # Uncomment the next lines so each resource's name have a custom prefix and/or suffix appended. 12 | # namePrefix: myprefix- 13 | # nameSuffix: -mysuffix 14 | 15 | # Uncomment the next lines (patches) in order to launch the certsuite pod with a different 16 | # test cases labels filter/expr. The following example changes the labels to "preflight". 17 | # patches: 18 | # - target: 19 | # version: v1 20 | # kind: Pod 21 | # name: certsuite 22 | # patch: | 23 | # - op: replace 24 | # path: /spec/containers/0/args/1 25 | # value: | 26 | # certsuite run -l 'preflight' ; sleep inf 27 | 28 | # Uncomment the next lines (patches) in order to allow intrusive TCs to run. 29 | # patches: 30 | # - target: 31 | # version: v1 32 | # kind: Pod 33 | # name: certsuite 34 | # patch: | 35 | # - op: replace 36 | # path: /spec/containers/0/args/1 37 | # value: | 38 | # certsuite run -l '!affiliated-certification-container-is-certified-digest && !access-control-security-context'; sleep inf 39 | -------------------------------------------------------------------------------- /pkg/provider/events_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022-2023 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package provider 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/stretchr/testify/assert" 23 | corev1 "k8s.io/api/core/v1" 24 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | ) 26 | 27 | func TestNewEvent(t *testing.T) { 28 | testEvent := corev1.Event{ 29 | ObjectMeta: metav1.ObjectMeta{ 30 | Name: "testEvent", 31 | }, 32 | Reason: "this is a test", 33 | } 34 | 35 | outputEvent := NewEvent(&testEvent) 36 | assert.Equal(t, "testEvent", outputEvent.Name) 37 | assert.Contains(t, outputEvent.String(), "reason=this is a test") 38 | } 39 | -------------------------------------------------------------------------------- /cmd/certsuite/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/redhat-best-practices-for-k8s/certsuite/internal/log" 7 | "github.com/spf13/cobra" 8 | 9 | "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/check" 10 | "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/claim" 11 | "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/generate" 12 | "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/info" 13 | "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/run" 14 | "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/upload" 15 | "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/version" 16 | ) 17 | 18 | func newRootCmd() *cobra.Command { 19 | rootCmd := cobra.Command{ 20 | Use: "certsuite", 21 | Short: "A CLI tool for the Red Hat Best Practices Test Suite for Kubernetes.", 22 | } 23 | 24 | rootCmd.AddCommand(claim.NewCommand()) 25 | rootCmd.AddCommand(generate.NewCommand()) 26 | rootCmd.AddCommand(check.NewCommand()) 27 | rootCmd.AddCommand(run.NewCommand()) 28 | rootCmd.AddCommand(info.NewCommand()) 29 | rootCmd.AddCommand(version.NewCommand()) 30 | rootCmd.AddCommand(upload.NewCommand()) 31 | 32 | return &rootCmd 33 | } 34 | 35 | func main() { 36 | rootCmd := newRootCmd() 37 | if err := rootCmd.Execute(); err != nil { 38 | log.Error("%v", err) 39 | os.Exit(1) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/lifecycle/scaling/scaling_helper.go: -------------------------------------------------------------------------------- 1 | package scaling 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/redhat-best-practices-for-k8s/certsuite/pkg/configuration" 7 | apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 8 | apiv1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | 10 | scalingv1 "k8s.io/api/autoscaling/v1" 11 | ) 12 | 13 | func GetResourceHPA(hpaList []*scalingv1.HorizontalPodAutoscaler, name, namespace, kind string) *scalingv1.HorizontalPodAutoscaler { 14 | for _, hpa := range hpaList { 15 | if hpa.Spec.ScaleTargetRef.Kind == kind && hpa.Spec.ScaleTargetRef.Name == name && hpa.Namespace == namespace { 16 | return hpa 17 | } 18 | } 19 | return nil 20 | } 21 | func IsManaged(podSetName string, managedPodSet []configuration.ManagedDeploymentsStatefulsets) bool { 22 | for _, ps := range managedPodSet { 23 | if ps.Name == podSetName { 24 | return true 25 | } 26 | } 27 | return false 28 | } 29 | 30 | func CheckOwnerReference(ownerReference []apiv1.OwnerReference, crdFilter []configuration.CrdFilter, crds []*apiextv1.CustomResourceDefinition) bool { 31 | for _, owner := range ownerReference { 32 | for _, aCrd := range crds { 33 | if aCrd.Spec.Names.Kind == owner.Kind { 34 | for _, crdF := range crdFilter { 35 | if strings.HasSuffix(aCrd.Name, crdF.NameSuffix) { 36 | return crdF.Scalable 37 | } 38 | } 39 | } 40 | } 41 | } 42 | return false 43 | } 44 | -------------------------------------------------------------------------------- /.github/actions/setup-partner-cluster/action.yml: -------------------------------------------------------------------------------- 1 | name: setup-partner-cluster 2 | description: 'Setup a partner cluster for testing.' 3 | 4 | inputs: 5 | make-command: 6 | description: 'The make command to run.' 7 | required: true 8 | 9 | runs: 10 | using: 'composite' 11 | steps: 12 | - name: Check out `certsuite-sample-workload` 13 | uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 14 | with: 15 | repository: redhat-best-practices-for-k8s/certsuite-sample-workload 16 | path: certsuite-sample-workload 17 | 18 | - name: Setup quick-k8s cluster 19 | uses: palmsoftware/quick-k8s@v0.0.44 20 | with: 21 | disableDefaultCni: true 22 | numControlPlaneNodes: 1 23 | numWorkerNodes: 2 24 | installOLM: true 25 | removeDefaultStorageClass: true 26 | removeControlPlaneTaint: true 27 | 28 | - name: Run 'make ${{inputs.make-command}}' 29 | uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2 30 | with: 31 | timeout_minutes: 150 32 | max_attempts: 3 33 | command: cd ${GITHUB_WORKSPACE}/certsuite-sample-workload; python3 -m venv .venv; source .venv/bin/activate; pip install --upgrade pip; pip install jinjanator; cp .venv/bin/jinjanate .venv/bin/j2; make ${{ inputs.make-command }} 34 | 35 | - name: Show pods 36 | shell: bash 37 | run: oc get pods -A 38 | -------------------------------------------------------------------------------- /config/certsuite_config.yml: -------------------------------------------------------------------------------- 1 | targetNameSpaces: 2 | - name: tnf 3 | podsUnderTestLabels: 4 | - "redhat-best-practices-for-k8s.com/generic: target" 5 | operatorsUnderTestLabels: 6 | - "redhat-best-practices-for-k8s.com/operator:target" 7 | - "redhat-best-practices-for-k8s.com/operator1:new" 8 | - "cnf/test:cr-scale-operator" 9 | targetCrdFilters: 10 | - nameSuffix: "group1.test.com" 11 | scalable: false 12 | - nameSuffix: "redhat-best-practices-for-k8s.com" 13 | scalable: false 14 | - nameSuffix: "memcacheds.cache.example.com" 15 | scalable: true 16 | managedDeployments: 17 | - name: memcached-sample 18 | managedStatefulsets: 19 | - name: memcached-sample 20 | acceptedKernelTaints: 21 | - module: vboxsf 22 | - module: vboxguest 23 | skipScalingTestDeployments: 24 | - name: deployment1 25 | namespace: tnf 26 | skipScalingTestStatefulsets: 27 | - name: statefulset1 28 | namespace: tnf 29 | skipHelmChartList: 30 | - name: coredns 31 | validProtocolNames: 32 | - "http3" 33 | - "sctp" 34 | servicesignorelist: 35 | - "new-pro-controller-manager-metrics-service" 36 | - "mysql" 37 | executedBy: "" 38 | partnerName: "" 39 | collectorAppPassword: "" 40 | collectorAppEndpoint: "http://claims-collector.cnf-certifications.sysdeseng.com" 41 | connectAPIConfig: 42 | baseURL: "https://access.redhat.com/hydra/cwe/rest/v1.0" 43 | apiKey: "" 44 | projectID: "" 45 | proxyURL: "" 46 | proxyPort: "" 47 | -------------------------------------------------------------------------------- /pkg/autodiscover/autodiscover_sriov_test.go: -------------------------------------------------------------------------------- 1 | package autodiscover 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/redhat-best-practices-for-k8s/certsuite/internal/clientsholder" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestGetSriovNetworks_NilClient(t *testing.T) { 11 | // Test with nil client - should not panic 12 | result, err := getSriovNetworks(nil, []string{"default"}) 13 | assert.NoError(t, err) 14 | assert.Empty(t, result) 15 | } 16 | 17 | func TestGetSriovNetworkNodePolicies_NilClient(t *testing.T) { 18 | // Test with nil client - should not panic 19 | result, err := getSriovNetworkNodePolicies(nil, []string{"default"}) 20 | assert.NoError(t, err) 21 | assert.Empty(t, result) 22 | } 23 | 24 | func TestGetSriovNetworks_NilDynamicClient(t *testing.T) { 25 | // Test with client that has nil DynamicClient - should not panic 26 | client := &clientsholder.ClientsHolder{ 27 | DynamicClient: nil, 28 | } 29 | result, err := getSriovNetworks(client, []string{"default"}) 30 | assert.NoError(t, err) 31 | assert.Empty(t, result) 32 | } 33 | 34 | func TestGetSriovNetworkNodePolicies_NilDynamicClient(t *testing.T) { 35 | // Test with client that has nil DynamicClient - should not panic 36 | client := &clientsholder.ClientsHolder{ 37 | DynamicClient: nil, 38 | } 39 | result, err := getSriovNetworkNodePolicies(client, []string{"default"}) 40 | assert.NoError(t, err) 41 | assert.Empty(t, result) 42 | } 43 | -------------------------------------------------------------------------------- /tests/common/constant.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package common 18 | 19 | // Constants shared by multiple test suite packages 20 | const ( 21 | defaultTimeoutSeconds = 10 22 | AccessControlTestKey = "access-control" 23 | LifecycleTestKey = "lifecycle" 24 | ManageabilityTestKey = "manageability" 25 | AffiliatedCertTestKey = "affiliated-certification" 26 | NetworkingTestKey = "networking" 27 | ObservabilityTestKey = "observability" 28 | OperatorTestKey = "operator" 29 | PlatformAlterationTestKey = "platform-alteration" 30 | PerformanceTestKey = "performance" 31 | PreflightTestKey = "preflight" 32 | ) 33 | -------------------------------------------------------------------------------- /cmd/certsuite/claim/show/failures/types.go: -------------------------------------------------------------------------------- 1 | package failures 2 | 3 | import "fmt" 4 | 5 | // Custom object type needed to provide a different JSON serialization than 6 | // the one in claim's test cases' skipReason field. 7 | type NonCompliantObject struct { 8 | Type string `json:"type"` 9 | Reason string `json:"reason"` 10 | Spec ObjectSpec `json:"spec"` 11 | } 12 | 13 | type ObjectSpec struct { 14 | Fields []struct{ Key, Value string } 15 | } 16 | 17 | func (spec *ObjectSpec) AddField(key, value string) { 18 | spec.Fields = append(spec.Fields, struct { 19 | Key string 20 | Value string 21 | }{key, value}) 22 | } 23 | 24 | func (spec *ObjectSpec) MarshalJSON() ([]byte, error) { 25 | if len(spec.Fields) == 0 { 26 | return []byte("{}"), nil 27 | } 28 | 29 | specStr := "{" 30 | for i := range spec.Fields { 31 | if i != 0 { 32 | specStr += ", " 33 | } 34 | specStr += fmt.Sprintf("%q:%q", spec.Fields[i].Key, spec.Fields[i].Value) 35 | } 36 | 37 | specStr += "}" 38 | 39 | return []byte(specStr), nil 40 | } 41 | 42 | type FailedTestCase struct { 43 | TestCaseName string `json:"name"` 44 | TestCaseDescription string `json:"description"` 45 | CheckDetails string `json:"checkDetails,omitempty"` 46 | NonCompliantObjects []NonCompliantObject `json:"nonCompliantObjects,omitempty"` 47 | } 48 | 49 | type FailedTestSuite struct { 50 | TestSuiteName string `json:"name"` 51 | FailingTestCases []FailedTestCase `json:"failures"` 52 | } 53 | -------------------------------------------------------------------------------- /.github/actions/slack-webhook-sender/action.yml: -------------------------------------------------------------------------------- 1 | name: slack-webhook-sender 2 | description: 'Sends a slack message plus some more workflow job related fields to a slack webhook endpoint.' 3 | inputs: 4 | message: 5 | description: 'Text that will be send in the json .message field.' 6 | required: true 7 | default: 'Hello, world!' 8 | slack_webhook: 9 | description: 'Slack webhook where the data will be posted.' 10 | required: true 11 | default: '' 12 | 13 | runs: 14 | using: 'composite' 15 | steps: 16 | - name: Post message data to slack's webhook url. 17 | shell: bash 18 | env: 19 | MESSAGE: ${{ inputs.message }} 20 | REPO_URL: 'github.com/${{ github.repository }}' 21 | COMMIT_URL: 'github.com/${{ github.repository }}/commit/${{ github.sha }}' 22 | JOB_URL: 'github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/attempts/${{ github.run_attempt }}' 23 | ATTEMPT: ${{ github.run_attempt }} 24 | run: | 25 | data="{ \ 26 | \"message\" : \"${MESSAGE}\", \ 27 | \"repo_url\" : \"${REPO_URL}\", \ 28 | \"job_url\" : \"${JOB_URL}\", \ 29 | \"commit_url\": \"${COMMIT_URL}\", \ 30 | \"attempt\" : \"${ATTEMPT}\" \ 31 | }" 32 | 33 | echo "Sending alert message data to slack webhook: $(echo $data | jq)" 34 | curl -X POST --data "${data}" -H 'Content-type: application/json; charset=UTF-8' '${{ inputs.slack_webhook }}' 35 | -------------------------------------------------------------------------------- /pkg/autodiscover/autodiscover_service_accounts.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | package autodiscover 17 | 18 | import ( 19 | "context" 20 | 21 | corev1 "k8s.io/api/core/v1" 22 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 | corev1client "k8s.io/client-go/kubernetes/typed/core/v1" 24 | ) 25 | 26 | func getServiceAccounts(oc corev1client.CoreV1Interface, namespaces []string) (servicesAccounts []*corev1.ServiceAccount, err error) { 27 | for _, ns := range namespaces { 28 | s, err := oc.ServiceAccounts(ns).List(context.TODO(), metav1.ListOptions{}) 29 | if err != nil { 30 | return servicesAccounts, err 31 | } 32 | for i := range s.Items { 33 | servicesAccounts = append(servicesAccounts, &s.Items[i]) 34 | } 35 | } 36 | return servicesAccounts, nil 37 | } 38 | -------------------------------------------------------------------------------- /cmd/certsuite/claim/compare/versions/versions.go: -------------------------------------------------------------------------------- 1 | package versions 2 | 3 | import ( 4 | "encoding/json" 5 | "log" 6 | 7 | officialClaimScheme "github.com/redhat-best-practices-for-k8s/certsuite-claim/pkg/claim" 8 | "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/claim/compare/diff" 9 | ) 10 | 11 | type DiffReport struct { 12 | Diffs *diff.Diffs `json:"differences"` 13 | } 14 | 15 | func (d *DiffReport) String() string { 16 | if d.Diffs == nil { 17 | return (&diff.Diffs{}).String() 18 | } 19 | 20 | return d.Diffs.String() 21 | } 22 | 23 | func Compare(claim1Versions, claim2Versions *officialClaimScheme.Versions) *DiffReport { 24 | // Convert the versions struct type to agnostic map[string]interface{} objects so 25 | // it can be compared using the diff.Compare func. 26 | 27 | bytes1, err := json.Marshal(claim1Versions) 28 | if err != nil { 29 | log.Fatalf("Failed to marshal versions from claim 1: %v\nq", err) 30 | } 31 | 32 | bytes2, err := json.Marshal(claim2Versions) 33 | if err != nil { 34 | log.Fatalf("Failed to marshal versions from claim 2: %v\n", err) 35 | } 36 | 37 | // Now let's unmarshal them into interface{} vars 38 | var v1, v2 interface{} 39 | err = json.Unmarshal(bytes1, &v1) 40 | if err != nil { 41 | log.Fatalf("Failed to unmarshal versions from claim 1: %v\n", err) 42 | } 43 | 44 | err = json.Unmarshal(bytes2, &v2) 45 | if err != nil { 46 | log.Fatalf("Failed to unmarshal versions from claim 2: %v\n", err) 47 | } 48 | 49 | return &DiffReport{ 50 | Diffs: diff.Compare("VERSIONS", v1, v2, nil), 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /pkg/autodiscover/autodiscover_pdbs.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package autodiscover 18 | 19 | import ( 20 | "context" 21 | 22 | policyv1 "k8s.io/api/policy/v1" 23 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | policyv1client "k8s.io/client-go/kubernetes/typed/policy/v1" 25 | ) 26 | 27 | func getPodDisruptionBudgets(oc policyv1client.PolicyV1Interface, namespaces []string) ([]policyv1.PodDisruptionBudget, error) { 28 | podDisruptionBudgets := []policyv1.PodDisruptionBudget{} 29 | for _, ns := range namespaces { 30 | pdbs, err := oc.PodDisruptionBudgets(ns).List(context.TODO(), metav1.ListOptions{}) 31 | if err != nil { 32 | return nil, err 33 | } 34 | podDisruptionBudgets = append(podDisruptionBudgets, pdbs.Items...) 35 | } 36 | 37 | return podDisruptionBudgets, nil 38 | } 39 | -------------------------------------------------------------------------------- /cmd/certsuite/claim/compare/testdata/diff2_same_claims.txt: -------------------------------------------------------------------------------- 1 | VERSIONS: Differences 2 | FIELD CLAIM 1 CLAIM 2 3 | 4 | 5 | VERSIONS: Only in CLAIM 1 6 | 7 | 8 | VERSIONS: Only in CLAIM 2 9 | 10 | 11 | RESULTS SUMMARY 12 | --------------- 13 | STATUS # in CLAIM-1 # in CLAIM-2 14 | passed 3 3 15 | skipped 86 86 16 | failed 1 1 17 | 18 | RESULTS DIFFERENCES 19 | ------------------- 20 | 21 | 22 | CONFIGURATIONS 23 | -------------- 24 | 25 | Cert Suite Configuration: Differences 26 | FIELD CLAIM 1 CLAIM 2 27 | 28 | 29 | Cert Suite Configuration: Only in CLAIM 1 30 | 31 | 32 | Cert Suite Configuration: Only in CLAIM 2 33 | 34 | 35 | Cluster abnormal events count 36 | CLAIM 1 CLAIM 2 37 | 1 1 38 | 39 | CLUSTER NODES DIFFERENCES 40 | ------------------------- 41 | 42 | Nodes: Differences 43 | FIELD CLAIM 1 CLAIM 2 44 | 45 | 46 | Nodes: Only in CLAIM 1 47 | 48 | 49 | Nodes: Only in CLAIM 2 50 | 51 | 52 | CNIs: Differences 53 | FIELD CLAIM 1 CLAIM 2 54 | 55 | 56 | CNIs: Only in CLAIM 1 57 | 58 | 59 | CNIs: Only in CLAIM 2 60 | 61 | 62 | CSIs: Differences 63 | FIELD CLAIM 1 CLAIM 2 64 | 65 | 66 | CSIs: Only in CLAIM 1 67 | 68 | 69 | CSIs: Only in CLAIM 2 70 | 71 | 72 | Hardware: Differences 73 | FIELD CLAIM 1 CLAIM 2 74 | 75 | 76 | Hardware: Only in CLAIM 1 77 | 78 | 79 | Hardware: Only in CLAIM 2 80 | 81 | 82 | -------------------------------------------------------------------------------- /tests/common/env.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package common 18 | 19 | import ( 20 | "path" 21 | "time" 22 | ) 23 | 24 | var ( 25 | // PathRelativeToRoot is used to calculate relative filepaths for the `redhat-best-practices-for-k8s` executable entrypoint. 26 | PathRelativeToRoot = path.Join("..") 27 | 28 | // RelativeSchemaPath is the relative path to the generic-test.schema.json JSON schema. 29 | RelativeSchemaPath = path.Join(PathRelativeToRoot, schemaPath) 30 | 31 | // schemaPath is the path to the generic-test.schema.json JSON schema relative to the project root. 32 | schemaPath = path.Join("schemas", "generic-test.schema.json") 33 | ) 34 | 35 | // DefaultTimeout for creating new interactive sessions (oc, ssh, tty) 36 | var DefaultTimeout = time.Duration(defaultTimeoutSeconds) * time.Second 37 | -------------------------------------------------------------------------------- /cmd/certsuite/claim/compare/configurations/configurations.go: -------------------------------------------------------------------------------- 1 | package configurations 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/claim/compare/diff" 7 | "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/pkg/claim" 8 | ) 9 | 10 | type AbnormalEventsCount struct { 11 | Claim1 int `json:"claim1"` 12 | Claim2 int `json:"claim2"` 13 | } 14 | 15 | func (c *AbnormalEventsCount) String() string { 16 | const ( 17 | rowHeaderFmt = "%-12s%-s\n" 18 | rowDataFmt = "%-12d%-d\n" 19 | ) 20 | 21 | str := "Cluster abnormal events count\n" 22 | str += fmt.Sprintf(rowHeaderFmt, "CLAIM 1", "CLAIM 2") 23 | str += fmt.Sprintf(rowDataFmt, c.Claim1, c.Claim2) 24 | 25 | return str 26 | } 27 | 28 | type DiffReport struct { 29 | Config *diff.Diffs `json:"CertSuiteConfig"` 30 | AbnormalEvents AbnormalEventsCount `json:"abnormalEventsCount"` 31 | } 32 | 33 | func (d *DiffReport) String() string { 34 | str := "CONFIGURATIONS\n" 35 | str += "--------------\n\n" 36 | 37 | str += d.Config.String() 38 | 39 | str += "\n" 40 | str += d.AbnormalEvents.String() 41 | 42 | return str 43 | } 44 | 45 | func GetDiffReport(claim1Configurations, claim2Configurations *claim.Configurations) *DiffReport { 46 | return &DiffReport{ 47 | Config: diff.Compare("Cert Suite Configuration", claim1Configurations.Config, claim2Configurations.Config, nil), 48 | AbnormalEvents: AbnormalEventsCount{ 49 | Claim1: len(claim1Configurations.AbnormalEvents), 50 | Claim2: len(claim2Configurations.AbnormalEvents), 51 | }, 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /pkg/versions/versions.go: -------------------------------------------------------------------------------- 1 | package versions 2 | 3 | import ( 4 | "regexp" 5 | 6 | "github.com/Masterminds/semver/v3" 7 | ) 8 | 9 | var ( 10 | // GitCommit is the latest commit in the current git branch 11 | GitCommit string 12 | // GitRelease is the list of tags (if any) applied to the latest commit 13 | // in the current branch 14 | GitRelease string 15 | // GitPreviousRelease is the last release at the date of the latest commit 16 | // in the current branch 17 | GitPreviousRelease string 18 | // GitDisplayRelease is a string used to hold the text to display 19 | // the version on screen and in the claim file 20 | GitDisplayRelease string 21 | // ClaimFormat is the current version for the claim file format to be produced by the TNF test suite. 22 | // A client decoding this claim file must support decoding its specific version. 23 | ClaimFormatVersion string 24 | ) 25 | 26 | // getGitVersion returns the git display version: the latest previously released 27 | // build in case this build is not released. Otherwise display the build version 28 | func GitVersion() string { 29 | if GitRelease == "" { 30 | GitDisplayRelease = "Unreleased build post " + GitPreviousRelease 31 | } else { 32 | GitDisplayRelease = GitRelease 33 | } 34 | 35 | return GitDisplayRelease + " (" + GitCommit + ")" 36 | } 37 | 38 | func IsValidSemanticVersion(version string) bool { 39 | _, err := semver.NewVersion(version) 40 | return err == nil 41 | } 42 | 43 | func IsValidK8sVersion(version string) bool { 44 | r := regexp.MustCompile(`^(v)([1-9]\d*)+((alpha|beta)([1-9]\d*)+){0,2}$`) 45 | return r.MatchString(version) 46 | } 47 | -------------------------------------------------------------------------------- /webserver/toast.js: -------------------------------------------------------------------------------- 1 | import '@rhds/elements/rh-alert/rh-alert.js'; 2 | 3 | export async function toast({ 4 | heading, 5 | message, 6 | state = 'info', 7 | timeout = 8_000, 8 | }) { 9 | await import('@rhds/elements/rh-alert/rh-alert.js'); 10 | const h2 = document.createElement('h2'); 11 | h2.textContent = heading; 12 | h2.slot = 'header'; 13 | const alert = document.createElement('rh-alert'); 14 | alert.setAttribute('aria-live', 'polite'); 15 | alert.dismissable = true; 16 | alert.state = state; 17 | alert.classList.add('toast'); 18 | alert.style.position = 'fixed'; 19 | alert.style.margin = '0'; 20 | alert.style.setProperty('z-index', '1000'); 21 | alert.style.setProperty('inset-inline-end', 'var(--rh-space-xl, 24px)'); 22 | alert.style.setProperty('inset-block-start', 'var(--rh-space-xl, 24px)'); 23 | alert.append(h2); 24 | if (message) { 25 | const p = document.createElement('p'); 26 | p.textContent = message; 27 | alert.append(message); 28 | } 29 | 30 | alert.animate({ translate: ['100% 0', '0 0'] }, { duration: 200 }); 31 | 32 | await Promise.all(Array.from(document.querySelectorAll('rh-alert.toast'), toast => 33 | // TODO: handle more than 2 toasts 34 | toast.animate({ 35 | translate: [ 36 | '0 auto', 37 | '0 calc(100% + 20px)', 38 | ], 39 | }, { 40 | duration: 200, 41 | composite: 'accumulate', 42 | rangeEnd: '100%', 43 | fill: 'forwards', 44 | }).finished)); 45 | 46 | setTimeout(() => { 47 | if (alert.isConnected) { 48 | alert.remove(); 49 | } 50 | }, timeout); 51 | 52 | document.body.append(alert); 53 | } -------------------------------------------------------------------------------- /pkg/autodiscover/autodiscover_services.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | package autodiscover 17 | 18 | import ( 19 | "context" 20 | 21 | "github.com/redhat-best-practices-for-k8s/certsuite/pkg/stringhelper" 22 | corev1 "k8s.io/api/core/v1" 23 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | corev1client "k8s.io/client-go/kubernetes/typed/core/v1" 25 | ) 26 | 27 | func getServices(oc corev1client.CoreV1Interface, namespaces, ignoreList []string) (allServices []*corev1.Service, err error) { 28 | for _, ns := range namespaces { 29 | s, err := oc.Services(ns).List(context.TODO(), metav1.ListOptions{}) 30 | if err != nil { 31 | return allServices, err 32 | } 33 | for i := range s.Items { 34 | if stringhelper.StringInSlice(ignoreList, s.Items[i].Name, false) { 35 | continue 36 | } 37 | allServices = append(allServices, &s.Items[i]) 38 | } 39 | } 40 | return allServices, nil 41 | } 42 | -------------------------------------------------------------------------------- /pkg/autodiscover/autodiscover_events.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package autodiscover 18 | 19 | import ( 20 | "context" 21 | 22 | "github.com/redhat-best-practices-for-k8s/certsuite/internal/log" 23 | corev1 "k8s.io/api/core/v1" 24 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | corev1client "k8s.io/client-go/kubernetes/typed/core/v1" 26 | ) 27 | 28 | func findAbnormalEvents(oc corev1client.CoreV1Interface, namespaces []string) (abnormalEvents []corev1.Event) { 29 | abnormalEvents = []corev1.Event{} 30 | for _, ns := range namespaces { 31 | someAbnormalEvents, err := oc.Events(ns).List(context.TODO(), metav1.ListOptions{FieldSelector: "type!=Normal"}) 32 | if err != nil { 33 | log.Error("Failed to get event list for namespace %q, err: %v", ns, err) 34 | continue 35 | } 36 | abnormalEvents = append(abnormalEvents, someAbnormalEvents.Items...) 37 | } 38 | return abnormalEvents 39 | } 40 | -------------------------------------------------------------------------------- /tests/manageability/suite_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package manageability 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/stretchr/testify/assert" 23 | ) 24 | 25 | func TestContainerPortNameFormatCheck(t *testing.T) { 26 | testCases := []struct { 27 | portName string 28 | expectedOutput bool 29 | }{ 30 | { 31 | portName: "http", 32 | expectedOutput: true, 33 | }, 34 | { 35 | portName: "tcp-probe", 36 | expectedOutput: true, 37 | }, 38 | { 39 | portName: "grpc-web-app1", 40 | expectedOutput: true, 41 | }, 42 | { 43 | portName: "sftp", 44 | expectedOutput: false, 45 | }, 46 | { 47 | portName: "sctp-endpoint", 48 | expectedOutput: false, 49 | }, 50 | } 51 | 52 | for _, tc := range testCases { 53 | res := containerPortNameFormatCheck(tc.portName) 54 | assert.Equal(t, tc.expectedOutput, res) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /docs/developers.md: -------------------------------------------------------------------------------- 1 | 2 | # Steps 3 | 4 | To test the newly added test / existing tests locally, follow the steps 5 | 6 | - Clone the repo 7 | - Set runtime environment variables, as per the requirement. 8 | 9 | For example, to deploy partner deployments in a custom namespace in the test config. 10 | 11 | ```yaml 12 | targetNameSpaces: 13 | - name: mynamespace 14 | ``` 15 | 16 | - Also, skip intrusive tests 17 | 18 | ```shell 19 | ./certsuite run --intrusive=false 20 | ``` 21 | 22 | - Set K8s config of the cluster where test pods are running 23 | 24 | ```shell 25 | export KUBECONFIG=<> 26 | ``` 27 | 28 | - Execute test suite, which would build and run the suite 29 | 30 | For example, to run `networking` tests 31 | 32 | ```shell 33 | ./certsuite run -l networking 34 | ``` 35 | 36 | ## Dependencies on other PR 37 | 38 | If you have dependencies on other Pull Requests, you can add a comment like that: 39 | 40 | ```text 41 | Depends-On: 42 | ``` 43 | 44 | and the dependent PR will automatically be extracted and injected in your change during the GitHub Action CI jobs and the DCI jobs. 45 | 46 | ## Linters for the Codebase 47 | 48 | - [`checkmake`](https://github.com/mrtazz/checkmake) 49 | - [`golangci-lint`](https://github.com/golangci/golangci-lint) 50 | - [`hadolint`](https://github.com/hadolint/hadolint) 51 | - [`markdownlint`](https://github.com/igorshubovych/markdownlint-cli) 52 | - [`shellcheck`](https://github.com/koalaman/shellcheck) 53 | - [`shfmt`](https://github.com/mvdan/sh) 54 | - [`typos`](https://github.com/crate-ci/typos) 55 | - [`yamllint`](https://github.com/adrienverge/yamllint) 56 | -------------------------------------------------------------------------------- /tests/accesscontrol/namespace/namespace_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package namespace 18 | 19 | import ( 20 | "os" 21 | "testing" 22 | 23 | "github.com/redhat-best-practices-for-k8s/certsuite/internal/log" 24 | "github.com/stretchr/testify/assert" 25 | ) 26 | 27 | func TestGetInvalidCRsNum(t *testing.T) { 28 | testCases := []struct { 29 | invalidCrs map[string]map[string][]string 30 | expectedInvalidCRs int 31 | }{ 32 | { 33 | invalidCrs: map[string]map[string][]string{ 34 | "cr1": { 35 | "ns1": { 36 | "testCRDs", 37 | }, 38 | }, 39 | }, 40 | expectedInvalidCRs: 1, 41 | }, 42 | { 43 | invalidCrs: map[string]map[string][]string{}, 44 | expectedInvalidCRs: 0, 45 | }, 46 | } 47 | 48 | for _, tc := range testCases { 49 | log.SetupLogger(os.Stdout, "INFO") 50 | result := GetInvalidCRsNum(tc.invalidCrs, log.GetLogger()) 51 | assert.Equal(t, tc.expectedInvalidCRs, result) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /pkg/postmortem/postmortem.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package postmortem 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/redhat-best-practices-for-k8s/certsuite/pkg/provider" 23 | corev1 "k8s.io/api/core/v1" 24 | ) 25 | 26 | func Log() (out string) { 27 | // Get current environment 28 | env := provider.GetTestEnvironment() 29 | 30 | // Set refresh 31 | env.SetNeedsRefresh() 32 | 33 | // Get up-to-date environment 34 | env = provider.GetTestEnvironment() 35 | 36 | out += "\nNode Status:\n" 37 | for _, n := range env.Nodes { 38 | out += fmt.Sprintf("node name=%s taints=%+v", n.Data.Name, n.Data.Spec.Taints) + "\n" 39 | } 40 | out += "\nPending Pods:\n" 41 | for _, p := range env.AllPods { 42 | if p.Status.Phase != corev1.PodSucceeded && p.Status.Phase != corev1.PodRunning { 43 | out += p.String() + "\n" 44 | } 45 | } 46 | out += "\nAbnormal events:\n" 47 | for _, e := range env.AbnormalEvents { 48 | out += e.String() + "\n" 49 | } 50 | return out 51 | } 52 | -------------------------------------------------------------------------------- /tests/platform/clusteroperator/clusteroperator_test.go: -------------------------------------------------------------------------------- 1 | package clusteroperator 2 | 3 | import ( 4 | "testing" 5 | 6 | configv1 "github.com/openshift/api/config/v1" 7 | "github.com/stretchr/testify/assert" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | ) 10 | 11 | func TestIsClusterOperatorAvailable(t *testing.T) { 12 | generateClusterOperator := func( 13 | availableStatus configv1.ConditionStatus, 14 | degradedStatus configv1.ConditionStatus, 15 | progressingStatus configv1.ConditionStatus) *configv1.ClusterOperator { 16 | return &configv1.ClusterOperator{ 17 | ObjectMeta: metav1.ObjectMeta{ 18 | Name: "test-cluster-operator", 19 | }, 20 | Status: configv1.ClusterOperatorStatus{ 21 | Conditions: []configv1.ClusterOperatorStatusCondition{ 22 | { 23 | Type: configv1.OperatorAvailable, 24 | Status: availableStatus, 25 | }, 26 | { 27 | Type: configv1.OperatorDegraded, 28 | Status: degradedStatus, 29 | }, 30 | { 31 | Type: configv1.OperatorProgressing, 32 | Status: progressingStatus, 33 | }, 34 | }, 35 | }, 36 | } 37 | } 38 | 39 | testCases := []struct { 40 | testAvailableStatus configv1.ConditionStatus 41 | testDegradedStatus configv1.ConditionStatus 42 | testProgressingStatus configv1.ConditionStatus 43 | expectedResult bool 44 | }{ 45 | { 46 | testAvailableStatus: configv1.ConditionTrue, 47 | testDegradedStatus: configv1.ConditionFalse, 48 | testProgressingStatus: configv1.ConditionFalse, 49 | expectedResult: true, 50 | }, 51 | } 52 | 53 | for _, tc := range testCases { 54 | assert.Equal(t, tc.expectedResult, IsClusterOperatorAvailable(generateClusterOperator(tc.testAvailableStatus, tc.testDegradedStatus, tc.testProgressingStatus))) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /docs/runtime-env.md: -------------------------------------------------------------------------------- 1 | 2 | # Runtime environment variables 3 | 4 | To run the test suite, some runtime environment variables are to be set. 5 | 6 | ## OCP >=4.12 Labels 7 | 8 | The following labels need to be added to your default namespace in your cluster 9 | if you are running OCP >=4.12: 10 | 11 | ```shell 12 | pod-security.kubernetes.io/enforce: privileged 13 | pod-security.kubernetes.io/enforce-version: latest 14 | ``` 15 | 16 | You can manually label the namespace with: 17 | 18 | ```shell 19 | oc label namespace/default pod-security.kubernetes.io/enforce=privileged 20 | oc label namespace/default pod-security.kubernetes.io/enforce-version=latest 21 | ``` 22 | 23 | ## Preflight Integration 24 | 25 | When running the `preflight` suite of tests, there are a few environment variables that 26 | will need to be set: 27 | 28 | `PFLT_DOCKERCONFIG` is a required variable for running the preflight test suite. This 29 | provides credentials to the underlying preflight library for being able to pull/manipulate 30 | images and image bundles for testing. 31 | 32 | When running as a container, the docker config is mounted to the container via volume mount. 33 | 34 | When running as a standalone binary, the environment variables are consumed directly from your local machine. 35 | 36 | See more about this variable in the [Preflight configuration documentation](https://github.com/redhat-openshift-ecosystem/openshift-preflight/blob/main/docs/CONFIG.md). 37 | 38 | `CERTSUITE_ALLOW_PREFLIGHT_INSECURE` (default: false) is required set to `true` if you are running 39 | against a private container registry that has self-signed certificates. 40 | 41 | Note that you can also specify the probe pod image to use with `SUPPORT_IMAGE` 42 | environment variable, default to `certsuite-probe:v0.0.30`. 43 | -------------------------------------------------------------------------------- /tests/lifecycle/volumes/volumes.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package volumes 18 | 19 | import ( 20 | corev1 "k8s.io/api/core/v1" 21 | ) 22 | 23 | func getPVCFromSlice(pvcs []corev1.PersistentVolumeClaim, pvcName string) *corev1.PersistentVolumeClaim { 24 | for i := range pvcs { 25 | if pvcs[i].Name == pvcName { 26 | return &pvcs[i] 27 | } 28 | } 29 | return nil 30 | } 31 | 32 | func IsPodVolumeReclaimPolicyDelete(vol *corev1.Volume, pvs []corev1.PersistentVolume, pvcs []corev1.PersistentVolumeClaim) bool { 33 | // Check if the Volume is bound to a PVC. 34 | if putPVC := getPVCFromSlice(pvcs, vol.PersistentVolumeClaim.ClaimName); putPVC != nil { 35 | // Loop through the PersistentVolumes in the cluster, looking for bound PV/PVCs. 36 | for pvIndex := range pvs { 37 | // Check to make sure its reclaim policy is DELETE. 38 | if putPVC.Spec.VolumeName == pvs[pvIndex].Name && pvs[pvIndex].Spec.PersistentVolumeReclaimPolicy == corev1.PersistentVolumeReclaimDelete { 39 | return true 40 | } 41 | } 42 | } 43 | 44 | return false 45 | } 46 | -------------------------------------------------------------------------------- /internal/datautil/data_util_test.go: -------------------------------------------------------------------------------- 1 | package datautil 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestIsMapSubset(t *testing.T) { 10 | testCasesStr := []struct { 11 | m map[string]string 12 | s map[string]string 13 | expected bool 14 | }{ 15 | { 16 | m: map[string]string{"k1": "v1", "k2": "v2", "k3": "v3"}, 17 | s: map[string]string{"k1": "v1", "k2": "v2"}, 18 | expected: true, 19 | }, 20 | { 21 | m: map[string]string{"k1": "v1", "k2": "v2", "k3": "v3"}, 22 | s: map[string]string{"k1": "v1", "k0": "v0"}, 23 | expected: false, 24 | }, 25 | { 26 | m: map[string]string{"k1": "v1", "k2": "v2", "k3": "v3"}, 27 | s: map[string]string{"k1": "v1", "k2": "v2", "k3": "v3", "k0": "v0"}, 28 | expected: false, 29 | }, 30 | { 31 | m: map[string]string{"k1": "v1", "k2": "v2", "k3": "v3"}, 32 | s: map[string]string{}, 33 | expected: true, 34 | }, 35 | } 36 | 37 | for _, tc := range testCasesStr { 38 | assert.Equal(t, tc.expected, IsMapSubset(tc.m, tc.s)) 39 | } 40 | 41 | testCasesInt := []struct { 42 | m map[string]int 43 | s map[string]int 44 | expected bool 45 | }{ 46 | { 47 | m: map[string]int{"k1": 1, "k2": 2, "k3": 3}, 48 | s: map[string]int{"k1": 1, "k2": 2}, 49 | expected: true, 50 | }, 51 | { 52 | m: map[string]int{"k1": 1, "k2": 2, "k3": 3}, 53 | s: map[string]int{"k1": 1, "k0": 0}, 54 | expected: false, 55 | }, 56 | { 57 | m: map[string]int{"k1": 1, "k2": 2, "k3": 3}, 58 | s: map[string]int{"k1": 1, "k2": 2, "k3": 3, "k0": 0}, 59 | expected: false, 60 | }, 61 | } 62 | 63 | for _, tc := range testCasesInt { 64 | assert.Equal(t, tc.expected, IsMapSubset(tc.m, tc.s)) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /pkg/autodiscover/autodiscover_clusteroperators_test.go: -------------------------------------------------------------------------------- 1 | package autodiscover 2 | 3 | import ( 4 | "testing" 5 | 6 | configv1 "github.com/openshift/api/config/v1" 7 | fakeClientConfigv1 "github.com/openshift/client-go/config/clientset/versioned/fake" 8 | "github.com/stretchr/testify/assert" 9 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 10 | ) 11 | 12 | func TestFindClusterOperators(t *testing.T) { 13 | generateClusterOperator := func(name string, availableStatus configv1.ConditionStatus, degradedStatus configv1.ConditionStatus, progressingStatus configv1.ConditionStatus) *configv1.ClusterOperator { 14 | return &configv1.ClusterOperator{ 15 | ObjectMeta: metav1.ObjectMeta{ 16 | Name: name, 17 | }, 18 | Status: configv1.ClusterOperatorStatus{ 19 | Conditions: []configv1.ClusterOperatorStatusCondition{ 20 | { 21 | Type: configv1.OperatorAvailable, 22 | Status: availableStatus, 23 | }, 24 | { 25 | Type: configv1.OperatorDegraded, 26 | Status: degradedStatus, 27 | }, 28 | { 29 | Type: configv1.OperatorProgressing, 30 | Status: progressingStatus, 31 | }, 32 | }, 33 | }, 34 | } 35 | } 36 | 37 | // Generate a test object, store it to the fake client, and then retrieve it. 38 | testObject := generateClusterOperator("test-cluster-operator", configv1.ConditionTrue, configv1.ConditionFalse, configv1.ConditionFalse) 39 | 40 | client := fakeClientConfigv1.NewClientset(testObject) 41 | clusterOperators, err := findClusterOperators(client.ConfigV1().ClusterOperators()) 42 | 43 | // Assert that the test object was retrieved successfully. 44 | assert.Nil(t, err) 45 | assert.Len(t, clusterOperators, 1) 46 | assert.Equal(t, testObject.Name, clusterOperators[0].Name) 47 | assert.Equal(t, testObject.Status.Conditions, clusterOperators[0].Status.Conditions) 48 | } 49 | -------------------------------------------------------------------------------- /tests/operator/openapi/openapi_test.go: -------------------------------------------------------------------------------- 1 | package openapi 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 8 | ) 9 | 10 | func TestIsCRDDefinedWithOpenAPI3Schema(t *testing.T) { 11 | testCases := []struct { 12 | testCRD *apiextv1.CustomResourceDefinition 13 | expectedOutput bool 14 | }{ 15 | { 16 | testCRD: &apiextv1.CustomResourceDefinition{ 17 | Spec: apiextv1.CustomResourceDefinitionSpec{ 18 | Versions: []apiextv1.CustomResourceDefinitionVersion{ 19 | { 20 | Schema: &apiextv1.CustomResourceValidation{ 21 | OpenAPIV3Schema: &apiextv1.JSONSchemaProps{}, 22 | }, 23 | }, 24 | }, 25 | }, 26 | }, 27 | expectedOutput: true, 28 | }, 29 | { 30 | testCRD: &apiextv1.CustomResourceDefinition{ 31 | Spec: apiextv1.CustomResourceDefinitionSpec{ 32 | Versions: []apiextv1.CustomResourceDefinitionVersion{ 33 | { 34 | Schema: &apiextv1.CustomResourceValidation{}, 35 | }, 36 | }, 37 | }, 38 | }, 39 | expectedOutput: true, 40 | }, 41 | { 42 | testCRD: &apiextv1.CustomResourceDefinition{ 43 | Spec: apiextv1.CustomResourceDefinitionSpec{ 44 | Versions: []apiextv1.CustomResourceDefinitionVersion{ 45 | { 46 | Schema: &apiextv1.CustomResourceValidation{ 47 | OpenAPIV3Schema: &apiextv1.JSONSchemaProps{}, 48 | }, 49 | }, 50 | }, 51 | }, 52 | }, 53 | expectedOutput: true, 54 | }, 55 | { 56 | testCRD: &apiextv1.CustomResourceDefinition{ 57 | Spec: apiextv1.CustomResourceDefinitionSpec{ 58 | Versions: nil, 59 | }, 60 | }, 61 | expectedOutput: false, 62 | }, 63 | } 64 | 65 | for _, tc := range testCases { 66 | assert.Equal(t, tc.expectedOutput, IsCRDDefinedWithOpenAPI3Schema(tc.testCRD)) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /.github/workflows/preflight.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Preflight 3 | 'on': 4 | schedule: 5 | - cron: '0 0 * * *' 6 | # pull_request: 7 | # branches: [ main ] 8 | workflow_dispatch: 9 | 10 | permissions: 11 | contents: read 12 | 13 | jobs: 14 | preflight-unstable: 15 | if: github.repository_owner == 'redhat-best-practices-for-k8s' 16 | runs-on: ubuntu-24.04 17 | env: 18 | SHELL: /bin/bash 19 | IMAGE_NAME: quay.io/redhat-best-practices-for-k8s/certsuite:unstable 20 | 21 | steps: 22 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 23 | 24 | - name: Set up Go 25 | uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 26 | with: 27 | go-version-file: go.mod 28 | 29 | - name: Disable default go problem matcher 30 | run: echo "::remove-matcher owner=go::" 31 | 32 | - name: Clone the preflight repository 33 | uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 34 | with: 35 | repository: redhat-openshift-ecosystem/openshift-preflight 36 | path: openshift-preflight 37 | ref: 1.14.1 38 | 39 | - name: Run preflight 40 | working-directory: openshift-preflight 41 | run: | 42 | make build 43 | ./preflight check container ${{ env.IMAGE_NAME }} --artifacts ${GITHUB_WORKSPACE}/openshift-preflight/artifacts 44 | 45 | ALLOWED_FAILURES=("HasLicense" "RunAsNonRoot") 46 | FAILURES=$(cat ${GITHUB_WORKSPACE}/openshift-preflight/artifacts/amd64/results.json | jq -r '.results.failed[].name') 47 | 48 | for FAILURE in $FAILURES; do 49 | FAILURE=$(echo $FAILURE | tr -d '"') 50 | if [[ ! "${ALLOWED_FAILURES[@]}" =~ "${FAILURE}" ]]; then 51 | echo >&2 "ERROR: $FAILURE is not an allowed failure" 52 | exit 1 53 | fi 54 | done 55 | -------------------------------------------------------------------------------- /tests/operator/access/access_test.go: -------------------------------------------------------------------------------- 1 | package access 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/operator-framework/api/pkg/operators/v1alpha1" 7 | "github.com/stretchr/testify/assert" 8 | rbacv1 "k8s.io/api/rbac/v1" 9 | ) 10 | 11 | func TestPermissionsHaveBadRule(t *testing.T) { 12 | generateSDP := func(apiGroups []string, resources []string) v1alpha1.StrategyDeploymentPermissions { 13 | return v1alpha1.StrategyDeploymentPermissions{ 14 | Rules: []rbacv1.PolicyRule{ 15 | { 16 | APIGroups: apiGroups, 17 | Resources: resources, 18 | }, 19 | }, 20 | } 21 | } 22 | 23 | testCases := []struct { 24 | testClusterPermissions []v1alpha1.StrategyDeploymentPermissions 25 | expectedResult bool 26 | }{ 27 | { // SCC granted - this is a bad rule 28 | testClusterPermissions: []v1alpha1.StrategyDeploymentPermissions{ 29 | generateSDP([]string{"security.openshift.io"}, []string{"*"}), 30 | }, 31 | expectedResult: true, 32 | }, 33 | { // SCC granted - this is a bad rule 34 | testClusterPermissions: []v1alpha1.StrategyDeploymentPermissions{ 35 | generateSDP([]string{"security.openshift.io"}, []string{"securitycontextconstraints"}), 36 | }, 37 | expectedResult: true, 38 | }, 39 | { // SCC granted - this is a bad rule 40 | testClusterPermissions: []v1alpha1.StrategyDeploymentPermissions{ 41 | generateSDP([]string{"security.openshift.io"}, []string{"*"}), 42 | generateSDP([]string{"security.openshift.io"}, []string{"securitycontextconstraints"}), 43 | }, 44 | expectedResult: true, 45 | }, 46 | { // No bad rule 47 | testClusterPermissions: []v1alpha1.StrategyDeploymentPermissions{ 48 | generateSDP([]string{"security.heathytest.io"}, []string{"*"}), 49 | }, 50 | expectedResult: false, 51 | }, 52 | } 53 | 54 | for _, tc := range testCases { 55 | assert.Equal(t, tc.expectedResult, PermissionsHaveBadRule(tc.testClusterPermissions)) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /pkg/provider/statefulsets.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package provider 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/redhat-best-practices-for-k8s/certsuite/pkg/autodiscover" 23 | appsv1 "k8s.io/api/apps/v1" 24 | appv1client "k8s.io/client-go/kubernetes/typed/apps/v1" 25 | ) 26 | 27 | type StatefulSet struct { 28 | *appsv1.StatefulSet 29 | } 30 | 31 | func (ss *StatefulSet) IsStatefulSetReady() bool { 32 | var replicas int32 33 | if ss.Spec.Replicas != nil { 34 | replicas = *(ss.Spec.Replicas) 35 | } else { 36 | replicas = 1 37 | } 38 | if ss.Status.ReadyReplicas != replicas || 39 | ss.Status.CurrentReplicas != replicas || 40 | ss.Status.UpdatedReplicas != replicas { 41 | return false 42 | } 43 | return true 44 | } 45 | 46 | func (ss *StatefulSet) ToString() string { 47 | return fmt.Sprintf("statefulset: %s ns: %s", 48 | ss.Name, 49 | ss.Namespace, 50 | ) 51 | } 52 | 53 | func GetUpdatedStatefulset(ac appv1client.AppsV1Interface, namespace, name string) (*StatefulSet, error) { 54 | result, err := autodiscover.FindStatefulsetByNameByNamespace(ac, namespace, name) 55 | return &StatefulSet{ 56 | result, 57 | }, err 58 | } 59 | -------------------------------------------------------------------------------- /tests/certification/suite_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package certification 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/redhat-best-practices-for-k8s/certsuite/pkg/provider" 23 | "github.com/stretchr/testify/assert" 24 | ) 25 | 26 | func TestGetContainersToQuery(t *testing.T) { 27 | var testEnv = provider.TestEnvironment{ 28 | Containers: []*provider.Container{ 29 | { 30 | ContainerImageIdentifier: provider.ContainerImageIdentifier{ 31 | Repository: "test1", 32 | Registry: "repo1", 33 | }, 34 | }, 35 | { 36 | ContainerImageIdentifier: provider.ContainerImageIdentifier{ 37 | Repository: "test2", 38 | Registry: "repo2", 39 | }, 40 | }, 41 | }, 42 | } 43 | 44 | testCases := []struct { 45 | expectedOutput map[provider.ContainerImageIdentifier]bool 46 | }{ 47 | { 48 | expectedOutput: map[provider.ContainerImageIdentifier]bool{ 49 | { 50 | Repository: "test1", 51 | Registry: "repo1", 52 | }: true, 53 | { 54 | Repository: "test2", 55 | Registry: "repo2", 56 | }: true, 57 | }, 58 | }, 59 | } 60 | 61 | for _, tc := range testCases { 62 | assert.Equal(t, tc.expectedOutput, getContainersToQuery(&testEnv)) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /cmd/certsuite/claim/compare/nodes/nodes.go: -------------------------------------------------------------------------------- 1 | package nodes 2 | 3 | import ( 4 | "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/claim/compare/diff" 5 | "github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/pkg/claim" 6 | ) 7 | 8 | // Structure that holds a summary of nodes roles and a slice of NodeDiffReports, 9 | // one per node found in both claim files. In case one node only exists in one 10 | // claim file, it will be marked as "not found in claim[1|2]". 11 | type DiffReport struct { 12 | Nodes *diff.Diffs `json:"nodes"` 13 | CNI *diff.Diffs `json:"CNI"` 14 | CSI *diff.Diffs `json:"CSI"` 15 | Hardware *diff.Diffs `json:"hardware"` 16 | } 17 | 18 | // Stringer method to show in a table the the differences found on each node 19 | // appearing on both claim files. If a node only appears in one claim file, it 20 | // will be flagged as "not found in claim[1|2]" 21 | func (d DiffReport) String() string { 22 | str := "CLUSTER NODES DIFFERENCES\n" 23 | str += "-------------------------\n\n" 24 | 25 | if d.Nodes != nil { 26 | str += d.Nodes.String() + "\n" 27 | } 28 | 29 | if d.CNI != nil { 30 | str += d.CNI.String() + "\n" 31 | } 32 | 33 | if d.CSI != nil { 34 | str += d.CSI.String() + "\n" 35 | } 36 | 37 | if d.Hardware != nil { 38 | str += d.Hardware.String() + "\n" 39 | } 40 | 41 | return str 42 | } 43 | 44 | // Generates a DiffReport from two pointers to claim.Nodes. The report consists 45 | // of a diff.Diffs object per node's section (CNIs, CSIs & Hardware). 46 | func GetDiffReport(claim1Nodes, claim2Nodes *claim.Nodes) *DiffReport { 47 | return &DiffReport{ 48 | Nodes: diff.Compare("Nodes", claim1Nodes.NodesSummary, claim2Nodes.NodesSummary, []string{"labels", "annotations"}), 49 | CNI: diff.Compare("CNIs", claim1Nodes.CniNetworks, claim2Nodes.CniNetworks, nil), 50 | CSI: diff.Compare("CSIs", claim1Nodes.CsiDriver, claim2Nodes.CsiDriver, nil), 51 | Hardware: diff.Compare("Hardware", claim1Nodes.NodesHwInfo, claim2Nodes.NodesHwInfo, nil), 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /pkg/autodiscover/autodiscover_networkpolicies_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package autodiscover 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/stretchr/testify/assert" 23 | networkingv1 "k8s.io/api/networking/v1" 24 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | "k8s.io/apimachinery/pkg/runtime" 26 | k8sfake "k8s.io/client-go/kubernetes/fake" 27 | ) 28 | 29 | func TestGetNetworkPolicies(t *testing.T) { 30 | testCases := []struct { 31 | expectedNetworkPolicies []*networkingv1.NetworkPolicy 32 | }{ 33 | { 34 | expectedNetworkPolicies: []*networkingv1.NetworkPolicy{ 35 | { 36 | ObjectMeta: metav1.ObjectMeta{ 37 | Name: "test-network-policy", 38 | Namespace: "test-namespace", 39 | }, 40 | }, 41 | }, 42 | }, 43 | } 44 | 45 | for _, testCase := range testCases { 46 | var runtimeObjects []runtime.Object 47 | for _, networkPolicy := range testCase.expectedNetworkPolicies { 48 | runtimeObjects = append(runtimeObjects, networkPolicy) 49 | } 50 | 51 | // Create fake client 52 | client := k8sfake.NewSimpleClientset(runtimeObjects...) 53 | networkPolicies, err := getNetworkPolicies(client.NetworkingV1()) 54 | assert.Nil(t, err) 55 | assert.Len(t, networkPolicies, len(testCase.expectedNetworkPolicies)) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /pkg/provider/scale_object_test.go: -------------------------------------------------------------------------------- 1 | package provider 2 | 3 | import ( 4 | "testing" 5 | 6 | scalingv1 "k8s.io/api/autoscaling/v1" 7 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 8 | ) 9 | 10 | func TestCrScale_ToString(t *testing.T) { 11 | type fields struct { 12 | Scale *scalingv1.Scale 13 | } 14 | tests := []struct { 15 | name string 16 | fields fields 17 | want string 18 | }{ 19 | { 20 | name: "test1", 21 | fields: fields{ 22 | Scale: &scalingv1.Scale{ 23 | ObjectMeta: metav1.ObjectMeta{ 24 | Name: "test1", 25 | Namespace: "testNS", 26 | }, 27 | }, 28 | }, 29 | want: "cr: test1 ns: testNS", 30 | }, 31 | } 32 | for _, tt := range tests { 33 | t.Run(tt.name, func(t *testing.T) { 34 | crScale := CrScale{ 35 | Scale: tt.fields.Scale, 36 | } 37 | if got := crScale.ToString(); got != tt.want { 38 | t.Errorf("CrScale.ToString() = %v, want %v", got, tt.want) 39 | } 40 | }) 41 | } 42 | } 43 | 44 | func TestIsScaleObjectReady(t *testing.T) { 45 | type fields struct { 46 | Scale *scalingv1.Scale 47 | } 48 | tests := []struct { 49 | name string 50 | fields fields 51 | want bool 52 | }{ 53 | { 54 | name: "test1", 55 | fields: fields{ 56 | Scale: &scalingv1.Scale{ 57 | Spec: scalingv1.ScaleSpec{ 58 | Replicas: 2, 59 | }, 60 | Status: scalingv1.ScaleStatus{ 61 | Replicas: 2, 62 | }, 63 | }, 64 | }, 65 | want: true, 66 | }, 67 | { 68 | name: "test2", 69 | fields: fields{ 70 | Scale: &scalingv1.Scale{ 71 | Spec: scalingv1.ScaleSpec{ 72 | Replicas: 2, 73 | }, 74 | Status: scalingv1.ScaleStatus{ 75 | Replicas: 3, 76 | }, 77 | }, 78 | }, 79 | want: false, 80 | }, 81 | } 82 | for _, tt := range tests { 83 | t.Run(tt.name, func(t *testing.T) { 84 | crScale := CrScale{ 85 | Scale: tt.fields.Scale, 86 | } 87 | if got := crScale.IsScaleObjectReady(); got != tt.want { 88 | t.Errorf("CrScale.IsScaleObjectReady() = %v, want %v", got, tt.want) 89 | } 90 | }) 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /tests/accesscontrol/pidshelper.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package accesscontrol 18 | 19 | import ( 20 | "fmt" 21 | "strconv" 22 | "strings" 23 | 24 | "github.com/redhat-best-practices-for-k8s/certsuite/internal/clientsholder" 25 | ) 26 | 27 | const nbProcessesIndex = 2 28 | 29 | // getNbOfProcessesInPidNamespace retrieves the number of processes in the Pid namespace. 30 | // Returns: 31 | // - int : the number of processes in the PID namespace associated with the specified process ID 32 | // - error : An error, if any occurred during the execution of the command or parsing of the output. 33 | func getNbOfProcessesInPidNamespace(ctx clientsholder.Context, targetPid int, ch clientsholder.Command) (int, error) { 34 | cmd := "lsns -p " + strconv.Itoa(targetPid) + " -t pid -n" 35 | 36 | outStr, errStr, err := ch.ExecCommandContainer(ctx, cmd) 37 | if err != nil { 38 | return 0, fmt.Errorf("can not execute command: \" %s \", err:%s", cmd, err) 39 | } 40 | if errStr != "" { 41 | return 0, fmt.Errorf("cmd: \" %s \" returned %s", cmd, errStr) 42 | } 43 | 44 | retValues := strings.Fields(outStr) 45 | if len(retValues) <= nbProcessesIndex { 46 | return 0, fmt.Errorf("cmd: \" %s \" returned an invalid value %s", cmd, outStr) 47 | } 48 | return strconv.Atoi(retValues[nbProcessesIndex]) 49 | } 50 | -------------------------------------------------------------------------------- /docs/assets/images/overview.drawio: -------------------------------------------------------------------------------- 1 | 3VrZcqM4FP0aP8YldnhMnGUeekmVa6qnn7pkEIYZjGghx/Z8/UggDEh4DZCMSaqCroRA5567SZkYs9X2hcAs+ooDlEx0EGwnxuNE1zVT1yf8FwS7UuI4XilYkjgQg2rBPP4XCSEQ0nUcoLw1kGKc0DhrC32cpsinLRkkBG/aw0KctN+awSVSBHMfJqr0RxzQqJS6Fqjlf6B4GVVv1oDoWcFqsBDkEQzwpiEynibGjGBMy7vVdoYSDl6FS/nc84He/YcRlNJzHnhJol+zr/DHvfc0/5NqL9rvx7s73S6neYPJWqxYfC3dVRAQvE4DxGcBE+NhE8UUzTPo894NUzqTRXSVsJbGbsM4SWY4waR41gggckOfyXNK8D+o0WP7LlqErEddh1jaGyIUbRsisa4XhFeIkh0bUvU6AmNBsj3mm1plVqWyqKEuvXoQCpos93PXSLIbAeYFwA6Ma2jxn05ci4s/gVPakJdXT3i7Et6GirfmdeENhsJbV/DOcMAEWr+wh6Hud9I5sBe2ZfcDry7Da6vwOpaKrjkUuI4C7uzbMxNwIAn3yCinCs5ssbQNZhu0FKdIQliIYBIvU9b0GYRsfuOBQxczn3wvOlZxEPDXdGqvrd+x2A462T6QPtzTzgWlwT0PfzWqAcyjAhatrRUuf4WUIZ0WEh0Ye11VIY+h88AAJLu/OKxTq2r+FHMUjcetwLxs7U5pIMdr4qMjyzRFvIdkiehp20dBK5Sr+mxGgw51VTKCEkjjt3YC0KVD8YZXHLOV7eligjZdTJkG5brFU82ALU9ktScy5GBVAqNMVFBqv+zrWaZ5KqsYxHPRxIRGeIlTmDzVUsn66jFfMM4EWf5GlO5EpgfXFLfpiLYxLVmmW6L5s9FVk4w3dk3GjcrNKj89SU7zTHJexjpm23DXGJBxEuRHSClxqSLpudwz7ePjDc09Np7dlF/cK0ENNbg3CSr8Xm+M1Bp0FDw7SEglPwDAcgBQMwoAXAjaFG4SuMHnj6Ow7vXN4XdFv+q7G+HP5wlCyFIEGuO0rAYpjFOenDyjLfL7TQJdH3UngQvX4obTS9ZhapL376hpulJse7AMGygojhEOas+uX+Ta6zjinB9HxjCmQeKB4pBtOQvRrsxCDN2ZWsenOpCHXByjXOk98obGqfHu8fG65x0bP0yM2ht+7azImruoojx9bjgqsIA5CkQ1lSu2djPllCEzs6O6PbB5MJRnU+vbiW4nVGyitPRg/17jquMuL7zWPd9mcLNt3cnulvzv9wyleRSHtJqOfV45Y9l/u0q2vLaS9xttTSUboyrZU5TcUA9YwZwWVsgtkuAk4Y2b2bCz7Lbr29tgUx16hzoG21Iy1CRuhgn6PmeyVxb5QkxWzEzgisOaLvKsy1xuSCHWhyukYw9pgGLqcGF0bQF0sKC6omwbIf+riD90Amg6EsOuTQAteSLZRQ+8DcVMTvYU2d5B3HqyZGlSztrhuM0xw6j5efdcGqUisFul4hSY+gkvUrReEYkZTFzvh3Zx+PW+Te0PKxTfp3c1XhOUJcwycsSdxTvP2dTzNMdbdO2XhSGyi82XHoxLcx0pK7IU43JGNS7V0xWHmNt+M58POcQ0PvoQ01TjSIvB6S0wuAvkURmsUliNF5//aPKTHCXqFXqyei/N4di7p7YtpXHWqGmcaf8PEofLKo9B0gPjzPRgmHNFlTm2c5w2Z1PQM6cWqC+J2RojqOPV18jkdD4tOYck2ejkca/1X3IyYY1bg5rup+XHiM5rcLpYEl20a32NTJfeYh1r1v+xWw6v/+/ZePoP -------------------------------------------------------------------------------- /cmd/certsuite/claim/show/csv/cnf-type.json: -------------------------------------------------------------------------------- 1 | { 2 | "klusterlet-product": "Telco", 3 | "elasticsearch-operator": "Telco", 4 | "mtv-operator": "Telco", 5 | "sandboxed-containers-operator": "Telco", 6 | "sriov-network-operator": "Telco", 7 | "multicluster-engine": "Telco", 8 | "openshift-gitops-operator": "Telco", 9 | "bare-metal-event-relay": "Telco", 10 | "jaeger-product": "Telco", 11 | "kubevirt-hyperconverged": "Telco", 12 | "clusterresourceoverride": "Telco", 13 | "node-maintenance-operator": "Telco", 14 | "costmanagement-metrics-operator": "Telco", 15 | "loki-operator": "Telco", 16 | "opentelemetry-product": "Telco", 17 | "openshift-secondary-scheduler-operator": "Telco", 18 | "openshift-pipelines-operator-rh": "Telco", 19 | "dpu-network-operator": "Telco", 20 | "devspaces": "Telco", 21 | "jws-operator": "Telco", 22 | "compliance-operator": "Telco", 23 | "vertical-pod-autoscaler": "Telco", 24 | "nfd": "Telco", 25 | "quay-operator": "Telco", 26 | "node-observability-operator": "Telco", 27 | "container-security-operator": "Telco", 28 | "aws-efs-csi-driver-operator": "Telco", 29 | "redhat-oadp-operator": "Telco", 30 | "cluster-logging": "Telco", 31 | "quay-bridge-operator": "Telco", 32 | "web-terminal": "Telco", 33 | "openshift-cert-manager-operator": "Telco", 34 | "aws-load-balancer-operator": "Telco", 35 | "topology-aware-lifecycle-manager": "Telco", 36 | "openshift-custom-metrics-autoscaler-operator": "Telco", 37 | "serverless-operator": "Telco", 38 | "metallb-operator": "Telco", 39 | "rhsso-operator": "Telco", 40 | "external-dns-operator": "Telco", 41 | "local-storage-operator": "Telco", 42 | "ptp-operator": "Telco", 43 | "numaresources-operator": "Telco", 44 | "kubernetes-nmstate-operator": "Telco", 45 | "self-node-remediation": "Telco", 46 | "servicemeshoperator": "Telco", 47 | "file-integrity-operator": "Telco", 48 | "kiali-ossm": "Telco", 49 | "node-healthcheck-operator": "Telco", 50 | "lvms-operator": "Telco", 51 | "power-monitoring-operator": "Telco", 52 | "tempo-operator": "Telco", 53 | "loki-operator": "Telco" 54 | } -------------------------------------------------------------------------------- /pkg/arrayhelper/arrayhelper.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2023 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package arrayhelper 18 | 19 | import ( 20 | "strings" 21 | ) 22 | 23 | // ArgListToMap takes a list of strings of the form "key=value" and translate it into a map 24 | // of the form {key: value} 25 | func ArgListToMap(lst []string) map[string]string { 26 | retval := make(map[string]string) 27 | for _, arg := range lst { 28 | arg = strings.ReplaceAll(arg, `"`, ``) 29 | splitArgs := strings.Split(arg, "=") 30 | if len(splitArgs) == 1 { 31 | retval[splitArgs[0]] = "" 32 | } else { 33 | retval[splitArgs[0]] = splitArgs[1] 34 | } 35 | } 36 | return retval 37 | } 38 | 39 | // FilterArray takes a list and a predicate and returns a list of all elements for whom the predicate returns true 40 | func FilterArray(vs []string, f func(string) bool) []string { 41 | vsf := make([]string, 0) 42 | for _, v := range vs { 43 | if f(v) { 44 | vsf = append(vsf, v) 45 | } 46 | } 47 | return vsf 48 | } 49 | 50 | func Unique(slice []string) []string { 51 | // create a map with all the values as key 52 | uniqMap := make(map[string]struct{}) 53 | for _, v := range slice { 54 | uniqMap[v] = struct{}{} 55 | } 56 | 57 | // turn the map keys into a slice 58 | uniqSlice := make([]string, 0, len(uniqMap)) 59 | for v := range uniqMap { 60 | uniqSlice = append(uniqSlice, v) 61 | } 62 | return uniqSlice 63 | } 64 | -------------------------------------------------------------------------------- /docs/test-spec.md: -------------------------------------------------------------------------------- 1 | 2 | # Test Specifications 3 | 4 | ## Available Test Specs 5 | 6 | There are two categories for workload tests. 7 | 8 | - **General** 9 | 10 | These tests are designed to test any commodity workload running on OpenShift, and include specifications such as 11 | `Default` network connectivity. 12 | 13 | - **Workload-Specific** 14 | 15 | These tests are designed to test some unique aspects of the workload under test are behaving correctly. This could 16 | include specifications such as issuing a `GET` request to a web server, or passing traffic through an IPSEC tunnel. 17 | 18 | ### General tests 19 | 20 | These tests belong to multiple suites that can be run in any combination as is 21 | appropriate for the workload under test. 22 | 23 | !!! info 24 | 25 | Test suites group tests by the topic areas. 26 | 27 | Suite|Test Spec Description|Minimum OpenShift Version 28 | ---|---|--- 29 | `access-control`|The access-control test suite is used to test service account, namespace and cluster/pod role binding for the pods under test. It also tests the pods/containers configuration.|4.6.0 30 | `affiliated-certification`|The affiliated-certification test suite verifies that the containers and operators discovered or listed in the configuration file are certified by Redhat|4.6.0 31 | `lifecycle`| The lifecycle test suite verifies the pods deployment, creation, shutdown and survivability. |4.6.0 32 | `networking`|The networking test suite contains tests that check connectivity and networking config related best practices.|4.6.0 33 | `operator`|The operator test suite is designed to test basic Kubernetes Operator functionality.|4.6.0 34 | `platform-alteration`| verifies that key platform configuration is not modified by the workload under test|4.6.0 35 | `observability`| the observability test suite contains tests that check workload logging is following best practices and that CRDs have status fields|4.6.0 36 | 37 | !!! info 38 | 39 | Please refer [CATALOG.md](https://github.com/redhat-best-practices-for-k8s/certsuite/blob/main/CATALOG.md) for more details. 40 | 41 | ### Workload-specific tests 42 | 43 | TODO 44 | -------------------------------------------------------------------------------- /pkg/autodiscover/autodiscover_pv.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package autodiscover 18 | 19 | import ( 20 | "context" 21 | 22 | "github.com/redhat-best-practices-for-k8s/certsuite/internal/log" 23 | corev1 "k8s.io/api/core/v1" 24 | storagev1 "k8s.io/api/storage/v1" 25 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 | corev1client "k8s.io/client-go/kubernetes/typed/core/v1" 27 | storagev1typed "k8s.io/client-go/kubernetes/typed/storage/v1" 28 | ) 29 | 30 | func getPersistentVolumes(oc corev1client.CoreV1Interface) ([]corev1.PersistentVolume, error) { 31 | pvs, err := oc.PersistentVolumes().List(context.TODO(), metav1.ListOptions{}) 32 | if err != nil { 33 | return nil, err 34 | } 35 | return pvs.Items, nil 36 | } 37 | 38 | func getPersistentVolumeClaims(oc corev1client.CoreV1Interface) ([]corev1.PersistentVolumeClaim, error) { 39 | pvcs, err := oc.PersistentVolumeClaims("").List(context.TODO(), metav1.ListOptions{}) 40 | if err != nil { 41 | return nil, err 42 | } 43 | return pvcs.Items, nil 44 | } 45 | 46 | func getAllStorageClasses(client storagev1typed.StorageV1Interface) ([]storagev1.StorageClass, error) { 47 | storageclasslist, err := client.StorageClasses().List(context.TODO(), metav1.ListOptions{}) 48 | if err != nil { 49 | log.Error("Error when listing storage classes, err: %v", err) 50 | return nil, err 51 | } 52 | return storageclasslist.Items, nil 53 | } 54 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | site_name: Red Hat Best Practices Test Suite for Kubernetes 3 | repo_name: GitHub 4 | repo_url: https://github.com/redhat-best-practices-for-k8s/certsuite/ 5 | theme: 6 | name: material 7 | features: 8 | - navigation.indexes 9 | # - navigation.instant 10 | # - navigation.prune 11 | - navigation.sections 12 | - navigation.tabs 13 | # - navigation.tabs.sticky 14 | - navigation.top 15 | - navigation.tracking 16 | - content.tooltips 17 | - content.code.annotate 18 | palette: 19 | - scheme: default 20 | primary: indigo 21 | accent: indigo 22 | toggle: 23 | icon: material/brightness-7 24 | name: Switch to dark mode 25 | - scheme: slate 26 | primary: indigo 27 | accent: indigo 28 | toggle: 29 | icon: material/brightness-4 30 | name: Switch to light mode 31 | font: 32 | text: Roboto 33 | code: Roboto Mono 34 | 35 | markdown_extensions: 36 | - toc: 37 | permalink: true 38 | - abbr 39 | - attr_list 40 | - pymdownx.snippets 41 | - admonition 42 | - smarty 43 | - extra 44 | - codehilite 45 | - admonition 46 | - tables 47 | - pymdownx.details 48 | - pymdownx.superfences 49 | - markdown_include.include: 50 | base_path: docs 51 | - pymdownx.magiclink 52 | - pymdownx.superfences 53 | - pymdownx.details 54 | - pymdownx.mark 55 | - pymdownx.arithmatex: 56 | generic: true 57 | - pymdownx.snippets: 58 | auto_append: 59 | - includes/abbreviations.md 60 | 61 | plugins: 62 | - search 63 | 64 | nav: 65 | - "index.md" 66 | - Setup: 67 | - Test Configuration: "configuration.md" 68 | - Runtime environment variables: "runtime-env.md" 69 | - Run: "test-run.md" 70 | - Available Test Specs: 71 | - Test Specs: "test-spec.md" 72 | - Implementation: "test-spec-implementation.md" 73 | - Test Output: "test-output.md" 74 | - Exception Process: "exception.md" 75 | - Developers' Guide: 76 | - Developers: "developers.md" 77 | - Workload Developers: "workload-developers.md" 78 | - Reference: 79 | - reference.md 80 | - Data Collection: "data-collection.md" 81 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | 2 | # Overview 3 | 4 | This repository provides a set of test cases to verify the conformance of a workload with the Red Hat Best Practices for Kubernetes. 5 | 6 | !!! tip "Workload" 7 | 8 | The app (containers/pods/operators) we want to certify according Telco partner/Red Hat's best practices. 9 | 10 | !!! tip "Red Hat Best Practices Test Suite for Kubernetes" 11 | 12 | The tool we use to certify a workload. 13 | 14 | The purpose of the tests and the framework is to test the interaction of the workload with OpenShift Container Platform (OCP). 15 | 16 | !!! info 17 | 18 | This test suite is provided for the workload developers to test their workload's readiness for certification. 19 | Please see the [Developers' Guide](developers.md) for more information. 20 | 21 | **Features** 22 | 23 | * The test suite generates a report (`claim.json`) and saves the test execution log (`certsuite.log`) in a configurable output directory. 24 | 25 | * The catalog of the existing test cases and test building blocks are available in [CATALOG.md](https://github.com/redhat-best-practices-for-k8s/certsuite/blob/main/CATALOG.md) 26 | 27 | ## Architecture 28 | 29 | ![overview](assets/images/overview-new.svg) 30 | 31 | There are 3 building blocks in the above framework. 32 | 33 | * the `CertSuite` represents the workload to be certified. The Test Suite identifies the resources (containers/pods/operators etc) belonging to the workload via labels or static data entries in the Config File 34 | 35 | * the `Certification container/exec` is the Test Suite running on the platform or in a container. The executable verifies the workload under test configuration and its interactions with OpenShift 36 | 37 | * the `Debug` pods are part of a Kubernetes daemonset responsible to run various **privileged commands** on Kubernetes nodes. Debug pods are useful to run platform tests and test commands (e.g. ping) in container namespaces without changing the container image content. The probe daemonset is instantiated via the [privileged-daemonset](https://github.com/redhat-best-practices-for-k8s/privileged-daemonset) repository. 38 | -------------------------------------------------------------------------------- /tests/identifiers/identifiers_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021-2024 Red Hat, Inc. 2 | // Copyright (C) 2021-2024 Red Hat, Inc. 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License along 15 | // with this program; if not, write to the Free Software Foundation, Inc., 16 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | 18 | package identifiers 19 | 20 | import ( 21 | "testing" 22 | 23 | "github.com/redhat-best-practices-for-k8s/certsuite-claim/pkg/claim" 24 | "github.com/redhat-best-practices-for-k8s/certsuite/pkg/stringhelper" 25 | "github.com/stretchr/testify/assert" 26 | ) 27 | 28 | func TestGetTestIDAndLabels(t *testing.T) { 29 | testCases := []struct { 30 | testIdentifier claim.Identifier 31 | expectedIDOutput string 32 | expectedTagsOutput []string 33 | }{ 34 | { 35 | testIdentifier: claim.Identifier{ 36 | Id: "test-id-1", 37 | Suite: "test-suite", 38 | Tags: "tag1", 39 | }, 40 | expectedIDOutput: "test-id-1", 41 | expectedTagsOutput: []string{"tag1", "test-suite"}, 42 | }, 43 | { 44 | testIdentifier: claim.Identifier{ 45 | Id: "test-id-2", 46 | Suite: "test-suite2", 47 | Tags: "tag1,tag2,tag3", 48 | }, 49 | expectedIDOutput: "test-id-2", 50 | expectedTagsOutput: []string{"tag1", "tag2", "tag3", "test-suite2"}, 51 | }, 52 | } 53 | 54 | for _, tc := range testCases { 55 | resultID, resultTags := GetTestIDAndLabels(tc.testIdentifier) 56 | assert.Equal(t, tc.expectedIDOutput, resultID) 57 | for _, e := range tc.expectedTagsOutput { 58 | assert.True(t, stringhelper.StringInSlice(resultTags, e, false)) 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /tests/lifecycle/ownerreference/ownerreference.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package ownerreference 18 | 19 | import ( 20 | "github.com/redhat-best-practices-for-k8s/certsuite/internal/log" 21 | "github.com/redhat-best-practices-for-k8s/certsuite/pkg/testhelper" 22 | corev1 "k8s.io/api/core/v1" 23 | ) 24 | 25 | const ( 26 | // statefulSet variable 27 | statefulSet = "StatefulSet" 28 | // replicaSet variable 29 | replicaSet = "ReplicaSet" 30 | ) 31 | 32 | type OwnerReference struct { 33 | put *corev1.Pod 34 | result int 35 | } 36 | 37 | func NewOwnerReference(put *corev1.Pod) *OwnerReference { 38 | o := OwnerReference{ 39 | put: put, 40 | result: testhelper.ERROR, 41 | } 42 | return &o 43 | } 44 | 45 | // func (o *OwnerReference) run the tests and store results in 46 | // o.result 47 | func (o *OwnerReference) RunTest(logger *log.Logger) { 48 | for _, k := range o.put.OwnerReferences { 49 | if k.Kind == statefulSet || k.Kind == replicaSet { 50 | logger.Info("Pod %q owner reference kind is %q", o.put, k.Kind) 51 | o.result = testhelper.SUCCESS 52 | } else { 53 | logger.Error("Pod %q has owner of type %q (%q or %q expected)", o.put, k.Kind, replicaSet, statefulSet) 54 | o.result = testhelper.FAILURE 55 | return 56 | } 57 | } 58 | } 59 | 60 | // GetResults return result of the OwnerReference type 61 | func (o *OwnerReference) GetResults() int { 62 | return o.result 63 | } 64 | -------------------------------------------------------------------------------- /pkg/autodiscover/autodiscover_resources_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package autodiscover 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/redhat-best-practices-for-k8s/certsuite/internal/clientsholder" 23 | "github.com/stretchr/testify/assert" 24 | corev1 "k8s.io/api/core/v1" 25 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 | "k8s.io/apimachinery/pkg/runtime" 27 | ) 28 | 29 | func TestGetResourceQuotas(t *testing.T) { 30 | generateResourceQuota := func(name string) *corev1.ResourceQuota { 31 | return &corev1.ResourceQuota{ 32 | ObjectMeta: metav1.ObjectMeta{ 33 | Name: name, 34 | }, 35 | Spec: corev1.ResourceQuotaSpec{}, 36 | } 37 | } 38 | 39 | testCases := []struct { 40 | rqName string 41 | expectedRQs []corev1.ResourceQuota 42 | }{ 43 | { 44 | rqName: "test1", 45 | expectedRQs: []corev1.ResourceQuota{ 46 | { 47 | ObjectMeta: metav1.ObjectMeta{ 48 | Name: "test1", 49 | }, 50 | }, 51 | }, 52 | }, 53 | } 54 | 55 | for _, tc := range testCases { 56 | var testRuntimeObjects []runtime.Object 57 | testRuntimeObjects = append(testRuntimeObjects, generateResourceQuota(tc.rqName)) 58 | oc := clientsholder.GetTestClientsHolder(testRuntimeObjects) 59 | resourceQuotas, err := getResourceQuotas(oc.K8sClient.CoreV1()) 60 | assert.Nil(t, err) 61 | assert.Equal(t, tc.expectedRQs[0].Name, resourceQuotas[0].Name) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /pkg/labels/labels.go: -------------------------------------------------------------------------------- 1 | package labels 2 | 3 | import ( 4 | "fmt" 5 | "go/ast" 6 | "go/parser" 7 | "go/token" 8 | "strings" 9 | 10 | "github.com/redhat-best-practices-for-k8s/certsuite/internal/log" 11 | ) 12 | 13 | type LabelsExprEvaluator interface { 14 | Eval(labels []string) bool 15 | } 16 | 17 | type labelsExprParser struct { 18 | astRootNode ast.Expr 19 | } 20 | 21 | func NewLabelsExprEvaluator(labelsExpr string) (LabelsExprEvaluator, error) { 22 | goLikeExpr := strings.ReplaceAll(labelsExpr, "-", "_") 23 | goLikeExpr = strings.ReplaceAll(goLikeExpr, ",", "||") 24 | 25 | node, err := parser.ParseExpr(goLikeExpr) 26 | if err != nil { 27 | return nil, fmt.Errorf("failed to parse labels expression %s: %v", labelsExpr, err) 28 | } 29 | 30 | return labelsExprParser{ 31 | astRootNode: node, 32 | }, nil 33 | } 34 | 35 | // Evaluates the labels expression against the labels slice. 36 | func (exprParser labelsExprParser) Eval(labels []string) bool { 37 | // Define a map for fast name/ident checking when visiting nodes. 38 | labelsMap := make(map[string]bool) 39 | for _, label := range labels { 40 | labelsMap[strings.ReplaceAll(label, "-", "_")] = true 41 | } 42 | 43 | // Visit function to walk the labels expression's AST. 44 | var visit func(e ast.Expr) bool 45 | visit = func(e ast.Expr) bool { 46 | switch v := e.(type) { 47 | case *ast.Ident: 48 | // If the expression is an identifier, check if it exists in the wordMap. 49 | if _, ok := labelsMap[v.Name]; !ok { 50 | return false 51 | } 52 | return true 53 | case *ast.ParenExpr: 54 | return visit(v.X) 55 | case *ast.UnaryExpr: 56 | if v.Op == token.NOT { 57 | return !visit(v.X) 58 | } 59 | case *ast.BinaryExpr: 60 | // If the expression is a binary expression, evaluate both operands. 61 | left := visit(v.X) 62 | right := visit(v.Y) 63 | switch v.Op { 64 | case token.LAND: 65 | return left && right 66 | case token.LOR: 67 | return left || right 68 | default: 69 | return false 70 | } 71 | default: 72 | log.Error("Unexpected/not-implemented expr: %v", v) 73 | return false 74 | } 75 | return false 76 | } 77 | 78 | return visit(exprParser.astRootNode) 79 | } 80 | -------------------------------------------------------------------------------- /pkg/provider/nodes_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package provider 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/stretchr/testify/assert" 23 | corev1 "k8s.io/api/core/v1" 24 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | ) 26 | 27 | func TestHasWorkloadDeployed(t *testing.T) { 28 | generateNode := func(nodeName string) *Node { 29 | return &Node{ 30 | Data: &corev1.Node{ 31 | ObjectMeta: metav1.ObjectMeta{ 32 | Name: nodeName, 33 | }, 34 | }, 35 | } 36 | } 37 | 38 | testCases := []struct { 39 | testNodeName string 40 | testPods []*Pod 41 | expected bool 42 | }{ 43 | { 44 | testNodeName: "node1", 45 | testPods: []*Pod{ 46 | { 47 | Pod: &corev1.Pod{ 48 | ObjectMeta: metav1.ObjectMeta{ 49 | Name: "pod1", 50 | }, 51 | Spec: corev1.PodSpec{ 52 | NodeName: "node1", 53 | }, 54 | }, 55 | }, 56 | }, 57 | expected: true, 58 | }, 59 | { 60 | testNodeName: "node1", 61 | testPods: []*Pod{ 62 | { 63 | Pod: &corev1.Pod{ 64 | ObjectMeta: metav1.ObjectMeta{ 65 | Name: "pod1", 66 | }, 67 | Spec: corev1.PodSpec{ 68 | NodeName: "node2", 69 | }, 70 | }, 71 | }, 72 | }, 73 | expected: false, 74 | }, 75 | } 76 | 77 | for _, testCase := range testCases { 78 | n := generateNode(testCase.testNodeName) 79 | assert.Equal(t, testCase.expected, n.HasWorkloadDeployed(testCase.testPods)) 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /pkg/autodiscover/autodiscover_events_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package autodiscover 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/stretchr/testify/assert" 23 | corev1 "k8s.io/api/core/v1" 24 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | "k8s.io/apimachinery/pkg/runtime" 26 | k8sfake "k8s.io/client-go/kubernetes/fake" 27 | ) 28 | 29 | func TestFindAbnormalEvents(t *testing.T) { 30 | testCases := []struct { 31 | expectedEvents []*corev1.Event 32 | }{ 33 | { 34 | expectedEvents: []*corev1.Event{ 35 | { 36 | Reason: "FailedMount", 37 | Type: "Warning", 38 | ObjectMeta: metav1.ObjectMeta{ 39 | Namespace: "test-namespace", 40 | Name: "test-event", 41 | }, 42 | }, 43 | }, 44 | }, 45 | } 46 | 47 | for _, testCase := range testCases { 48 | var runtimeObjects []runtime.Object 49 | for _, event := range testCase.expectedEvents { 50 | runtimeObjects = append(runtimeObjects, event) 51 | } 52 | 53 | // Create fake client 54 | client := k8sfake.NewSimpleClientset(runtimeObjects...) 55 | abnormalEvents := findAbnormalEvents(client.CoreV1(), []string{"test-namespace"}) 56 | assert.Len(t, abnormalEvents, len(testCase.expectedEvents)) 57 | 58 | for _, event := range abnormalEvents { 59 | for _, event2 := range testCase.expectedEvents { 60 | if event.Name == event2.Name { 61 | assert.Equal(t, event.Reason, event2.Reason) 62 | assert.Equal(t, event.Type, event2.Type) 63 | } 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /pkg/configuration/utils.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package configuration 18 | 19 | import ( 20 | "os" 21 | 22 | "github.com/redhat-best-practices-for-k8s/certsuite/internal/log" 23 | "gopkg.in/yaml.v3" 24 | ) 25 | 26 | var ( 27 | configuration = TestConfiguration{} 28 | confLoaded = false 29 | parameters = TestParameters{} 30 | ) 31 | 32 | // LoadConfiguration return a function that loads 33 | // the configuration from a file once 34 | func LoadConfiguration(filePath string) (TestConfiguration, error) { 35 | if confLoaded { 36 | log.Debug("config file already loaded, return previous element") 37 | return configuration, nil 38 | } 39 | 40 | log.Info("Loading config from file: %s", filePath) 41 | contents, err := os.ReadFile(filePath) 42 | if err != nil { 43 | return configuration, err 44 | } 45 | 46 | err = yaml.Unmarshal(contents, &configuration) 47 | if err != nil { 48 | return configuration, err 49 | } 50 | 51 | // Set default namespace for the probe daemonset pods, in case it was not set. 52 | if configuration.ProbeDaemonSetNamespace == "" { 53 | log.Warn("No namespace configured for the probe daemonset. Defaulting to namespace %q", defaultProbeDaemonSetNamespace) 54 | configuration.ProbeDaemonSetNamespace = defaultProbeDaemonSetNamespace 55 | } else { 56 | log.Info("Namespace for probe daemonset: %s", configuration.ProbeDaemonSetNamespace) 57 | } 58 | 59 | confLoaded = true 60 | return configuration, nil 61 | } 62 | 63 | func GetTestParameters() *TestParameters { 64 | return ¶meters 65 | } 66 | -------------------------------------------------------------------------------- /internal/results/html.go: -------------------------------------------------------------------------------- 1 | package results 2 | 3 | import ( 4 | _ "embed" 5 | "fmt" 6 | "os" 7 | "path/filepath" 8 | ) 9 | 10 | const ( 11 | htmlResultsFileName = "results.html" 12 | jsClaimVarFileName = "claimjson.js" 13 | 14 | writeFilePerms = 0o644 15 | ) 16 | 17 | //go:embed html/results.html 18 | var htmlResultsFileContent []byte 19 | 20 | // Creates the claimjson.js file from the claim.json file. 21 | func createClaimJSFile(claimFilePath, outputDir string) (filePath string, err error) { 22 | // Read claim.json content. 23 | claimContent, err := os.ReadFile(claimFilePath) 24 | if err != nil { 25 | return "", fmt.Errorf("failed to read claim file %s content in %s: %v", claimFilePath, outputDir, err) 26 | } 27 | 28 | // Add the content as the value for the js variable. 29 | jsClaimContent := "var initialjson = " + string(claimContent) 30 | 31 | filePath = filepath.Join(outputDir, jsClaimVarFileName) 32 | err = os.WriteFile(filePath, []byte(jsClaimContent), writeFilePerms) 33 | if err != nil { 34 | return "", fmt.Errorf("failed to write file %s: %v", filePath, err) 35 | } 36 | 37 | return filePath, nil 38 | } 39 | 40 | // Creates all the html/web related files needed for parsing the claim file in outputDir. 41 | // - claimjson.js 42 | // - results.html 43 | // - classification.js 44 | // Returns a slice with the paths of every file created. 45 | func CreateResultsWebFiles(outputDir, claimFileName string) (filePaths []string, err error) { 46 | type file struct { 47 | Path string 48 | Content []byte 49 | } 50 | 51 | staticFiles := []file{ 52 | { 53 | Path: filepath.Join(outputDir, htmlResultsFileName), 54 | Content: htmlResultsFileContent, 55 | }, 56 | } 57 | 58 | claimFilePath := filepath.Join(outputDir, claimFileName) 59 | claimJSFilePath, err := createClaimJSFile(claimFilePath, outputDir) 60 | if err != nil { 61 | return nil, fmt.Errorf("failed to create file %s: %v", jsClaimVarFileName, err) 62 | } 63 | 64 | filePaths = []string{claimJSFilePath} 65 | for _, f := range staticFiles { 66 | err := os.WriteFile(f.Path, f.Content, writeFilePerms) 67 | if err != nil { 68 | return nil, fmt.Errorf("failed to create file %s: %v", f.Path, err) 69 | } 70 | 71 | // Add this file path to the slice. 72 | filePaths = append(filePaths, f.Path) 73 | } 74 | 75 | return filePaths, nil 76 | } 77 | -------------------------------------------------------------------------------- /tests/lifecycle/ownerreference/ownerreference_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package ownerreference_test 18 | 19 | import ( 20 | "strings" 21 | "testing" 22 | 23 | "github.com/redhat-best-practices-for-k8s/certsuite/internal/log" 24 | "github.com/redhat-best-practices-for-k8s/certsuite/pkg/testhelper" 25 | "github.com/redhat-best-practices-for-k8s/certsuite/tests/lifecycle/ownerreference" 26 | "github.com/stretchr/testify/assert" 27 | corev1 "k8s.io/api/core/v1" 28 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 | ) 30 | 31 | func TestRunTest(t *testing.T) { 32 | testCases := []struct { 33 | podKind string 34 | expectedResult int 35 | }{ 36 | { 37 | podKind: "StatefulSet", 38 | expectedResult: testhelper.SUCCESS, 39 | }, 40 | { 41 | podKind: "ReplicaSet", 42 | expectedResult: testhelper.SUCCESS, 43 | }, 44 | { 45 | podKind: "NotARealKind", 46 | expectedResult: testhelper.FAILURE, 47 | }, 48 | } 49 | 50 | for _, tc := range testCases { 51 | testPod := &corev1.Pod{ 52 | ObjectMeta: metav1.ObjectMeta{ 53 | Name: "testpod", 54 | OwnerReferences: []metav1.OwnerReference{ 55 | { 56 | Kind: tc.podKind, 57 | }, 58 | }, 59 | }, 60 | Spec: corev1.PodSpec{}, 61 | } 62 | 63 | ownerRef := ownerreference.NewOwnerReference(testPod) 64 | assert.NotNil(t, ownerRef) 65 | var logArchive strings.Builder 66 | log.SetupLogger(&logArchive, "INFO") 67 | ownerRef.RunTest(log.GetLogger()) 68 | assert.Equal(t, tc.expectedResult, ownerRef.GetResults()) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /pkg/autodiscover/autodiscover_pdbs_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package autodiscover 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/redhat-best-practices-for-k8s/certsuite/internal/clientsholder" 23 | "github.com/stretchr/testify/assert" 24 | policyv1 "k8s.io/api/policy/v1" 25 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 | "k8s.io/apimachinery/pkg/runtime" 27 | ) 28 | 29 | func TestGetPodDisruptionBudgets(t *testing.T) { 30 | generatePodDisruptionBudget := func(name, namespace string) *policyv1.PodDisruptionBudget { 31 | return &policyv1.PodDisruptionBudget{ 32 | ObjectMeta: metav1.ObjectMeta{ 33 | Name: name, 34 | Namespace: namespace, 35 | }, 36 | Spec: policyv1.PodDisruptionBudgetSpec{}, 37 | } 38 | } 39 | 40 | testCases := []struct { 41 | pdbName string 42 | pdbNamespace string 43 | expectedPDBs []policyv1.PodDisruptionBudget 44 | }{ 45 | { 46 | pdbName: "testPdb", 47 | pdbNamespace: "tnf", 48 | expectedPDBs: []policyv1.PodDisruptionBudget{ 49 | { 50 | ObjectMeta: metav1.ObjectMeta{ 51 | Name: "testPdb", 52 | Namespace: "tnf", 53 | }, 54 | }, 55 | }, 56 | }, 57 | } 58 | 59 | for _, tc := range testCases { 60 | var testRuntimeObjects []runtime.Object 61 | testRuntimeObjects = append(testRuntimeObjects, generatePodDisruptionBudget(tc.pdbName, tc.pdbNamespace)) 62 | oc := clientsholder.GetTestClientsHolder(testRuntimeObjects) 63 | pdbs, err := getPodDisruptionBudgets(oc.K8sClient.PolicyV1(), []string{tc.pdbNamespace}) 64 | assert.Nil(t, err) 65 | assert.Equal(t, tc.expectedPDBs, pdbs) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /webserver/submit.js: -------------------------------------------------------------------------------- 1 | /** @param {HTMLFormElement} form */ 2 | export async function submit(form) { 3 | form.elements.submit.disabled = true; 4 | const formdata = new FormData(form); 5 | // Iterate over form elements and add those with non-empty values to FormData 6 | Array.from(form.elements).forEach(element => { // this loop for the checkbox values 7 | if (element.hasAttribute('value') && element.type != "checkbox") { 8 | formdata.append((element.id.match(/[a-zA-Z]/g) || []).join(''), element.value); 9 | } 10 | }); 11 | for (const el of form.elements) if (el instanceof HTMLFieldSetElement) el.disabled = true 12 | 13 | // Collect data from form fields -- will take all the fields 14 | const fields = Array.from(formdata.entries()).reduce((acc, [key, val]) => { 15 | if (acc[key] === undefined) { 16 | // If the key is not in the accumulator, set it to the value or an array with the value 17 | acc[key] = [val]; 18 | } else if (Array.isArray(acc[key])) { 19 | // If the key is already an array, push the new value to the array 20 | acc[key].push(val); 21 | } else { 22 | // If the key is a single value, convert it to an array with both values 23 | acc[key] = [acc[key], val]; 24 | } 25 | return acc; 26 | }, {}); 27 | 28 | delete fields.submit; // delete unnrrd data 29 | console.log(fields); 30 | formdata.append("jsonData", JSON.stringify(fields)); 31 | 32 | // Send an HTTP request to the server to run the function 33 | let heading; 34 | let message; 35 | let state = 'success'; 36 | 37 | try { // post request with the collected data 38 | const data = await fetch('/runFunction', { 39 | method: 'POST', 40 | body: formdata, 41 | }).then(response => { 42 | if (response.ok) { 43 | return response.json(); 44 | } else { 45 | throw new Error(response.statusText); 46 | } 47 | }); 48 | 49 | heading = 'Success'; 50 | message = data.Message; 51 | 52 | console.log(data); 53 | } catch (error) { 54 | console.error(error); 55 | heading = 'Error' 56 | message = error.message+" Run Certification test failed, please check the logs"; 57 | state = 'danger'; 58 | } finally { 59 | form.elements.submit.disabled = false; 60 | for (const el of form.elements) if (el instanceof HTMLFieldSetElement) el.disabled = false 61 | } 62 | 63 | return { heading, message, state }; 64 | } -------------------------------------------------------------------------------- /cmd/certsuite/upload/results_spreadsheet/drive_utils.go: -------------------------------------------------------------------------------- 1 | package resultsspreadsheet 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/url" 7 | "strings" 8 | 9 | "google.golang.org/api/drive/v3" 10 | "google.golang.org/api/sheets/v4" 11 | ) 12 | 13 | func createDriveFolder(srv *drive.Service, folderName, parentFolderID string) (*drive.File, error) { 14 | driveFolder := &drive.File{ 15 | Name: folderName, 16 | Parents: []string{parentFolderID}, 17 | MimeType: "application/vnd.google-apps.folder", 18 | } 19 | 20 | // Search for an existing folder with the same name 21 | q := fmt.Sprintf("name = '%s' and mimeType = 'application/vnd.google-apps.folder' and '%s' in parents and trashed = false", folderName, parentFolderID) 22 | call := srv.Files.List().Q(q).Fields("files(id, name)") 23 | 24 | files, err := call.Do() 25 | if err != nil { 26 | return nil, fmt.Errorf("unable to list files: %v", err) 27 | } 28 | 29 | if len(files.Files) > 0 { 30 | return nil, fmt.Errorf("folder %s already exists in %s folder ID", folderName, parentFolderID) 31 | } 32 | 33 | createdFolder, err := srv.Files.Create(driveFolder).Do() 34 | if err != nil { 35 | return nil, fmt.Errorf("unable to create folder: %v", err) 36 | } 37 | 38 | return createdFolder, nil 39 | } 40 | 41 | func MoveSpreadSheetToFolder(srv *drive.Service, folder *drive.File, spreadsheet *sheets.Spreadsheet) error { 42 | file, err := srv.Files.Get(spreadsheet.SpreadsheetId).Fields("parents").Do() 43 | if err != nil { 44 | log.Fatalf("Unable to get file: %v", err) 45 | } 46 | 47 | // Collect the current parent IDs to remove (if needed) 48 | oldParents := append([]string{}, file.Parents...) 49 | 50 | updateCall := srv.Files.Update(spreadsheet.SpreadsheetId, nil) 51 | updateCall.AddParents(folder.Id) 52 | 53 | // Remove the file from its old parents 54 | if len(oldParents) > 0 { 55 | for _, parent := range oldParents { 56 | updateCall.RemoveParents(parent) 57 | } 58 | } 59 | 60 | _, err = updateCall.Do() 61 | if err != nil { 62 | log.Fatalf("Unable change file location: %v", err) 63 | } 64 | 65 | return nil 66 | } 67 | 68 | func extractFolderIDFromURL(u string) (string, error) { 69 | parsedURL, err := url.Parse(u) 70 | if err != nil { 71 | return "", err 72 | } 73 | 74 | pathSegments := strings.Split(parsedURL.Path, "/") 75 | 76 | // The folder ID is the last segment in the path 77 | return pathSegments[len(pathSegments)-1], nil 78 | } 79 | -------------------------------------------------------------------------------- /pkg/autodiscover/autodiscover_services_accounts_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | package autodiscover 17 | 18 | import ( 19 | "testing" 20 | 21 | "github.com/redhat-best-practices-for-k8s/certsuite/internal/clientsholder" 22 | "github.com/stretchr/testify/assert" 23 | corev1 "k8s.io/api/core/v1" 24 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | "k8s.io/apimachinery/pkg/runtime" 26 | ) 27 | 28 | func TestGetServiceAccounts(t *testing.T) { 29 | generateServiceAccount := func(name, namespace string) *corev1.ServiceAccount { 30 | return &corev1.ServiceAccount{ 31 | ObjectMeta: metav1.ObjectMeta{ 32 | Name: name, 33 | Namespace: namespace, 34 | }, 35 | } 36 | } 37 | 38 | testCases := []struct { 39 | serviceAccountName string 40 | serviceAccountNamespace string 41 | expectedServiceAccounts []*corev1.ServiceAccount 42 | }{ 43 | { 44 | serviceAccountName: "testServiceAccount", 45 | serviceAccountNamespace: "tnf", 46 | expectedServiceAccounts: []*corev1.ServiceAccount{ 47 | { 48 | ObjectMeta: metav1.ObjectMeta{ 49 | Name: "testServiceAccount", 50 | Namespace: "tnf", 51 | }, 52 | }, 53 | }, 54 | }, 55 | } 56 | 57 | for _, tc := range testCases { 58 | var testRuntimeObjects []runtime.Object 59 | testRuntimeObjects = append(testRuntimeObjects, generateServiceAccount(tc.serviceAccountName, tc.serviceAccountNamespace)) 60 | oc := clientsholder.GetTestClientsHolder(testRuntimeObjects) 61 | services, err := getServiceAccounts(oc.K8sClient.CoreV1(), []string{tc.serviceAccountNamespace}) 62 | assert.Nil(t, err) 63 | assert.Equal(t, tc.expectedServiceAccounts, services) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /tests/platform/operatingsystem/operatingsystem.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package operatingsystem 18 | 19 | import ( 20 | _ "embed" 21 | "strings" 22 | ) 23 | 24 | const ( 25 | NotFoundStr = "version-not-found" 26 | ) 27 | 28 | //go:embed files/rhcos_version_map 29 | var rhcosVersionMap string 30 | 31 | func GetRHCOSMappedVersions(rhcosVersionMap string) (map[string]string, error) { 32 | capturedInfo := make(map[string]string) 33 | 34 | // Example: Translate `Red Hat Enterprise Linux CoreOS 410.84.202205031645-0 (Ootpa)` into a RHCOS version number 35 | // and long-form counterpart 36 | 37 | /// Example lines from the captured file 38 | // 4.9.21 / 49.84.202202081504-0 39 | // 4.9.25 / 49.84.202203112054-0 40 | // 4.10.14 / 410.84.202205031645-0 41 | 42 | versions := strings.Split(rhcosVersionMap, "\n") 43 | for _, v := range versions { 44 | // Skip any empty lines 45 | if strings.TrimSpace(v) == "" { 46 | continue 47 | } 48 | 49 | // Split on the / and capture the line into the map 50 | splitVersion := strings.Split(v, "/") 51 | capturedInfo[strings.TrimSpace(splitVersion[0])] = strings.TrimSpace(splitVersion[1]) 52 | } 53 | 54 | return capturedInfo, nil 55 | } 56 | 57 | func GetShortVersionFromLong(longVersion string) (string, error) { 58 | capturedVersions, err := GetRHCOSMappedVersions(rhcosVersionMap) 59 | if err != nil { 60 | return "", err 61 | } 62 | 63 | // search through all available rhcos versions for a match 64 | for s, l := range capturedVersions { 65 | if l == longVersion { 66 | return s, nil 67 | } 68 | } 69 | 70 | // return "version-not-found" if the short version cannot be found 71 | return NotFoundStr, nil 72 | } 73 | -------------------------------------------------------------------------------- /pkg/provider/deployments.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package provider 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/redhat-best-practices-for-k8s/certsuite/pkg/autodiscover" 23 | appsv1 "k8s.io/api/apps/v1" 24 | appv1client "k8s.io/client-go/kubernetes/typed/apps/v1" 25 | ) 26 | 27 | type Deployment struct { 28 | *appsv1.Deployment 29 | } 30 | 31 | func (d *Deployment) IsDeploymentReady() bool { 32 | notReady := true 33 | 34 | // Check the deployment's conditions for deploymentAvailable. 35 | for _, condition := range d.Status.Conditions { 36 | if condition.Type == appsv1.DeploymentAvailable { 37 | notReady = false // Deployment is ready 38 | break 39 | } 40 | } 41 | 42 | // Find the number of expected replicas 43 | var replicas int32 44 | if d.Spec.Replicas != nil { 45 | replicas = *(d.Spec.Replicas) 46 | } else { 47 | replicas = 1 48 | } 49 | 50 | // If condition says that the deployment is not ready or replicas do not match totals specified in spec.replicas. 51 | if notReady || 52 | d.Status.UnavailableReplicas != 0 || // 53 | d.Status.ReadyReplicas != replicas || // eg. 10 ready replicas == 10 total replicas 54 | d.Status.AvailableReplicas != replicas || 55 | d.Status.UpdatedReplicas != replicas { 56 | return false 57 | } 58 | return true 59 | } 60 | 61 | func (d *Deployment) ToString() string { 62 | return fmt.Sprintf("deployment: %s ns: %s", 63 | d.Name, 64 | d.Namespace, 65 | ) 66 | } 67 | 68 | func GetUpdatedDeployment(ac appv1client.AppsV1Interface, namespace, name string) (*Deployment, error) { 69 | result, err := autodiscover.FindDeploymentByNameByNamespace(ac, namespace, name) 70 | return &Deployment{ 71 | result, 72 | }, err 73 | } 74 | -------------------------------------------------------------------------------- /.github/workflows/update-rhcos-mapping.yml: -------------------------------------------------------------------------------- 1 | name: Update RHCOS version mapping 2 | 3 | on: 4 | # Triggers the workflow every day 5 | schedule: 6 | - cron: "0 0 * * *" 7 | # pull_request: 8 | # branches: 9 | # - main 10 | workflow_dispatch: 11 | permissions: 12 | contents: read 13 | 14 | jobs: 15 | update-certification: 16 | if: github.repository_owner == 'redhat-best-practices-for-k8s' 17 | permissions: 18 | contents: write # for peter-evans/create-pull-request to create branch 19 | pull-requests: write # for peter-evans/create-pull-request to create a PR 20 | name: Update offline mapping of RHCOS to OCP version 21 | runs-on: ubuntu-24.04 22 | env: 23 | SHELL: /bin/bash 24 | 25 | steps: 26 | - name: Check out code 27 | uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 28 | with: 29 | ref: main 30 | 31 | - name: Check and install 'oc' OpenShift client 32 | run: | 33 | if ! command -v oc &> /dev/null; then 34 | echo "'oc' not found, installing..." 35 | TEMP_DIR=$(mktemp -d) 36 | curl -Lo $TEMP_DIR/openshift-client-linux.tar.gz https://mirror.openshift.com/pub/openshift-v4/clients/ocp/latest/openshift-client-linux.tar.gz 37 | tar -xvf $TEMP_DIR/openshift-client-linux.tar.gz -C $TEMP_DIR 38 | sudo mv $TEMP_DIR/oc $TEMP_DIR/kubectl /usr/local/bin/ 39 | rm -rf $TEMP_DIR 40 | else 41 | echo "'oc' is already installed." 42 | fi 43 | 44 | - name: Execute `make update-rhcos-versions` 45 | run: make update-rhcos-versions 46 | 47 | - name: Set up Go 48 | uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 49 | with: 50 | go-version-file: go.mod 51 | 52 | # This prevents any failures due to the updated rhcos_versions_map file from 53 | # making it into the PR phase. 54 | - name: Run unit tests 55 | run: make test 56 | 57 | - name: Create PR 58 | uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0 59 | env: 60 | GITHUB_TOKEN: ${{ secrets.UPDATE_CERTIFIED_DB_TOKEN }} 61 | with: 62 | commit-message: Update RHCOS to OCP version map 63 | title: Update RHCOS to OCP version map 64 | body: | 65 | - RHCOS version map update 66 | branch: update-rhcos-map 67 | -------------------------------------------------------------------------------- /tests/networking/netutil/netutil_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020-2024 Red Hat, Inc. 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | package netutil 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/stretchr/testify/assert" 23 | ) 24 | 25 | func TestParseListeningPorts(t *testing.T) { 26 | testCases := []struct { 27 | inputStr string 28 | expectedListeningPorts map[PortInfo]bool 29 | }{ 30 | { 31 | inputStr: "tcp LISTEN 0 128 0.0.0.0:8080 0.0.0.0:*\n", 32 | expectedListeningPorts: map[PortInfo]bool{{PortNumber: 8080, Protocol: "TCP"}: true}, 33 | }, 34 | { 35 | inputStr: "", 36 | expectedListeningPorts: map[PortInfo]bool{}, 37 | }, 38 | { 39 | inputStr: "\n", 40 | expectedListeningPorts: map[PortInfo]bool{}, 41 | }, 42 | { 43 | inputStr: "tcp LISTEN 0 128 0.0.0.0:8080 0.0.0.0:*\ntcp LISTEN 0 128 0.0.0.0:7878 0.0.0.0:*\n", 44 | expectedListeningPorts: map[PortInfo]bool{{PortNumber: 8080, Protocol: "TCP"}: true, {PortNumber: 7878, Protocol: "TCP"}: true}, 45 | }, 46 | { 47 | inputStr: "udp LISTEN 0 128 0.0.0.0:8080 0.0.0.0:*\nudp LISTEN 0 128 0.0.0.0:7878 0.0.0.0:*\n", 48 | expectedListeningPorts: map[PortInfo]bool{{PortNumber: 8080, Protocol: "UDP"}: true, {PortNumber: 7878, Protocol: "UDP"}: true}, 49 | }, 50 | { 51 | inputStr: "tcp LISTEN 0 128 [::]:22\n", 52 | expectedListeningPorts: map[PortInfo]bool{{PortNumber: 22, Protocol: "TCP"}: true}, 53 | }, 54 | } 55 | for _, tc := range testCases { 56 | listeningPorts, err := parseListeningPorts(tc.inputStr) 57 | if assert.NoError(t, err) { 58 | assert.Equal(t, tc.expectedListeningPorts, listeningPorts) 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /pkg/provider/catalogsources_test.go: -------------------------------------------------------------------------------- 1 | package provider 2 | 3 | import ( 4 | "testing" 5 | 6 | olmv1Alpha "github.com/operator-framework/api/pkg/operators/v1alpha1" 7 | olmpkgv1 "github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/apis/operators/v1" 8 | "github.com/stretchr/testify/assert" 9 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 10 | ) 11 | 12 | func TestGetCatalogSourceBundleCount(t *testing.T) { 13 | generateEnv := func(channelEntries []olmpkgv1.ChannelEntry) *TestEnvironment { 14 | return &TestEnvironment{ 15 | AllPackageManifests: []*olmpkgv1.PackageManifest{ 16 | { 17 | Status: olmpkgv1.PackageManifestStatus{ 18 | CatalogSource: "test-catalog-source", 19 | CatalogSourceNamespace: "test-catalog-source-namespace", 20 | Channels: []olmpkgv1.PackageChannel{ 21 | { 22 | Entries: channelEntries, 23 | }, 24 | }, 25 | }, 26 | }, 27 | }, 28 | } 29 | } 30 | 31 | testCases := []struct { 32 | testEnv *TestEnvironment 33 | testCS *olmv1Alpha.CatalogSource 34 | expected int 35 | }{ 36 | { // Test case 1 37 | testEnv: generateEnv([]olmpkgv1.ChannelEntry{ 38 | { 39 | Name: "test-csv.v1.0.0", 40 | }, 41 | { 42 | Name: "test-csv.v1.0.1", 43 | }, 44 | }), 45 | testCS: &olmv1Alpha.CatalogSource{ 46 | ObjectMeta: metav1.ObjectMeta{ 47 | Name: "test-catalog-source", 48 | Namespace: "test-catalog-source-namespace", 49 | }, 50 | }, 51 | expected: 2, 52 | }, 53 | { // Test Case 2 - No matching catalog source found, expecting 0 54 | testEnv: generateEnv([]olmpkgv1.ChannelEntry{ 55 | { 56 | Name: "test-csv.v1.0.0", 57 | }, 58 | { 59 | Name: "test-csv.v1.0.1", 60 | }, 61 | }), 62 | testCS: &olmv1Alpha.CatalogSource{ 63 | ObjectMeta: metav1.ObjectMeta{ 64 | Name: "test-catalog-source2", 65 | Namespace: "test-catalog-source-namespace", 66 | }, 67 | }, 68 | expected: 0, 69 | }, 70 | { // Test Case 3 - No images in the catalog source, expecting 0 71 | testEnv: generateEnv([]olmpkgv1.ChannelEntry{}), 72 | testCS: &olmv1Alpha.CatalogSource{ 73 | ObjectMeta: metav1.ObjectMeta{ 74 | Name: "test-catalog-source", 75 | Namespace: "test-catalog-source-namespace", 76 | }, 77 | }, 78 | expected: 0, 79 | }, 80 | } 81 | 82 | for _, testCase := range testCases { 83 | assert.Equal(t, testCase.expected, GetCatalogSourceBundleCount(testCase.testEnv, testCase.testCS)) 84 | } 85 | } 86 | --------------------------------------------------------------------------------