Skip to content

Commit

Permalink
input validation wip
Browse files Browse the repository at this point in the history
  • Loading branch information
tsebastiani committed Oct 15, 2024
1 parent 95237af commit fc16493
Show file tree
Hide file tree
Showing 9 changed files with 277 additions and 44 deletions.
47 changes: 40 additions & 7 deletions cmd/describe.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package cmd

import (
"fmt"
"github.com/fatih/color"
"github.com/krkn-chaos/krknctl/pkg/provider/factory"
"github.com/krkn-chaos/krknctl/pkg/provider/models"
"github.com/krkn-chaos/krknctl/pkg/text"
"github.com/spf13/cobra"
"log"
)

func NewDescribeCommand(factory *factory.ProviderFactory) *cobra.Command {
Expand All @@ -18,21 +23,49 @@ func NewDescribeCommand(factory *factory.ProviderFactory) *cobra.Command {
return []string{}, cobra.ShellCompDirectiveError
}
provider := GetProvider(offline, factory)
scenarios, err := provider.GetScenarios()

scenarios, err := FetchScenarios(provider)
if err != nil {
log.Fatalf("Error fetching scenarios: %v", err)
return []string{}, cobra.ShellCompDirectiveError
}
var foundScenarios []string
for _, scenario := range *scenarios {
foundScenarios = append(foundScenarios, scenario.Name)
}
return foundScenarios, cobra.ShellCompDirectiveNoFileComp

return *scenarios, cobra.ShellCompDirectiveNoFileComp

},
RunE: func(cmd *cobra.Command, args []string) error {

offline, err := cmd.Flags().GetBool("offline")
if err != nil {
return err
}
spinner := NewSpinnerWithSuffix("fetching scenario details...")
spinner.Start()
provider := GetProvider(offline, factory)
scenarioDetail, err := provider.GetScenarioDetail(args[0])
if err != nil {
return err
}
spinner.Stop()
if scenarioDetail == nil {
return fmt.Errorf("could not find %s scenario", args[0])
}
PrintScenarioDetail(scenarioDetail)
return nil
},
}
return describeCmd
}

func PrintScenarioDetail(scenarioDetail *models.ScenarioDetail) {
fmt.Print("\n")
_, _ = color.New(color.FgGreen, color.Underline).Println(scenarioDetail.Name)
justifiedText := text.Justify(scenarioDetail.Description, 50)
for _, line := range justifiedText {
fmt.Println(line)
}
fmt.Print("\n")
argumentTable := NewArgumentTable(scenarioDetail.Fields)
argumentTable.Print()
fmt.Print("\n")

}
16 changes: 4 additions & 12 deletions cmd/list.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"fmt"
provider_factory "github.com/krkn-chaos/krknctl/pkg/provider/factory"
"github.com/spf13/cobra"
"log"
Expand All @@ -27,20 +28,11 @@ func NewListCommand(factory *provider_factory.ProviderFactory) *cobra.Command {
log.Fatalf("failed to fetch scenarios: %v", err)
}
s.Stop()
test := NewScenarioTable(scenarios)
(*test).Print()
scenarioTable := NewScenarioTable(scenarios)
scenarioTable.Print()
fmt.Print("\n")
return nil
},
}
return listCmd
}

func GetProvider(offline bool, factory *provider_factory.ProviderFactory) provider_factory.ScenarioDataProvider {
var provider provider_factory.ScenarioDataProvider
if offline {
provider = factory.NewInstance(provider_factory.Offline)
} else {
provider = factory.NewInstance(provider_factory.Online)
}
return provider
}
26 changes: 5 additions & 21 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,10 @@ package cmd

import (
"fmt"
"github.com/briandowns/spinner"
"github.com/krkn-chaos/krknctl/pkg/provider/factory"
"github.com/spf13/cobra"
"os"
"time"
)

func NewSpinnerWithSuffix(suffix string) *spinner.Spinner {
s := spinner.New(spinner.CharSets[39], 100*time.Millisecond)
s.Suffix = suffix
return s
}

func NewRootCommand(factory *factory.ProviderFactory) *cobra.Command {
var rootCmd = &cobra.Command{
Use: "krknctl",
Short: "krkn CLI",
Long: `krkn Command Line Interface`,
RunE: func(cmd *cobra.Command, args []string) error {
return cmd.Help()
},
}
return rootCmd
}

func Execute(factory *factory.ProviderFactory) {
var jsonFlag bool
var offlineFlag bool
Expand All @@ -42,6 +21,11 @@ func Execute(factory *factory.ProviderFactory) {

describeCmd := NewDescribeCommand(factory)
rootCmd.AddCommand(describeCmd)

runCmd := NewRunCommand(factory)
runCmd.DisableFlagParsing = true
rootCmd.AddCommand(runCmd)

if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
Expand Down
99 changes: 99 additions & 0 deletions cmd/run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package cmd

import (
"fmt"
"github.com/krkn-chaos/krknctl/pkg/provider/factory"
"github.com/spf13/cobra"
"log"
"strings"
)

func NewRunCommand(factory *factory.ProviderFactory) *cobra.Command {
collectedFlags := make(map[string]*string)
var runCmd = &cobra.Command{
Use: "run",
Short: "runs a scenario",
Long: `runs a scenario`,
DisableFlagParsing: false,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
offline, err := cmd.Flags().GetBool("offline")
//offlineRepo, err := cmd.Flags().GetString("offline-repo-config")
if err != nil {
return []string{}, cobra.ShellCompDirectiveError
}
provider := GetProvider(offline, factory)
scenarios, err := FetchScenarios(provider)
if err != nil {
log.Fatalf("Error fetching scenarios: %v", err)
return []string{}, cobra.ShellCompDirectiveError
}
return *scenarios, cobra.ShellCompDirectiveNoFileComp
},

PreRunE: func(cmd *cobra.Command, args []string) error {
offline, err := cmd.Flags().GetBool("offline")
if err != nil {
return err
}
provider := GetProvider(offline, factory)
scenarioDetail, err := provider.GetScenarioDetail(args[0])
if err != nil {
return err
}
if scenarioDetail == nil {
return fmt.Errorf("%s scenario not found", args[0])
}

for _, field := range scenarioDetail.Fields {
var defaultValue string = ""
if field.Default != nil {
defaultValue = *field.Default
}
collectedFlags[*field.Name] = cmd.LocalFlags().String(*field.Name, defaultValue, *field.Description)
if err != nil {
return err
}

}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
spinner := NewSpinnerWithSuffix("validating input...")
offline, err := cmd.Flags().GetBool("offline")
if err != nil {
return err
}
spinner.Start()

provider := GetProvider(offline, factory)
scenarioDetail, err := provider.GetScenarioDetail(args[0])
if err != nil {
return err
}
spinner.Stop()
// default
for k, _ := range collectedFlags {
field := scenarioDetail.GetFieldByName(k)
var foundArg *string = nil
for i, a := range args {
if a == fmt.Sprintf("--%s", k) {
if len(args) < i+2 || strings.HasPrefix(args[i+1], "--") {
return fmt.Errorf("%s has no value", args[i])
}
foundArg = &args[i+1]
}
}
if field != nil {
value, err := field.Validate(foundArg)
if err != nil {
return err
}
fmt.Println(fmt.Sprintf("%s: valid", *value))
}

}
return nil
},
}
return runCmd
}
20 changes: 16 additions & 4 deletions cmd/tables.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
package cmd

import (
"fmt"
"github.com/fatih/color"
"github.com/krkn-chaos/krknctl/pkg/provider/models"
"github.com/krkn-chaos/krknctl/pkg/typing"
)
import "github.com/rodaine/table"

func NewScenarioTable(scenarios *[]models.ScenarioTag) *table.Table {
headerFmt := color.New(color.FgGreen, color.Underline).SprintfFunc()
columnFmt := color.New(color.FgYellow).SprintfFunc()
var headerFmt = color.New(color.FgGreen, color.Underline).SprintfFunc()
var columnFmt = color.New(color.FgYellow).SprintfFunc()

func NewScenarioTable(scenarios *[]models.ScenarioTag) table.Table {
tbl := table.New("Name", "Size", "Digest", "Last Modified")
tbl.WithHeaderFormatter(headerFmt).WithFirstColumnFormatter(columnFmt)
for _, scenario := range *scenarios {
tbl.AddRow(scenario.Name, scenario.Size, scenario.Digest, scenario.LastModified)
}
return &tbl
return tbl
}

func NewArgumentTable(inputFields []typing.InputField) table.Table {
tbl := table.New("Name", "Type", "Description", "Required")
tbl.WithHeaderFormatter(headerFmt).WithFirstColumnFormatter(columnFmt)
for _, inputField := range inputFields {
tbl.AddRow(fmt.Sprintf("--%s", *inputField.Name), inputField.Type.String(), *inputField.ShortDescription, inputField.Default == nil)
}
return tbl
}
48 changes: 48 additions & 0 deletions cmd/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package cmd

import (
"github.com/briandowns/spinner"
"github.com/krkn-chaos/krknctl/pkg/provider/factory"
"github.com/spf13/cobra"
"time"
)

func NewSpinnerWithSuffix(suffix string) *spinner.Spinner {
s := spinner.New(spinner.CharSets[39], 100*time.Millisecond)
s.Suffix = suffix
return s
}

func NewRootCommand(factory *factory.ProviderFactory) *cobra.Command {
var rootCmd = &cobra.Command{
Use: "krknctl",
Short: "krkn CLI",
Long: `krkn Command Line Interface`,
RunE: func(cmd *cobra.Command, args []string) error {
return cmd.Help()
},
}
return rootCmd
}

func GetProvider(offline bool, providerFactory *factory.ProviderFactory) factory.ScenarioDataProvider {
var provider factory.ScenarioDataProvider
if offline {
provider = providerFactory.NewInstance(factory.Offline)
} else {
provider = providerFactory.NewInstance(factory.Online)
}
return provider
}

func FetchScenarios(provider factory.ScenarioDataProvider) (*[]string, error) {
scenarios, err := provider.GetScenarios()
if err != nil {
return nil, err
}
var foundScenarios []string
for _, scenario := range *scenarios {
foundScenarios = append(foundScenarios, scenario.Name)
}
return &foundScenarios, nil
}
9 changes: 9 additions & 0 deletions pkg/provider/models/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,12 @@ type ScenarioDetail struct {
Description string `json:"description"`
Fields []typing.InputField
}

func (s *ScenarioDetail) GetFieldByName(name string) *typing.InputField {
for _, v := range s.Fields {
if *v.Name == name {
return &v
}
}
return nil
}
4 changes: 4 additions & 0 deletions pkg/provider/quay/quay_scenario_provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,8 @@ func TestQuayScenarioProvider_GetScenarioDetail(t *testing.T) {
assert.True(t, strings.Contains(err.Error(), "krkn.inputfields LABEL not found in tag: cpu-memory-noinput"))
assert.Nil(t, scenario)

scenario, err = provider.GetScenarioDetail("not-found")
assert.Nil(t, err)
assert.Nil(t, scenario)

}
Loading

0 comments on commit fc16493

Please sign in to comment.