From cd6bfdfb2738e195306abbd9de03072cb3d59aee Mon Sep 17 00:00:00 2001 From: Bryan Cox Date: Fri, 24 Apr 2026 10:44:55 -0400 Subject: [PATCH 1/2] ci: shard unit tests and add Go build cache Split unit tests into 5 parallel GitHub Actions matrix shards (cpo-hostedcontrolplane, cpo-other, hypershift-operator, cmd-support, other) to reduce CI wall time from ~14 min to ~6 min. Add a test-shard Makefile target that runs tests for a specified set of packages with coverage output. Persist the Go build cache across runs using actions/cache to speed up warm cache builds. Add change detection to skip test jobs when only contrib, .github, or docs files are modified. Handle workflow_dispatch events by always running tests since there is no base commit to diff against. Upload per-shard coverage profiles to Codecov with shard-specific flags for proper coverage merging. JIRA: CNTRLPLANE-3330 Co-Authored-By: Claude Opus 4.6 --- .github/workflows/test.yaml | 66 ++++++++++++++++++++++++++++++------- Makefile | 9 +++++ 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 143208d98d0f..e24fcf54a7df 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -15,10 +15,12 @@ permissions: contents: read jobs: - test: - name: Unit Tests + changes: + name: Detect Changes runs-on: arc-runner-set - timeout-minutes: 30 + timeout-minutes: 5 + outputs: + run_tests: ${{ steps.changes.outputs.run_tests }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: @@ -27,23 +29,65 @@ jobs: - name: Check for non-contrib changes id: changes run: | - if [ "${{ github.event_name }}" = "pull_request" ]; then + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + echo "run_tests=true" >> "$GITHUB_OUTPUT" + exit 0 + elif [ "${{ github.event_name }}" = "pull_request" ]; then FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD) else - FILES=$(git diff --name-only HEAD~1) + if [ "${{ github.event.before }}" = "0000000000000000000000000000000000000000" ]; then + echo "run_tests=true" >> "$GITHUB_OUTPUT" + exit 0 + fi + FILES=$(git diff --name-only ${{ github.event.before }}..${{ github.sha }}) fi - if echo "$FILES" | grep -qvE '^(contrib|\.github)/'; then + if echo "$FILES" | grep -qvE '^(contrib|\.github|docs)/'; then echo "run_tests=true" >> "$GITHUB_OUTPUT" else echo "run_tests=false" >> "$GITHUB_OUTPUT" fi - - if: steps.changes.outputs.run_tests == 'true' - run: make test - - if: steps.changes.outputs.run_tests == 'true' - name: Upload to Codecov + + test: + name: Unit Tests (${{ matrix.shard }}) + needs: changes + if: needs.changes.outputs.run_tests == 'true' + runs-on: arc-runner-set + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + include: + - shard: cpo-hostedcontrolplane + packages: ./control-plane-operator/controllers/hostedcontrolplane/... + - shard: cpo-other + packages: ./control-plane-operator/controllers/awsprivatelink/... ./control-plane-operator/controllers/azureprivatelinkservice/... ./control-plane-operator/controllers/gcpprivateserviceconnect/... ./control-plane-operator/controllers/healthcheck/... ./control-plane-operator/controllers/openshiftmanager/... ./control-plane-operator/endpoint-resolver/... ./control-plane-operator/hostedclusterconfigoperator/... ./control-plane-operator/metrics-proxy/... + - shard: hypershift-operator + packages: ./hypershift-operator/... + - shard: cmd-support + packages: ./cmd/... ./support/... + - shard: other + packages: ./karpenter-operator/... ./control-plane-pki-operator/... ./contrib/... ./ignition-server/... ./pkg/... ./dnsresolver/... ./product-cli/... ./client/... ./test/integration/... ./test/e2e/util/... ./test/util/... ./availability-prober/... ./konnectivity-socks5-proxy/... ./konnectivity-https-proxy/... ./kubernetes-default-proxy/... ./kubevirtexternalinfra/... ./etcd-defrag/... ./etcd-backup/... ./etcd-recovery/... ./etcd-upload/... ./kas-bootstrap/... ./sharedingress-config-generator/... ./sync-fg-configmap/... ./sync-global-pullsecret/... ./token-minter/... + env: + GOCACHE: /tmp/go-build-cache + GOMODCACHE: /tmp/go-mod-cache + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + persist-credentials: false + - name: Restore Go build cache + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: /tmp/go-build-cache + key: go-build-${{ matrix.shard }}-${{ github.sha }} + restore-keys: go-build-${{ matrix.shard }}- + - name: Run tests + run: make test-shard TEST_PACKAGES="${{ matrix.packages }}" COVER_PROFILE="cover-${{ matrix.shard }}.out" + - name: Upload to Codecov uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0 env: HOME: /tmp CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} with: - files: cover.out + files: cover-${{ matrix.shard }}.out + flags: ${{ matrix.shard }} diff --git a/Makefile b/Makefile index af1d63497d0a..90c15eea02b2 100644 --- a/Makefile +++ b/Makefile @@ -362,6 +362,15 @@ test: generate @echo "Running tests with $(NUM_CORES) parallel jobs..." $(GO) test -race -parallel=$(NUM_CORES) -count=1 -timeout=30m ./... -coverprofile cover.out +# Run a subset of unit tests (used by CI sharding). +# Usage: make test-shard TEST_PACKAGES="./cmd/... ./support/..." COVER_PROFILE="cover-shard.out" +TEST_PACKAGES ?= ./... +COVER_PROFILE ?= cover.out +.PHONY: test-shard +test-shard: generate + @echo "Running shard tests for packages: $(TEST_PACKAGES)" + $(GO) test -race -parallel=$(NUM_CORES) -count=1 -timeout=30m $(TEST_PACKAGES) -coverprofile $(COVER_PROFILE) + # OCP envtest index for downstream kubebuilder assets ENVTEST_OCP_INDEX := https://raw.githubusercontent.com/openshift/api/master/envtest-releases.yaml # OCP version to Kubernetes version mapping (OCP 4.x -> K8s 1.(x+13)) From a4b3600acabcefba212a1676809b181e0a2af894 Mon Sep 17 00:00:00 2001 From: Bryan Cox Date: Fri, 24 Apr 2026 10:45:10 -0400 Subject: [PATCH 2/2] test: add t.Parallel() to heaviest unit test files Add t.Parallel() to tests in the heaviest test files to improve test execution speed within each shard. Tests that use t.Setenv or modify global state are left sequential. Files modified: - hostedcluster_controller_test.go (39 tests parallelized) - hostedcontrolplane_controller_test.go (8 tests parallelized) - infra_test.go (7 tests parallelized) - nodepool_controller_test.go (15 tests parallelized) - capi_test.go (13 tests parallelized) - resources_test.go (19 tests parallelized) JIRA: CNTRLPLANE-3330 Co-Authored-By: Claude Opus 4.6 --- .../hostedcontrolplane_controller_test.go | 8 ++++ .../hostedcontrolplane/infra/infra_test.go | 7 ++++ .../controllers/resources/resources_test.go | 18 +++++++++ .../hostedcluster_controller_test.go | 39 +++++++++++++++++++ .../controllers/nodepool/capi_test.go | 18 +++++++++ .../nodepool/nodepool_controller_test.go | 25 ++++++++++++ 6 files changed, 115 insertions(+) diff --git a/control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller_test.go b/control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller_test.go index a5936e9c0454..fab1afdb57cb 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller_test.go +++ b/control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller_test.go @@ -72,6 +72,7 @@ import ( ) func TestReconcileKubeadminPassword(t *testing.T) { + t.Parallel() targetNamespace := "test" testsCases := []struct { @@ -353,6 +354,7 @@ func TestReconcileIgnitionServer(t *testing.T) { } func TestEtcdRestoredCondition(t *testing.T) { + t.Parallel() testsCases := []struct { name string sts *appsv1.StatefulSet @@ -792,6 +794,7 @@ func (c *createTrackingWorkqueue) Add(item reconcile.Request) { } func TestNonReadyInfraTriggersRequeueAfter(t *testing.T) { + t.Parallel() mockCtrl := gomock.NewController(t) mockedProviderWithOpenshiftImageRegistryOverrides := releaseinfo.NewMockProviderWithOpenShiftImageRegistryOverrides(mockCtrl) mockedProviderWithOpenshiftImageRegistryOverrides.EXPECT(). @@ -1313,6 +1316,7 @@ func TestControlPlaneComponents(t *testing.T) { } func TestAWSSecurityGroupTags(t *testing.T) { + t.Parallel() tests := []struct { name string hcp *hyperv1.HostedControlPlane @@ -1540,6 +1544,7 @@ func componentsFakeDependencies(componentName string, namespace string) []client } func TestControlPlaneComponentsAvailable(t *testing.T) { + t.Parallel() testNamespace := "test-namespace" testCases := []struct { @@ -1774,6 +1779,7 @@ func TestControlPlaneComponentsAvailable(t *testing.T) { } func TestRemoveHCPIngressFromRoutes(t *testing.T) { + t.Parallel() const namespace = "test-ns" tests := []struct { @@ -2202,6 +2208,7 @@ func TestRemoveHCPIngressFromRoutes(t *testing.T) { } func TestReconcileAvailabilityStatus(t *testing.T) { + t.Parallel() testCases := []struct { name string conditions []metav1.Condition @@ -2472,6 +2479,7 @@ func TestReconcileAvailabilityStatus(t *testing.T) { } func TestEtcdStatefulSetCondition(t *testing.T) { + t.Parallel() testNamespace := "test-namespace" testCases := []struct { diff --git a/control-plane-operator/controllers/hostedcontrolplane/infra/infra_test.go b/control-plane-operator/controllers/hostedcontrolplane/infra/infra_test.go index 55d9b5f8c723..1fd09db41e46 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/infra/infra_test.go +++ b/control-plane-operator/controllers/hostedcontrolplane/infra/infra_test.go @@ -715,6 +715,7 @@ func simulateInfraProvisioning(ctx context.Context, c client.Client, hcp *hyperv } func TestReconcileInfrastructure_ErrorCases(t *testing.T) { + t.Parallel() testCases := []struct { name string hcp *hyperv1.HostedControlPlane @@ -811,6 +812,7 @@ func TestReconcileInfrastructure_ErrorCases(t *testing.T) { } func TestReconcileInfrastructure_WhenTransitioningFromPublicToPrivate_ItShouldCleanUpPublicResources(t *testing.T) { + t.Parallel() g := NewGomegaWithT(t) // Start with Public configuration @@ -865,6 +867,7 @@ func TestReconcileInfrastructure_WhenTransitioningFromPublicToPrivate_ItShouldCl } func TestReconcileInfrastructure_WhenTransitioningFromPrivateToPublic_ItShouldCleanUpPrivateResources(t *testing.T) { + t.Parallel() g := NewGomegaWithT(t) // Start with Private configuration @@ -921,6 +924,7 @@ func TestReconcileInfrastructure_WhenTransitioningFromPrivateToPublic_ItShouldCl // Tests moved from hostedcontrolplane_controller_test.go func TestReconcileOAuthService(t *testing.T) { + t.Parallel() targetNamespace := "test" apiPort := int32(config.KASSVCPort) hostname := "test.example.com" @@ -1149,6 +1153,7 @@ func TestReconcileOAuthService(t *testing.T) { } func TestReconcileAPIServerService(t *testing.T) { + t.Parallel() targetNamespace := "test" apiPort := int32(config.KASSVCPort) kasPort := "client" @@ -1676,6 +1681,7 @@ func (c *fakeMessageCollector) ErrorMessages(resource client.Object) ([]string, var _ events.MessageCollector = &fakeMessageCollector{} func TestReconcileRouterServiceStatus(t *testing.T) { + t.Parallel() const namespace = "test-ns" const svcName = "test" tests := []struct { @@ -1826,6 +1832,7 @@ func TestReconcileInternalRouterServiceStatus(t *testing.T) { } func TestReconcileOAuthService_AzureLoadBalancer(t *testing.T) { + t.Parallel() targetNamespace := "test" apiPort := int32(config.KASSVCPort) ipFamilyPolicy := corev1.IPFamilyPolicyPreferDualStack diff --git a/control-plane-operator/hostedclusterconfigoperator/controllers/resources/resources_test.go b/control-plane-operator/hostedclusterconfigoperator/controllers/resources/resources_test.go index 7260aec5a724..67225afb258f 100644 --- a/control-plane-operator/hostedclusterconfigoperator/controllers/resources/resources_test.go +++ b/control-plane-operator/hostedclusterconfigoperator/controllers/resources/resources_test.go @@ -228,6 +228,7 @@ func TestReconcileErrorHandling(t *testing.T) { } func TestReconcileOLM(t *testing.T) { + t.Parallel() var errs []error hcp := fakeHCP() hcp.Namespace = "openshift-operator-lifecycle-manager" @@ -475,6 +476,7 @@ func withICS(hcp *hyperv1.HostedControlPlane) *hyperv1.HostedControlPlane { } func TestReconcileKubeadminPasswordHashSecret(t *testing.T) { + t.Parallel() testNamespace := "master-cluster1" testHCPName := "cluster1" @@ -548,6 +550,7 @@ func TestReconcileKubeadminPasswordHashSecret(t *testing.T) { } func TestReconcileUserCertCABundle(t *testing.T) { + t.Parallel() testNamespace := "master-cluster1" testHCPName := "cluster1" tests := map[string]struct { @@ -637,6 +640,7 @@ func TestReconcileUserCertCABundle(t *testing.T) { var _ manifestReconciler = manifestAndReconcile[*rbacv1.ClusterRole]{} func TestDestroyCloudResources(t *testing.T) { + t.Parallel() originalConditionTime := time.Now().Add(-1 * time.Hour) fakeHostedControlPlane := func() *hyperv1.HostedControlPlane { return &hyperv1.HostedControlPlane{ @@ -950,6 +954,7 @@ func TestDestroyCloudResources(t *testing.T) { } func TestDestroyCloudResourcesWithKASUnavailable(t *testing.T) { + t.Parallel() fakeHCP := &hyperv1.HostedControlPlane{ ObjectMeta: metav1.ObjectMeta{ Name: "test-hcp", @@ -1038,6 +1043,7 @@ func (e *mockNetError) Timeout() bool { return e.timeout } func (e *mockNetError) Temporary() bool { return e.temporary } func TestConnectionErrorTracking(t *testing.T) { + t.Parallel() tests := []struct { name string @@ -1107,6 +1113,7 @@ func TestConnectionErrorTracking(t *testing.T) { } func TestListAccessor(t *testing.T) { + t.Parallel() pod := func(name string) corev1.Pod { return corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -1130,6 +1137,7 @@ func TestListAccessor(t *testing.T) { } func TestReconcileClusterVersion(t *testing.T) { + t.Parallel() hcp := &hyperv1.HostedControlPlane{ Spec: hyperv1.HostedControlPlaneSpec{ ClusterID: "test-cluster-id", @@ -1205,6 +1213,7 @@ func TestReconcileClusterVersion(t *testing.T) { } func TestReconcileClusterVersionWithDisabledCapabilities(t *testing.T) { + t.Parallel() hcp := &hyperv1.HostedControlPlane{ Spec: hyperv1.HostedControlPlaneSpec{ ClusterID: "test-cluster-id", @@ -1282,6 +1291,7 @@ func TestReconcileClusterVersionWithDisabledCapabilities(t *testing.T) { } func TestReconcileClusterVersionWithEnabledCapabilities(t *testing.T) { + t.Parallel() hcp := &hyperv1.HostedControlPlane{ Spec: hyperv1.HostedControlPlaneSpec{ ClusterID: "test-cluster-id", @@ -1360,6 +1370,7 @@ func TestReconcileClusterVersionWithEnabledCapabilities(t *testing.T) { } func TestReconcileImageContentPolicyType(t *testing.T) { + t.Parallel() testCases := []struct { name string hcp *hyperv1.HostedControlPlane @@ -1433,6 +1444,7 @@ func compareICSAndIDMS(g *WithT, ics []hyperv1.ImageContentSource, idms *configv } func TestReconcileKASEndpoints(t *testing.T) { + t.Parallel() testCases := []struct { name string @@ -1490,6 +1502,7 @@ func TestReconcileKASEndpoints(t *testing.T) { } func TestReconcileKubeletConfig(t *testing.T) { + t.Parallel() hcpNamespace := "hostedcontrolplane-namespace" hcNamespace := "openshift-config-managed" npName1 := "nodepool-test1" @@ -1576,6 +1589,7 @@ func TestReconcileKubeletConfig(t *testing.T) { } func TestBuildAWSWebIdentityCredentials(t *testing.T) { + t.Parallel() type args struct { roleArn string region string @@ -2323,6 +2337,7 @@ func newCondition(conditionType string, status metav1.ConditionStatus, reason, m } func Test_reconciler_reconcileDataPlaneConnectionAvailable(t *testing.T) { + t.Parallel() newKonnectivityAgentPod := func(name string, phase corev1.PodPhase) corev1.Pod { return corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -2518,6 +2533,7 @@ func Test_reconciler_reconcileDataPlaneConnectionAvailable(t *testing.T) { } func Test_reconciler_reconcileControlPlaneConnectionAvailable(t *testing.T) { + t.Parallel() newConnectivityConfigMap := func(data map[string]string) *corev1.ConfigMap { return &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ @@ -2683,6 +2699,7 @@ func Test_reconciler_reconcileControlPlaneConnectionAvailable(t *testing.T) { } func Test_reconciler_reconcileKASConnectionCheckerDeployment(t *testing.T) { + t.Parallel() const testCLIImage = "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:cli-test" tests := []struct { @@ -2969,6 +2986,7 @@ func Test_reconciler_reconcileKASConnectionCheckerDeployment(t *testing.T) { } func TestReconcileMetricsForwarder(t *testing.T) { + t.Parallel() tests := []struct { name string annotations map[string]string diff --git a/hypershift-operator/controllers/hostedcluster/hostedcluster_controller_test.go b/hypershift-operator/controllers/hostedcluster/hostedcluster_controller_test.go index 1a594e950d00..8922764adda8 100644 --- a/hypershift-operator/controllers/hostedcluster/hostedcluster_controller_test.go +++ b/hypershift-operator/controllers/hostedcluster/hostedcluster_controller_test.go @@ -107,6 +107,7 @@ func (rp fakeReleaseProvider) GetMetadataProvider() hyperutil.ImageMetadataProvi } func TestHasBeenAvailable(t *testing.T) { + t.Parallel() mockCtrl := gomock.NewController(t) now := time.Now().Truncate(time.Second) reconcilerNow := metav1.Time{Time: now.Add(time.Second)} @@ -251,6 +252,7 @@ func TestHasBeenAvailable(t *testing.T) { } func TestReconcileHostedControlPlaneAdditionalTrustBundle(t *testing.T) { + t.Parallel() tests := []struct { name string cluster hyperv1.HostedCluster @@ -308,6 +310,7 @@ func TestReconcileHostedControlPlaneAdditionalTrustBundle(t *testing.T) { } func TestReconcileHostedControlPlaneUpgrades(t *testing.T) { + t.Parallel() // TODO: the spec/status comparison of control plane is a weak check; the // conditions should give us more information about e.g. whether that // image ever _will_ be achieved (e.g. if the problem is fatal) @@ -411,6 +414,7 @@ func TestReconcileHostedControlPlaneUpgrades(t *testing.T) { } func TestComputeHostedClusterAvailability(t *testing.T) { + t.Parallel() tests := map[string]struct { Cluster hyperv1.HostedCluster ControlPlane *hyperv1.HostedControlPlane @@ -494,6 +498,7 @@ func TestComputeHostedClusterAvailability(t *testing.T) { } func TestReconcileHostedControlPlaneAPINetwork(t *testing.T) { + t.Parallel() tests := []struct { name string networking *hyperv1.APIServerNetworking @@ -554,6 +559,7 @@ func TestReconcileHostedControlPlaneAPINetwork(t *testing.T) { } func TestReconcileHostedControlPlaneConfiguration(t *testing.T) { + t.Parallel() idp := configv1.IdentityProvider{ Name: "htpasswd", IdentityProviderConfig: configv1.IdentityProviderConfig{ @@ -604,6 +610,7 @@ func TestReconcileHostedControlPlaneConfiguration(t *testing.T) { } func TestReconcileHostedControlPlaneAnnotations(t *testing.T) { + t.Parallel() type testCase struct { name string hcpAnnotations map[string]string @@ -851,6 +858,7 @@ func TestReconcileHostedControlPlaneAnnotations(t *testing.T) { } func TestAnnotationsForCertRenewal(t *testing.T) { + t.Parallel() tests := []struct { name string shouldSkip bool @@ -923,6 +931,7 @@ func TestAnnotationsForCertRenewal(t *testing.T) { } func TestShouldCheckForStaleCerts(t *testing.T) { + t.Parallel() tests := []struct { name string hcAnnotations map[string]string @@ -974,6 +983,7 @@ func TestShouldCheckForStaleCerts(t *testing.T) { } func TestServiceFirstNodePortAvailable(t *testing.T) { + t.Parallel() tests := []struct { name string inputService *corev1.Service @@ -1034,6 +1044,7 @@ func TestServiceFirstNodePortAvailable(t *testing.T) { } func TestServicePublishingStrategyByType(t *testing.T) { + t.Parallel() tests := []struct { name string inputHostedCluster *hyperv1.HostedCluster @@ -1095,6 +1106,7 @@ func TestServicePublishingStrategyByType(t *testing.T) { } func TestReconcileCAPICluster(t *testing.T) { + t.Parallel() testCases := []struct { name string capiCluster *v1beta1.Cluster @@ -1234,6 +1246,7 @@ func TestReconcileCAPICluster(t *testing.T) { } func TestReconcileAWSResourceTags(t *testing.T) { + t.Parallel() testCases := []struct { name string in hyperv1.HostedClusterSpec @@ -1834,6 +1847,7 @@ func TestHostedClusterWatchesEverythingItCreates(t *testing.T) { } func TestReconcileCLISecrets(t *testing.T) { + t.Parallel() const ( infraID = "infraId" ns = "myns" @@ -2041,6 +2055,7 @@ func (c *createTypeTrackingClient) Create(ctx context.Context, obj crclient.Obje } func TestValidateConfigAndClusterCapabilities(t *testing.T) { + t.Parallel() // For network test below. clusterNet := make([]hyperv1.ClusterNetworkEntry, 2) @@ -2255,6 +2270,7 @@ func TestValidateConfigAndClusterCapabilities(t *testing.T) { } func TestValidateReleaseImage(t *testing.T) { + t.Parallel() mockCtrl := gomock.NewController(t) testCases := []struct { name string @@ -2677,6 +2693,7 @@ var equateErrorMessage = cmp.FilterValues(func(x, y interface{}) bool { })) func TestPauseHostedControlPlane(t *testing.T) { + t.Parallel() fakePauseAnnotationValue := "true" fakeHCPName := "cluster1" fakeHCPNamespace := "master-cluster1" @@ -2733,6 +2750,7 @@ func TestPauseHostedControlPlane(t *testing.T) { } func TestPauseCAPICluster(t *testing.T) { + t.Parallel() fakeHCName := "cluster1" fakeHCNamespace := "master" fakeInfraID := "infra-123" @@ -2885,6 +2903,7 @@ func TestPauseCAPICluster(t *testing.T) { } func TestDefaultClusterIDsIfNeeded(t *testing.T) { + t.Parallel() testHC := func(infraID, clusterID string) *hyperv1.HostedCluster { return &hyperv1.HostedCluster{ ObjectMeta: metav1.ObjectMeta{ @@ -2945,6 +2964,7 @@ func TestDefaultClusterIDsIfNeeded(t *testing.T) { } func TestIsUpgradeable(t *testing.T) { + t.Parallel() mockCtrl := gomock.NewController(t) releaseImageFrom := "image-4.13" releaseImageTo := "image-4.14" @@ -3183,6 +3203,7 @@ func TestIsUpgradeable(t *testing.T) { } func TestReconciliationSuccessConditionSetting(t *testing.T) { + t.Parallel() // Serialization seems to round to seconds, so we have to do the // same to be able to compare. @@ -3332,6 +3353,7 @@ func TestReconciliationSuccessConditionSetting(t *testing.T) { } func TestIsProgressing(t *testing.T) { + t.Parallel() mockCtrl := gomock.NewController(t) tests := []struct { name string @@ -3588,6 +3610,7 @@ func TestIsProgressing(t *testing.T) { } func TestComputeAWSEndpointServiceCondition(t *testing.T) { + t.Parallel() tests := []struct { name string endpointAConditions []metav1.Condition @@ -3727,6 +3750,7 @@ func TestComputeAWSEndpointServiceCondition(t *testing.T) { } func TestValidateSliceNetworkCIDRs(t *testing.T) { + t.Parallel() tests := []struct { name string mn []hyperv1.MachineNetworkEntry @@ -3917,6 +3941,7 @@ func TestValidateSliceNetworkCIDRs(t *testing.T) { } func TestCheckAdvertiseAddressOverlapping(t *testing.T) { + t.Parallel() tests := []struct { name string mn []hyperv1.MachineNetworkEntry @@ -3989,6 +4014,7 @@ func TestCheckAdvertiseAddressOverlapping(t *testing.T) { } func TestFindAdvertiseAddress(t *testing.T) { + t.Parallel() tests := []struct { name string aa *hyperv1.APIServerNetworking @@ -4058,6 +4084,7 @@ func TestFindAdvertiseAddress(t *testing.T) { } func TestValidateNetworkStackAddresses(t *testing.T) { + t.Parallel() tests := []struct { name string cn []hyperv1.ClusterNetworkEntry @@ -4170,6 +4197,7 @@ func TestValidateNetworkStackAddresses(t *testing.T) { } func TestKubevirtETCDEncKey(t *testing.T) { + t.Parallel() for _, testCase := range []struct { name string hc *hyperv1.HostedCluster @@ -4617,6 +4645,7 @@ func TestKubevirtETCDEncKey(t *testing.T) { } func TestReconcileComponents(t *testing.T) { + t.Parallel() mockCtrl := gomock.NewController(t) mockedProviderWithOpenshiftImageRegistryOverrides := releaseinfo.NewMockProviderWithOpenShiftImageRegistryOverrides(mockCtrl) mockedProviderWithOpenshiftImageRegistryOverrides.EXPECT(). @@ -4855,6 +4884,7 @@ func TestEnsureHostedResourcesAreEmpty(t *testing.T) { } func TestReconcileAdditionalTrustBundle(t *testing.T) { + t.Parallel() const ( testNamespace = "test-ns" controlPlaneNamespace = "test-hcp-ns" @@ -5027,6 +5057,7 @@ func TestReconcileAdditionalTrustBundle(t *testing.T) { } func TestValidateNodePortVsServiceNetwork(t *testing.T) { + t.Parallel() testCases := []struct { name string hostedCluster *hyperv1.HostedCluster @@ -5079,6 +5110,7 @@ func TestValidateNodePortVsServiceNetwork(t *testing.T) { } func TestParseNodePortRange(t *testing.T) { + t.Parallel() testCases := []struct { name string rangeStr string @@ -5183,6 +5215,7 @@ func TestParseNodePortRange(t *testing.T) { } func TestValidateNodePortPortRange(t *testing.T) { + t.Parallel() testCases := []struct { name string hostedCluster *hyperv1.HostedCluster @@ -5403,6 +5436,7 @@ func TestValidateNodePortPortRange(t *testing.T) { } func TestServiceAccountSigningKeyBytes(t *testing.T) { + t.Parallel() g := NewWithT(t) // Helper function to generate a test RSA key pair @@ -5579,6 +5613,7 @@ func TestServiceAccountSigningKeyBytes(t *testing.T) { } func TestIsAWSNodeTerminationHandlerNeeded(t *testing.T) { + t.Parallel() testCases := []struct { name string hcluster *hyperv1.HostedCluster @@ -5829,6 +5864,7 @@ func TestIsAWSNodeTerminationHandlerNeeded(t *testing.T) { } func TestComputeGCPPSCCondition(t *testing.T) { + t.Parallel() tests := []struct { name string pscConditions []metav1.Condition @@ -5991,6 +6027,7 @@ func TestComputeGCPPSCCondition(t *testing.T) { } func TestReconcileCustomExternalKubeconfig(t *testing.T) { + t.Parallel() hcpNamespace := "test-hcp-ns" hclusterNamespace := "test-hc-ns" hclusterName := "test-cluster" @@ -6091,6 +6128,7 @@ func TestReconcileCustomExternalKubeconfig(t *testing.T) { } func TestComputeAzurePLSCondition(t *testing.T) { + t.Parallel() tests := []struct { name string plsConditions []metav1.Condition @@ -6392,6 +6430,7 @@ func TestValidateAzureConfig(t *testing.T) { } func TestComputeEndpointServiceCondition(t *testing.T) { + t.Parallel() g := NewGomegaWithT(t) const ( diff --git a/hypershift-operator/controllers/nodepool/capi_test.go b/hypershift-operator/controllers/nodepool/capi_test.go index d651ffd38b13..b67d2c9f66de 100644 --- a/hypershift-operator/controllers/nodepool/capi_test.go +++ b/hypershift-operator/controllers/nodepool/capi_test.go @@ -36,6 +36,7 @@ import ( ) func TestSetMachineSetReplicas(t *testing.T) { + t.Parallel() testCases := []struct { name string nodePool *hyperv1.NodePool @@ -272,6 +273,7 @@ func TestSetMachineSetReplicas(t *testing.T) { } func TestSetMachineDeploymentReplicas(t *testing.T) { + t.Parallel() testCases := []struct { name string nodePool *hyperv1.NodePool @@ -758,14 +760,17 @@ func RunTestMachineTemplateBuilders(t *testing.T, preCreateMachineTemplate bool) } func TestMachineTemplateBuilders(t *testing.T) { + t.Parallel() RunTestMachineTemplateBuilders(t, false) } func TestMachineTemplateBuildersPreexisting(t *testing.T) { + t.Parallel() RunTestMachineTemplateBuilders(t, true) } func TestCleanupMachineTemplates(t *testing.T) { + t.Parallel() g := NewWithT(t) nodePool := &hyperv1.NodePool{ @@ -898,6 +903,7 @@ func TestListMachineTemplatesAWS(t *testing.T) { } func TestListMachineTemplatesIBMCloud(t *testing.T) { + t.Parallel() g := NewWithT(t) c := fake.NewClientBuilder().WithScheme(api.Scheme).WithObjects().Build() r := &NodePoolReconciler{ @@ -931,6 +937,7 @@ func TestListMachineTemplatesIBMCloud(t *testing.T) { } func TestInPlaceUpgradeMaxUnavailable(t *testing.T) { + t.Parallel() intPointer1 := intstr.FromInt(1) intPointer2 := intstr.FromInt(2) strPointer10 := intstr.FromString("10%") @@ -1012,6 +1019,7 @@ func TestInPlaceUpgradeMaxUnavailable(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + t.Parallel() g := NewWithT(t) maxUnavailable, err := getInPlaceMaxUnavailable(tc.nodePool) g.Expect(err).ToNot(HaveOccurred()) @@ -1021,6 +1029,7 @@ func TestInPlaceUpgradeMaxUnavailable(t *testing.T) { } func TestTaintsToJSON(t *testing.T) { + t.Parallel() testCases := []struct { name string taints []hyperv1.Taint @@ -1051,6 +1060,7 @@ func TestTaintsToJSON(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + t.Parallel() g := NewWithT(t) taints, err := taintsToJSON(tc.taints) g.Expect(err).ToNot(HaveOccurred()) @@ -1068,6 +1078,7 @@ func TestTaintsToJSON(t *testing.T) { } func TestReconcileMachineHealthCheck(t *testing.T) { + t.Parallel() hostedcluster := func(opts ...func(client.Object)) *hyperv1.HostedCluster { hc := &hyperv1.HostedCluster{ObjectMeta: metav1.ObjectMeta{Namespace: "ns", Name: "cluster"}} for _, o := range opts { @@ -1256,6 +1267,7 @@ func TestReconcileMachineHealthCheck(t *testing.T) { } func TestCAPIReconcile(t *testing.T) { + t.Parallel() maxUnavailable := intstr.FromInt(0) maxSurge := intstr.FromInt(1) // This is the generated name by machineTemplateBuilders. @@ -1688,6 +1700,7 @@ func TestCAPIReconcile(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() g := NewWithT(t) c := fake.NewClientBuilder(). WithScheme(api.Scheme). @@ -1864,6 +1877,7 @@ func TestCAPIReconcile(t *testing.T) { } func TestGlobalPSManagedLabelOnMachines(t *testing.T) { + t.Parallel() maxUnavailable := intstr.FromInt(0) maxSurge := intstr.FromInt(1) awsMachineTemplateName := "test-nodepool-29e4de4b" @@ -2185,6 +2199,7 @@ func TestGlobalPSManagedLabelOnMachines(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() g := NewWithT(t) objects := append([]client.Object{tt.nodePool}, tt.objects...) @@ -2249,6 +2264,7 @@ func TestGlobalPSManagedLabelOnMachines(t *testing.T) { } func TestPause(t *testing.T) { + t.Parallel() g := NewWithT(t) nodePool := &hyperv1.NodePool{ @@ -2316,6 +2332,7 @@ func TestPause(t *testing.T) { } func TestNewCAPI(t *testing.T) { + t.Parallel() testCases := []struct { name string token *Token @@ -2348,6 +2365,7 @@ func TestNewCAPI(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + t.Parallel() g := NewWithT(t) capi, err := newCAPI(tc.token, tc.capiClusterName) diff --git a/hypershift-operator/controllers/nodepool/nodepool_controller_test.go b/hypershift-operator/controllers/nodepool/nodepool_controller_test.go index 4eeb94091fee..b4c4eeff5234 100644 --- a/hypershift-operator/controllers/nodepool/nodepool_controller_test.go +++ b/hypershift-operator/controllers/nodepool/nodepool_controller_test.go @@ -47,6 +47,7 @@ import ( ) func TestIsUpdatingConfig(t *testing.T) { + t.Parallel() testCases := []struct { name string nodePool *hyperv1.NodePool @@ -81,6 +82,7 @@ func TestIsUpdatingConfig(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + t.Parallel() g := NewWithT(t) g.Expect(isUpdatingConfig(tc.nodePool, tc.target)).To(Equal(tc.expect)) }) @@ -88,6 +90,7 @@ func TestIsUpdatingConfig(t *testing.T) { } func TestIsUpdatingVersion(t *testing.T) { + t.Parallel() testCases := []struct { name string nodePool *hyperv1.NodePool @@ -118,6 +121,7 @@ func TestIsUpdatingVersion(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + t.Parallel() g := NewWithT(t) g.Expect(isUpdatingVersion(tc.nodePool, tc.target)).To(Equal(tc.expect)) }) @@ -125,6 +129,7 @@ func TestIsUpdatingVersion(t *testing.T) { } func TestIsAutoscalingEnabled(t *testing.T) { + t.Parallel() testCases := []struct { name string nodePool *hyperv1.NodePool @@ -165,6 +170,7 @@ func TestIsAutoscalingEnabled(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + t.Parallel() g := NewWithT(t) g.Expect(isAutoscalingEnabled(tc.nodePool)).To(Equal(tc.expect)) }) @@ -172,6 +178,7 @@ func TestIsAutoscalingEnabled(t *testing.T) { } func TestValidateManagement(t *testing.T) { + t.Parallel() intstrPointer1 := intstr.FromInt(1) testCases := []struct { name string @@ -291,6 +298,7 @@ func TestValidateManagement(t *testing.T) { } func TestValidateInfraID(t *testing.T) { + t.Parallel() g := NewWithT(t) err := validateInfraID("") g.Expect(err).To(HaveOccurred()) @@ -300,6 +308,7 @@ func TestValidateInfraID(t *testing.T) { } func TestGetName(t *testing.T) { + t.Parallel() g := NewWithT(t) alphaNumeric := regexp.MustCompile(`^[a-z0-9]*$`) @@ -321,6 +330,7 @@ func TestGetName(t *testing.T) { } func TestGetNodePoolNamespacedName(t *testing.T) { + t.Parallel() testControlPlaneNamespace := "control-plane-ns" testNodePoolNamespace := "clusters" testNodePoolName := "nodepool-1" @@ -400,6 +410,7 @@ func TestGetNodePoolNamespacedName(t *testing.T) { } func TestNodepoolDeletionDoesntRequireHCluster(t *testing.T) { + t.Parallel() nodePool := &hyperv1.NodePool{ ObjectMeta: metav1.ObjectMeta{ Name: "some-nodepool", @@ -431,6 +442,7 @@ func TestNodepoolDeletionDoesntRequireHCluster(t *testing.T) { } func TestCreateValidGeneratedPayloadCondition(t *testing.T) { + t.Parallel() testCases := []struct { name string tokenSecret *corev1.Secret @@ -504,6 +516,7 @@ func TestCreateValidGeneratedPayloadCondition(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + t.Parallel() g := NewWithT(t) var client client.Client @@ -525,6 +538,7 @@ func TestCreateValidGeneratedPayloadCondition(t *testing.T) { } func TestDefaultNodePoolAMI(t *testing.T) { + t.Parallel() testCases := []struct { name string region string @@ -589,6 +603,7 @@ func TestDefaultNodePoolAMI(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + t.Parallel() g := NewWithT(t) other := []client.Object{ @@ -640,6 +655,7 @@ func TestDefaultNodePoolAMI(t *testing.T) { } func TestGetHostedClusterVersion(t *testing.T) { + t.Parallel() testCases := []struct { name string versionStatus *hyperv1.ClusterVersionStatus @@ -698,6 +714,7 @@ func TestGetHostedClusterVersion(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + t.Parallel() g := NewWithT(t) releaseProvider := &fakereleaseprovider.FakeReleaseProvider{ @@ -874,6 +891,7 @@ func (t *testCondition) Compare(g Gomega, cond *hyperv1.NodePoolCondition) { } func TestSetMachineAndNodeConditions(t *testing.T) { + t.Parallel() g := NewWithT(t) s := runtime.NewScheme() g.Expect(hyperv1.AddToScheme(s)).To(Succeed()) @@ -2289,6 +2307,7 @@ func newKVInfraMapMock(objects []client.Object) kvinfra.KubevirtInfraClientMap { } func TestIsArchAndPlatformSupported(t *testing.T) { + t.Parallel() testCases := []struct { name string nodePool *hyperv1.NodePool @@ -2394,6 +2413,7 @@ func TestIsArchAndPlatformSupported(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + t.Parallel() g := NewWithT(t) g.Expect(isArchAndPlatformSupported(tc.nodePool)).To(Equal(tc.expect)) }) @@ -2401,6 +2421,7 @@ func TestIsArchAndPlatformSupported(t *testing.T) { } func Test_validateHCPayloadSupportsNodePoolCPUArch(t *testing.T) { + t.Parallel() testCases := []struct { name string hc *hyperv1.HostedCluster @@ -2447,6 +2468,7 @@ func Test_validateHCPayloadSupportsNodePoolCPUArch(t *testing.T) { } for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { + t.Parallel() g := NewWithT(t) err := validateHCPayloadSupportsNodePoolCPUArch(tt.hc, tt.np) @@ -2709,6 +2731,7 @@ kind: Config`), } func TestSupportedVersionSkewCondition(t *testing.T) { + t.Parallel() basePullSecret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: "pull-secret", @@ -3012,6 +3035,7 @@ func TestSupportedVersionSkewCondition(t *testing.T) { } func TestNodePoolReconciler_reconcile(t *testing.T) { + t.Parallel() tests := []struct { name string // description of this test case // Named input parameters for target function. @@ -3179,6 +3203,7 @@ func TestNodePoolReconciler_reconcile(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() g := NewWithT(t) pullSecret := &corev1.Secret{