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
135 changes: 7 additions & 128 deletions cmd/amazon-cloudwatch-agent-config-wizard/wizard.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,139 +4,18 @@
package main

import (
"bufio"
"flag"
"fmt"
"log"
"os"

"github.com/aws/amazon-cloudwatch-agent/tool/data"
"github.com/aws/amazon-cloudwatch-agent/tool/processors"
"github.com/aws/amazon-cloudwatch-agent/tool/processors/basicInfo"
"github.com/aws/amazon-cloudwatch-agent/tool/processors/migration/linux"
"github.com/aws/amazon-cloudwatch-agent/tool/processors/migration/windows"
"github.com/aws/amazon-cloudwatch-agent/tool/processors/serialization"
"github.com/aws/amazon-cloudwatch-agent/tool/processors/tracesconfig"
"github.com/aws/amazon-cloudwatch-agent/tool/runtime"
"github.com/aws/amazon-cloudwatch-agent/tool/stdin"
"github.com/aws/amazon-cloudwatch-agent/tool/testutil"
"github.com/aws/amazon-cloudwatch-agent/tool/util"
"github.com/aws/amazon-cloudwatch-agent/tool/cmdwrapper"
"github.com/aws/amazon-cloudwatch-agent/tool/wizard/flags"
)

type IMainProcessor interface {
VerifyProcessor(processor interface{})
}
type MainProcessorStruct struct{}

var MainProcessorGlobal IMainProcessor = &MainProcessorStruct{}

var isNonInteractiveWindowsMigration *bool

var configOutputPath *string

var isNonInteractiveXrayMigration *bool

func main() {
// Parse command line args for non-interactive Windows migration
isNonInteractiveWindowsMigration = flag.Bool("isNonInteractiveWindowsMigration", false,
"If true, it will use command line args to bypass the wizard. Default value is false.")

isNonInteractiveLinuxMigration := flag.Bool("isNonInteractiveLinuxMigration", false,
"If true, it will do the linux config migration. Default value is false.")

tracesOnly := flag.Bool("tracesOnly", false, "If true, only trace configuration will be generated")
useParameterStore := flag.Bool("useParameterStore", false,
"If true, it will use the parameter store for the migrated config storage.")
isNonInteractiveXrayMigration = flag.Bool("nonInteractiveXrayMigration", false, "If true, then this is part of non Interactive xray migration tool.")
configFilePath := flag.String("configFilePath", "",
fmt.Sprintf("The path of the old config file. Default is %s on Windows or %s on Linux", windows.DefaultFilePathWindowsConfiguration, linux.DefaultFilePathLinuxConfiguration))

configOutputPath = flag.String("configOutputPath", "", "Specifies where to write the configuration file generated by the wizard")
parameterStoreName := flag.String("parameterStoreName", "", "The parameter store name. Default is AmazonCloudWatch-windows")
parameterStoreRegion := flag.String("parameterStoreRegion", "", "The parameter store region. Default is us-east-1")

flag.Parse()
log.Printf("Starting config-wizard, this will map back to a call to amazon-cloudwatch-agent")

if *isNonInteractiveWindowsMigration {
addWindowsMigrationInputs(*configFilePath, *parameterStoreName, *parameterStoreRegion, *useParameterStore)
} else if *isNonInteractiveLinuxMigration {
ctx := new(runtime.Context)
config := new(data.Config)
ctx.HasExistingLinuxConfig = true
ctx.ConfigFilePath = *configFilePath
if ctx.ConfigFilePath == "" {
ctx.ConfigFilePath = linux.DefaultFilePathLinuxConfiguration
}
process(ctx, config, linux.Processor, serialization.Processor)
return
} else if *tracesOnly {
ctx := new(runtime.Context)
config := new(data.Config)
ctx.TracesOnly = true
ctx.ConfigOutputPath = *configOutputPath
if *isNonInteractiveXrayMigration {
ctx.NonInteractiveXrayMigration = true
}
process(ctx, config, tracesconfig.Processor, serialization.Processor)
return
}

startProcessing()
}

func init() {
stdin.Scanln = func(a ...interface{}) (n int, err error) {
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
if len(a) > 0 {
*a[0].(*string) = scanner.Text()
n = len(*a[0].(*string))
}
err = scanner.Err()
return
}
processors.StartProcessor = basicInfo.Processor
}

func addWindowsMigrationInputs(configFilePath string, parameterStoreName string, parameterStoreRegion string, useParameterStore bool) {
inputChan := testutil.SetUpTestInputStream()
if useParameterStore {
testutil.Type(inputChan, "2", "1", "2", "1", configFilePath, "1", parameterStoreName, parameterStoreRegion, "1")
} else {
testutil.Type(inputChan, "2", "1", "2", "1", configFilePath, "2")
}
}

func process(ctx *runtime.Context, config *data.Config, processors ...processors.Processor) {
for _, processor := range processors {
processor.Process(ctx, config)
}
}

func startProcessing() {
ctx := new(runtime.Context)
config := new(data.Config)
ctx.ConfigOutputPath = *configOutputPath
var processor interface{}
processor = processors.StartProcessor
if *isNonInteractiveWindowsMigration {
ctx.WindowsNonInteractiveMigration = true
}
if *isNonInteractiveXrayMigration {
ctx.NonInteractiveXrayMigration = true
}
for {
if processor == nil {
if util.CurOS() == util.OsTypeWindows && !*isNonInteractiveWindowsMigration {
util.EnterToExit()
}
fmt.Println("Program exits now.")
break
}
MainProcessorGlobal.VerifyProcessor(processor) // For testing purposes
processor.(processors.Processor).Process(ctx, config)
processor = processor.(processors.Processor).NextProcessor(ctx, config)
}
}
fs, wizardFlags := cmdwrapper.CreateFlagSet(flags.Command, flags.WizardFlags)
fs.Parse(os.Args[1:]) // Skip program name only

func (p *MainProcessorStruct) VerifyProcessor(processor interface{}) {
_ = cmdwrapper.ExecuteSubcommand(flags.Command, wizardFlags)
}
78 changes: 0 additions & 78 deletions cmd/amazon-cloudwatch-agent-config-wizard/wizard_test.go

This file was deleted.

44 changes: 43 additions & 1 deletion cmd/amazon-cloudwatch-agent/amazon-cloudwatch-agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,20 @@ import (
"github.com/aws/amazon-cloudwatch-agent/internal/version"
cwaLogger "github.com/aws/amazon-cloudwatch-agent/logger"
"github.com/aws/amazon-cloudwatch-agent/logs"
_ "github.com/aws/amazon-cloudwatch-agent/plugins"
_ "github.com/aws/amazon-cloudwatch-agent/plugins" // do not remove, necessary for telegraf to know what plugins are used
"github.com/aws/amazon-cloudwatch-agent/profiler"
"github.com/aws/amazon-cloudwatch-agent/receiver/adapter"
"github.com/aws/amazon-cloudwatch-agent/service/configprovider"
"github.com/aws/amazon-cloudwatch-agent/service/defaultcomponents"
"github.com/aws/amazon-cloudwatch-agent/service/registry"
"github.com/aws/amazon-cloudwatch-agent/tool/cmdwrapper"
"github.com/aws/amazon-cloudwatch-agent/tool/downloader"
downloaderflags "github.com/aws/amazon-cloudwatch-agent/tool/downloader/flags"
"github.com/aws/amazon-cloudwatch-agent/tool/paths"
"github.com/aws/amazon-cloudwatch-agent/tool/translator"
"github.com/aws/amazon-cloudwatch-agent/tool/wizard"
wizardflags "github.com/aws/amazon-cloudwatch-agent/tool/wizard/flags"
translatorflags "github.com/aws/amazon-cloudwatch-agent/translator/flags"
"github.com/aws/amazon-cloudwatch-agent/translator/tocwconfig/toyamlconfig"
)

Expand Down Expand Up @@ -492,6 +499,40 @@ func (p *program) Stop(_ service.Service) error {

func main() {
flag.Var(&fOtelConfigs, configprovider.OtelConfigFlagName, "YAML configuration files to run OTel pipeline")

// Check for subcommands first
if len(os.Args) > 1 {
subcommand := os.Args[1]
if subcommand == translatorflags.TranslatorCommand || subcommand == downloaderflags.Command || subcommand == wizardflags.Command {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: stylistically I'd rather use a switch statement here but I think this is perfectly fine

subcommands := map[string]map[string]cmdwrapper.Flag{
translatorflags.TranslatorCommand: translatorflags.TranslatorFlags,
downloaderflags.Command: downloaderflags.DownloaderFlags,
wizardflags.Command: wizardflags.WizardFlags,
}
handlers := map[string]func(map[string]*string) error{
translatorflags.TranslatorCommand: translator.RunTranslator,
downloaderflags.Command: downloader.RunDownloaderFromFlags,
wizardflags.Command: wizard.RunWizardFromFlags,
}

if err := cmdwrapper.HandleSubcommand(subcommands, handlers); err != nil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we already did all of the work here to find the subcommand and we already know which handler and flag set to use so the HandleSubcommand function seems to duplicate a lot of work. Is it used elsewhere or could we just replace HandleSubcommand with handler[subccommand](subcommands[subcommand]flags) or something similar?

Not that important to update though since the duplicate work is not going to impact performance in any meaningful way

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think this is a fair point. We can improve this in a separate PR as a follow up.

log.Fatalf("E! %s", err.Error())
}
return
}
}

// Override flag.Usage to include subcommand help
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
flag.PrintDefaults()
fmt.Fprintf(os.Stderr, "\nAvailable subcommands:\n")
fmt.Fprintf(os.Stderr, " %s\t\tTranslate configuration files\n", translatorflags.TranslatorCommand)
fmt.Fprintf(os.Stderr, " %s\t\tDownload configuration from remote sources\n", downloaderflags.Command)
fmt.Fprintf(os.Stderr, " %s\t\t\tInteractive configuration wizard\n", wizardflags.Command)
fmt.Fprintf(os.Stderr, "\nUse '%s <subcommand> --help' for more information about a subcommand.\n", os.Args[0])
}
Comment on lines +526 to +534

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really nice 👍


flag.Parse()
if len(fOtelConfigs) == 0 {
_ = fOtelConfigs.Set(getFallbackOtelConfig(*fTomlConfig, paths.YamlConfigPath))
Expand Down Expand Up @@ -614,6 +655,7 @@ func main() {
}
}
return

}

if runtime.GOOS == "windows" && windowsRunAsService() {
Expand Down
Loading
Loading