Skip to content

Commit

Permalink
graph run and scaffold with global env vars
Browse files Browse the repository at this point in the history
Signed-off-by: Tullio Sebastiani <[email protected]>
  • Loading branch information
tsebastiani committed Dec 12, 2024
1 parent d581c76 commit 78efe5a
Show file tree
Hide file tree
Showing 11 changed files with 135 additions and 83 deletions.
24 changes: 23 additions & 1 deletion cmd/graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,20 +197,37 @@ func validateScenariosInput(provider provider.ScenarioDataProvider, nodes map[st
err error
}{name: &n.Name, err: nil}
scenarioDetail, err := provider.GetScenarioDetail(n.Name)

if err != nil {
scenarioNameChannel <- &struct {
name *string
err error
}{name: &n.Name, err: err}
return
}

if scenarioDetail == nil {
scenarioNameChannel <- &struct {
name *string
err error
}{name: &n.Name, err: fmt.Errorf("scenario %s not found", n.Name)}
return
}

globalDetail, err := provider.GetGlobalEnvironment()
if err != nil {
scenarioNameChannel <- &struct {
name *string
err error
}{name: &n.Name, err: err}
return
}

// adding the global env fields to the scenario fields so, if global env is
// added to the scenario the validation is available

scenarioDetail.Fields = append(scenarioDetail.Fields, globalDetail.Fields...)

for k, v := range n.Env {
field := scenarioDetail.GetFieldByEnvVar(k)
if field == nil {
Expand Down Expand Up @@ -272,7 +289,12 @@ func NewGraphScaffoldCommand(factory *providerfactory.ProviderFactory, config co
},
RunE: func(cmd *cobra.Command, args []string) error {
dataProvider := GetProvider(false, factory)
output, err := dataProvider.ScaffoldScenarios(args)
includeGlobalEnv, err := cmd.Flags().GetBool("global-env")
if err != nil {
return err
}

output, err := dataProvider.ScaffoldScenarios(args, includeGlobalEnv)
if err != nil {
return err
}
Expand Down
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ func Execute(providerFactory *factory.ProviderFactory, scenarioOrchestrator *sce
graphRunCmd.Flags().Bool("debug", false, "if set this flag will enable debug output in krkn")

graphScaffoldCmd := NewGraphScaffoldCommand(providerFactory, config)
graphScaffoldCmd.Flags().Bool("global-env", false, "if set this flag will add global environment variables to each scenario in the graph")
graphCmd.AddCommand(graphRunCmd)
graphCmd.AddCommand(graphScaffoldCmd)
rootCmd.AddCommand(graphCmd)
Expand Down
43 changes: 2 additions & 41 deletions cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ import (
"github.com/fatih/color"
"github.com/krkn-chaos/krknctl/pkg/config"
"github.com/krkn-chaos/krknctl/pkg/provider/factory"
"github.com/krkn-chaos/krknctl/pkg/provider/models"
"github.com/krkn-chaos/krknctl/pkg/scenario_orchestrator"
"github.com/krkn-chaos/krknctl/pkg/scenario_orchestrator/utils"
"github.com/krkn-chaos/krknctl/pkg/typing"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"log"
Expand Down Expand Up @@ -187,11 +185,11 @@ func NewRunCommand(factory *factory.ProviderFactory, scenarioOrchestrator *scena
volumes[*alertsProfile] = config.AlertsProfilePath
}
//dynamic flags parsing
scenarioEnv, scenarioVol, err := parseFlags(scenarioDetail, args, scenarioCollectedFlags, false)
scenarioEnv, scenarioVol, err := ParseFlags(scenarioDetail, args, scenarioCollectedFlags, false)
if err != nil {
return err
}
globalEnv, globalVol, err := parseFlags(globalDetail, args, globalCollectedFlags, true)
globalEnv, globalVol, err := ParseFlags(globalDetail, args, globalCollectedFlags, true)
if err != nil {
return err
}
Expand Down Expand Up @@ -273,43 +271,6 @@ func NewRunCommand(factory *factory.ProviderFactory, scenarioOrchestrator *scena
return command
}

func parseFlags(scenarioDetail *models.ScenarioDetail, args []string, scenarioCollectedFlags map[string]*string, skipDefault bool) (vol *map[string]string, env *map[string]string, err error) {
environment := make(map[string]string)
volumes := make(map[string]string)
for k := range scenarioCollectedFlags {
field := scenarioDetail.GetFieldByName(k)
if field == nil {
return nil, nil, fmt.Errorf("field %s not found", 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 nil, nil, fmt.Errorf("%s has no value", args[i])
}
foundArg = &args[i+1]
}
}
var value *string = nil
if foundArg != nil || skipDefault == false {
value, err = field.Validate(foundArg)
if err != nil {
return nil, nil, err
}
}

if value != nil && field.Type != typing.File {
environment[*field.Variable] = *value
} else if value != nil && field.Type == typing.File {
fileSrcDst := strings.Split(*value, ":")
volumes[fileSrcDst[0]] = fileSrcDst[1]
}

}

return &environment, &volumes, nil
}

func checkStringArgValue(args []string, index int) error {
if len(args) < index+2 || strings.HasPrefix(args[index+1], "--") {
return fmt.Errorf("%s has no value", args[index])
Expand Down
41 changes: 41 additions & 0 deletions cmd/utils.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package cmd

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

Expand Down Expand Up @@ -57,3 +61,40 @@ func CheckFileExists(filePath string) bool {
}
return true
}

func ParseFlags(scenarioDetail *models.ScenarioDetail, args []string, scenarioCollectedFlags map[string]*string, skipDefault bool) (vol *map[string]string, env *map[string]string, err error) {
environment := make(map[string]string)
volumes := make(map[string]string)
for k := range scenarioCollectedFlags {
field := scenarioDetail.GetFieldByName(k)
if field == nil {
return nil, nil, fmt.Errorf("field %s not found", 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 nil, nil, fmt.Errorf("%s has no value", args[i])
}
foundArg = &args[i+1]
}
}
var value *string = nil
if foundArg != nil || skipDefault == false {
value, err = field.Validate(foundArg)
if err != nil {
return nil, nil, err
}
}

if value != nil && field.Type != typing.File {
environment[*field.Variable] = *value
} else if value != nil && field.Type == typing.File {
fileSrcDst := strings.Split(*value, ":")
volumes[fileSrcDst[0]] = fileSrcDst[1]
}

}

return &environment, &volumes, nil
}
2 changes: 1 addition & 1 deletion pkg/provider/offline/scenario_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func (p *ScenarioProvider) GetScenarioDetail(scenario string) (*models.ScenarioD
return nil, errors.New("not yet implemented")
}

func (p *ScenarioProvider) ScaffoldScenarios(scenarios []string) (*string, error) {
func (p *ScenarioProvider) ScaffoldScenarios(scenarios []string, includeGlobalEnv bool) (*string, error) {
//TODO implement me
panic("implement me")
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ type ScenarioDataProvider interface {
GetRegistryImages() (*[]models.ScenarioTag, error)
GetGlobalEnvironment() (*models.ScenarioDetail, error)
GetScenarioDetail(scenario string) (*models.ScenarioDetail, error)
ScaffoldScenarios(scenarios []string) (*string, error)
ScaffoldScenarios(scenarios []string, includeGlobalEnv bool) (*string, error)
}
14 changes: 13 additions & 1 deletion pkg/provider/quay/scenario_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func (p *ScenarioProvider) getInstructionScenario(rootNodeName string) models2.S
return node
}

func (p *ScenarioProvider) ScaffoldScenarios(scenarios []string) (*string, error) {
func (p *ScenarioProvider) ScaffoldScenarios(scenarios []string, includeGlobalEnv bool) (*string, error) {
var scenarioDetails []models.ScenarioDetail

// handles babble panic when american word dictionary is not installed
Expand Down Expand Up @@ -157,6 +157,18 @@ func (p *ScenarioProvider) ScaffoldScenarios(scenarios []string) (*string, error
}

}

if includeGlobalEnv == true {
globalDetail, err := p.GetGlobalEnvironment()
if err != nil {
return nil, err
}

for _, field := range globalDetail.Fields {
scenarioNode.Env[*field.Variable] = *field.Default

}
}
scenarioNodes[indexes[i]] = scenarioNode
}

Expand Down
8 changes: 6 additions & 2 deletions pkg/provider/quay/scenario_provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,15 @@ func TestQuayScenarioProvider_ScaffoldScenarios(t *testing.T) {
assert.NotNil(t, scenarios)
scenarioNames := []string{"node-cpu-hog", "node-memory-hog", "dummy-scenario"}

json, err := provider.ScaffoldScenarios(scenarioNames)
json, err := provider.ScaffoldScenarios(scenarioNames, false)
assert.Nil(t, err)
assert.NotNil(t, json)

json, err = provider.ScaffoldScenarios([]string{"node-cpu-hog", "does-not-exist"})
json, err = provider.ScaffoldScenarios(scenarioNames, true)
assert.Nil(t, err)
assert.NotNil(t, json)

json, err = provider.ScaffoldScenarios([]string{"node-cpu-hog", "does-not-exist"}, false)
assert.Nil(t, json)
assert.NotNil(t, err)

Expand Down
3 changes: 0 additions & 3 deletions pkg/scenario_orchestrator/docker/scenario_orchestrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,6 @@ func (c *ScenarioOrchestrator) Run(image string, containerName string, env map[s
envVars = append(envVars, fmt.Sprintf("%s='True'", c.GetConfig().DebugEnvironmentVariable))
}

// THIS WILL BE REMOVED WHEN GLOBAL ENV WILL BE INTRODUCED
envVars = append(envVars, "WAIT_DURATION=1")

for k, v := range env {
envVars = append(envVars, fmt.Sprintf("%s=%s", k, v))
}
Expand Down
3 changes: 0 additions & 3 deletions pkg/scenario_orchestrator/podman/scenario_orchestrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,6 @@ func (c *ScenarioOrchestrator) Run(image string, containerName string, env map[s
s.Env[c.GetConfig().DebugEnvironmentVariable] = "True"
}

// THIS WILL BE REMOVED WHEN GLOBAL ENV WILL BE INTRODUCED
s.Env["WAIT_DURATION"] = "1"

for k, v := range volumeMounts {
containerMount := specs.Mount{
Destination: v,
Expand Down
77 changes: 47 additions & 30 deletions plan.json
Original file line number Diff line number Diff line change
@@ -1,38 +1,55 @@
{
"_comment": {
"_comment": "****DELETE THIS NODE**** To create your scenario run plan, assign an ID to each scenario definition (or keep the existing randomly assigned ones if preferred). Define dependencies between scenarios using the `depends_on` field, ensuring there are no cycles (including transitive ones) or self-references.Nodes not referenced will not be executed, Nodes without dependencies will run first, while nodes that share the same parent will execute in parallel. [CURRENT ROOT SCENARIO IS `node-cpu-hog-lachrymogenic`]"
"_comment": "**READ CAREFULLY** To create your scenario run plan, assign an ID to each scenario definition (or keep the existing randomly assigned ones if preferred). Define dependencies between scenarios using the `depends_on` field, ensuring there are no cycles (including transitive ones) or self-references.Nodes not referenced will not be executed, Nodes without dependencies will run first, while nodes that share the same parent will execute in parallel. [CURRENT ROOT SCENARIO IS `dummy-scenario-keraterpeton`]"
},
"node-cpu-hog-arctogaeal": {
"image": "quay.io/krkn-chaos/krkn-hub:node-cpu-hog",
"name": "node-cpu-hog",
"dummy-scenario-keraterpeton": {
"_comment": "I'm the root Node!",
"image": "quay.io/krkn-chaos/krkn-hub:dummy-scenario",
"name": "dummy-scenario",
"env": {
"NAMESPACE": "default",
"NODE_CPU_CORE": "2",
"NODE_CPU_PERCENTAGE": "50",
"TOTAL_CHAOS_DURATION": "5"
},
"depends_on": "node-cpu-hog-lachrymogenic"
},
"node-cpu-hog-lachrymogenic": {
"image": "quay.io/krkn-chaos/krkn-hub:node-cpu-hog",
"name": "node-cpu-hog",
"env": {
"NAMESPACE": "default",
"NODE_CPU_CORE": "2",
"NODE_CPU_PERCENTAGE": "50",
"TOTAL_CHAOS_DURATION": "5"
"ALERTS_PATH": "config/alerts.yaml",
"CAPTURE_METRICS": "False",
"CERBERUS_ENABLED": "False",
"CERBERUS_URL": "http://0.0.0.0:8080",
"CHECK_CRITICAL_ALERTS": "False",
"DAEMON_MODE": "False",
"DISTRIBUTION": "openshift",
"ENABLE_ALERTS": "False",
"ENABLE_ES": "False",
"END": "10",
"ES_ALERTS_INDEX": "krkn-alerts",
"ES_COLLECT_ALERTS": "False",
"ES_COLLECT_METRICS": "False",
"ES_METRICS_INDEX": "krkn-metrics",
"ES_PASSWORD": "",
"ES_PORT": "443",
"ES_SERVER": "http://0.0.0.0",
"ES_TELEMETRY_INDEX": "krkn-telemetry",
"ES_USERNAME": "elastic",
"ES_VERIFY_CERTS": "False",
"EXIT_STATUS": "0",
"ITERATIONS": "1",
"KRKN_DEBUG": "False",
"KRKN_KUBE_CONFIG": "/home/krkn/.kube/config",
"TELEMETRY_API_URL": "https://ulnmf9xv7j.execute-api.us-west-2.amazonaws.com/production",
"TELEMETRY_ARCHIVE_PATH": "/tmp",
"TELEMETRY_ARCHIVE_SIZE": "1000",
"TELEMETRY_BACKUP_THREADS": "5",
"TELEMETRY_CLI_PATH": "",
"TELEMETRY_ENABLED": "False",
"TELEMETRY_EVENTS_BACKUP": "True",
"TELEMETRY_FILTER_PATTERN": "[\"(\\\\w{3}\\\\s\\\\d{1,2}\\\\s\\\\d{2}:\\\\d{2}:\\\\d{2}\\\\.\\\\d+).+\",\"kinit (\\\\d+/\\\\d+/\\\\d+\\\\s\\\\d{2}:\\\\d{2}:\\\\d{2})\\\\s+\",\"(\\\\d{4}-\\\\d{2}-\\\\d{2}T\\\\d{2}:\\\\d{2}:\\\\d{2}\\\\.\\\\d+Z).+\"]",
"TELEMETRY_FULL_PROMETHEUS_BACKUP": "False",
"TELEMETRY_GROUP": "default",
"TELEMETRY_LOGS_BACKUP": "False",
"TELEMETRY_MAX_RETRIES": "0",
"TELEMETRY_PASSWORD": "",
"TELEMETRY_PROMETHEUS_BACKUP": "True",
"TELEMETRY_RUN_TAG": "chaos",
"TELEMETRY_USERNAME": "redhat-chaos",
"UUID": "",
"WAIT_DURATION": "1"
}
},
"node-cpu-hog-tutelo": {
"image": "quay.io/krkn-chaos/krkn-hub:node-cpu-hog",
"name": "node-cpu-hog",
"env": {
"NAMESPACE": "default",
"NODE_CPU_CORE": "2",
"NODE_CPU_PERCENTAGE": "50",
"TOTAL_CHAOS_DURATION": "5"
},
"depends_on": "node-cpu-hog-lachrymogenic"
}
}

0 comments on commit 78efe5a

Please sign in to comment.