Repository navigation
fix(admin): initialise V1Scale spec before setting replicas (#7698) - #7710
Merged
Merged
Conversation
Aias00
approved these changes
Oct 17, 2026
Aias00
left a comment
Contributor
There was a problem hiding this comment.
Summary
Fixes #7698. KubernetesScaler#scaleByNum constructed a bare new V1Scale() and immediately dereferenced its spec via Objects.requireNonNull(scale.getSpec()).setReplicas(...). Because a freshly built V1Scale has a null spec, every replica update threw an NPE before the Kubernetes API call — the fixed / time-window scaling policies and the dynamic scaleByAction path were all dead on arrival. The NPE also escaped the surrounding catch (ApiException).
What the change does
shenyu-admin/.../scale/scaler/KubernetesScaler.java:73: replacesObjects.requireNonNull(scale.getSpec()).setReplicas(replicaCount)withscale.setSpec(new V1ScaleSpec().replicas(replicaCount)), so a non-null spec carrying the requested replica count reachesreplaceNamespacedDeploymentScale.V1ScaleSpecwas already imported, andObjectsremains used inscaleByAction.- Adds the scale module's first unit test
KubernetesScalerTest.javawith a Mockito-mockedAppsV1Api:testScaleByNumSetsSpecBeforeReplaceasserts the capturedV1Scalepassed to the replace call has a non-null spec with the requested replicas;testScaleByActionReadsCurrentAndAppliesDeltamocksreadNamespacedDeploymentScale(replicas=2) and assertsscaleByAction(SCALE_UP)replaces with replicas=3.
Verification
- Master comparison: master's
scaleByNumused therequireNonNull(scale.getSpec())form (as shown in the diff); head (56c0892f97c35722e5bdc99eca64339da6fe6895) usessetSpec(new V1ScaleSpec()...).V1ScaleSpecimport confirmed present in the current head file; the constructor signatureKubernetesScaler(Optional<AppsV1Api>, DeploymentProperties)matches the test'snew KubernetesScaler(Optional.of(appsV1Api), deploymentProperties). - Red-green is credible from the code:
new V1Scale().getSpec()is null by construction, so the old line throws before the API call; the new line is a straightforward, faithful replacement with no behavioural change beyond reaching the API server. - CI: all relevant checks pass on this head —
pr_build,Analyze (java),check-license-header,rat_check,scope,sql-matrix,registry_dependencies, allbuild (shenyu-integrated-test-*),agent_gateway_migrations, and thee2eaggregator. No reds to attribute.
Notes
- Non-blocking: the scale module previously had no tests; adding a Mockito-based unit test here is a welcome first step. Test class uses
@MockitoSettings(strictness = Strictness.LENIENT)andisNull()matchers for the trailingpretty/dryRun/fieldManager/fieldValidationargs, which are correct given they are passed as null. - No change to the other replace-call arguments; no impact on unrelated modules.
Conclusion
APPROVE. Correct, minimal fix for a real NPE that disabled the Kubernetes scaling policy paths, backed by a targeted unit test and fully green CI.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #7698.
Summary
KubernetesScaler#scaleByNumconstructs a bareV1Scaleand dereferences its spec withObjects.requireNonNull. A freshV1Scalehas a null spec, so every replica update throws NPE before reaching the Kubernetes API — the fixed and time-window scaling policies and the dynamicscaleByActionare all dead on arrival. The NPE also escapes the surroundingcatch (ApiException).Modifications
scale.setSpec(new V1ScaleSpec().replicas(replicaCount))instead ofrequireNonNull(scale.getSpec()).setReplicas(...).V1ScaleSpecwas already imported in the file.KubernetesScalerTest, the scale module's first unit test, with a Mockito-mockedAppsV1Api:testScaleByNumSetsSpecBeforeReplacecaptures the scale passed toreplaceNamespacedDeploymentScaleand asserts the spec is non-null with the requested replicas.testScaleByActionReadsCurrentAndAppliesDeltamocksreadNamespacedDeploymentScale(replicas=2) and assertsscaleByAction(SCALE_UP)replaces with replicas=3.Verifying this change
Red-green: with the original
requireNonNullline restored, both new tests fail withNullPointerExceptionatKubernetesScaler.scaleByNum(matching the stack trace in the issue); with the fix they pass (2/2).Targeted tests pass:
./mvnw -B -ntp -pl shenyu-admin test -Dtest=KubernetesScalerTest2/2 green.
Checkstyle passes:
clean.
Notes
The replace call's other arguments (
pretty/dryRun/fieldManager/fieldValidation) stay null, unchanged. No behaviour change beyond making the call actually reach the API server.