Skip to content

Commit 61455d0

Browse files
authored
Merge pull request #5049 from camilamacedo86/fix-logs-moreplaces
🐛 (fix) reformat subprocess output for consistent logging during alpha commands (Follow up: #4968)
2 parents f49c452 + 3856f0e commit 61455d0

File tree

6 files changed

+86
-50
lines changed

6 files changed

+86
-50
lines changed

cmd/cmd.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ import (
3636
helmv1alpha1 "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v1alpha"
3737
)
3838

39-
func init() {
39+
// Run bootstraps & runs the CLI
40+
func Run() {
41+
// Initialize custom logging handler FIRST - applies to ALL CLI operations
4042
opts := logging.HandlerOptions{
4143
SlogOpts: slog.HandlerOptions{
4244
Level: slog.LevelInfo,
@@ -45,10 +47,6 @@ func init() {
4547
handler := logging.NewHandler(os.Stdout, opts)
4648
logger := slog.New(handler)
4749
slog.SetDefault(logger)
48-
}
49-
50-
// Run bootstraps & runs the CLI
51-
func Run() {
5250
// Bundle plugin which built the golang projects scaffold with base.go/v4 and kustomize/v2 plugins
5351
gov4Bundle, _ := plugin.NewBundleWithOptions(plugin.WithName(golang.DefaultNameQualifier),
5452
plugin.WithVersion(plugin.Version{Number: 4}),

pkg/cli/alpha/generate.go

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,8 @@ import (
2020
"github.com/spf13/cobra"
2121

2222
"sigs.k8s.io/kubebuilder/v4/pkg/cli/alpha/internal"
23-
"sigs.k8s.io/kubebuilder/v4/pkg/logging"
2423
)
2524

26-
func init() {
27-
// Initialize consistent logging for alpha commands
28-
opts := logging.HandlerOptions{
29-
SlogOpts: slog.HandlerOptions{
30-
Level: slog.LevelInfo,
31-
},
32-
}
33-
handler := logging.NewHandler(os.Stdout, opts)
34-
logger := slog.New(handler)
35-
slog.SetDefault(logger)
36-
}
37-
3825
// NewScaffoldCommand returns a new scaffold command, providing the `kubebuilder alpha generate`
3926
// feature to re-scaffold projects and assist users with updates.
4027
//

pkg/cli/alpha/internal/generate.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ package internal
1919
import (
2020
"errors"
2121
"fmt"
22-
log "log/slog"
22+
"log/slog"
2323
"os"
2424
"os/exec"
2525
"strings"
@@ -56,17 +56,17 @@ func (opts *Generate) Generate() error {
5656
}
5757
opts.OutputDir = cwd
5858
if _, err = os.Stat(opts.OutputDir); err == nil {
59-
log.Warn("Using current working directory to re-scaffold the project")
60-
log.Warn("This directory will be cleaned up and all files removed before the re-generation")
59+
slog.Warn("Using current working directory to re-scaffold the project")
60+
slog.Warn("This directory will be cleaned up and all files removed before the re-generation")
6161

6262
// Ensure we clean the correct directory
63-
log.Info("Cleaning directory", "dir", opts.OutputDir)
63+
slog.Info("Cleaning directory", "dir", opts.OutputDir)
6464

6565
// Use an absolute path to target files directly
6666
cleanupCmd := fmt.Sprintf("rm -rf %s/*", opts.OutputDir)
6767
err = util.RunCmd("Running cleanup", "sh", "-c", cleanupCmd)
6868
if err != nil {
69-
log.Error("Cleanup failed", "error", err)
69+
slog.Error("Cleanup failed", "error", err)
7070
return fmt.Errorf("cleanup failed: %w", err)
7171
}
7272

@@ -77,7 +77,7 @@ func (opts *Generate) Generate() error {
7777
)
7878
err = util.RunCmd("Running cleanup", "sh", "-c", cleanupCmd)
7979
if err != nil {
80-
log.Error("Cleanup failed", "error", err)
80+
slog.Error("Cleanup failed", "error", err)
8181
return fmt.Errorf("cleanup failed: %w", err)
8282
}
8383
}
@@ -123,13 +123,13 @@ func (opts *Generate) Generate() error {
123123

124124
// Run make targets to ensure the project is properly set up.
125125
// These steps are performed on a best-effort basis: if any of the targets fail,
126-
// we log a warning to inform the user, but we do not stop the process or return an error.
126+
// we slog a warning to inform the user, but we do not stop the process or return an error.
127127
// This is to avoid blocking the migration flow due to non-critical issues during setup.
128128
targets := []string{"manifests", "generate", "fmt", "vet", "lint-fix"}
129129
for _, target := range targets {
130130
err := util.RunCmd(fmt.Sprintf("Running make %s", target), "make", target)
131131
if err != nil {
132-
log.Warn("make target failed", "target", target, "error", err)
132+
slog.Warn("make target failed", "target", target, "error", err)
133133
}
134134
}
135135

@@ -220,7 +220,7 @@ func migrateGrafanaPlugin(s store.Store, src, des string) error {
220220
var grafanaPlugin struct{}
221221
err := s.Config().DecodePluginConfig(plugin.KeyFor(v1alpha.Plugin{}), grafanaPlugin)
222222
if errors.As(err, &config.PluginKeyNotFoundError{}) {
223-
log.Info("Grafana plugin not found, skipping migration")
223+
slog.Info("Grafana plugin not found, skipping migration")
224224
return nil
225225
} else if err != nil {
226226
return fmt.Errorf("failed to decode grafana plugin config: %w", err)
@@ -241,7 +241,7 @@ func migrateAutoUpdatePlugin(s store.Store) error {
241241
var autoUpdatePlugin struct{}
242242
err := s.Config().DecodePluginConfig(plugin.KeyFor(autoupdate.Plugin{}), autoUpdatePlugin)
243243
if errors.As(err, &config.PluginKeyNotFoundError{}) {
244-
log.Info("Auto Update plugin not found, skipping migration")
244+
slog.Info("Auto Update plugin not found, skipping migration")
245245
return nil
246246
} else if err != nil {
247247
return fmt.Errorf("failed to decode autoupdate plugin config: %w", err)
@@ -259,7 +259,7 @@ func migrateDeployImagePlugin(s store.Store) error {
259259
var deployImagePlugin v1alpha1.PluginConfig
260260
err := s.Config().DecodePluginConfig(plugin.KeyFor(v1alpha1.Plugin{}), &deployImagePlugin)
261261
if errors.As(err, &config.PluginKeyNotFoundError{}) {
262-
log.Info("Deploy-image plugin not found, skipping migration")
262+
slog.Info("Deploy-image plugin not found, skipping migration")
263263
return nil
264264
} else if err != nil {
265265
return fmt.Errorf("failed to decode deploy-image plugin config: %w", err)
@@ -300,7 +300,7 @@ func getInitArgs(s store.Store) []string {
300300
// Replace outdated plugins and exit after the first replacement
301301
for i, plg := range plugins {
302302
if newPlugin, exists := outdatedPlugins[plg]; exists {
303-
log.Warn("We checked that your PROJECT file is configured with deprecated layout. "+
303+
slog.Warn("We checked that your PROJECT file is configured with deprecated layout. "+
304304
"However, we will try our best to re-generate the project using new one",
305305
"deprecated_layout", plg,
306306
"new_layout", newPlugin)
@@ -503,8 +503,8 @@ func hasHelmPlugin(cfg store.Store) bool {
503503
if errors.As(err, &config.PluginKeyNotFoundError{}) {
504504
return false
505505
}
506-
// Log other errors if needed
507-
log.Error("error decoding Helm plugin config", "error", err)
506+
// slog other errors if needed
507+
slog.Error("error decoding Helm plugin config", "error", err)
508508
return false
509509
}
510510

pkg/cli/alpha/internal/update/helpers/git_commands.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ package helpers
1919
import (
2020
"errors"
2121
"fmt"
22-
log "log/slog"
22+
"log/slog"
2323
"os/exec"
2424
)
2525

@@ -30,7 +30,7 @@ func CommitIgnoreEmpty(msg, ctx string) error {
3030
var ee *exec.ExitError
3131
if errors.As(err, &ee) && ee.ExitCode() == 1 {
3232
// nothing to commit
33-
log.Info("No changes to commit", "context", ctx, "message", msg)
33+
slog.Info("No changes to commit", "context", ctx, "message", msg)
3434
return nil
3535
}
3636
return fmt.Errorf("git commit failed (%s): %w", ctx, err)

pkg/cli/alpha/internal/update/update.go

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,15 @@ limitations under the License.
1717
package update
1818

1919
import (
20+
"bufio"
2021
"bytes"
2122
"errors"
2223
"fmt"
24+
"io"
2325
log "log/slog"
2426
"os"
2527
"os/exec"
28+
"regexp"
2629
"strings"
2730
"time"
2831

@@ -503,10 +506,26 @@ func runAlphaGenerate(tempDir, version string) error {
503506
tempBinaryPath := tempDir + "/kubebuilder"
504507
cmd := exec.Command(tempBinaryPath, "alpha", "generate")
505508
cmd.Env = envWithPrefixedPath(tempDir)
506-
cmd.Stdout = os.Stdout
507-
cmd.Stderr = os.Stderr
508509

509-
if err := cmd.Run(); err != nil {
510+
// Capture and reformat subprocess output to match our logging style
511+
stdout, err := cmd.StdoutPipe()
512+
if err != nil {
513+
return fmt.Errorf("failed to create stdout pipe: %w", err)
514+
}
515+
stderr, err := cmd.StderrPipe()
516+
if err != nil {
517+
return fmt.Errorf("failed to create stderr pipe: %w", err)
518+
}
519+
520+
if err := cmd.Start(); err != nil {
521+
return fmt.Errorf("failed to start alpha generate: %w", err)
522+
}
523+
524+
// Forward output while reformatting old-style logs
525+
go forwardAndReformat(stdout, false)
526+
go forwardAndReformat(stderr, true)
527+
528+
if err := cmd.Wait(); err != nil {
510529
return fmt.Errorf("failed to run alpha generate: %w", err)
511530
}
512531

@@ -515,6 +534,51 @@ func runAlphaGenerate(tempDir, version string) error {
515534
return nil
516535
}
517536

537+
// forwardAndReformat reads from a subprocess stream and reformats old-style logging to new style
538+
func forwardAndReformat(reader io.Reader, isStderr bool) {
539+
scanner := bufio.NewScanner(reader)
540+
541+
// Regex to match old-style log format: level=info msg="message"
542+
logPattern := regexp.MustCompile(`^level=(\w+)\s+msg="?([^"]*)"?(.*)$`)
543+
544+
for scanner.Scan() {
545+
line := scanner.Text()
546+
547+
// Check if this line matches the old log format
548+
if matches := logPattern.FindStringSubmatch(line); matches != nil {
549+
level := strings.ToUpper(matches[1])
550+
message := matches[2]
551+
rest := matches[3]
552+
553+
// Convert to new format based on level
554+
switch level {
555+
case "INFO":
556+
log.Info(message + rest)
557+
case "WARN", "WARNING":
558+
log.Warn(message + rest)
559+
case "ERROR":
560+
log.Error(message + rest)
561+
case "DEBUG":
562+
log.Debug(message + rest)
563+
default:
564+
// Fallback: print as-is to appropriate stream
565+
if isStderr {
566+
fmt.Fprintln(os.Stderr, line)
567+
} else {
568+
fmt.Println(line)
569+
}
570+
}
571+
} else {
572+
// Not a log line, print as-is to appropriate stream
573+
if isStderr {
574+
fmt.Fprintln(os.Stderr, line)
575+
} else {
576+
fmt.Println(line)
577+
}
578+
}
579+
}
580+
}
581+
518582
func envWithPrefixedPath(dir string) []string {
519583
env := os.Environ()
520584
prefix := "PATH="

pkg/cli/alpha/update.go

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,8 @@ import (
2424
"github.com/spf13/cobra"
2525

2626
"sigs.k8s.io/kubebuilder/v4/pkg/cli/alpha/internal/update"
27-
"sigs.k8s.io/kubebuilder/v4/pkg/logging"
2827
)
2928

30-
func init() {
31-
// Initialize consistent logging for alpha commands
32-
opts := logging.HandlerOptions{
33-
SlogOpts: slog.HandlerOptions{
34-
Level: slog.LevelInfo,
35-
},
36-
}
37-
handler := logging.NewHandler(os.Stdout, opts)
38-
logger := slog.New(handler)
39-
slog.SetDefault(logger)
40-
}
41-
4229
// NewUpdateCommand creates and returns a new Cobra command for updating Kubebuilder projects.
4330
func NewUpdateCommand() *cobra.Command {
4431
opts := update.Update{}

0 commit comments

Comments
 (0)