From b48ba62e7080639d1d661a1925583306a29a39f2 Mon Sep 17 00:00:00 2001 From: miampf Date: Fri, 9 Feb 2024 16:44:46 +0100 Subject: [PATCH 01/16] first implementation of feature --- cli/internal/cmd/apply.go | 65 +++++++++++++++++++-------------- cli/internal/cmd/apply_test.go | 2 +- internal/constants/constants.go | 2 + 3 files changed, 40 insertions(+), 29 deletions(-) diff --git a/cli/internal/cmd/apply.go b/cli/internal/cmd/apply.go index 70d66daa67..69a1ecf635 100644 --- a/cli/internal/cmd/apply.go +++ b/cli/internal/cmd/apply.go @@ -351,8 +351,11 @@ The control flow is as follows: func (a *applyCmd) apply( cmd *cobra.Command, configFetcher attestationconfigapi.Fetcher, upgradeDir string, ) error { + // Create debug log file and handler + debugFileHandler := file.NewHandler(afero.NewOsFs()) + // Validate inputs - conf, stateFile, err := a.validateInputs(cmd, configFetcher) + conf, stateFile, err := a.validateInputs(cmd, configFetcher, debugFileHandler) if err != nil { return err } @@ -395,8 +398,8 @@ func (a *applyCmd) apply( // Apply Attestation Config if !a.flags.skipPhases.contains(skipAttestationConfigPhase) { - a.log.Debug("Applying new attestation config to cluster") - if err := a.applyJoinConfig(cmd, conf.GetAttestationConfig(), stateFile.ClusterValues.MeasurementSalt); err != nil { + logDebug(a.log, debugFileHandler, "Applying new attestation config to cluster") + if err := a.applyJoinConfig(cmd, conf.GetAttestationConfig(), stateFile.ClusterValues.MeasurementSalt, debugFileHandler); err != nil { return fmt.Errorf("applying attestation config: %w", err) } } @@ -440,9 +443,9 @@ func (a *applyCmd) apply( return nil } -func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationconfigapi.Fetcher) (*config.Config, *state.State, error) { +func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationconfigapi.Fetcher, debugFileHandler file.Handler) (*config.Config, *state.State, error) { // Read user's config and state file - a.log.Debug(fmt.Sprintf("Reading config from %s", a.flags.pathPrefixer.PrefixPrintablePath(constants.ConfigFilename))) + logDebug(a.log, debugFileHandler, fmt.Sprintf("Reading config from %s", a.flags.pathPrefixer.PrefixPrintablePath(constants.ConfigFilename))) conf, err := config.New(a.fileHandler, constants.ConfigFilename, configFetcher, a.flags.force) var configValidationErr *config.ValidationError if errors.As(err, &configValidationErr) { @@ -452,7 +455,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc return nil, nil, err } - a.log.Debug(fmt.Sprintf("Reading state file from %s", a.flags.pathPrefixer.PrefixPrintablePath(constants.StateFilename))) + logDebug(a.log, debugFileHandler, fmt.Sprintf("Reading state file from %s", a.flags.pathPrefixer.PrefixPrintablePath(constants.StateFilename))) stateFile, err := state.CreateOrRead(a.fileHandler, constants.StateFilename) if err != nil { return nil, nil, err @@ -463,7 +466,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc // We don't run "hard" verification of skip-phases flags and state file here, // a user may still end up skipping phases that could result in errors later on. // However, we perform basic steps, like ensuring init phase is not skipped if - a.log.Debug("Validating state file") + logDebug(a.log, debugFileHandler, "Validating state file") preCreateValidateErr := stateFile.Validate(state.PreCreate, conf.GetAttestationConfig().GetVariant()) preInitValidateErr := stateFile.Validate(state.PreInit, conf.GetAttestationConfig().GetVariant()) postInitValidateErr := stateFile.Validate(state.PostInit, conf.GetAttestationConfig().GetVariant()) @@ -472,16 +475,16 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc // in which case the workspace has to be clean if preCreateValidateErr == nil { // We can't skip the infrastructure phase if no infrastructure has been defined - a.log.Debug("State file is in pre-create state, checking workspace") + logDebug(a.log, debugFileHandler, "State file is in pre-create state, checking workspace") if a.flags.skipPhases.contains(skipInfrastructurePhase) { return nil, nil, preInitValidateErr } - if err := a.checkCreateFilesClean(); err != nil { + if err := a.checkCreateFilesClean(debugFileHandler); err != nil { return nil, nil, err } - a.log.Debug("No Terraform state found in current working directory. Preparing to create a new cluster.") + logDebug(a.log, debugFileHandler, "No Terraform state found in current working directory. Preparing to create a new cluster.") printCreateWarnings(cmd.ErrOrStderr(), conf) } @@ -490,12 +493,12 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc // If so, we need to run the init RPC if preInitValidateErr == nil || (preCreateValidateErr == nil && !a.flags.skipPhases.contains(skipInitPhase)) { // We can't skip the init phase if the init RPC hasn't been run yet - a.log.Debug("State file is in pre-init state, checking workspace") + logDebug(a.log, debugFileHandler, "State file is in pre-init state, checking workspace") if a.flags.skipPhases.contains(skipInitPhase) { return nil, nil, postInitValidateErr } - if err := a.checkInitFilesClean(); err != nil { + if err := a.checkInitFilesClean(debugFileHandler); err != nil { return nil, nil, err } @@ -506,7 +509,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc // If the state file is in a post-init state, // we need to make sure specific files exist in the workspace if postInitValidateErr == nil { - a.log.Debug("State file is in post-init state, checking workspace") + logDebug(a.log, debugFileHandler, "State file is in post-init state, checking workspace") if err := a.checkPostInitFilesExist(); err != nil { return nil, nil, err } @@ -521,16 +524,16 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc // If we need to run the init RPC, the version has to be valid // Otherwise, we are able to use an outdated version, meaning we skip the K8s upgrade // We skip version validation if the user explicitly skips the Kubernetes phase - a.log.Debug(fmt.Sprintf("Validating Kubernetes version %s", conf.KubernetesVersion)) + logDebug(a.log, debugFileHandler, fmt.Sprintf("Validating Kubernetes version %s", conf.KubernetesVersion)) validVersion, err := versions.NewValidK8sVersion(string(conf.KubernetesVersion), true) if err != nil { - a.log.Debug(fmt.Sprintf("Kubernetes version not valid: %s", err)) + logDebug(a.log, debugFileHandler, fmt.Sprintf("Kubernetes version not valid: %s", err)) if !a.flags.skipPhases.contains(skipInitPhase) { return nil, nil, err } if !a.flags.skipPhases.contains(skipK8sPhase) { - a.log.Debug("Checking if user wants to continue anyway") + logDebug(a.log, debugFileHandler, "Checking if user wants to continue anyway") if !a.flags.yes { confirmed, err := askToConfirm(cmd, fmt.Sprintf( @@ -547,7 +550,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc } a.flags.skipPhases.add(skipK8sPhase) - a.log.Debug("Outdated Kubernetes version accepted, Kubernetes upgrade will be skipped") + logDebug(a.log, debugFileHandler, "Outdated Kubernetes version accepted, Kubernetes upgrade will be skipped") } validVersionString, err := versions.ResolveK8sPatchVersion(xsemver.MajorMinor(string(conf.KubernetesVersion))) @@ -563,7 +566,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc cmd.PrintErrf("Warning: Constellation with Kubernetes %s is still in preview. Use only for evaluation purposes.\n", validVersion) } conf.KubernetesVersion = validVersion - a.log.Debug(fmt.Sprintf("Target Kubernetes version set to %s", conf.KubernetesVersion)) + logDebug(a.log, debugFileHandler, fmt.Sprintf("Target Kubernetes version set to %s", conf.KubernetesVersion)) // Validate microservice version (helm versions) in the user's config matches the version of the CLI // This makes sure we catch potential errors early, not just after we already ran Terraform migrations or the init RPC @@ -588,12 +591,12 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc // applyJoinConfig creates or updates the cluster's join config. // If the config already exists, and is different from the new config, the user is asked to confirm the upgrade. func (a *applyCmd) applyJoinConfig(cmd *cobra.Command, newConfig config.AttestationCfg, measurementSalt []byte, -) error { +debugFileHandler file.Handler) error { clusterAttestationConfig, err := a.applier.GetClusterAttestationConfig(cmd.Context(), newConfig.GetVariant()) if err != nil { - a.log.Debug(fmt.Sprintf("Getting cluster attestation config failed: %s", err)) + logDebug(a.log, debugFileHandler, fmt.Sprintf("Getting cluster attestation config failed: %s", err)) if k8serrors.IsNotFound(err) { - a.log.Debug("Creating new join config") + logDebug(a.log, debugFileHandler, "Creating new join config") return a.applier.ApplyJoinConfig(cmd.Context(), newConfig, measurementSalt) } return fmt.Errorf("getting cluster attestation config: %w", err) @@ -605,7 +608,7 @@ func (a *applyCmd) applyJoinConfig(cmd *cobra.Command, newConfig config.Attestat return fmt.Errorf("comparing attestation configs: %w", err) } if equal { - a.log.Debug("Current attestation config is equal to the new config, nothing to do") + logDebug(a.log, debugFileHandler, "Current attestation config is equal to the new config, nothing to do") return nil } @@ -680,11 +683,11 @@ func (a *applyCmd) runK8sVersionUpgrade(cmd *cobra.Command, conf *config.Config) } // checkCreateFilesClean ensures that the workspace is clean before creating a new cluster. -func (a *applyCmd) checkCreateFilesClean() error { - if err := a.checkInitFilesClean(); err != nil { +func (a *applyCmd) checkCreateFilesClean(debugFileHandler file.Handler) error { + if err := a.checkInitFilesClean(debugFileHandler); err != nil { return err } - a.log.Debug("Checking Terraform state") + logDebug(a.log, debugFileHandler, "Checking Terraform state") if _, err := a.fileHandler.Stat(constants.TerraformWorkingDir); err == nil { return fmt.Errorf( "terraform state %q already exists in working directory, run 'constellation terminate' before creating a new cluster", @@ -698,8 +701,8 @@ func (a *applyCmd) checkCreateFilesClean() error { } // checkInitFilesClean ensures that the workspace is clean before running the init RPC. -func (a *applyCmd) checkInitFilesClean() error { - a.log.Debug("Checking admin configuration file") +func (a *applyCmd) checkInitFilesClean(debugFileHandler file.Handler) error { + logDebug(a.log, debugFileHandler, "Checking admin configuration file") if _, err := a.fileHandler.Stat(constants.AdminConfFilename); err == nil { return fmt.Errorf( "file %q already exists in working directory, run 'constellation terminate' before creating a new cluster", @@ -708,7 +711,7 @@ func (a *applyCmd) checkInitFilesClean() error { } else if !errors.Is(err, fs.ErrNotExist) { return fmt.Errorf("checking for %q: %w", a.flags.pathPrefixer.PrefixPrintablePath(constants.AdminConfFilename), err) } - a.log.Debug("Checking master secrets file") + logDebug(a.log, debugFileHandler, "Checking master secrets file") if _, err := a.fileHandler.Stat(constants.MasterSecretFilename); err == nil { return fmt.Errorf( "file %q already exists in working directory. Constellation won't overwrite previous master secrets. Move it somewhere or delete it before creating a new cluster", @@ -858,3 +861,9 @@ type imageFetcher interface { image, region string, useMarketplaceImage bool, ) (string, error) } + +func logDebug(logger debugLog, filehandler file.Handler, msg string) { + logger.Debug(msg) + + filehandler.Write(constants.InitDebugLogFile, []byte(msg), file.OptAppend) +} diff --git a/cli/internal/cmd/apply_test.go b/cli/internal/cmd/apply_test.go index 55f0556697..dfe8c9a1ad 100644 --- a/cli/internal/cmd/apply_test.go +++ b/cli/internal/cmd/apply_test.go @@ -447,7 +447,7 @@ func TestValidateInputs(t *testing.T) { flags: tc.flags, } - conf, state, err := a.validateInputs(cmd, &stubAttestationFetcher{}) + conf, state, err := a.validateInputs(cmd, &stubAttestationFetcher{}, file.NewHandler(afero.NewMemMapFs())) if tc.wantErr { assert.Error(err) return diff --git a/internal/constants/constants.go b/internal/constants/constants.go index 68d0fd6e22..187c7e54e4 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -40,6 +40,8 @@ const ( DefaultControlPlaneGroupName = "control_plane_default" // DefaultWorkerGroupName is the name of the default worker node group. DefaultWorkerGroupName = "worker_default" + // InitDebugLogFile is the name of the debug log file for constellation init/constellation apply + InitDebugLogFile = "constellation-debug.log" // // Ports. From 482d682830ee81ebc0bb4fbc9ed0e44bcee5e74f Mon Sep 17 00:00:00 2001 From: miampf Date: Tue, 13 Feb 2024 14:21:57 +0100 Subject: [PATCH 02/16] added MemMapFs to forgotten unit test --- cli/internal/cmd/create_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/internal/cmd/create_test.go b/cli/internal/cmd/create_test.go index fe3119ee38..7e745fec0e 100644 --- a/cli/internal/cmd/create_test.go +++ b/cli/internal/cmd/create_test.go @@ -296,7 +296,7 @@ func TestCheckDirClean(t *testing.T) { require.NoError(fh.Write(f, []byte{1, 2, 3}, file.OptNone)) } a := &applyCmd{log: logger.NewTest(t), fileHandler: fh} - err := a.checkInitFilesClean() + err := a.checkInitFilesClean(file.NewHandler(afero.NewMemMapFs())) if tc.wantErr { assert.Error(err) From cedf8c52eb8c4a00b87782d9834c02d6faffd905 Mon Sep 17 00:00:00 2001 From: miampf Date: Tue, 13 Feb 2024 14:24:14 +0100 Subject: [PATCH 03/16] add newline to debug message --- cli/internal/cmd/apply.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/internal/cmd/apply.go b/cli/internal/cmd/apply.go index 69a1ecf635..6194487ea6 100644 --- a/cli/internal/cmd/apply.go +++ b/cli/internal/cmd/apply.go @@ -865,5 +865,5 @@ type imageFetcher interface { func logDebug(logger debugLog, filehandler file.Handler, msg string) { logger.Debug(msg) - filehandler.Write(constants.InitDebugLogFile, []byte(msg), file.OptAppend) + filehandler.Write(constants.InitDebugLogFile, []byte(msg + "\n"), file.OptAppend) } From 216558686315864a13de6e8bf589584d4f5022c1 Mon Sep 17 00:00:00 2001 From: miampf Date: Tue, 13 Feb 2024 14:29:18 +0100 Subject: [PATCH 04/16] pass filehandler as parameter to apply() --- cli/internal/cmd/apply.go | 7 ++----- cli/internal/cmd/create_test.go | 2 +- cli/internal/cmd/init_test.go | 2 +- cli/internal/cmd/upgradeapply_test.go | 2 +- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/cli/internal/cmd/apply.go b/cli/internal/cmd/apply.go index 6194487ea6..eea15a385e 100644 --- a/cli/internal/cmd/apply.go +++ b/cli/internal/cmd/apply.go @@ -261,7 +261,7 @@ func runApply(cmd *cobra.Command, _ []string) error { defer cancel() cmd.SetContext(ctx) - return apply.apply(cmd, attestationconfigapi.NewFetcher(), upgradeDir) + return apply.apply(cmd, attestationconfigapi.NewFetcher(), upgradeDir, fileHandler) } type applyCmd struct { @@ -349,11 +349,8 @@ The control flow is as follows: └────────────────────┘ */ func (a *applyCmd) apply( - cmd *cobra.Command, configFetcher attestationconfigapi.Fetcher, upgradeDir string, + cmd *cobra.Command, configFetcher attestationconfigapi.Fetcher, upgradeDir string, debugFileHandler file.Handler, ) error { - // Create debug log file and handler - debugFileHandler := file.NewHandler(afero.NewOsFs()) - // Validate inputs conf, stateFile, err := a.validateInputs(cmd, configFetcher, debugFileHandler) if err != nil { diff --git a/cli/internal/cmd/create_test.go b/cli/internal/cmd/create_test.go index 7e745fec0e..f8aabbd1f9 100644 --- a/cli/internal/cmd/create_test.go +++ b/cli/internal/cmd/create_test.go @@ -237,7 +237,7 @@ func TestCreate(t *testing.T) { applier: &stubConstellApplier{}, } - err := a.apply(cmd, stubAttestationFetcher{}, "create") + err := a.apply(cmd, stubAttestationFetcher{}, "create", fileHandler) if tc.wantErr { assert.Error(err) diff --git a/cli/internal/cmd/init_test.go b/cli/internal/cmd/init_test.go index de6278d660..05dbba2013 100644 --- a/cli/internal/cmd/init_test.go +++ b/cli/internal/cmd/init_test.go @@ -247,7 +247,7 @@ func TestInitialize(t *testing.T) { }, } - err := i.apply(cmd, stubAttestationFetcher{}, "test") + err := i.apply(cmd, stubAttestationFetcher{}, "test", fileHandler) if tc.wantErr { assert.Error(err) diff --git a/cli/internal/cmd/upgradeapply_test.go b/cli/internal/cmd/upgradeapply_test.go index 488a512d51..c8e83194f9 100644 --- a/cli/internal/cmd/upgradeapply_test.go +++ b/cli/internal/cmd/upgradeapply_test.go @@ -263,7 +263,7 @@ func TestUpgradeApply(t *testing.T) { }, imageFetcher: &stubImageFetcher{fetchReferenceErr: tc.fetchImageErr}, } - err := upgrader.apply(cmd, stubAttestationFetcher{}, "test") + err := upgrader.apply(cmd, stubAttestationFetcher{}, "test", file.NewHandler(afero.NewMemMapFs())) if tc.wantErr { assert.Error(err) return From 8beeb1b6064994bc43a47347be8c440a26ad290f Mon Sep 17 00:00:00 2001 From: miampf Date: Tue, 13 Feb 2024 15:09:48 +0100 Subject: [PATCH 05/16] tidy --- cli/internal/cmd/apply.go | 7 ++++--- internal/constants/constants.go | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cli/internal/cmd/apply.go b/cli/internal/cmd/apply.go index eea15a385e..7c7da72c04 100644 --- a/cli/internal/cmd/apply.go +++ b/cli/internal/cmd/apply.go @@ -588,7 +588,8 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc // applyJoinConfig creates or updates the cluster's join config. // If the config already exists, and is different from the new config, the user is asked to confirm the upgrade. func (a *applyCmd) applyJoinConfig(cmd *cobra.Command, newConfig config.AttestationCfg, measurementSalt []byte, -debugFileHandler file.Handler) error { + debugFileHandler file.Handler, +) error { clusterAttestationConfig, err := a.applier.GetClusterAttestationConfig(cmd.Context(), newConfig.GetVariant()) if err != nil { logDebug(a.log, debugFileHandler, fmt.Sprintf("Getting cluster attestation config failed: %s", err)) @@ -860,7 +861,7 @@ type imageFetcher interface { } func logDebug(logger debugLog, filehandler file.Handler, msg string) { - logger.Debug(msg) + logger.Debug(msg) - filehandler.Write(constants.InitDebugLogFile, []byte(msg + "\n"), file.OptAppend) + filehandler.Write(constants.InitDebugLogFile, []byte(msg+"\n"), file.OptAppend) } diff --git a/internal/constants/constants.go b/internal/constants/constants.go index 187c7e54e4..40424abbfe 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -40,8 +40,8 @@ const ( DefaultControlPlaneGroupName = "control_plane_default" // DefaultWorkerGroupName is the name of the default worker node group. DefaultWorkerGroupName = "worker_default" - // InitDebugLogFile is the name of the debug log file for constellation init/constellation apply - InitDebugLogFile = "constellation-debug.log" + // InitDebugLogFile is the name of the debug log file for constellation init/constellation apply + InitDebugLogFile = "constellation-debug.log" // // Ports. From 8c325f3c33b030806f9e68eaaded3ca0370a8075 Mon Sep 17 00:00:00 2001 From: miampf Date: Tue, 13 Feb 2024 15:28:07 +0100 Subject: [PATCH 06/16] ignore error from filehandler.Write --- cli/internal/cmd/apply.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/internal/cmd/apply.go b/cli/internal/cmd/apply.go index 7c7da72c04..620b71b374 100644 --- a/cli/internal/cmd/apply.go +++ b/cli/internal/cmd/apply.go @@ -863,5 +863,5 @@ type imageFetcher interface { func logDebug(logger debugLog, filehandler file.Handler, msg string) { logger.Debug(msg) - filehandler.Write(constants.InitDebugLogFile, []byte(msg+"\n"), file.OptAppend) + _ = filehandler.Write(constants.InitDebugLogFile, []byte(msg+"\n"), file.OptAppend) } From 39a063f6ca58a1b08d0a74a4b0cb8032a00a51bb Mon Sep 17 00:00:00 2001 From: miampf Date: Tue, 13 Feb 2024 15:41:09 +0100 Subject: [PATCH 07/16] tidy again --- cli/internal/cmd/apply.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/internal/cmd/apply.go b/cli/internal/cmd/apply.go index 620b71b374..a8eb705834 100644 --- a/cli/internal/cmd/apply.go +++ b/cli/internal/cmd/apply.go @@ -863,5 +863,5 @@ type imageFetcher interface { func logDebug(logger debugLog, filehandler file.Handler, msg string) { logger.Debug(msg) - _ = filehandler.Write(constants.InitDebugLogFile, []byte(msg+"\n"), file.OptAppend) + _ = filehandler.Write(constants.InitDebugLogFile, []byte(msg+"\n"), file.OptAppend) } From ed4f270e5e2c22799e05838b98d6dce28794fb5a Mon Sep 17 00:00:00 2001 From: miampf Date: Tue, 13 Feb 2024 16:26:14 +0100 Subject: [PATCH 08/16] wrote struct --- cli/internal/cmd/apply.go | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/cli/internal/cmd/apply.go b/cli/internal/cmd/apply.go index a8eb705834..94ef73f0c5 100644 --- a/cli/internal/cmd/apply.go +++ b/cli/internal/cmd/apply.go @@ -223,7 +223,8 @@ func runApply(cmd *cobra.Command, _ []string) error { return err } - fileHandler := file.NewHandler(afero.NewOsFs()) + fileHandler := file.NewHandler(afero.NewOsFs()) + logger := debugFileLogger{fileHandler: file.NewHandler(afero.NewOsFs()), log: log} newDialer := func(validator atls.Validator) *dialer.Dialer { return dialer.New(nil, validator, &net.Dialer{}) @@ -248,7 +249,7 @@ func runApply(cmd *cobra.Command, _ []string) error { apply := &applyCmd{ fileHandler: fileHandler, flags: flags, - log: log, + log: logger, wLog: &warnLogger{cmd: cmd, log: log}, spinner: spinner, merger: &kubeconfigMerger{log: log}, @@ -860,8 +861,13 @@ type imageFetcher interface { ) (string, error) } -func logDebug(logger debugLog, filehandler file.Handler, msg string) { - logger.Debug(msg) +type debugFileLogger struct { + fileHandler file.Handler + log debugLog +} + +func (l debugFileLogger) Debug(msg string, args ...any) { + l.log.Debug(msg) - _ = filehandler.Write(constants.InitDebugLogFile, []byte(msg+"\n"), file.OptAppend) + _ = l.fileHandler.Write(constants.InitDebugLogFile, []byte(msg+"\n"), file.OptAppend) } From c663b8b0fb4edd05dfa200e98c7192efbc2de443 Mon Sep 17 00:00:00 2001 From: miampf Date: Tue, 13 Feb 2024 17:01:24 +0100 Subject: [PATCH 09/16] changed logging calls to struct calls --- cli/internal/cmd/apply.go | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/cli/internal/cmd/apply.go b/cli/internal/cmd/apply.go index 94ef73f0c5..2158b5be9f 100644 --- a/cli/internal/cmd/apply.go +++ b/cli/internal/cmd/apply.go @@ -396,7 +396,7 @@ func (a *applyCmd) apply( // Apply Attestation Config if !a.flags.skipPhases.contains(skipAttestationConfigPhase) { - logDebug(a.log, debugFileHandler, "Applying new attestation config to cluster") + a.log.Debug("Applying new attestation config to cluster") if err := a.applyJoinConfig(cmd, conf.GetAttestationConfig(), stateFile.ClusterValues.MeasurementSalt, debugFileHandler); err != nil { return fmt.Errorf("applying attestation config: %w", err) } @@ -443,7 +443,7 @@ func (a *applyCmd) apply( func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationconfigapi.Fetcher, debugFileHandler file.Handler) (*config.Config, *state.State, error) { // Read user's config and state file - logDebug(a.log, debugFileHandler, fmt.Sprintf("Reading config from %s", a.flags.pathPrefixer.PrefixPrintablePath(constants.ConfigFilename))) + a.log.Debug(fmt.Sprintf("Reading config from %s", a.flags.pathPrefixer.PrefixPrintablePath(constants.ConfigFilename))) conf, err := config.New(a.fileHandler, constants.ConfigFilename, configFetcher, a.flags.force) var configValidationErr *config.ValidationError if errors.As(err, &configValidationErr) { @@ -453,7 +453,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc return nil, nil, err } - logDebug(a.log, debugFileHandler, fmt.Sprintf("Reading state file from %s", a.flags.pathPrefixer.PrefixPrintablePath(constants.StateFilename))) + a.log.Debug(fmt.Sprintf("Reading state file from %s", a.flags.pathPrefixer.PrefixPrintablePath(constants.StateFilename))) stateFile, err := state.CreateOrRead(a.fileHandler, constants.StateFilename) if err != nil { return nil, nil, err @@ -464,7 +464,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc // We don't run "hard" verification of skip-phases flags and state file here, // a user may still end up skipping phases that could result in errors later on. // However, we perform basic steps, like ensuring init phase is not skipped if - logDebug(a.log, debugFileHandler, "Validating state file") + a.log.Debug("Validating state file") preCreateValidateErr := stateFile.Validate(state.PreCreate, conf.GetAttestationConfig().GetVariant()) preInitValidateErr := stateFile.Validate(state.PreInit, conf.GetAttestationConfig().GetVariant()) postInitValidateErr := stateFile.Validate(state.PostInit, conf.GetAttestationConfig().GetVariant()) @@ -473,7 +473,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc // in which case the workspace has to be clean if preCreateValidateErr == nil { // We can't skip the infrastructure phase if no infrastructure has been defined - logDebug(a.log, debugFileHandler, "State file is in pre-create state, checking workspace") + a.log.Debug("State file is in pre-create state, checking workspace") if a.flags.skipPhases.contains(skipInfrastructurePhase) { return nil, nil, preInitValidateErr } @@ -482,7 +482,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc return nil, nil, err } - logDebug(a.log, debugFileHandler, "No Terraform state found in current working directory. Preparing to create a new cluster.") + a.log.Debug("No Terraform state found in current working directory. Preparing to create a new cluster.") printCreateWarnings(cmd.ErrOrStderr(), conf) } @@ -491,7 +491,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc // If so, we need to run the init RPC if preInitValidateErr == nil || (preCreateValidateErr == nil && !a.flags.skipPhases.contains(skipInitPhase)) { // We can't skip the init phase if the init RPC hasn't been run yet - logDebug(a.log, debugFileHandler, "State file is in pre-init state, checking workspace") + a.log.Debug("State file is in pre-init state, checking workspace") if a.flags.skipPhases.contains(skipInitPhase) { return nil, nil, postInitValidateErr } @@ -507,7 +507,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc // If the state file is in a post-init state, // we need to make sure specific files exist in the workspace if postInitValidateErr == nil { - logDebug(a.log, debugFileHandler, "State file is in post-init state, checking workspace") + a.log.Debug("State file is in post-init state, checking workspace") if err := a.checkPostInitFilesExist(); err != nil { return nil, nil, err } @@ -522,16 +522,16 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc // If we need to run the init RPC, the version has to be valid // Otherwise, we are able to use an outdated version, meaning we skip the K8s upgrade // We skip version validation if the user explicitly skips the Kubernetes phase - logDebug(a.log, debugFileHandler, fmt.Sprintf("Validating Kubernetes version %s", conf.KubernetesVersion)) + a.log.Debug(fmt.Sprintf("Validating Kubernetes version %s", conf.KubernetesVersion)) validVersion, err := versions.NewValidK8sVersion(string(conf.KubernetesVersion), true) if err != nil { - logDebug(a.log, debugFileHandler, fmt.Sprintf("Kubernetes version not valid: %s", err)) + a.log.Debug(fmt.Sprintf("Kubernetes version not valid: %s", err)) if !a.flags.skipPhases.contains(skipInitPhase) { return nil, nil, err } if !a.flags.skipPhases.contains(skipK8sPhase) { - logDebug(a.log, debugFileHandler, "Checking if user wants to continue anyway") + a.log.Debug("Checking if user wants to continue anyway") if !a.flags.yes { confirmed, err := askToConfirm(cmd, fmt.Sprintf( @@ -548,7 +548,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc } a.flags.skipPhases.add(skipK8sPhase) - logDebug(a.log, debugFileHandler, "Outdated Kubernetes version accepted, Kubernetes upgrade will be skipped") + a.log.Debug("Outdated Kubernetes version accepted, Kubernetes upgrade will be skipped") } validVersionString, err := versions.ResolveK8sPatchVersion(xsemver.MajorMinor(string(conf.KubernetesVersion))) @@ -564,7 +564,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc cmd.PrintErrf("Warning: Constellation with Kubernetes %s is still in preview. Use only for evaluation purposes.\n", validVersion) } conf.KubernetesVersion = validVersion - logDebug(a.log, debugFileHandler, fmt.Sprintf("Target Kubernetes version set to %s", conf.KubernetesVersion)) + a.log.Debug(fmt.Sprintf("Target Kubernetes version set to %s", conf.KubernetesVersion)) // Validate microservice version (helm versions) in the user's config matches the version of the CLI // This makes sure we catch potential errors early, not just after we already ran Terraform migrations or the init RPC @@ -593,9 +593,9 @@ func (a *applyCmd) applyJoinConfig(cmd *cobra.Command, newConfig config.Attestat ) error { clusterAttestationConfig, err := a.applier.GetClusterAttestationConfig(cmd.Context(), newConfig.GetVariant()) if err != nil { - logDebug(a.log, debugFileHandler, fmt.Sprintf("Getting cluster attestation config failed: %s", err)) + a.log.Debug(fmt.Sprintf("Getting cluster attestation config failed: %s", err)) if k8serrors.IsNotFound(err) { - logDebug(a.log, debugFileHandler, "Creating new join config") + a.log.Debug("Creating new join config") return a.applier.ApplyJoinConfig(cmd.Context(), newConfig, measurementSalt) } return fmt.Errorf("getting cluster attestation config: %w", err) @@ -607,7 +607,7 @@ func (a *applyCmd) applyJoinConfig(cmd *cobra.Command, newConfig config.Attestat return fmt.Errorf("comparing attestation configs: %w", err) } if equal { - logDebug(a.log, debugFileHandler, "Current attestation config is equal to the new config, nothing to do") + a.log.Debug("Current attestation config is equal to the new config, nothing to do") return nil } @@ -686,7 +686,7 @@ func (a *applyCmd) checkCreateFilesClean(debugFileHandler file.Handler) error { if err := a.checkInitFilesClean(debugFileHandler); err != nil { return err } - logDebug(a.log, debugFileHandler, "Checking Terraform state") + a.log.Debug("Checking Terraform state") if _, err := a.fileHandler.Stat(constants.TerraformWorkingDir); err == nil { return fmt.Errorf( "terraform state %q already exists in working directory, run 'constellation terminate' before creating a new cluster", @@ -701,7 +701,7 @@ func (a *applyCmd) checkCreateFilesClean(debugFileHandler file.Handler) error { // checkInitFilesClean ensures that the workspace is clean before running the init RPC. func (a *applyCmd) checkInitFilesClean(debugFileHandler file.Handler) error { - logDebug(a.log, debugFileHandler, "Checking admin configuration file") + a.log.Debug("Checking admin configuration file") if _, err := a.fileHandler.Stat(constants.AdminConfFilename); err == nil { return fmt.Errorf( "file %q already exists in working directory, run 'constellation terminate' before creating a new cluster", @@ -710,7 +710,7 @@ func (a *applyCmd) checkInitFilesClean(debugFileHandler file.Handler) error { } else if !errors.Is(err, fs.ErrNotExist) { return fmt.Errorf("checking for %q: %w", a.flags.pathPrefixer.PrefixPrintablePath(constants.AdminConfFilename), err) } - logDebug(a.log, debugFileHandler, "Checking master secrets file") + a.log.Debug("Checking master secrets file") if _, err := a.fileHandler.Stat(constants.MasterSecretFilename); err == nil { return fmt.Errorf( "file %q already exists in working directory. Constellation won't overwrite previous master secrets. Move it somewhere or delete it before creating a new cluster", From 804fac00ec7c99fe99627a59de19225f13b6a2e8 Mon Sep 17 00:00:00 2001 From: miampf Date: Wed, 14 Feb 2024 13:53:45 +0100 Subject: [PATCH 10/16] fixed issues with unit tests --- cli/internal/cmd/apply.go | 21 ++++++++++----------- cli/internal/cmd/apply_test.go | 2 +- cli/internal/cmd/create_test.go | 4 ++-- cli/internal/cmd/init_test.go | 2 +- cli/internal/cmd/upgradeapply_test.go | 2 +- 5 files changed, 15 insertions(+), 16 deletions(-) diff --git a/cli/internal/cmd/apply.go b/cli/internal/cmd/apply.go index 2158b5be9f..1364b13b01 100644 --- a/cli/internal/cmd/apply.go +++ b/cli/internal/cmd/apply.go @@ -262,7 +262,7 @@ func runApply(cmd *cobra.Command, _ []string) error { defer cancel() cmd.SetContext(ctx) - return apply.apply(cmd, attestationconfigapi.NewFetcher(), upgradeDir, fileHandler) + return apply.apply(cmd, attestationconfigapi.NewFetcher(), upgradeDir) } type applyCmd struct { @@ -350,10 +350,10 @@ The control flow is as follows: └────────────────────┘ */ func (a *applyCmd) apply( - cmd *cobra.Command, configFetcher attestationconfigapi.Fetcher, upgradeDir string, debugFileHandler file.Handler, + cmd *cobra.Command, configFetcher attestationconfigapi.Fetcher, upgradeDir string, ) error { // Validate inputs - conf, stateFile, err := a.validateInputs(cmd, configFetcher, debugFileHandler) + conf, stateFile, err := a.validateInputs(cmd, configFetcher) if err != nil { return err } @@ -397,7 +397,7 @@ func (a *applyCmd) apply( // Apply Attestation Config if !a.flags.skipPhases.contains(skipAttestationConfigPhase) { a.log.Debug("Applying new attestation config to cluster") - if err := a.applyJoinConfig(cmd, conf.GetAttestationConfig(), stateFile.ClusterValues.MeasurementSalt, debugFileHandler); err != nil { + if err := a.applyJoinConfig(cmd, conf.GetAttestationConfig(), stateFile.ClusterValues.MeasurementSalt); err != nil { return fmt.Errorf("applying attestation config: %w", err) } } @@ -441,7 +441,7 @@ func (a *applyCmd) apply( return nil } -func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationconfigapi.Fetcher, debugFileHandler file.Handler) (*config.Config, *state.State, error) { +func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationconfigapi.Fetcher) (*config.Config, *state.State, error) { // Read user's config and state file a.log.Debug(fmt.Sprintf("Reading config from %s", a.flags.pathPrefixer.PrefixPrintablePath(constants.ConfigFilename))) conf, err := config.New(a.fileHandler, constants.ConfigFilename, configFetcher, a.flags.force) @@ -478,7 +478,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc return nil, nil, preInitValidateErr } - if err := a.checkCreateFilesClean(debugFileHandler); err != nil { + if err := a.checkCreateFilesClean(); err != nil { return nil, nil, err } @@ -496,7 +496,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc return nil, nil, postInitValidateErr } - if err := a.checkInitFilesClean(debugFileHandler); err != nil { + if err := a.checkInitFilesClean(); err != nil { return nil, nil, err } @@ -589,7 +589,6 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc // applyJoinConfig creates or updates the cluster's join config. // If the config already exists, and is different from the new config, the user is asked to confirm the upgrade. func (a *applyCmd) applyJoinConfig(cmd *cobra.Command, newConfig config.AttestationCfg, measurementSalt []byte, - debugFileHandler file.Handler, ) error { clusterAttestationConfig, err := a.applier.GetClusterAttestationConfig(cmd.Context(), newConfig.GetVariant()) if err != nil { @@ -682,8 +681,8 @@ func (a *applyCmd) runK8sVersionUpgrade(cmd *cobra.Command, conf *config.Config) } // checkCreateFilesClean ensures that the workspace is clean before creating a new cluster. -func (a *applyCmd) checkCreateFilesClean(debugFileHandler file.Handler) error { - if err := a.checkInitFilesClean(debugFileHandler); err != nil { +func (a *applyCmd) checkCreateFilesClean() error { + if err := a.checkInitFilesClean(); err != nil { return err } a.log.Debug("Checking Terraform state") @@ -700,7 +699,7 @@ func (a *applyCmd) checkCreateFilesClean(debugFileHandler file.Handler) error { } // checkInitFilesClean ensures that the workspace is clean before running the init RPC. -func (a *applyCmd) checkInitFilesClean(debugFileHandler file.Handler) error { +func (a *applyCmd) checkInitFilesClean() error { a.log.Debug("Checking admin configuration file") if _, err := a.fileHandler.Stat(constants.AdminConfFilename); err == nil { return fmt.Errorf( diff --git a/cli/internal/cmd/apply_test.go b/cli/internal/cmd/apply_test.go index dfe8c9a1ad..55f0556697 100644 --- a/cli/internal/cmd/apply_test.go +++ b/cli/internal/cmd/apply_test.go @@ -447,7 +447,7 @@ func TestValidateInputs(t *testing.T) { flags: tc.flags, } - conf, state, err := a.validateInputs(cmd, &stubAttestationFetcher{}, file.NewHandler(afero.NewMemMapFs())) + conf, state, err := a.validateInputs(cmd, &stubAttestationFetcher{}) if tc.wantErr { assert.Error(err) return diff --git a/cli/internal/cmd/create_test.go b/cli/internal/cmd/create_test.go index f8aabbd1f9..fe3119ee38 100644 --- a/cli/internal/cmd/create_test.go +++ b/cli/internal/cmd/create_test.go @@ -237,7 +237,7 @@ func TestCreate(t *testing.T) { applier: &stubConstellApplier{}, } - err := a.apply(cmd, stubAttestationFetcher{}, "create", fileHandler) + err := a.apply(cmd, stubAttestationFetcher{}, "create") if tc.wantErr { assert.Error(err) @@ -296,7 +296,7 @@ func TestCheckDirClean(t *testing.T) { require.NoError(fh.Write(f, []byte{1, 2, 3}, file.OptNone)) } a := &applyCmd{log: logger.NewTest(t), fileHandler: fh} - err := a.checkInitFilesClean(file.NewHandler(afero.NewMemMapFs())) + err := a.checkInitFilesClean() if tc.wantErr { assert.Error(err) diff --git a/cli/internal/cmd/init_test.go b/cli/internal/cmd/init_test.go index 05dbba2013..de6278d660 100644 --- a/cli/internal/cmd/init_test.go +++ b/cli/internal/cmd/init_test.go @@ -247,7 +247,7 @@ func TestInitialize(t *testing.T) { }, } - err := i.apply(cmd, stubAttestationFetcher{}, "test", fileHandler) + err := i.apply(cmd, stubAttestationFetcher{}, "test") if tc.wantErr { assert.Error(err) diff --git a/cli/internal/cmd/upgradeapply_test.go b/cli/internal/cmd/upgradeapply_test.go index c8e83194f9..488a512d51 100644 --- a/cli/internal/cmd/upgradeapply_test.go +++ b/cli/internal/cmd/upgradeapply_test.go @@ -263,7 +263,7 @@ func TestUpgradeApply(t *testing.T) { }, imageFetcher: &stubImageFetcher{fetchReferenceErr: tc.fetchImageErr}, } - err := upgrader.apply(cmd, stubAttestationFetcher{}, "test", file.NewHandler(afero.NewMemMapFs())) + err := upgrader.apply(cmd, stubAttestationFetcher{}, "test") if tc.wantErr { assert.Error(err) return From 6eb55ee3db6d5687bdea1d00bd26238a9208a015 Mon Sep 17 00:00:00 2001 From: miampf Date: Wed, 14 Feb 2024 13:54:33 +0100 Subject: [PATCH 11/16] tidy --- cli/internal/cmd/apply.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cli/internal/cmd/apply.go b/cli/internal/cmd/apply.go index 1364b13b01..ff177395bc 100644 --- a/cli/internal/cmd/apply.go +++ b/cli/internal/cmd/apply.go @@ -223,8 +223,8 @@ func runApply(cmd *cobra.Command, _ []string) error { return err } - fileHandler := file.NewHandler(afero.NewOsFs()) - logger := debugFileLogger{fileHandler: file.NewHandler(afero.NewOsFs()), log: log} + fileHandler := file.NewHandler(afero.NewOsFs()) + logger := debugFileLogger{fileHandler: file.NewHandler(afero.NewOsFs()), log: log} newDialer := func(validator atls.Validator) *dialer.Dialer { return dialer.New(nil, validator, &net.Dialer{}) @@ -350,7 +350,7 @@ The control flow is as follows: └────────────────────┘ */ func (a *applyCmd) apply( - cmd *cobra.Command, configFetcher attestationconfigapi.Fetcher, upgradeDir string, + cmd *cobra.Command, configFetcher attestationconfigapi.Fetcher, upgradeDir string, ) error { // Validate inputs conf, stateFile, err := a.validateInputs(cmd, configFetcher) @@ -861,8 +861,8 @@ type imageFetcher interface { } type debugFileLogger struct { - fileHandler file.Handler - log debugLog + fileHandler file.Handler + log debugLog } func (l debugFileLogger) Debug(msg string, args ...any) { From 93e2adad12a508a2af2711acabba2fbea676b038 Mon Sep 17 00:00:00 2001 From: miampf Date: Wed, 14 Feb 2024 14:43:56 +0100 Subject: [PATCH 12/16] also log further args --- cli/internal/cmd/apply.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/internal/cmd/apply.go b/cli/internal/cmd/apply.go index ff177395bc..5b8b3c6f07 100644 --- a/cli/internal/cmd/apply.go +++ b/cli/internal/cmd/apply.go @@ -866,7 +866,7 @@ type debugFileLogger struct { } func (l debugFileLogger) Debug(msg string, args ...any) { - l.log.Debug(msg) + l.log.Debug(msg, args...) _ = l.fileHandler.Write(constants.InitDebugLogFile, []byte(msg+"\n"), file.OptAppend) } From 9e9d3439fddbbf9bc32e3e4f254134faa239d10f Mon Sep 17 00:00:00 2001 From: miampf Date: Wed, 14 Feb 2024 14:44:34 +0100 Subject: [PATCH 13/16] add dot to comment --- internal/constants/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/constants/constants.go b/internal/constants/constants.go index 40424abbfe..2844f8851e 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -40,7 +40,7 @@ const ( DefaultControlPlaneGroupName = "control_plane_default" // DefaultWorkerGroupName is the name of the default worker node group. DefaultWorkerGroupName = "worker_default" - // InitDebugLogFile is the name of the debug log file for constellation init/constellation apply + // InitDebugLogFile is the name of the debug log file for constellation init/constellation apply. InitDebugLogFile = "constellation-debug.log" // From d9c1f5e0cf6bc9bae0229d562381454cc5a782ea Mon Sep 17 00:00:00 2001 From: miampf Date: Wed, 14 Feb 2024 14:48:36 +0100 Subject: [PATCH 14/16] use existing file handler --- cli/internal/cmd/apply.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/internal/cmd/apply.go b/cli/internal/cmd/apply.go index 5b8b3c6f07..9d61ef8783 100644 --- a/cli/internal/cmd/apply.go +++ b/cli/internal/cmd/apply.go @@ -224,7 +224,7 @@ func runApply(cmd *cobra.Command, _ []string) error { } fileHandler := file.NewHandler(afero.NewOsFs()) - logger := debugFileLogger{fileHandler: file.NewHandler(afero.NewOsFs()), log: log} + logger := debugFileLogger{fileHandler: fileHandler, log: log} newDialer := func(validator atls.Validator) *dialer.Dialer { return dialer.New(nil, validator, &net.Dialer{}) From fd5bd9236621b962eba945348bf57833591c0c33 Mon Sep 17 00:00:00 2001 From: miampf Date: Mon, 19 Feb 2024 13:27:52 +0100 Subject: [PATCH 15/16] renamed constant to CLIDebugLogFile --- cli/internal/cmd/apply.go | 2 +- internal/constants/constants.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cli/internal/cmd/apply.go b/cli/internal/cmd/apply.go index 9d61ef8783..5b69baf3ca 100644 --- a/cli/internal/cmd/apply.go +++ b/cli/internal/cmd/apply.go @@ -868,5 +868,5 @@ type debugFileLogger struct { func (l debugFileLogger) Debug(msg string, args ...any) { l.log.Debug(msg, args...) - _ = l.fileHandler.Write(constants.InitDebugLogFile, []byte(msg+"\n"), file.OptAppend) + _ = l.fileHandler.Write(constants.CLIDebugLogFile, []byte(msg+"\n"), file.OptAppend) } diff --git a/internal/constants/constants.go b/internal/constants/constants.go index 2844f8851e..c313b74a68 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -40,8 +40,8 @@ const ( DefaultControlPlaneGroupName = "control_plane_default" // DefaultWorkerGroupName is the name of the default worker node group. DefaultWorkerGroupName = "worker_default" - // InitDebugLogFile is the name of the debug log file for constellation init/constellation apply. - InitDebugLogFile = "constellation-debug.log" + // CLIDebugLogFile is the name of the debug log file for constellation init/constellation apply. + CLIDebugLogFile = "constellation-debug.log" // // Ports. From 407db06aefcfbad9f6364abd0d193a28de6c1669 Mon Sep 17 00:00:00 2001 From: miampf Date: Mon, 19 Feb 2024 14:42:59 +0100 Subject: [PATCH 16/16] added slog-multi + rewritten code to use it --- bazel/toolchains/go_module_deps.bzl | 16 ++++++++++++ cli/internal/cmd/BUILD.bazel | 1 + cli/internal/cmd/apply.go | 40 ++++++++++++++++++++++++----- go.mod | 3 +++ go.sum | 4 +++ 5 files changed, 57 insertions(+), 7 deletions(-) diff --git a/bazel/toolchains/go_module_deps.bzl b/bazel/toolchains/go_module_deps.bzl index 7375136464..a91c4cebf5 100644 --- a/bazel/toolchains/go_module_deps.bzl +++ b/bazel/toolchains/go_module_deps.bzl @@ -4435,6 +4435,22 @@ def go_dependencies(): sum = "h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=", version = "v1.0.0", ) + go_repository( + name = "com_github_samber_lo", + build_file_generation = "on", + build_file_proto_mode = "disable_global", + importpath = "github.com/samber/lo", + sum = "h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=", + version = "v1.38.1", + ) + go_repository( + name = "com_github_samber_slog_multi", + build_file_generation = "on", + build_file_proto_mode = "disable_global", + importpath = "github.com/samber/slog-multi", + sum = "h1:6BVH9uHGAsiGkbbtQgAOQJMpKgV8unMrHhhJaw+X1EQ=", + version = "v1.0.2", + ) go_repository( name = "com_github_sassoftware_relic", build_file_generation = "on", diff --git a/cli/internal/cmd/BUILD.bazel b/cli/internal/cmd/BUILD.bazel index afccfc643b..8c300b62ad 100644 --- a/cli/internal/cmd/BUILD.bazel +++ b/cli/internal/cmd/BUILD.bazel @@ -97,6 +97,7 @@ go_library( "@com_github_google_uuid//:uuid", "@com_github_mattn_go_isatty//:go-isatty", "@com_github_rogpeppe_go_internal//diff", + "@com_github_samber_slog_multi//:slog-multi", "@com_github_siderolabs_talos_pkg_machinery//config/encoder", "@com_github_spf13_afero//:afero", "@com_github_spf13_cobra//:cobra", diff --git a/cli/internal/cmd/apply.go b/cli/internal/cmd/apply.go index 5b69baf3ca..ea7679a508 100644 --- a/cli/internal/cmd/apply.go +++ b/cli/internal/cmd/apply.go @@ -13,7 +13,9 @@ import ( "fmt" "io" "io/fs" + "log/slog" "net" + "os" "path/filepath" "slices" "strings" @@ -38,6 +40,7 @@ import ( "github.com/edgelesssys/constellation/v2/internal/kms/uri" "github.com/edgelesssys/constellation/v2/internal/semver" "github.com/edgelesssys/constellation/v2/internal/versions" + "github.com/samber/slog-multi" "github.com/spf13/afero" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -224,7 +227,10 @@ func runApply(cmd *cobra.Command, _ []string) error { } fileHandler := file.NewHandler(afero.NewOsFs()) - logger := debugFileLogger{fileHandler: fileHandler, log: log} + logger, err := newDebugFileLogger(cmd, fileHandler) + if err != nil { + return err + } newDialer := func(validator atls.Validator) *dialer.Dialer { return dialer.New(nil, validator, &net.Dialer{}) @@ -860,13 +866,33 @@ type imageFetcher interface { ) (string, error) } -type debugFileLogger struct { - fileHandler file.Handler - log debugLog +func newDebugFileLogger(cmd *cobra.Command, fileHandler file.Handler) (debugLog, error) { + logLvl := slog.LevelInfo + debugLog, err := cmd.Flags().GetBool("debug") + if err != nil { + return nil, err + } + if debugLog { + logLvl = slog.LevelDebug + } + + fileWriter := &fileWriter{ + fileHandler: fileHandler, + } + return slog.New( + slogmulti.Fanout( + slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{AddSource: true, Level: logLvl}), // first handler: stderr at log level + slog.NewJSONHandler(fileWriter, &slog.HandlerOptions{AddSource: true, Level: slog.LevelDebug}), // second handler: debug JSON log to file + ), + ), nil } -func (l debugFileLogger) Debug(msg string, args ...any) { - l.log.Debug(msg, args...) +type fileWriter struct { + fileHandler file.Handler +} - _ = l.fileHandler.Write(constants.CLIDebugLogFile, []byte(msg+"\n"), file.OptAppend) +// Write satisfies the io.Writer interface by writing a message to file. +func (l *fileWriter) Write(msg []byte) (int, error) { + err := l.fileHandler.Write(constants.CLIDebugLogFile, msg, file.OptAppend) + return len(msg), err } diff --git a/go.mod b/go.mod index ab69a22003..4870e40e37 100644 --- a/go.mod +++ b/go.mod @@ -111,6 +111,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/regclient/regclient v0.5.5 github.com/rogpeppe/go-internal v1.11.0 + github.com/samber/slog-multi v1.0.2 github.com/schollz/progressbar/v3 v3.13.1 github.com/siderolabs/talos/pkg/machinery v1.4.6 github.com/sigstore/rekor v1.2.2 @@ -152,6 +153,8 @@ require ( sigs.k8s.io/yaml v1.4.0 ) +require github.com/samber/lo v1.38.1 // indirect + require ( cloud.google.com/go v0.110.8 // indirect cloud.google.com/go/iam v1.1.2 // indirect diff --git a/go.sum b/go.sum index 3f6789fae1..2f8a184299 100644 --- a/go.sum +++ b/go.sum @@ -894,6 +894,10 @@ github.com/rubenv/sql-migrate v1.5.2 h1:bMDqOnrJVV/6JQgQ/MxOpU+AdO8uzYYA/TxFUBzF github.com/rubenv/sql-migrate v1.5.2/go.mod h1:H38GW8Vqf8F0Su5XignRyaRcbXbJunSWxs+kmzlg0Is= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= +github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= +github.com/samber/slog-multi v1.0.2 h1:6BVH9uHGAsiGkbbtQgAOQJMpKgV8unMrHhhJaw+X1EQ= +github.com/samber/slog-multi v1.0.2/go.mod h1:uLAvHpGqbYgX4FSL0p1ZwoLuveIAJvBECtE07XmYvFo= github.com/sassoftware/relic v7.2.1+incompatible h1:Pwyh1F3I0r4clFJXkSI8bOyJINGqpgjJU3DYAZeI05A= github.com/sassoftware/relic v7.2.1+incompatible/go.mod h1:CWfAxv73/iLZ17rbyhIEq3K9hs5w6FpNMdUT//qR+zk= github.com/sassoftware/relic/v7 v7.5.5 h1:2ZUM6ovo3STCAp0hZnO9nQY9lOB8OyfneeYIi4YUxMU=