Skip to content

Commit

Permalink
Apply fixes, apply suggestions
Browse files Browse the repository at this point in the history
  • Loading branch information
mszostok committed Jul 13, 2023
1 parent 76f349e commit 1c09236
Show file tree
Hide file tree
Showing 10 changed files with 39 additions and 60 deletions.
2 changes: 1 addition & 1 deletion cmd/cli/cmd/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func NewInstall() *cobra.Command {
flags.StringVar(&opts.HelmParams.Version, "version", install.LatestVersionTag, "Botkube version. Possible values @latest, 1.2.0, ...")
flags.StringVar(&opts.HelmParams.Namespace, "namespace", install.Namespace, "Botkube installation namespace.")
flags.StringVar(&opts.HelmParams.ReleaseName, "release-name", install.ReleaseName, "Botkube Helm chart release name.")
flags.StringVar(&opts.HelmParams.ChartName, "chart-name", "botkube", "Botkube Helm chart name.")
flags.StringVar(&opts.HelmParams.ChartName, "chart-name", install.HelmChartName, "Botkube Helm chart name.")
flags.StringVar(&opts.HelmParams.RepoLocation, "repo", install.HelmRepoStable, fmt.Sprintf("Botkube Helm chart repository location. It can be relative path to current working directory or URL. Use %s tag to select repository which holds the stable Helm chart versions.", install.StableVersionTag))
flags.BoolVar(&opts.HelmParams.DryRun, "dry-run", false, "Simulate an install")
flags.BoolVar(&opts.HelmParams.Force, "force", false, "Force resource updates through a replacement strategy")
Expand Down
4 changes: 3 additions & 1 deletion internal/cli/install/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ const (
ReleaseName = "botkube"
// HelmRepoStable URL of the stable Botkube Helm charts repository.
HelmRepoStable = "https://charts.botkube.io/"
// HelmChartName represents Botkube Helm chart name in a given Helm repository.
HelmChartName = "botkube"
// LocalChartsPath path to Helm charts in botkube repository.
LocalChartsPath = "./helm/botkube/"
LocalChartsPath = "./helm/"
)

// Config holds parameters for Botkube installation on cluster.
Expand Down
12 changes: 9 additions & 3 deletions internal/cli/install/helm/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"errors"
"fmt"
"os"
"path"
"strings"
"time"

"github.com/AlecAivazis/survey/v2"
Expand All @@ -20,6 +20,7 @@ import (
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/rest"

"github.com/kubeshop/botkube/internal/cli"
"github.com/kubeshop/botkube/internal/cli/install/iox"
"github.com/kubeshop/botkube/internal/cli/printer"
"github.com/kubeshop/botkube/internal/ptr"
Expand Down Expand Up @@ -116,7 +117,8 @@ func (c *Helm) getChart(repoLocation string, chartName string, version string) (
}

if isLocalDir(repoLocation) {
location = path.Join(repoLocation, chartName)
repoLocation = strings.TrimSuffix(repoLocation, "/")
location = fmt.Sprintf("%s/%s", repoLocation, chartName)
chartOptions.RepoURL = ""
}

Expand Down Expand Up @@ -192,7 +194,11 @@ func getConfiguration(k8sCfg *rest.Config, forNamespace string) (*action.Configu
}

debugLog := func(format string, v ...interface{}) {
// noop
if cli.VerboseMode.IsTracing() {
fmt.Print(" Helm log: ") // if enabled, we need to nest that under Helm step which was already printed with 2 spaces.
fmt.Printf(format, v...)
fmt.Println()
}
}

err := actionConfig.Init(helmCfg, forNamespace, helmDriver, debugLog)
Expand Down
22 changes: 11 additions & 11 deletions internal/cli/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,16 +78,16 @@ func Install(ctx context.Context, w io.Writer, k8sCfg *kubex.ConfigWithMeta, opt
return err
}

timeBeforeInstall := time.Now()
parallel, _ := errgroup.WithContext(ctxWithTimeout)

podScheduledIndicator := make(chan string)
podWaitResult := make(chan error, 1)
parallel.Go(func() error {
err := kubex.WaitForPod(ctxWithTimeout, clientset, opts.HelmParams.Namespace, opts.HelmParams.ReleaseName, kubex.PodReady(podScheduledIndicator, time.Now()))
err := kubex.WaitForPod(ctxWithTimeout, clientset, opts.HelmParams.Namespace, opts.HelmParams.ReleaseName, kubex.PodReady(podScheduledIndicator, timeBeforeInstall))
podWaitResult <- err
return nil
})

rel, err := helmInstaller.Install(ctxWithTimeout, status, opts.HelmParams)
if err != nil {
return err
Expand All @@ -107,7 +107,7 @@ func Install(ctx context.Context, w io.Writer, k8sCfg *kubex.ConfigWithMeta, opt
select {
case podName = <-podScheduledIndicator:
status.End(true)
case <-time.After(opts.Timeout):
case <-ctxWithTimeout.Done():
return fmt.Errorf("Timed out waiting for Pod")
}

Expand All @@ -123,10 +123,6 @@ func Install(ctx context.Context, w io.Writer, k8sCfg *kubex.ConfigWithMeta, opt
podName,
)

parallel.Go(func() error {
logsPrinter.Start(ctxWithTimeout, status)
return nil
})
parallel.Go(func() error {
for {
select {
Expand All @@ -140,17 +136,19 @@ func Install(ctx context.Context, w io.Writer, k8sCfg *kubex.ConfigWithMeta, opt
}
})

status.InfoWithBody("Streaming logs...", indent.String(fmt.Sprintf("Pod: %s\n", podName), 4))

parallel.Go(func() error {
for {
select {
case <-ctxWithTimeout.Done(): // it's canceled on OS signals or if function passed to 'Go' method returns a non-nil error
return ctxWithTimeout.Err()
case entry, ok := <-messages:
if !ok {
logsPrinter.Stop()
status.Infof("Finished logs streaming")
return nil
}
logsPrinter.AppendLogEntry(string(entry))
logsPrinter.PrintLine(string(entry))
}
}
})
Expand Down Expand Up @@ -204,15 +202,17 @@ var failedInstallGoTpl = `
│ kubectl logs -n {{ .Namespace }} pod/{{ .PodName }}
│ To receive assistance, please join our Slack community at {{ .SlackURL | Underline | Blue }}.
│ We'll be glad to help you get Botkube up and running!
│ To resolve the issue, see Botkube documentation on {{ .DocsURL | Underline | Blue }}.
| If that doesn't help, join our Slack community at {{ .SlackURL | Underline | Blue }}.
│ We'll be glad to get your Botkube up and running!
`

func printFailedInstallMessage(version string, namespace string, name string, w io.Writer) error {
renderer := style.NewGoTemplateRender(style.DefaultConfig(failedInstallGoTpl))

props := map[string]string{
"SlackURL": "https://join.botkube.io",
"DocsURL": "https://docs.botkube.io",
"Version": version,
"Namespace": namespace,
"PodName": name,
Expand Down
2 changes: 1 addition & 1 deletion internal/cli/install/logs/json_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func (j *JSONParser) ParseLineIntoCharm(line string) ([]any, charmlog.Level) {
sort.Strings(keys)
for _, k := range keys {
switch k {
case "level", "msg", "time": // already process
case "level", "msg", "time": // already processed
continue
case "component", "url":
if !cli.VerboseMode.IsEnabled() {
Expand Down
49 changes: 7 additions & 42 deletions internal/cli/install/logs/printer.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
package logs

import (
"context"
"fmt"
"os"
"strings"

"github.com/charmbracelet/log"
charmlog "github.com/charmbracelet/log"
"github.com/morikuni/aec"
"github.com/muesli/reflow/indent"

"github.com/kubeshop/botkube/internal/cli"
"github.com/kubeshop/botkube/internal/cli/printer"
)

// Printer knows how to print Botkube logs.
type Printer struct {
podName string
newLog chan string
Expand All @@ -36,55 +33,23 @@ func NewPrinter(podName string) *Printer {
}
}

// Start starts the log streaming process.
func (f *Printer) Start(ctx context.Context, status *printer.StatusPrinter) {
status.InfoWithBody("Streaming logs...", indent.String(fmt.Sprintf("Pod: %s", f.podName), 4))
fmt.Println()

for {
select {
case <-f.stop:
return
case <-ctx.Done():
status.Infof("Requested logs streaming cancel...")
return
case entry := <-f.newLog:
f.printLogs(entry)
}
}
}

// AppendLogEntry appends a log entry to the printer.
func (f *Printer) AppendLogEntry(entry string) {
if strings.TrimSpace(entry) == "" {
return
}
select {
case f.newLog <- entry:
default:
}
}

// Stop stops the printer.
func (f *Printer) Stop() {
close(f.stop)
}

func (f *Printer) printLogs(item string) {
fields, lvl := f.parser.ParseLineIntoCharm(item)
if fields == nil {
f.printLogLine(item)
func (f *Printer) PrintLine(line string) {
fields, lvl := f.parser.ParseLineIntoCharm(line)
if fields == nil { // it was not recognized as JSON log entry, so let's print it as plain text.
f.printLogLine(line)
return
}
if lvl == charmlog.DebugLevel && !cli.VerboseMode.IsEnabled() {
return
}

fmt.Print(aec.EraseLine(aec.EraseModes.Tail))
fmt.Print(aec.Column(6))
f.logger.With(fields...).Print(nil)
}

func (f *Printer) printLogLine(line string) {
fmt.Print(aec.EraseLine(aec.EraseModes.Tail))
fmt.Print(aec.Column(6))
fmt.Print(line)
}
4 changes: 4 additions & 0 deletions internal/cli/printer/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"time"

"github.com/fatih/color"
"github.com/morikuni/aec"
"k8s.io/apimachinery/pkg/util/duration"

"github.com/kubeshop/botkube/internal/cli"
Expand Down Expand Up @@ -105,6 +106,7 @@ func (s *StatusPrinter) Infof(format string, a ...interface{}) {
// Ensure that previously started step is finished. Without that we will mess up our output.
s.End(true)

fmt.Fprint(s.w, aec.Column(0))
fmt.Fprintf(s.w, " • %s\n", fmt.Sprintf(format, a...))
}

Expand All @@ -118,6 +120,7 @@ func (s *StatusPrinter) Debugf(format string, a ...interface{}) {
// Ensure that previously started step is finished. Without that we will mess up our output.
s.End(true)

fmt.Fprint(s.w, aec.Column(0))
fmt.Fprintf(s.w, " • %s\n", fmt.Sprintf(format, a...))
}

Expand All @@ -126,5 +129,6 @@ func (s *StatusPrinter) InfoWithBody(header, body string) {
// Ensure that previously started step is finished. Without that we will mess up our output.
s.End(true)

fmt.Fprint(s.w, aec.Column(0))
fmt.Fprintf(s.w, " • %s\n%s", header, body)
}
2 changes: 1 addition & 1 deletion internal/kubex/wait.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ var (
errPodRestartedWithError = errors.New("pod restarted with non zero exit code")
)

// PodReady returns true if the Pod is read.
// PodReady returns true if the Pod is ready.
func PodReady(podScheduledIndicator chan string, since time.Time) func(event watch.Event) (bool, error) {
informed := false
sinceK8sTime := metav1.NewTime(since)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ settings:
log:
level: error
disableColors: false
formatter: ""
informersResyncPeriod: 30m0s
kubeconfig: kubeconfig-from-env
saCredentialsPathPrefix: ""
Expand Down
1 change: 1 addition & 0 deletions pkg/execute/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ func TestConfigExecutorShowConfig(t *testing.T) {
log:
level: ""
disableColors: false
formatter: ""
informersResyncPeriod: 0s
kubeconfig: ""
saCredentialsPathPrefix: ""
Expand Down

0 comments on commit 1c09236

Please sign in to comment.