Skip to content

Fixes unmarshalling of YAML #3116

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

vsantwana
Copy link
Member

@vsantwana vsantwana commented Jun 9, 2025

Release Notes

Bug Fixes

  • This PR fixes the bug with flink application create. It fails with YAML files, because it is unable to read apiVersion. For somereason, the YAML parser is looking for ApiVersion instead of apiVersion, despite the json tag available. The fix for this at the moment is to not use the YAML library but instead first convert it to JSON and then unmarshal it.
  • There was a similar issue with ComputePool, which is also fixed.
  • This fix also gave up an opportunity to fix another bug. Earlier when we used to return something with YAML output, it was returned as apiversion, but now it will be returned as apiVersion

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 verified this PR in Confluent Cloud pre-prod or production environment, if applicable.
  • I have verified this PR in Confluent Platform on-premises environment, if applicable.
  • 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

Blast Radius

References

Test & Review

Has been manually tested for the example mentioned in the ticket
hello.yaml

apiVersion: cmf.confluent.io/v1
kind: FlinkApplication
metadata:
  name: fraud-detection-1
spec:
  image: confluentinc/cp-flink:1.19.1-cp1
  flinkVersion: v1_19
  flinkConfiguration:
    taskmanager.numberOfTaskSlots: "2"
    metrics.reporter.prom.factory.class: org.apache.flink.metrics.prometheus.PrometheusReporterFactory
    metrics.reporter.prom.port: "9249-9250"
  serviceAccount: flink
  jobManager:
    resource:
      memory: "1024m"
      cpu: 1
  taskManager:
    resource:
      memory: "1024m"
      cpu: 1
  job:
    jarURI: "local:///opt/flink/examples/streaming/StateMachineExample.jar"
    state: running
    parallelism: 2
    upgradeMode: stateless

And it passes

./confluent flink application create --environment santwana hello.yaml
A major version update is available for confluent from (current: 0.0.0, latest: 4.29.0).
To view release notes and install the update, please run `confluent update --major`.

{
  "apiVersion": "cmf.confluent.io/v1",
  "kind": "FlinkApplication",
  "metadata": {
    "creationTimestamp": "2025-06-20T07:42:41.704067Z",
    "name": "fraud-detection",
    "updateTimestamp": "2025-06-20T07:42:41.704073Z"
  },
  "spec": {
    "flinkConfiguration": {
      "metrics.reporter.prom.factory.class": "org.apache.flink.metrics.prometheus.PrometheusReporterFactory",
      "metrics.reporter.prom.port": "9249-9250",
      "taskmanager.numberOfTaskSlots": "2"
    },
    "flinkVersion": "v1_19",
    "image": "confluentinc/cp-flink:1.19.1-cp1",
    "job": {
      "jarURI": "local:///opt/flink/examples/streaming/StateMachineExample.jar",
      "parallelism": 2,
      "state": "running",
      "upgradeMode": "stateless"
    },
    "jobManager": {
      "resource": {
        "cpu": 1,
        "memory": "1024m"
      }
    },
    "serviceAccount": "flink",
    "taskManager": {
      "resource": {
        "cpu": 1,
        "memory": "1024m"
      }
    }
  },
  "status": {
    "jobStatus": {
      "jobName": "",
      "state": ""
    }
  }
}

@Copilot Copilot AI review requested due to automatic review settings June 9, 2025 03:40
@vsantwana vsantwana requested a review from a team as a code owner June 9, 2025 03:40
@confluent-cla-assistant
Copy link

🎉 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.

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR improves YAML unmarshalling by first parsing into a generic map to preserve key casing, then converting to JSON to leverage struct JSON tags, and adds a fallback for apiVersion if it wasn’t populated during the JSON unmarshal.

  • Introduce a two-step YAML→map→JSON→struct unmarshalling flow
  • Add fallback assignment for application.ApiVersion from raw map
  • (Unintended) add a debug print of the application struct
Comments suppressed due to low confidence (1)

internal/flink/command_application_create.go:62

  • Add unit tests for the new YAML unmarshalling path, including cases where apiVersion is populated via the raw map fallback.
var raw map[string]interface{}

default:
return errors.NewErrorWithSuggestions(fmt.Sprintf("unsupported file format: %s", ext), "Supported file formats are .json, .yaml, and .yml.")
}
if err != nil {
return err
}

fmt.Print("application", application)
Copy link
Preview

Copilot AI Jun 9, 2025

Choose a reason for hiding this comment

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

Remove this debug print or replace it with a proper logger call at the appropriate log level to avoid dumping raw structs to stdout in production.

Suggested change
fmt.Print("application", application)
log.Printf("Debug: application struct: %+v", application)

Copilot uses AI. Check for mistakes.

// First unmarshal into a generic map to preserve the case
var raw map[string]interface{}
if err = yaml.Unmarshal(data, &raw); err != nil {
return fmt.Errorf("failed to unmarshal YAML: %v", err)
Copy link
Preview

Copilot AI Jun 9, 2025

Choose a reason for hiding this comment

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

Use fmt.Errorf("failed to unmarshal YAML: %w", err) to wrap the original error and preserve unwrapping support.

Suggested change
return fmt.Errorf("failed to unmarshal YAML: %v", err)
return fmt.Errorf("failed to unmarshal YAML: %w", err)

Copilot uses AI. Check for mistakes.

Comment on lines 61 to 84
// First unmarshal into a generic map to preserve the case
var raw map[string]interface{}
if err = yaml.Unmarshal(data, &raw); err != nil {
return fmt.Errorf("failed to unmarshal YAML: %v", err)
}

// Convert to JSON bytes to use the struct's JSON tags
jsonBytes, err := json.Marshal(raw)
if err != nil {
return fmt.Errorf("failed to convert to JSON: %v", err)
}

// Now unmarshal into the struct using JSON unmarshaler
// This will respect the json tags in the struct
if err = json.Unmarshal(jsonBytes, &application); err != nil {
return fmt.Errorf("failed to unmarshal JSON: %v", err)
}

// Verify the apiVersion was set correctly
if application.ApiVersion == "" {
// If still empty, try to get it directly from the raw map
if apiVer, ok := raw["apiVersion"].(string); ok {
application.ApiVersion = apiVer
}
Copy link
Preview

Copilot AI Jun 9, 2025

Choose a reason for hiding this comment

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

[nitpick] Converting YAML to JSON through an intermediate map adds overhead; consider using a YAML library or decoder that respects JSON struct tags directly to avoid double marshalling.

Suggested change
// First unmarshal into a generic map to preserve the case
var raw map[string]interface{}
if err = yaml.Unmarshal(data, &raw); err != nil {
return fmt.Errorf("failed to unmarshal YAML: %v", err)
}
// Convert to JSON bytes to use the struct's JSON tags
jsonBytes, err := json.Marshal(raw)
if err != nil {
return fmt.Errorf("failed to convert to JSON: %v", err)
}
// Now unmarshal into the struct using JSON unmarshaler
// This will respect the json tags in the struct
if err = json.Unmarshal(jsonBytes, &application); err != nil {
return fmt.Errorf("failed to unmarshal JSON: %v", err)
}
// Verify the apiVersion was set correctly
if application.ApiVersion == "" {
// If still empty, try to get it directly from the raw map
if apiVer, ok := raw["apiVersion"].(string); ok {
application.ApiVersion = apiVer
}
// Unmarshal YAML directly into the struct
if err = yaml.Unmarshal(data, &application); err != nil {
return fmt.Errorf("failed to unmarshal YAML: %v", err)
}
// Verify the apiVersion was set correctly
if application.ApiVersion == "" {
return fmt.Errorf("apiVersion is missing in the YAML file")

Copilot uses AI. Check for mistakes.

@sonarqube-confluent

This comment has been minimized.

@vsantwana vsantwana requested a review from sgagniere June 20, 2025 16:00
@sonarqube-confluent

This comment has been minimized.

@airlock-confluentinc airlock-confluentinc bot force-pushed the cf-3631_fix_flink_application_payload branch 2 times, most recently from b7aff45 to 67c21bf Compare June 27, 2025 16:43
@sonarqube-confluent

This comment has been minimized.

@airlock-confluentinc airlock-confluentinc bot force-pushed the cf-3631_fix_flink_application_payload branch from 67c21bf to ded01e8 Compare June 27, 2025 17:16
Copy link
Member

@sgagniere sgagniere left a comment

Choose a reason for hiding this comment

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

Thanks, looks good.

But it looks like we have some test issues to sort out.

@sonarqube-confluent
Copy link

Failed

  • 64.60% Coverage on New Code (is less than 80.00%)

Analysis Details

8 Issues

  • Bug 0 Bugs
  • Vulnerability 0 Vulnerabilities
  • Code Smell 8 Code Smells

Coverage and Duplications

  • Coverage 64.60% Coverage (77.30% Estimated after merge)
  • Duplications No duplication information (0.20% Estimated after merge)

Project ID: cli

View in 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