From 22e3dfa42c64e17837cfc0ad96ddb37766e9ad19 Mon Sep 17 00:00:00 2001 From: Antonin Stefanutti Date: Fri, 14 Jan 2022 15:28:48 +0100 Subject: [PATCH 1/2] fix(log): Structure keytool logs --- pkg/util/command.go | 67 ++++++++++++++++++++++++++++++++++++++++ pkg/util/jvm/keystore.go | 25 ++++++++++----- 2 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 pkg/util/command.go diff --git a/pkg/util/command.go b/pkg/util/command.go new file mode 100644 index 0000000000..70f9d44e87 --- /dev/null +++ b/pkg/util/command.go @@ -0,0 +1,67 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "bufio" + "context" + "os/exec" + + "golang.org/x/sync/errgroup" +) + +// RunAndLog starts the provided command, scans its standard and error outputs line by line, +// to feed the provided handlers, and waits until the scans complete and the command returns. +func RunAndLog(ctx context.Context, cmd *exec.Cmd, stdOutF func(string), stdErrF func(string)) (err error) { + stdOut, err := cmd.StdoutPipe() + if err != nil { + return + } + stdErr, err := cmd.StderrPipe() + if err != nil { + return + } + err = cmd.Start() + if err != nil { + return + } + g, _ := errgroup.WithContext(ctx) + g.Go(func() error { + scanner := bufio.NewScanner(stdOut) + for scanner.Scan() { + stdOutF(scanner.Text()) + } + return nil + }) + g.Go(func() error { + scanner := bufio.NewScanner(stdErr) + for scanner.Scan() { + stdErrF(scanner.Text()) + } + return nil + }) + err = g.Wait() + if err != nil { + return + } + err = cmd.Wait() + if err != nil { + return + } + return +} diff --git a/pkg/util/jvm/keystore.go b/pkg/util/jvm/keystore.go index eb055b2cc0..1b8bf2a73e 100644 --- a/pkg/util/jvm/keystore.go +++ b/pkg/util/jvm/keystore.go @@ -27,6 +27,16 @@ import ( "path" "strings" "time" + + "github.com/apache/camel-k/pkg/util" + "github.com/apache/camel-k/pkg/util/log" +) + +var ( + logger = log.WithName("keytool") + + loggerInfo = func(s string) { logger.Info(s) } + loggerError = func(s string) { logger.Error(nil, s) } ) func GenerateKeystore(ctx context.Context, keystoreDir, keystoreName, keystorePass string, data []byte) error { @@ -34,10 +44,9 @@ func GenerateKeystore(ctx context.Context, keystoreDir, keystoreName, keystorePa cmd := exec.CommandContext(ctx, "keytool", args...) cmd.Dir = keystoreDir cmd.Stdin = bytes.NewReader(data) - cmd.Stderr = os.Stderr - cmd.Stdout = os.Stdout - - err := cmd.Run() + // keytool logs info messages to stderr, as stdout is used to output results, + // otherwise it logs error messages to stdout. + err := util.RunAndLog(ctx, cmd, loggerError, loggerInfo) if err != nil { return err } @@ -51,10 +60,9 @@ func GenerateKeystore(ctx context.Context, keystoreDir, keystoreName, keystorePa args := strings.Fields(fmt.Sprintf("-importkeystore -noprompt -srckeystore %s -srcstorepass %s -destkeystore %s -deststorepass %s", caCertsPath, "changeit", keystoreName, keystorePass)) cmd := exec.CommandContext(ctx, "keytool", args...) cmd.Dir = keystoreDir - cmd.Stderr = os.Stderr - cmd.Stdout = os.Stdout - - err := cmd.Run() + // keytool logs info messages to stderr, as stdout is used to output results, + // otherwise it logs error messages to stdout. + err := util.RunAndLog(ctx, cmd, loggerError, loggerInfo) if err != nil { return err } @@ -63,6 +71,7 @@ func GenerateKeystore(ctx context.Context, keystoreDir, keystoreName, keystorePa return nil } +// NewKeystorePassword generates a random password. // The keytool CLI mandates a password at least 6 characters long // to access any key stores. func NewKeystorePassword() string { From fe8404ccba650f5509aa8b032bd368055d7487bc Mon Sep 17 00:00:00 2001 From: Antonin Stefanutti Date: Fri, 14 Jan 2022 15:33:03 +0100 Subject: [PATCH 2/2] chore(log): Better structured Maven logs --- pkg/util/maven/maven_command.go | 31 +------------------------------ pkg/util/maven/maven_log.go | 12 ++++++++++++ 2 files changed, 13 insertions(+), 30 deletions(-) diff --git a/pkg/util/maven/maven_command.go b/pkg/util/maven/maven_command.go index 96c819b8ba..908d81944e 100644 --- a/pkg/util/maven/maven_command.go +++ b/pkg/util/maven/maven_command.go @@ -18,7 +18,6 @@ limitations under the License. package maven import ( - "bufio" "context" "fmt" "io" @@ -124,35 +123,7 @@ func (c *Command) Do(ctx context.Context) error { Log.WithValues("MAVEN_OPTS", mavenOptions).Infof("executing: %s", strings.Join(cmd.Args, " ")) - stdOut, err := cmd.StdoutPipe() - if err != nil { - return err - } - - err = cmd.Start() - - if err != nil { - return err - } - - scanner := bufio.NewScanner(stdOut) - - Log.Debug("About to start parsing the Maven output") - for scanner.Scan() { - line := scanner.Text() - mavenLog, parseError := parseLog(line) - if parseError == nil { - normalizeLog(mavenLog) - } else { - // Why we are ignoring the parsing errors here: there are a few scenarios where this would likely occur. - // For example, if something outside of Maven outputs something (i.e.: the JDK, a misbehaved plugin, - // etc). The build may still have succeeded, though. - nonNormalizedLog(line) - } - } - Log.Debug("Finished parsing Maven output") - - return cmd.Wait() + return util.RunAndLog(ctx, cmd, mavenLogHandler, mavenLogHandler) } func NewContext(buildDir string) Context { diff --git a/pkg/util/maven/maven_log.go b/pkg/util/maven/maven_log.go index c7f6b6b745..0ed0c84f98 100644 --- a/pkg/util/maven/maven_log.go +++ b/pkg/util/maven/maven_log.go @@ -47,6 +47,18 @@ const ( var mavenLogger = log.WithName("maven.build") +func mavenLogHandler(s string) { + mavenLog, parseError := parseLog(s) + if parseError == nil { + normalizeLog(mavenLog) + } else { + // Why we are ignoring the parsing errors here: there are a few scenarios where this would likely occur. + // For example, if something outside of Maven outputs something (i.e.: the JDK, a misbehaved plugin, + // etc). The build may still have succeeded, though. + nonNormalizedLog(s) + } +} + func parseLog(line string) (l mavenLog, err error) { err = json.Unmarshal([]byte(line), &l) return