Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions internal/flink/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func New(cfg *config.Config, prerunner pcmd.PreRunner) *cobra.Command {
cmd.AddCommand(c.newDetachedSavepointCommand())
cmd.AddCommand(c.newEnvironmentCommand())
cmd.AddCommand(c.newSavepointCommand())
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},
}

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=10f08ad8-1790-4ef2-9cb4-b77dd69ab367&open=10f08ad8-1790-4ef2-9cb4-b77dd69ab367
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