Skip to content
Merged
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
5 changes: 5 additions & 0 deletions cmd/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ func NewFlagsCmd(client flags.Client) (*cobra.Command, error) {
if err != nil {
return nil, err
}
getCmd, err := NewGetCmd(client)
if err != nil {
return nil, err
}
updateCmd, err := NewUpdateCmd(client)
if err != nil {
return nil, err
Expand All @@ -32,6 +36,7 @@ func NewFlagsCmd(client flags.Client) (*cobra.Command, error) {
}

cmd.AddCommand(createCmd)
cmd.AddCommand(getCmd)
cmd.AddCommand(updateCmd)
cmd.AddCommand(toggleOnUpdateCmd)
cmd.AddCommand(toggleOffUpdateCmd)
Expand Down
80 changes: 80 additions & 0 deletions cmd/flags/get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package flags

import (
"context"
"fmt"

"github.com/spf13/cobra"
"github.com/spf13/viper"

"ldcli/cmd/cliflags"
"ldcli/cmd/validators"
"ldcli/internal/flags"
)

func NewGetCmd(client flags.Client) (*cobra.Command, error) {
cmd := &cobra.Command{
Args: validators.Validate(),
Long: "Get a flag to check its details",
RunE: runGet(client),
Short: "Get a flag",
Use: "get",
}

cmd.Flags().String(cliflags.FlagFlag, "", "Flag key")
err := cmd.MarkFlagRequired(cliflags.FlagFlag)
if err != nil {
return nil, err
}
err = viper.BindPFlag(cliflags.FlagFlag, cmd.Flags().Lookup(cliflags.FlagFlag))
if err != nil {
return nil, err
}

cmd.Flags().String(cliflags.ProjectFlag, "", "Project key")
err = cmd.MarkFlagRequired(cliflags.ProjectFlag)
if err != nil {
return nil, err
}
err = viper.BindPFlag(cliflags.ProjectFlag, cmd.Flags().Lookup(cliflags.ProjectFlag))
if err != nil {
return nil, err
}

cmd.Flags().String(cliflags.EnvironmentFlag, "", "Environment key")
err = cmd.MarkFlagRequired(cliflags.EnvironmentFlag)
if err != nil {
return nil, err
}
err = viper.BindPFlag(cliflags.EnvironmentFlag, cmd.Flags().Lookup(cliflags.EnvironmentFlag))
if err != nil {
return nil, err
}

return cmd, nil
}

func runGet(client flags.Client) func(*cobra.Command, []string) error {
return func(cmd *cobra.Command, args []string) error {
// rebind flags used in other subcommands
_ = viper.BindPFlag(cliflags.FlagFlag, cmd.Flags().Lookup(cliflags.FlagFlag))
_ = viper.BindPFlag(cliflags.ProjectFlag, cmd.Flags().Lookup(cliflags.ProjectFlag))
_ = viper.BindPFlag(cliflags.EnvironmentFlag, cmd.Flags().Lookup(cliflags.EnvironmentFlag))

response, err := client.Get(
context.Background(),
viper.GetString(cliflags.AccessTokenFlag),
viper.GetString(cliflags.BaseURIFlag),
viper.GetString(cliflags.FlagFlag),
viper.GetString(cliflags.ProjectFlag),
viper.GetString(cliflags.EnvironmentFlag),
)
if err != nil {
return err
}

fmt.Fprintf(cmd.OutOrStdout(), string(response)+"\n")

return nil
}
}
106 changes: 106 additions & 0 deletions cmd/flags/get_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package flags_test

import (
"ldcli/cmd"
"ldcli/internal/errors"
"ldcli/internal/flags"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestGet(t *testing.T) {
errorHelp := ". See `ldcli flags get --help` for supported flags and usage."
mockArgs := []interface{}{
"testAccessToken",
"http://test.com",
"test-key",
"test-proj-key",
"test-env-key",
}

t.Run("with valid flags calls API", func(t *testing.T) {
client := flags.MockClient{}
client.
On("Get", mockArgs...).
Return([]byte(cmd.ValidResponse), nil)
args := []string{
"flags", "get",
"--access-token", "testAccessToken",
"--base-uri", "http://test.com",
"--flag", "test-key",
"--project", "test-proj-key",
"--environment", "test-env-key",
}

output, err := cmd.CallCmd(t, nil, &client, nil, nil, args)

require.NoError(t, err)
assert.JSONEq(t, `{"valid": true}`, string(output))
})

t.Run("with valid flags from environment variables calls API", func(t *testing.T) {
teardownTest := cmd.SetupTestEnvVars(t)
defer teardownTest(t)
client := flags.MockClient{}
client.
On("Get", mockArgs...).
Return([]byte(cmd.ValidResponse), nil)
args := []string{
"flags", "get",
"--flag", "test-key",
"--project", "test-proj-key",
"--environment", "test-env-key",
}

output, err := cmd.CallCmd(t, nil, &client, nil, nil, args)

require.NoError(t, err)
assert.JSONEq(t, `{"valid": true}`, string(output))
})

t.Run("with an error response is an error", func(t *testing.T) {
client := flags.MockClient{}
client.
On("Get", mockArgs...).
Return([]byte(`{}`), errors.NewError("An error"))
args := []string{
"flags", "get",
"--access-token", "testAccessToken",
"--base-uri", "http://test.com",
"--flag", "test-key",
"--project", "test-proj-key",
"--environment", "test-env-key",
}

_, err := cmd.CallCmd(t, nil, &client, nil, nil, args)

require.EqualError(t, err, "An error")
})

t.Run("with missing required flags is an error", func(t *testing.T) {
args := []string{
"flags", "get",
}

_, err := cmd.CallCmd(t, nil, &flags.MockClient{}, nil, nil, args)

assert.EqualError(t, err, `required flag(s) "access-token", "environment", "flag", "project" not set`+errorHelp)
})

t.Run("with invalid base-uri is an error", func(t *testing.T) {
args := []string{
"flags", "get",
"--access-token", "testAccessToken",
"--base-uri", "invalid",
"--flag", "test-key",
"--project", "test-proj-key",
"--environment", "test-env-key",
}

_, err := cmd.CallCmd(t, nil, &flags.MockClient{}, nil, nil, args)

assert.EqualError(t, err, "base-uri is invalid"+errorHelp)
})
}
22 changes: 22 additions & 0 deletions internal/flags/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type UpdateInput struct {

type Client interface {
Create(ctx context.Context, accessToken, baseURI, name, key, projKey string) ([]byte, error)
Get(ctx context.Context, accessToken, baseURI, key, projKey, envKey string) ([]byte, error)
Update(
ctx context.Context,
accessToken,
Expand Down Expand Up @@ -54,7 +55,28 @@ func (c FlagsClient) Create(
flag, _, err := client.FeatureFlagsApi.PostFeatureFlag(ctx, projectKey).FeatureFlagBody(*post).Execute()
if err != nil {
return nil, errors.NewLDAPIError(err)
}

responseJSON, err := json.Marshal(flag)
if err != nil {
return nil, err
}

return responseJSON, nil
}

func (c FlagsClient) Get(
ctx context.Context,
accessToken,
baseURI,
key,
projectKey,
environmentKey string,
) ([]byte, error) {
client := client.New(accessToken, baseURI, c.cliVersion)
flag, _, err := client.FeatureFlagsApi.GetFeatureFlag(ctx, projectKey, key).Env(environmentKey).Execute()
if err != nil {
return nil, errors.NewLDAPIError(err)
}

responseJSON, err := json.Marshal(flag)
Expand Down
13 changes: 13 additions & 0 deletions internal/flags/mock_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,19 @@ func (c *MockClient) Create(
return args.Get(0).([]byte), args.Error(1)
}

func (c *MockClient) Get(
ctx context.Context,
accessToken,
baseURI,
key,
projKey,
envKey string,
) ([]byte, error) {
args := c.Called(accessToken, baseURI, key, projKey, envKey)

return args.Get(0).([]byte), args.Error(1)
}

func (c *MockClient) Update(
ctx context.Context,
accessToken,
Expand Down