From 0fa32dfead5c25df395972f2894f09792f8bfaa7 Mon Sep 17 00:00:00 2001 From: Aaron Croissette Date: Wed, 27 Nov 2024 15:34:16 -0500 Subject: [PATCH 1/3] feat: stub out interactive mode option for transfer-config --- .../commands/transferconfig/transferconfig.go | 37 +++++++++++++++++++ general/utils.go | 8 ++-- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/artifactory/commands/transferconfig/transferconfig.go b/artifactory/commands/transferconfig/transferconfig.go index 42af06f40..899eb3601 100644 --- a/artifactory/commands/transferconfig/transferconfig.go +++ b/artifactory/commands/transferconfig/transferconfig.go @@ -18,6 +18,7 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils/precheckrunner" "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" "github.com/jfrog/jfrog-cli-core/v2/common/commands" + general "github.com/jfrog/jfrog-cli-core/v2/general" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" "github.com/jfrog/jfrog-client-go/artifactory/services" @@ -43,6 +44,7 @@ type TransferConfigCommand struct { force bool verbose bool preChecks bool + interactive bool sourceWorkingDir string targetWorkingDir string } @@ -55,6 +57,11 @@ func (tcc *TransferConfigCommand) CommandName() string { return "rt_transfer_config" } +func (tcc *TransferConfigCommand) SetInteractive(value bool) *TransferConfigCommand { + tcc.interactive = value + return tcc +} + func (tcc *TransferConfigCommand) SetDryRun(dryRun bool) *TransferConfigCommand { tcc.dryRun = dryRun return tcc @@ -137,6 +144,36 @@ func (tcc *TransferConfigCommand) Run() (err error) { return } + if tcc.interactive { + tcc.LogTitle("Phase 3.5/5 - Modify configuration (press any key to continue...)") + + filename := "config_" + time.Now().Format(general.SafeDateFileFormat) + ".xml" + + // open output file + fo, err2 := os.Create(filename) + if err2 != nil { + return + } + + // close fo on exit and check for its returned error + defer func() { + if err := fo.Close(); err != nil { + return + } + + err := os.Remove(filename) + if err != nil { + return + } + }() + + log.Info("Waiting for you to modify the file:") + log.Info(filename) + log.Info("Press any key to continue...") + // TODO: yield execution back + // or separate the phases and add two calls in the consumer + } + // Import the archive to the target Artifactory tcc.LogTitle("Phase 4/5 - Import configuration to the target Artifactory") err = tcc.importToTargetArtifactory(archiveConfig) diff --git a/general/utils.go b/general/utils.go index 3aee57434..3ab807399 100644 --- a/general/utils.go +++ b/general/utils.go @@ -1,15 +1,17 @@ package general import ( - "github.com/jfrog/jfrog-cli-core/v2/common/commands" - "github.com/jfrog/jfrog-cli-core/v2/utils/config" - "github.com/jfrog/jfrog-client-go/utils/errorutils" "net" "net/url" "strings" + + "github.com/jfrog/jfrog-cli-core/v2/common/commands" + "github.com/jfrog/jfrog-cli-core/v2/utils/config" + "github.com/jfrog/jfrog-client-go/utils/errorutils" ) const defaultServerId = "default-server" +const SafeDateFileFormat = "2006-01-02_15-04-05" // Deduce the server ID from the URL and add server details to config. func ConfigServerWithDeducedId(server *config.ServerDetails, interactive, webLogin bool) error { From a21c6783b9ca22c3ae7983b642c9f62bfa1a532f Mon Sep 17 00:00:00 2001 From: Aaron Croissette Date: Mon, 2 Dec 2024 15:23:29 -0500 Subject: [PATCH 2/3] feat: write zip, wait for input, read zip, debug logging for interactive transfer-config modification --- .../commands/transferconfig/transferconfig.go | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/artifactory/commands/transferconfig/transferconfig.go b/artifactory/commands/transferconfig/transferconfig.go index 899eb3601..31f988fbd 100644 --- a/artifactory/commands/transferconfig/transferconfig.go +++ b/artifactory/commands/transferconfig/transferconfig.go @@ -5,6 +5,7 @@ import ( "context" "errors" "fmt" + "io" "net/http" "os" "strings" @@ -18,7 +19,6 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils/precheckrunner" "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" "github.com/jfrog/jfrog-cli-core/v2/common/commands" - general "github.com/jfrog/jfrog-cli-core/v2/general" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" "github.com/jfrog/jfrog-client-go/artifactory/services" @@ -147,10 +147,11 @@ func (tcc *TransferConfigCommand) Run() (err error) { if tcc.interactive { tcc.LogTitle("Phase 3.5/5 - Modify configuration (press any key to continue...)") - filename := "config_" + time.Now().Format(general.SafeDateFileFormat) + ".xml" + // filename := "config_" + time.Now().Format(general.SafeDateFileFormat) + ".zip" + filename := "config_*.zip" // open output file - fo, err2 := os.Create(filename) + fo, err2 := os.CreateTemp("", filename) if err2 != nil { return } @@ -167,11 +168,28 @@ func (tcc *TransferConfigCommand) Run() (err error) { } }() + // write file to disk + fo.Write(archiveConfig.Bytes()) + fo.Sync() + log.Info("Waiting for you to modify the file:") log.Info(filename) log.Info("Press any key to continue...") - // TODO: yield execution back + + // TODO: yield execution back? // or separate the phases and add two calls in the consumer + fmt.Scanln() + + // Read file from disk + buf := bytes.NewBuffer(nil) + written, err3 := io.Copy(buf, fo) + + if err3 != nil { + return + } + + log.Debug("Copied ", written, " bytes ", len(buf.Bytes()), len(archiveConfig.Bytes())) + archiveConfig = buf } // Import the archive to the target Artifactory From f2082498db2d59772916d31208477bd7b8ebd268 Mon Sep 17 00:00:00 2001 From: Aaron Croissette Date: Mon, 2 Dec 2024 15:33:37 -0500 Subject: [PATCH 3/3] refactor: clean up code and add more logging --- .../commands/transferconfig/transferconfig.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/artifactory/commands/transferconfig/transferconfig.go b/artifactory/commands/transferconfig/transferconfig.go index 31f988fbd..6dd897d39 100644 --- a/artifactory/commands/transferconfig/transferconfig.go +++ b/artifactory/commands/transferconfig/transferconfig.go @@ -145,7 +145,7 @@ func (tcc *TransferConfigCommand) Run() (err error) { } if tcc.interactive { - tcc.LogTitle("Phase 3.5/5 - Modify configuration (press any key to continue...)") + tcc.LogTitle("Phase 3.5/5 - Modify configuration interactively") // filename := "config_" + time.Now().Format(general.SafeDateFileFormat) + ".zip" filename := "config_*.zip" @@ -153,23 +153,33 @@ func (tcc *TransferConfigCommand) Run() (err error) { // open output file fo, err2 := os.CreateTemp("", filename) if err2 != nil { + log.Error("Failed to create temporary file ", filename, " ", err2) return } // close fo on exit and check for its returned error defer func() { if err := fo.Close(); err != nil { + // log.Error(err) return } err := os.Remove(filename) if err != nil { + log.Error("Failed to remove temporary file ", filename, " ", err) return } }() // write file to disk - fo.Write(archiveConfig.Bytes()) + writtenToDisk, err3 := fo.Write(archiveConfig.Bytes()) + + if err3 != nil { + log.Error("Failed to write temporary file ", filename, " ", err3) + return + } + + log.Debug("Wrote ", writtenToDisk, " bytes ", len(archiveConfig.Bytes())) fo.Sync() log.Info("Waiting for you to modify the file:") @@ -182,13 +192,14 @@ func (tcc *TransferConfigCommand) Run() (err error) { // Read file from disk buf := bytes.NewBuffer(nil) - written, err3 := io.Copy(buf, fo) + readFromDisk, err3 := io.Copy(buf, fo) if err3 != nil { + log.Error("Failed to read temporary file ", filename, " ", err3) return } - log.Debug("Copied ", written, " bytes ", len(buf.Bytes()), len(archiveConfig.Bytes())) + log.Debug("Read ", readFromDisk, " bytes ", len(buf.Bytes()), " ", len(archiveConfig.Bytes())) archiveConfig = buf }