Skip to content
Merged
1 change: 1 addition & 0 deletions internal/flink/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ func New(cfg *config.Config, prerunner pcmd.PreRunner) *cobra.Command {
cmd.AddCommand(c.newEnvironmentCommand())
cmd.AddCommand(c.newSavepointCommand())
cmd.AddCommand(c.newSecretCommand())
cmd.AddCommand(c.newSecretMappingCommand())

// On-Prem and Cloud Commands
cmd.AddCommand(c.newComputePoolCommand(cfg))
Expand Down
126 changes: 126 additions & 0 deletions internal/flink/command_secret_mapping.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package flink

import (
"encoding/json"
"fmt"
"os"
"path/filepath"

"github.com/spf13/cobra"
"gopkg.in/yaml.v3"

cmfsdk "github.com/confluentinc/cmf-sdk-go/v1"

pcmd "github.com/confluentinc/cli/v4/pkg/cmd"
"github.com/confluentinc/cli/v4/pkg/errors"
"github.com/confluentinc/cli/v4/pkg/output"
)

type secretMappingOut struct {
CreationTime string `human:"Creation Time" serialized:"creation_time"`
Name string `human:"Name" serialized:"name"`
SecretName string `human:"Secret Name" serialized:"secret_name"`
}

func (c *command) newSecretMappingCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "secret-mapping",
Short: "Manage Flink secret mappings.",
Long: "Manage Flink environment secret mappings in Confluent Platform.",
Annotations: map[string]string{pcmd.RunRequirement: pcmd.RequireCloudLogout},
}
Comment thread
paras-negi-flink marked this conversation as resolved.

cmd.AddCommand(c.newSecretMappingCreateCommand())
cmd.AddCommand(c.newSecretMappingDeleteCommand())
cmd.AddCommand(c.newSecretMappingDescribeCommand())
cmd.AddCommand(c.newSecretMappingListCommand())
cmd.AddCommand(c.newSecretMappingUpdateCommand())

return cmd
}

func printSecretMappingOutput(cmd *cobra.Command, sdkMapping cmfsdk.EnvironmentSecretMapping) error {
if output.GetFormat(cmd) == output.Human {
table := output.NewTable(cmd)
var creationTime, name, secretName string
if sdkMapping.Metadata != nil {
if sdkMapping.Metadata.CreationTimestamp != nil {
creationTime = *sdkMapping.Metadata.CreationTimestamp
}
if sdkMapping.Metadata.Name != nil {
name = *sdkMapping.Metadata.Name
}
}
if sdkMapping.Spec != nil {
secretName = sdkMapping.Spec.SecretName
}
table.Add(&secretMappingOut{
CreationTime: creationTime,
Name: name,
SecretName: secretName,
})
return table.Print()
}

localMapping := convertSdkSecretMappingToLocalSecretMapping(sdkMapping)
return output.SerializedOutput(cmd, localMapping)
}

func readSecretMappingResourceFile(resourceFilePath string) (cmfsdk.EnvironmentSecretMapping, error) {
data, err := os.ReadFile(resourceFilePath)
if err != nil {
return cmfsdk.EnvironmentSecretMapping{}, fmt.Errorf("failed to read file: %w", err)
}

var genericData map[string]interface{}
ext := filepath.Ext(resourceFilePath)
switch ext {
case ".json":
err = json.Unmarshal(data, &genericData)
case ".yaml", ".yml":
err = yaml.Unmarshal(data, &genericData)
default:
return cmfsdk.EnvironmentSecretMapping{}, errors.NewErrorWithSuggestions(fmt.Sprintf("unsupported file format: %s", ext), "Supported file formats are .json, .yaml, and .yml.")
}
if err != nil {
return cmfsdk.EnvironmentSecretMapping{}, fmt.Errorf("failed to parse input file: %w", err)
}

jsonBytes, err := json.Marshal(genericData)
if err != nil {
return cmfsdk.EnvironmentSecretMapping{}, fmt.Errorf("failed to marshal intermediate data: %w", err)
}

var sdkMapping cmfsdk.EnvironmentSecretMapping
if err = json.Unmarshal(jsonBytes, &sdkMapping); err != nil {
return cmfsdk.EnvironmentSecretMapping{}, fmt.Errorf("failed to bind data to EnvironmentSecretMapping model: %w", err)
}

return sdkMapping, nil
}

func convertSdkSecretMappingToLocalSecretMapping(sdkMapping cmfsdk.EnvironmentSecretMapping) LocalSecretMapping {
localMapping := LocalSecretMapping{
ApiVersion: sdkMapping.ApiVersion,
Kind: sdkMapping.Kind,
}

if sdkMapping.Metadata != nil {
localMapping.Metadata = LocalSecretMappingMetadata{
Name: sdkMapping.Metadata.GetName(),
CreationTimestamp: sdkMapping.Metadata.CreationTimestamp,
UpdateTimestamp: sdkMapping.Metadata.UpdateTimestamp,
Uid: sdkMapping.Metadata.Uid,
Labels: sdkMapping.Metadata.Labels,
Annotations: sdkMapping.Metadata.Annotations,
}
}

if sdkMapping.Spec != nil {
localMapping.Spec = LocalSecretMappingSpec{
SecretName: sdkMapping.Spec.SecretName,
}
}

return localMapping
}
50 changes: 50 additions & 0 deletions internal/flink/command_secret_mapping_create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package flink

import (
"github.com/spf13/cobra"

pcmd "github.com/confluentinc/cli/v4/pkg/cmd"
)

func (c *command) newSecretMappingCreateCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "create <resourceFilePath>",
Short: "Create a Flink secret mapping.",
Long: "Create a Flink environment secret mapping in Confluent Platform.",
Args: cobra.ExactArgs(1),
RunE: c.secretMappingCreate,
}

cmd.Flags().String("environment", "", "Name of the Flink environment.")
cobra.CheckErr(cmd.MarkFlagRequired("environment"))
addCmfFlagSet(cmd)
pcmd.AddOutputFlag(cmd)

return cmd
}

func (c *command) secretMappingCreate(cmd *cobra.Command, args []string) error {
resourceFilePath := args[0]

environment, err := cmd.Flags().GetString("environment")
if err != nil {
return err
}

client, err := c.GetCmfClient(cmd)
if err != nil {
return err
}

sdkMapping, err := readSecretMappingResourceFile(resourceFilePath)
if err != nil {
return err
}

sdkOutputMapping, err := client.CreateSecretMapping(c.createContext(), environment, sdkMapping)
if err != nil {
return err
}

return printSecretMappingOutput(cmd, sdkOutputMapping)
}
57 changes: 57 additions & 0 deletions internal/flink/command_secret_mapping_delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package flink

import (
"github.com/spf13/cobra"

pcmd "github.com/confluentinc/cli/v4/pkg/cmd"
"github.com/confluentinc/cli/v4/pkg/deletion"
"github.com/confluentinc/cli/v4/pkg/errors"
"github.com/confluentinc/cli/v4/pkg/resource"
)

func (c *command) newSecretMappingDeleteCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "delete <name-1> [name-2] ... [name-n]",
Short: "Delete one or more Flink secret mappings.",
Long: "Delete one or more Flink environment secret mappings in Confluent Platform.",
Args: cobra.MinimumNArgs(1),
RunE: c.secretMappingDelete,
}

cmd.Flags().String("environment", "", "Name of the Flink environment.")
cobra.CheckErr(cmd.MarkFlagRequired("environment"))
addCmfFlagSet(cmd)
pcmd.AddForceFlag(cmd)

return cmd
}

func (c *command) secretMappingDelete(cmd *cobra.Command, args []string) error {
environment, err := cmd.Flags().GetString("environment")
if err != nil {
return err
}

client, err := c.GetCmfClient(cmd)
if err != nil {
return err
}

existenceFunc := func(name string) bool {
_, err := client.DescribeSecretMapping(c.createContext(), environment, name)
return err == nil
}

if err := deletion.ValidateAndConfirm(cmd, args, existenceFunc, resource.FlinkSecretMapping); err != nil {
suggestions := "List available Flink secret mappings with `confluent flink secret-mapping list --environment <envName>`."
suggestions += "\nCheck that CMF is running and accessible."
return errors.NewErrorWithSuggestions(err.Error(), suggestions)
}

deleteFunc := func(name string) error {
return client.DeleteSecretMapping(c.createContext(), environment, name)
}

_, err = deletion.Delete(cmd, args, deleteFunc, resource.FlinkSecretMapping)
return err
}
45 changes: 45 additions & 0 deletions internal/flink/command_secret_mapping_describe.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package flink

import (
"github.com/spf13/cobra"

pcmd "github.com/confluentinc/cli/v4/pkg/cmd"
)

func (c *command) newSecretMappingDescribeCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "describe <name>",
Short: "Describe a Flink secret mapping.",
Long: "Describe a Flink environment secret mapping in Confluent Platform.",
Args: cobra.ExactArgs(1),
RunE: c.secretMappingDescribe,
}

cmd.Flags().String("environment", "", "Name of the Flink environment.")
cobra.CheckErr(cmd.MarkFlagRequired("environment"))
addCmfFlagSet(cmd)
pcmd.AddOutputFlag(cmd)

return cmd
}

func (c *command) secretMappingDescribe(cmd *cobra.Command, args []string) error {
name := args[0]

environment, err := cmd.Flags().GetString("environment")
if err != nil {
return err
}

client, err := c.GetCmfClient(cmd)
if err != nil {
return err
}

sdkOutputMapping, err := client.DescribeSecretMapping(c.createContext(), environment, name)
if err != nil {
return err
}

return printSecretMappingOutput(cmd, sdkOutputMapping)
}
73 changes: 73 additions & 0 deletions internal/flink/command_secret_mapping_list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package flink

import (
"github.com/spf13/cobra"

pcmd "github.com/confluentinc/cli/v4/pkg/cmd"
"github.com/confluentinc/cli/v4/pkg/output"
)

func (c *command) newSecretMappingListCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "list",
Short: "List Flink secret mappings.",
Long: "List Flink environment secret mappings in Confluent Platform.",
Args: cobra.NoArgs,
RunE: c.secretMappingList,
}

cmd.Flags().String("environment", "", "Name of the Flink environment.")
cobra.CheckErr(cmd.MarkFlagRequired("environment"))
addCmfFlagSet(cmd)
pcmd.AddOutputFlag(cmd)

return cmd
}

func (c *command) secretMappingList(cmd *cobra.Command, _ []string) error {

Check failure on line 27 in internal/flink/command_secret_mapping_list.go

View check run for this annotation

SonarQube-Confluent / SonarQube Code Analysis

Refactor this method to reduce its Cognitive Complexity from 21 to the 15 allowed.

[S3776] Cognitive Complexity of functions should not be too high See more on https://sonarqube.confluent.io/project/issues?id=cli&pullRequest=3306&issues=b31840fb-5717-4699-80d3-42727a75d094&open=b31840fb-5717-4699-80d3-42727a75d094
environment, err := cmd.Flags().GetString("environment")
if err != nil {
return err
}

client, err := c.GetCmfClient(cmd)
if err != nil {
return err
}

sdkMappings, err := client.ListSecretMappings(c.createContext(), environment)
if err != nil {
return err
}

if output.GetFormat(cmd) == output.Human {
list := output.NewList(cmd)
for _, mapping := range sdkMappings {
var creationTime, name, secretName string
if mapping.Metadata != nil {
if mapping.Metadata.CreationTimestamp != nil {
creationTime = *mapping.Metadata.CreationTimestamp
}
if mapping.Metadata.Name != nil {
name = *mapping.Metadata.Name
}
}
if mapping.Spec != nil {
secretName = mapping.Spec.SecretName
}
list.Add(&secretMappingOut{
CreationTime: creationTime,
Name: name,
SecretName: secretName,
})
}
return list.Print()
}

localMappings := make([]LocalSecretMapping, 0, len(sdkMappings))
for _, sdkMapping := range sdkMappings {
localMappings = append(localMappings, convertSdkSecretMappingToLocalSecretMapping(sdkMapping))
}

return output.SerializedOutput(cmd, localMappings)
}
Loading