Skip to content

CF-3931 : Reject mis-shaped --statement-defaults instead of silently ignoring it#3397

Open
Paras Negi (paras-negi-flink) wants to merge 2 commits into
mainfrom
cf-3931-strict-statement-defaults
Open

CF-3931 : Reject mis-shaped --statement-defaults instead of silently ignoring it#3397
Paras Negi (paras-negi-flink) wants to merge 2 commits into
mainfrom
cf-3931-strict-statement-defaults

Conversation

@paras-negi-flink

@paras-negi-flink Paras Negi (paras-negi-flink) commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Release Notes

Breaking Changes

  • NONE

New Features

  • NONE

Bug Fixes

  • confluent flink environment create/update now reject a mis-shaped --statement-defaults value with a clear error instead of silently ignoring it and reporting success.

Checklist

  • I have successfully built and used a custom CLI binary, without linter issues from this PR.
  • I have clearly specified in the What section below whether this PR applies to Confluent Cloud, Confluent Platform, or both.
  • I have attached manual CLI verification results or screenshots in the Test & Review section below.
  • I have added appropriate CLI integration or unit tests for any new or updated commands and functionality.
  • I confirm that this PR introduces no breaking changes or backward compatibility issues.
  • I have indicated the potential customer impact if something goes wrong in the Blast Radius section below.
  • I have put checkmarks below confirming that the feature associated with this PR is enabled in:
    • Confluent Cloud prod
    • Confluent Cloud stag
    • Confluent Platform
    • Check this box if the feature is enabled for certain organizations only

What

Confluent Platform (CP Flink / CMF on-prem).

  • --statement-defaults was parsed with plain json.Unmarshal, which silently drops keys that don't map to a field. A wrong-shape value (e.g. {"config-overrides":{...}}) set nothing yet exited 0 -- and, since update is a full replace, cleared any existing statement defaults.
  • Fix: parseDefaultsAsGenericType now decodes strictly (DisallowUnknownFields / YAML KnownFields). Safe for the map-based --defaults/--compute-pool-defaults (a map has no unknown fields), so only the typed --statement-defaults path is tightened. Flag help now documents the expected shape.

Blast Radius

  • A --statement-defaults value with unknown/mis-nested keys now errors (non-zero exit) instead of silently succeeding -- the intended correction; automation relying on the old silent-drop will now surface an error.
  • --defaults and --compute-pool-defaults are unaffected.
  • Separate, not fixed here: environment update is a full replace, so a partial update also clears the other defaults (tracked separately).

References

Test & Review

Environment: local CMF cmf-app 2.4-SNAPSHOT (HTTP, --cmf.k8s.enabled=false); CLI built from this branch vs released confluent v4.54.0.

Manual CLI validation: attached in the comment below.

Copilot AI review requested due to automatic review settings July 6, 2026 04:06
@confluent-cla-assistant

Copy link
Copy Markdown

🎉 All Contributor License Agreements have been signed. Ready to merge.
Please push an empty commit if you would like to re-run the checks to verify CLA status for all contributors.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Tightens parsing for the on-prem confluent flink environment create|update --statement-defaults flag so structurally valid-but-mis-shaped JSON/YAML is rejected with a clear error, and updates help/fixtures to document the expected shape.

Changes:

  • Switch defaults parsing to strict JSON/YAML decoding to surface unknown fields instead of silently dropping them.
  • Document the expected --statement-defaults JSON shape in command help output.
  • Add/adjust integration tests and golden fixtures to assert failure for wrong-shape --statement-defaults.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
internal/flink/command_environment_create.go Implements strict JSON/YAML decoding helpers and uses them for defaults parsing; updates --statement-defaults help text.
internal/flink/command_environment_update.go Updates --statement-defaults help text for the update command.
test/flink_onprem_test.go Adds integration test cases asserting invalid --statement-defaults input fails for create/update.
test/fixtures/output/flink/environment/create-statement-defaults-invalid.golden New golden asserting the parse error for invalid statement defaults (create).
test/fixtures/output/flink/environment/update-statement-defaults-invalid.golden New golden asserting the parse error for invalid statement defaults (update).
test/fixtures/output/flink/environment/create-help-onprem.golden Updates help golden with documented expected shape for --statement-defaults.
test/fixtures/output/flink/environment/update-help-onprem.golden Updates help golden with documented expected shape for --statement-defaults.
test/fixtures/output/flink/environment/create-no-namespace.golden Updates help golden with documented expected shape for --statement-defaults.
test/fixtures/output/flink/environment/missing-flag-failure.golden Updates help golden with documented expected shape for --statement-defaults.
Comments suppressed due to low confidence (1)

test/flink_onprem_test.go:272

  • The new strict decoding also applies to YAML input when the flag value is a path ending in .yml/.yaml, but the added integration tests only cover the inline JSON case. Adding a YAML fixture file with an intentionally mis-shaped statement defaults document (and an assertion it fails) would help ensure yaml.Decoder.KnownFields(true) is exercised and stays working.
		{args: "flink environment create default-failure --kubernetes-namespace default-staging", fixture: "flink/environment/create-failure.golden", exitCode: 1},
		{args: "flink environment create default --kubernetes-namespace default-staging", fixture: "flink/environment/create-existing.golden", exitCode: 1},
		{args: "flink environment create default", fixture: "flink/environment/create-no-namespace.golden", exitCode: 1},
		{args: "flink environment create default-2 --kubernetes-namespace default-staging --statement-defaults '{\"config-overrides\":{\"key\":\"value\"}}'", fixture: "flink/environment/create-statement-defaults-invalid.golden", exitCode: 1},
		// success with application, statement and compute pool defaults
		{args: "flink environment create default-2" +
			" --defaults test/fixtures/input/flink/environment/application-defaults.json" +
			" --statement-defaults test/fixtures/input/flink/environment/statement-defaults.json" +
			" --compute-pool-defaults test/fixtures/input/flink/environment/compute-pool-defaults.json" +

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +152 to +163
func decodeStrictJson(data []byte, out any) error {
decoder := json.NewDecoder(bytes.NewReader(data))
decoder.DisallowUnknownFields()
return decoder.Decode(out)
}

// decodeStrictYaml is the YAML counterpart of decodeStrictJson.
func decodeStrictYaml(data []byte, out any) error {
decoder := yaml.NewDecoder(bytes.NewReader(data))
decoder.KnownFields(true)
return decoder.Decode(out)
}
@paras-negi-flink

Copy link
Copy Markdown
Contributor Author

Manual CLI validation

Local CMF (cmf-app 2.4-SNAPSHOT, HTTP, --cmf.k8s.enabled=false). environment update with a wrong-shape --statement-defaults (top-level key config-overrides instead of interactive/detached).

Before — released confluent v4.54.0 (silent no-op, exits 0)

$ confluent --url $CMF flink environment update demo --statement-defaults '{"config-overrides":{"sql.state-ttl":"1h"}}' -o json
{
  "secrets": {},
  "name": "cf3931-cmt-demo",
  "created_time": "2026-07-07T05:05:29.46Z",
  "updated_time": "2026-07-07T05:05:29.558837Z",
  "kubernetesNamespace": "default",
  "statementDefaults": {}
}
# exit code: 0  (statementDefaults is empty -- input was dropped)

After — this PR (rejects it, non-zero exit)

$ confluent --url $CMF flink environment update demo --statement-defaults '{"config-overrides":{"sql.state-ttl":"1h"}}' -o json
Error: failed to parse statement defaults: json: unknown field "config-overrides"
# exit code: 1

After — valid input still applies

$ confluent --url $CMF flink environment update demo --statement-defaults '{"interactive":{"flinkConfiguration":{"pipeline.name":"my-job"}}}' -o json
{
  "secrets": {},
  "name": "cf3931-cmt-demo",
  "created_time": "2026-07-07T05:05:29.46Z",
  "updated_time": "2026-07-07T05:05:30.222805Z",
  "kubernetesNamespace": "default",
  "statementDefaults": {
    "interactive": {
      "flinkConfiguration": {
        "pipeline.name": "my-job"
      }
    }
  }
}
# exit code: 0

@paras-negi-flink Paras Negi (paras-negi-flink) marked this pull request as ready for review July 7, 2026 06:06
@paras-negi-flink Paras Negi (paras-negi-flink) requested a review from a team as a code owner July 7, 2026 06:06
@sonarqube-confluent

Copy link
Copy Markdown

Quality Gate failed Quality Gate failed

Failed conditions
52.4% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants