Skip to content

Commit

Permalink
fix: run output, permission setting, healthcheck timeout
Browse files Browse the repository at this point in the history
  • Loading branch information
23doors committed Aug 31, 2021
1 parent 70001c1 commit 27c2e1d
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 66 deletions.
8 changes: 4 additions & 4 deletions cmd/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func setupEnvVars(env *cli.Environment) {
env.AddVarWithDefault("log_level", "set logging level: debug | warn | error", "warn")
}

func (e *Executor) commandPreRun() error {
func (e *Executor) commandPreRun(ctx context.Context) error {
var skipLoadConfig, skipLoadPlugins, skipCheckConfig bool

e.opts.env = e.v.GetString("env")
Expand Down Expand Up @@ -91,15 +91,15 @@ func (e *Executor) commandPreRun() error {

cfgPath := fileutil.FindYAMLGoingUp(pwd, config.ProjectYAMLName)

v, err := e.opts.valueOpts.MergeValues(cmd.Context(), filepath.Dir(cfgPath), getter.All())
v, err := e.opts.valueOpts.MergeValues(ctx, filepath.Dir(cfgPath), getter.All())
if err != nil && (len(e.opts.valueOpts.ValueFiles) != 1 || e.opts.valueOpts.ValueFiles[0] != defValuesYAML) {
return err
}

vals := map[string]interface{}{"var": v}

// Load config file.
if err := e.loadProjectConfig(cmd.Context(), cfgPath, vals, skipLoadPlugins, skipCheckConfig); err != nil && !errors.Is(err, config.ErrProjectConfigNotFound) {
if err := e.loadProjectConfig(ctx, cfgPath, vals, skipLoadPlugins, skipCheckConfig); err != nil && !errors.Is(err, config.ErrProjectConfigNotFound) {
return err
}

Expand Down Expand Up @@ -153,7 +153,7 @@ func (e *Executor) Execute(ctx context.Context) error {
return err
}

if err := e.commandPreRun(); err != nil {
if err := e.commandPreRun(ctx); err != nil {
return err
}

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ require (
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/mapstructure v1.4.1 // indirect
github.com/otiai10/copy v1.6.0
github.com/outblocks/outblocks-plugin-go v0.0.0-20210827220856-7521c046d330
github.com/outblocks/outblocks-plugin-go v0.0.0-20210831215844-947852a3f59a
github.com/pelletier/go-toml v1.9.1 // indirect
github.com/pterm/pterm v0.12.29
github.com/spf13/afero v1.6.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,8 @@ github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
github.com/otiai10/mint v1.3.2 h1:VYWnrP5fXmz1MXvjuUvcBrXSjGE6xjON+axB/UrpO3E=
github.com/otiai10/mint v1.3.2/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
github.com/outblocks/outblocks-plugin-go v0.0.0-20210827220856-7521c046d330 h1:4gB4dw6qZ1+HoJeteJzoDGQptbmTI2ru3czTnNbjOyc=
github.com/outblocks/outblocks-plugin-go v0.0.0-20210827220856-7521c046d330/go.mod h1:vAn4Vv7fXTyrjNEvAVcKtKJ2Bwaqk3Oy63lqnBRIct4=
github.com/outblocks/outblocks-plugin-go v0.0.0-20210831215844-947852a3f59a h1:+9QqJsvrNYvkh8WhEj1ocgHz1MpBvbblrkCFVxrRCmk=
github.com/outblocks/outblocks-plugin-go v0.0.0-20210831215844-947852a3f59a/go.mod h1:50dr9Bbwu7d8RpOAIU4+lS+wTchPBuAmPlt/D9gRgWA=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.9.1 h1:a6qW1EVNZWH9WGI6CsYdD8WAylkoXBS5yv0XHlh17Tc=
Expand Down
121 changes: 75 additions & 46 deletions pkg/actions/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package actions

import (
"context"
"errors"
"fmt"
"net/http"
"net/http/httputil"
Expand All @@ -22,6 +23,7 @@ import (
plugin_go "github.com/outblocks/outblocks-plugin-go"
"github.com/outblocks/outblocks-plugin-go/types"
plugin_util "github.com/outblocks/outblocks-plugin-go/util"
"github.com/outblocks/outblocks-plugin-go/util/errgroup"
"github.com/pterm/pterm"
"github.com/txn2/txeh"
)
Expand Down Expand Up @@ -54,10 +56,11 @@ type runInfo struct {
}

const (
loopbackHost = "outblocks.host"
loopbackIP = "127.0.0.1"
cleanupTimeout = 10 * time.Second
healthcheckSleep = 1 * time.Second
loopbackHost = "outblocks.host"
loopbackIP = "127.0.0.1"
cleanupTimeout = 10 * time.Second
healthcheckSleep = 1 * time.Second
healthcheckTimeout = 3 * time.Second
)

func NewRun(log logger.Logger, cfg *config.Project, opts *RunOptions) *Run {
Expand Down Expand Up @@ -366,11 +369,11 @@ func (d *Run) runAll(ctx context.Context, runInfo *runInfo) ([]*run.PluginRunRes
func (d *Run) waitAll(ctx context.Context, runInfo *runInfo) error {
spinner, _ := d.log.Spinner().WithRemoveWhenDone(true).Start("Waiting for apps and dependencies to be up...")

var wg sync.WaitGroup

httpClient := &http.Client{}
httpClient := &http.Client{
Timeout: healthcheckTimeout,
}

wg.Add(len(runInfo.apps))
g, _ := errgroup.WithContext(ctx)

for _, app := range runInfo.apps {
app := app
Expand All @@ -380,51 +383,88 @@ func (d *Run) waitAll(ctx context.Context, runInfo *runInfo) error {
return err
}

go func() {
g.Go(func() error {
for {
resp, err := httpClient.Do(req)
if errors.Is(err, context.Canceled) {
return err
}

if err == nil {
_ = resp.Body.Close()

d.log.Printf("%s App '%s' is UP.\n", strings.Title(app.App.Type), app.App.Name)
wg.Done()

return
return nil
}

time.Sleep(healthcheckSleep)
}
}()
})
}

wg.Wait()

err := g.Wait()
_ = spinner.Stop()

return nil
return err
}

func formatRunOutput(log logger.Logger, r *plugin_go.RunOutputResponse) {
msg := plugin_util.StripAnsi(r.Message)

switch r.Source {
case plugin_go.RunOutpoutSourceApp:
if r.IsStderr {
log.StderrPrintf("%s %s\n", pterm.FgRed.Sprintf("APP:%s:", r.Name), r.Message)
log.Printf("%s %s\n", pterm.FgRed.Sprintf("APP:%s:", r.Name), msg)
} else {
log.Printf("%s %s\n", pterm.FgGreen.Sprintf("APP:%s:", r.Name), r.Message)
log.Printf("%s %s\n", pterm.FgGreen.Sprintf("APP:%s:", r.Name), msg)
}
case plugin_go.RunOutpoutSourceDependency:
if r.IsStderr {
log.StderrPrintf("%s %s\n", pterm.FgRed.Sprintf("DEP:%s:", r.Name), r.Message)
log.Printf("%s %s\n", pterm.FgRed.Sprintf("DEP:%s:", r.Name), msg)
} else {
log.Printf("%s %s\n", pterm.FgGreen.Sprintf("DEP:%s:", r.Name), r.Message)
log.Printf("%s %s\n", pterm.FgGreen.Sprintf("DEP:%s:", r.Name), msg)
}
}
}

func (d *Run) addAllHosts(runInfo *runInfo) (map[*url.URL]*url.URL, error) {
hosts := map[string]struct{}{
d.loopbackHost(): {},
}

routing := make(map[*url.URL]*url.URL)

for _, s := range runInfo.apps {
u, _ := url.Parse(s.URL)
hosts[u.Hostname()] = struct{}{}

uLocal := *u
uLocal.Host = fmt.Sprintf("%s:%d", s.IP, s.Port)
uLocal.Path = s.App.PathRedirect

routing[u] = &uLocal
}

hostsList := make([]string, 0, len(hosts))

for h := range hosts {
hostsList = append(hostsList, h)
}

err := d.AddHosts(hostsList...)
if err != nil {
return nil, fmt.Errorf("are you running with sudo? or try running with hosts-routing disabled")
}

return routing, nil
}

func (d *Run) start(ctx context.Context, runInfo *runInfo) (*sync.WaitGroup, error) {
var (
wg sync.WaitGroup
routing map[*url.URL]*url.URL
err error
)

errCh := make(chan error, 1)
Expand All @@ -433,32 +473,9 @@ func (d *Run) start(ctx context.Context, runInfo *runInfo) (*sync.WaitGroup, err
defer runnerCancel()

if d.opts.HostsRouting {
hosts := map[string]struct{}{
d.loopbackHost(): {},
}

routing = make(map[*url.URL]*url.URL)

for _, s := range runInfo.apps {
u, _ := url.Parse(s.URL)
hosts[u.Hostname()] = struct{}{}

uLocal := *u
uLocal.Host = fmt.Sprintf("%s:%d", s.IP, s.Port)
uLocal.Path = s.App.PathRedirect

routing[u] = &uLocal
}

hostsList := make([]string, 0, len(hosts))

for h := range hosts {
hostsList = append(hostsList, h)
}

err := d.AddHosts(hostsList...)
routing, err = d.addAllHosts(runInfo)
if err != nil {
return &wg, fmt.Errorf("are you running with sudo? or try running with hosts-routing disabled")
return &wg, err
}
}

Expand Down Expand Up @@ -543,9 +560,15 @@ func (d *Run) start(ctx context.Context, runInfo *runInfo) (*sync.WaitGroup, err
}

// Healthcheck.
err = d.waitAll(ctx, runInfo)
err = d.waitAll(runnerCtx, runInfo)
if err != nil {
return nil, err
select {
case err := <-errCh:
return &wg, err
default:
}

return &wg, err
}

// Show apps status.
Expand All @@ -556,6 +579,8 @@ func (d *Run) start(ctx context.Context, runInfo *runInfo) (*sync.WaitGroup, err
d.log.Printf("%s App '%s' listening at %s\n", strings.Title(a.App.Type), a.App.Name, a.URL)
}

d.log.Println()

<-runnerCtx.Done()

select {
Expand Down Expand Up @@ -585,6 +610,10 @@ func (d *Run) Run(ctx context.Context) error {
if err != nil {
wg.Wait()

if errors.Is(err, context.Canceled) {
return nil
}

return err
}

Expand Down
16 changes: 8 additions & 8 deletions pkg/actions/run/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,14 @@ func RunLocal(ctx context.Context, localApps []*LocalApp, localDeps []*LocalDepe
ret.Apps[app.App.ID] = info
}

for _, dep := range localDeps {
info, err := dep.Run()
if err != nil {
return nil, err
}

ret.Deps[dep.Dependency.ID] = info
}
// for _, dep := range localDeps {
// info, err := dep.Run()
// if err != nil {
// return nil, err
// }

// ret.Deps[dep.Dependency.ID] = info
// }

return ret, nil
}
2 changes: 1 addition & 1 deletion pkg/plugins/downloader_vcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func (d *VCSDownloader) fetch(_ context.Context, pi *pluginInfo) (vcs.Repo, erro
return nil, fmt.Errorf("cannot find source repo: %w", err)
}

return repo, nil
return repo, plugin_util.LchownRToUser(cachePath)
}

func (d *VCSDownloader) download(ctx context.Context, pi *pluginInfo) (*DownloadedPlugin, string, error) {
Expand Down
6 changes: 2 additions & 4 deletions pkg/plugins/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ func (l *Loader) downloadPlugin(ctx context.Context, pi *pluginInfo) (string, *s
return "", nil, fmt.Errorf("failed to copy downloaded plugin %s: %w", destPath, err)
}

if err := plugin_util.ChownRToUser(destPath); err != nil {
if err := plugin_util.LchownRToUser(destPath); err != nil {
return "", nil, fmt.Errorf("failed to set permissions on downloaded plugin %s: %w", destPath, err)
}

Expand Down Expand Up @@ -222,11 +222,9 @@ func (l *Loader) installPlugin(pi *pluginInfo, from string) error {
if err := copy.Copy(from, dest); err != nil {
return fmt.Errorf("failed to copy cached plugin %s: %w", from, err)
}

return plugin_util.ChownRToUser(dest)
}

return nil
return plugin_util.LchownRToUser(dest)
}

func (l *Loader) loadPlugin(pi *pluginInfo, path string, ver *semver.Version) (*Plugin, error) {
Expand Down

0 comments on commit 27c2e1d

Please sign in to comment.