Skip to content
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

add disable feature command #45

Merged
merged 2 commits into from
Jul 2, 2024
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
64 changes: 64 additions & 0 deletions pkg/cmd/disable-feature.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package cmd

import (
"strings"

toolchainv1alpha1 "github.com/codeready-toolchain/api/api/v1alpha1"
"github.com/kubesaw/ksctl/pkg/client"
clicontext "github.com/kubesaw/ksctl/pkg/context"
"github.com/kubesaw/ksctl/pkg/ioutils"
"k8s.io/utils/strings/slices"

"github.com/spf13/cobra"
)

func NewDisableFeatureCmd() *cobra.Command {
return &cobra.Command{
Use: "disable-feature <space-name> <feature-name>",
Short: "Disable a feature for the given Space",
Long: `Disable a feature toggle for the given Space. There are two expected
parameters - the first one is the Space name and the second is the name of the feature toggle that should be disabled for the Space.`,
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
term := ioutils.NewTerminal(cmd.InOrStdin, cmd.OutOrStdout)
ctx := clicontext.NewCommandContext(term, client.DefaultNewClient)
return DisableFeature(ctx, args[0], args[1])
},

Check warning on line 26 in pkg/cmd/disable-feature.go

View check run for this annotation

Codecov / codecov/patch

pkg/cmd/disable-feature.go#L23-L26

Added lines #L23 - L26 were not covered by tests
}
}

func DisableFeature(ctx *clicontext.CommandContext, spaceName, featureToggleName string) error {
return client.PatchSpace(ctx, spaceName, func(space *toolchainv1alpha1.Space) (bool, error) {
currentFeatures := strings.TrimSpace(space.Annotations[toolchainv1alpha1.FeatureToggleNameAnnotationKey])
var enabledFeatures []string
if currentFeatures != "" {
enabledFeatures = strings.Split(currentFeatures, ",")
}
if err := ctx.PrintObject(space, "The current Space"); err != nil {
return false, err

Check warning on line 38 in pkg/cmd/disable-feature.go

View check run for this annotation

Codecov / codecov/patch

pkg/cmd/disable-feature.go#L38

Added line #L38 was not covered by tests
}

if !slices.Contains(enabledFeatures, featureToggleName) {
ctx.Println("")
ctx.Println("The Space doesn't have the feature toggle enabled. There is nothing to do.")
ctx.Println("")
return false, nil
}

confirmation := ctx.AskForConfirmation(ioutils.WithMessagef(
"disable the feature toggle '%s' for the Space '%s'? The enabled feature toggles are '%s'.",
featureToggleName, spaceName, currentFeatures))

if confirmation {
index := slices.Index(enabledFeatures, featureToggleName)
enabledFeatures = append(enabledFeatures[:index], enabledFeatures[index+1:]...)
if len(enabledFeatures) == 0 {
delete(space.Annotations, toolchainv1alpha1.FeatureToggleNameAnnotationKey)
} else {
space.Annotations[toolchainv1alpha1.FeatureToggleNameAnnotationKey] = strings.Join(enabledFeatures, ",")
}
return true, nil
}
return false, nil
}, "Successfully disabled feature toggle for the Space")
}
140 changes: 140 additions & 0 deletions pkg/cmd/disable_feature_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package cmd_test

import (
"fmt"
"testing"

toolchainv1alpha1 "github.com/codeready-toolchain/api/api/v1alpha1"
"github.com/kubesaw/ksctl/pkg/cmd"
clicontext "github.com/kubesaw/ksctl/pkg/context"
. "github.com/kubesaw/ksctl/pkg/test"

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

func TestDisableFeatureCmd(t *testing.T) {
// given
SetFileConfig(t, Host())

var combinations = []struct {
alreadyEnabled string
afterDisable map[string]string
}{
{
alreadyEnabled: "feature-x",
afterDisable: nil,
},
{
alreadyEnabled: "feature-x,feature0",
afterDisable: map[string]string{
toolchainv1alpha1.FeatureToggleNameAnnotationKey: "feature0",
},
},
{
alreadyEnabled: "feature1,feature2,feature-x,feature3",
afterDisable: map[string]string{
toolchainv1alpha1.FeatureToggleNameAnnotationKey: "feature1,feature2,feature3",
},
},
}

for _, data := range combinations {
t.Run("with the already enabled features: "+data.alreadyEnabled, func(t *testing.T) {
// given
space := newSpace()
if data.alreadyEnabled != "" {
space.Annotations = map[string]string{
toolchainv1alpha1.FeatureToggleNameAnnotationKey: data.alreadyEnabled,
}
}

for _, answer := range []string{"Y", "n"} {

t.Run("when answer is "+answer, func(t *testing.T) {
// given
newClient, fakeClient := NewFakeClients(t, space)
term := NewFakeTerminalWithResponse(answer)
ctx := clicontext.NewCommandContext(term, newClient)

// when
err := cmd.DisableFeature(ctx, space.Name, "feature-x")

// then
require.NoError(t, err)

output := term.Output()
assert.Contains(t, output, fmt.Sprintf("disable the feature toggle 'feature-x' for the Space 'testspace'? The enabled feature toggles are '%s'.", data.alreadyEnabled))
assert.NotContains(t, output, "cool-token")
expectedSpace := newSpace()

if answer == "Y" {
expectedSpace.Annotations = data.afterDisable
assert.Contains(t, output, "Successfully disabled feature toggle for the Space")

} else {
expectedSpace.Annotations = space.Annotations
assert.NotContains(t, output, "Successfully disabled feature toggle for the Space")
}
assertSpaceAnnotations(t, fakeClient, expectedSpace)

})
}
})
}
}

func TestDisableFeatureCmdWhenFeatureIsNotEnabled(t *testing.T) {
// given
SetFileConfig(t, Host())

for _, alreadyEnabled := range []string{"", "feature0", "feature1,feature2,feature3"} {
t.Run("with the already enabled features: "+alreadyEnabled, func(t *testing.T) {
// given
space := newSpace()
if alreadyEnabled != "" {
space.Annotations = map[string]string{
toolchainv1alpha1.FeatureToggleNameAnnotationKey: alreadyEnabled,
}
}
// given
newClient, fakeClient := NewFakeClients(t, space)
term := NewFakeTerminalWithResponse("Y")
ctx := clicontext.NewCommandContext(term, newClient)

// when
err := cmd.DisableFeature(ctx, space.Name, "feature-x")

// then
require.NoError(t, err)
assertSpaceAnnotations(t, fakeClient, space) // no change

output := term.Output()
assert.Contains(t, output, "The Space doesn't have the feature toggle enabled. There is nothing to do.")
assert.NotContains(t, output, "disable the feature toggle 'feature-x' for the Space 'testspace'?")
assert.NotContains(t, output, "Successfully disabled feature toggle for the Space")
assert.NotContains(t, output, "cool-token")

})
}
}

func TestDisableFeatureCmdWhenSpaceNotFound(t *testing.T) {
// given
space := newSpace()
newClient, fakeClient := NewFakeClients(t, space)
SetFileConfig(t, Host())
term := NewFakeTerminalWithResponse("Y")
ctx := clicontext.NewCommandContext(term, newClient)

// when
err := cmd.DisableFeature(ctx, "another", "feature-x")

// then
require.EqualError(t, err, "spaces.toolchain.dev.openshift.com \"another\" not found")
assertSpaceAnnotations(t, fakeClient, space) // unrelated space should be unchanged
output := term.Output()
assert.NotContains(t, output, "disable the feature toggle 'feature-x' for the Space 'testspace'?")
assert.NotContains(t, output, "Successfully disabled feature toggle for the Space")
assert.NotContains(t, output, "cool-token")
}
1 change: 1 addition & 0 deletions pkg/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func init() {
rootCmd.AddCommand(NewLogsCmd())
rootCmd.AddCommand(NewDescribeCmd())
rootCmd.AddCommand(NewDisableUserCmd())
rootCmd.AddCommand(NewDisableFeatureCmd())
rootCmd.AddCommand(NewEnableFeatureCmd())

// administrative commands
Expand Down
Loading