Skip to content

Commit

Permalink
Updating the wizard so user can build traces w/ questions and update/…
Browse files Browse the repository at this point in the history
…review traces (aws#354)
  • Loading branch information
Paramadon authored Jul 25, 2023
1 parent 59627dc commit 1beefdc
Show file tree
Hide file tree
Showing 2 changed files with 294 additions and 7 deletions.
221 changes: 216 additions & 5 deletions tool/processors/tracesconfig/tracesconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ package tracesconfig
import (
_ "embed"
"encoding/json"
"errors"
"fmt"
"os"
"strconv"

"github.com/aws/private-amazon-cloudwatch-agent-staging/tool/data"
"github.com/aws/private-amazon-cloudwatch-agent-staging/tool/data/config"
Expand All @@ -22,6 +24,8 @@ var Processor processors.Processor = &processor{}

type processor struct{}

const addr = "127.0.0.1"

func (p *processor) Process(ctx *runtime.Context, cfg *data.Config) {
//skip if linux or windows noninteractive migration
if ctx.WindowsNonInteractiveMigration {
Expand All @@ -39,6 +43,10 @@ func (p *processor) Process(ctx *runtime.Context, cfg *data.Config) {
return
}
cfg.TracesConfig = newTraces
//user can review and update their current configurations
if cfg.TracesConfig != nil {
cfg.TracesConfig = updateUserConfig(cfg.TracesConfig)
}
}

func (p *processor) NextProcessor(ctx *runtime.Context, config *data.Config) interface{} {
Expand All @@ -53,6 +61,202 @@ const (
filePathXrayConfigQuestion = "What is the file path for the existing X-Ray Daemon configuration file?"
)

func userBuildsTracesConfig(tracesConfig *config.Traces) *config.Traces {

json.Unmarshal(DefaultTracesConfigFile, &tracesConfig)
whichUDPPort(tracesConfig)
whichTCPPort(tracesConfig)
chooseBufferSize(tracesConfig)
chooseConcurrency(tracesConfig)
chooseRegion(tracesConfig)
return tracesConfig
}

func whichUDPPort(tracesConfig *config.Traces) {
answer := util.AskWithDefault("Which UDP port do you want XRay daemon to listen to?", "2000")
num, err := strconv.Atoi(answer)
if err != nil || num < 0 {
tracesConfig.TracesCollected.Xray.BindAddress = addr + ":2000"
}
newAddr := fmt.Sprintf("%s:%s", addr, answer)
tracesConfig.TracesCollected.Xray.BindAddress = newAddr

}
func whichTCPPort(tracesConfig *config.Traces) {
answer := util.AskWithDefault("Which TCP port do you want XRay daemon to listen to?", "2000")
num, err := strconv.Atoi(answer)
if err != nil || num < 0 {
tracesConfig.TracesCollected.Xray.BindAddress = addr + ":2000"
}
newAddr := fmt.Sprintf("%s:%s", addr, answer)
tracesConfig.TracesCollected.Xray.TcpProxy.BindAddress = newAddr

}

func chooseBufferSize(tracesConfig *config.Traces) {
answer := util.AskWithDefault("Enter Total Buffer Size in MB (minimum 3)", "3")
bufferSize, err := strconv.Atoi(answer)
if err != nil || bufferSize < 3 {
fmt.Println("Buffer size set to 3 because input smaller than 3 or not a number")
bufferSize = 3
}
tracesConfig.BufferSizeMB = bufferSize
}

func chooseConcurrency(tracesConfig *config.Traces) {
answer := util.AskWithDefault("Enter the maximum number of concurrent calls to AWS X-Ray to upload segment documents: ", "8")
concurrency, err := strconv.Atoi(answer)
if err != nil || concurrency < 0 {
fmt.Println("Concurrency set to default value of 8 because input smaller than 0 or not a number")
concurrency = 8
}
tracesConfig.Concurrency = concurrency
}

func chooseRegion(tracesConfig *config.Traces) {
answer := util.Ask("Enter the AWS Region to send segments to AWS X-Ray service (Optional)")
tracesConfig.RegionOverride = answer

}

// made to print traces config correctly
type TracesWrapper struct {
Traces config.Traces `json:"traces"`
}

func updateUserConfig(tracesConfig *config.Traces) *config.Traces {

fieldOptions := generateFieldOptions()
for {
jsonData := TracesWrapper{
Traces: *tracesConfig,
}
fmt.Println("Current Traces Configurations:")
jsonByte, _ := json.MarshalIndent(jsonData, "", "\t")
fmt.Println(string(jsonByte))
fmt.Println("Enter a number of the field you would like to update (or 0 to exit)")
for i := 0; i < len(fieldOptions); i++ {
fmt.Println(fieldOptions[i])
}
answer := util.Ask("")
if answer == "" {
//Exit if user does not input anything
break
}
option, err := strconv.Atoi(answer)

if option < 0 || option > 11 || err != nil {
fmt.Println("Please input a number from 0-11")
continue
}
if option == 0 {
break
}
switch option {
case 1, 2, 5, 8, 9, 10, 11:
newValue := util.Ask("Enter value you would like to update to: (Enter nothing to remove)")
updateStringValueInConfig(tracesConfig, option, newValue)
case 3, 4:
answer := util.Ask("Enter value you would like to update to: (Enter nothing to remove)")

newValue, err := strconv.Atoi(answer)
if err != nil {
fmt.Println("Wrong Input! Input has go be a int.")
continue
} else {
updateIntValueInConfig(tracesConfig, option, newValue)
}

case 6, 7:
answer := util.Ask("Enter value you would like to update to: (Enter nothing to remove)")
newValue, err := strconv.ParseBool(answer)
if err != nil {
fmt.Println("Wrong Input! Input has go be a bool")
} else {
updateBoolValueInConfig(tracesConfig, option, newValue)
}
}
}
return tracesConfig
}

// array of fields
func generateFieldOptions() []string {
options := []string{
"0: Exit",
"1: UDP BindAddress",
"2: TCP BindAddress",
"3: concurrency",
"4: buffer_size_mb",
"5: resource_arn",
"6: local_mode",
"7: insecure",
"8: role_arn",
"9: endpoint_override",
"10: region_override",
"11: proxy_override",
}
return options
}

func updateIntValueInConfig(tracesConfig *config.Traces, option int, value int) error {
switch option {
case 3:
tracesConfig.Concurrency = value
case 4:
if value < 3 {
fmt.Println("Input has to be bigger than 3! Value has been set to 3")
tracesConfig.BufferSizeMB = 3
return nil
}
tracesConfig.BufferSizeMB = value
default:
return errors.New("Unknown option")
}
return nil
}

func updateStringValueInConfig(tracesConfig *config.Traces, option int, value string) error {
switch option {
case 5:
tracesConfig.ResourceArn = value
case 9:
tracesConfig.EndpointOverride = value
case 10:
tracesConfig.RegionOverride = value
case 11:
tracesConfig.ProxyOverride = value
case 1:
tracesConfig.TracesCollected.Xray.BindAddress = value
case 2:
tracesConfig.TracesCollected.Xray.TcpProxy.BindAddress = value
case 8:
if value == "" {
tracesConfig.Credentials = nil
} else if tracesConfig.Credentials == nil {
tracesConfig.Credentials = &struct {
RoleArn string `json:"role_arn,omitempty"`
}{}
tracesConfig.Credentials.RoleArn = value
}
default:
return errors.New("Unknown Option")
}
return nil
}

func updateBoolValueInConfig(tracesConfig *config.Traces, option int, value bool) error {
switch option {
case 6:
tracesConfig.LocalMode = value
case 7:
tracesConfig.Insecure = value

default:
return errors.New("Unknown Option")
}
return nil
}
func getCmdlines(processes []xraydaemonmigration.Process) []string {
var cmdlines []string
for i := 0; i < len(processes); i++ {
Expand All @@ -75,7 +279,13 @@ func generateTracesConfiguration(ctx *runtime.Context) (*config.Traces, error) {
return nil, err
}
if len(processes) == 0 {
return askUserInput(tracesFile, nil)
yes := util.Yes(anyExistingDaemonConfiguration)
if yes {
return askUserInput(tracesFile, nil, yes)
} else { //user can build config if they do not have a traces file
return userBuildsTracesConfig(tracesFile), nil

}
}

var chosenProcess xraydaemonmigration.Process
Expand Down Expand Up @@ -107,14 +317,15 @@ func generateTracesConfiguration(ctx *runtime.Context) (*config.Traces, error) {
//incorrect configFilePath, user can decide to give path of default config will be used
if err != nil {
fmt.Println("Unable to import configuration from Detected Daemon")
return askUserInput(tracesFile, chosenProcess)
yes := util.Yes(anyExistingDaemonConfiguration)
return askUserInput(tracesFile, chosenProcess, yes)
}
return xraydaemonmigration.ConvertYamlToJson(yamlFile, chosenProcess)
}

func askUserInput(tracesFile *config.Traces, chosenProcess xraydaemonmigration.Process) (*config.Traces, error) {
yes := util.Yes(anyExistingDaemonConfiguration)
if yes {
func askUserInput(tracesFile *config.Traces, chosenProcess xraydaemonmigration.Process, userHasImportConfig bool) (*config.Traces, error) {

if userHasImportConfig {
configFilePath := util.Ask(filePathXrayConfigQuestion)
yamlFile, err := os.ReadFile(configFilePath)
//error reading filepath given by user, using default config
Expand Down
80 changes: 78 additions & 2 deletions tool/processors/tracesconfig/tracesconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/stretchr/testify/assert"

"github.com/aws/private-amazon-cloudwatch-agent-staging/tool/data/config"
"github.com/aws/private-amazon-cloudwatch-agent-staging/tool/runtime"
"github.com/aws/private-amazon-cloudwatch-agent-staging/tool/testutil"
"github.com/aws/private-amazon-cloudwatch-agent-staging/tool/xraydaemonmigration"
Expand Down Expand Up @@ -50,7 +51,7 @@ var mockProcesses = func() ([]xraydaemonmigration.Process, error) {
var correctDaemonProcess = &proc{
pid: 123,
name: "xray",
cmdline: []string{"xray", "-c", filepath.Join("testdata", "cfg.yaml"), "-b", "127.0.0.1:2000", "-t", "127.0.0.1:2000", "-a", "resourceTesting", "-n", "us-east-1", "-m", "23", "-r", "roleTest", "-p", "127.0.0.1:2000"},
cmdline: []string{"xray", "-c", filepath.Join("testdata", "cfg.yaml"), "-b", addr + ":2000", "-t", addr + ":2000", "-a", "resourceTesting", "-n", "us-east-1", "-m", "23", "-r", "roleTest", "-p", "127.0.0.1:2000"},
cwd: "",
strcmdline: "./xray -c ./cfg.yaml -b 127.0.0.1:2000 -t 127.0.0.1:2000 -a resourceTesting -n us-east-1 -m 23 -r roleTest -p 127.0.0.1:2000",
}
Expand Down Expand Up @@ -108,7 +109,7 @@ func TestGenerateTracesConfiguration(t *testing.T) {
//Xray run as a servie
xraydaemonmigration.GetProcesses = mockProcessesXrayService
inputChan = testutil.SetUpTestInputStream()
testutil.Type(inputChan, "2")
testutil.Type(inputChan, "2", "2000", "2000", "", "", "")
jsonStruct, err = generateTracesConfiguration(ctx)
assert.Nil(t, jsonStruct)

Expand Down Expand Up @@ -149,3 +150,78 @@ func TestGenerateTracesConfiguration(t *testing.T) {
jsonFile, err = json.MarshalIndent(*jsonStruct, "", "\t")
assert.JSONEq(t, string(expectedDefaultConfigFile), string(jsonFile))
}

func TestUserBuildsTracesConfig(t *testing.T) {
inputChan := testutil.SetUpTestInputStream()
testutil.Type(inputChan, "3000", "4000", "10", "20", "us-east-1", "This should be a number", "This should be a number", "", "", "", "", "")

tracesConfig := &config.Traces{}

whichUDPPort(tracesConfig)
whichTCPPort(tracesConfig)
chooseBufferSize(tracesConfig)
chooseConcurrency(tracesConfig)
chooseRegion(tracesConfig)

//checking if variable of traces config are the values they supposed to be
assert.Equal(t, addr+":3000", tracesConfig.TracesCollected.Xray.BindAddress)
assert.Equal(t, addr+":4000", tracesConfig.TracesCollected.Xray.TcpProxy.BindAddress)
assert.Equal(t, 10, tracesConfig.BufferSizeMB)
assert.Equal(t, 20, tracesConfig.Concurrency)
assert.Equal(t, "us-east-1", tracesConfig.RegionOverride)
//wrong inputs
chooseConcurrency(tracesConfig)
chooseBufferSize(tracesConfig)
assert.Equal(t, tracesConfig.Concurrency, 8)
assert.Equal(t, tracesConfig.BufferSizeMB, 3)

//blank answers (no input)
whichUDPPort(tracesConfig)
whichTCPPort(tracesConfig)
chooseBufferSize(tracesConfig)
chooseConcurrency(tracesConfig)
chooseRegion(tracesConfig)
assert.Equal(t, addr+":2000", tracesConfig.TracesCollected.Xray.BindAddress)
assert.Equal(t, addr+":2000", tracesConfig.TracesCollected.Xray.TcpProxy.BindAddress)
assert.Equal(t, 3, tracesConfig.BufferSizeMB)
assert.Equal(t, 8, tracesConfig.Concurrency)
assert.Equal(t, "", tracesConfig.RegionOverride)
}

func TestUpdateUserConfig(t *testing.T) {
//Replicating user inputs
inputs := []string{
"1", addr + ":3000",
"2", addr + ":4000",
"3", "10",
"4", "10",
"5", "resourceArn",
"6", "true",
"7", "true",
"8", "roleArn",
"9", "endpointOverride",
"10", "regionOverride",
"11", "proxyOverride",
"0",
}
inputChan := testutil.SetUpTestInputStream()
testutil.Type(inputChan, inputs...)
tracesConfig := &config.Traces{}

//calling update function
updateUserConfig(tracesConfig)

//checking all tests
assert.Equal(t, addr+":3000", tracesConfig.TracesCollected.Xray.BindAddress)
assert.Equal(t, addr+":4000", tracesConfig.TracesCollected.Xray.TcpProxy.BindAddress)
assert.Equal(t, 10, tracesConfig.BufferSizeMB)
assert.Equal(t, 10, tracesConfig.Concurrency)
assert.Equal(t, "resourceArn", tracesConfig.ResourceArn)
assert.Equal(t, true, tracesConfig.LocalMode)
assert.Equal(t, true, tracesConfig.Insecure)
assert.Equal(t, "roleArn", tracesConfig.Credentials.RoleArn)
assert.Equal(t, "endpointOverride", tracesConfig.EndpointOverride)
assert.Equal(t, "regionOverride", tracesConfig.RegionOverride)
assert.Equal(t, "proxyOverride", tracesConfig.ProxyOverride)

}

0 comments on commit 1beefdc

Please sign in to comment.