Skip to content

Commit

Permalink
fix: handle service exit code 137 as success
Browse files Browse the repository at this point in the history
  • Loading branch information
kameshsampath committed Oct 27, 2022
1 parent a1532ca commit c0c5021
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 34 deletions.
2 changes: 1 addition & 1 deletion backend/pkg/drone/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ func exec(cliContext *cli.Context) error {
}
step.Labels = labels.Combine(step.Labels, extraLabels)

log.Infof("Step %s, Labels: %#v", step.Name, step.Labels)
log.Tracef("Step %s, Labels: %#v", step.Name, step.Labels)
}

// include only steps that are in the include list,
Expand Down
115 changes: 115 additions & 0 deletions backend/pkg/drone/flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright 2019 Drone.IO Inc. All rights reserved.
// Use of this source code is governed by the Polyform License
// that can be found in the LICENSE file.

package drone

import (
"strings"

"github.com/drone-runners/drone-runner-docker/engine/compiler"
"github.com/drone/drone-go/drone"
"github.com/joho/godotenv"
"github.com/urfave/cli/v2"
)

// Flags maps
type Flags struct {
Build *drone.Build
Netrc *drone.Netrc
Repo *drone.Repo
Stage *drone.Stage
System *drone.System
}

type execCommand struct {
*Flags

Source string
Include []string
Exclude []string
Privileged []string
Networks []string
Volumes map[string]string
Environ map[string]string
Labels map[string]string
Secrets map[string]string
Resources compiler.Resources
Tmate compiler.Tmate
Clone bool
Config string
Pretty bool
Procs int64
Debug bool
Trace bool
Dump bool
PublicKey string
PrivateKey string
}

func toExecCommand(input *cli.Context) (returnVal *execCommand) {
pipelineFile := input.Args().First()
if pipelineFile == "" {
pipelineFile = ".drone.yml"
}
returnVal = &execCommand{
Flags: &Flags{
Build: &drone.Build{
Event: input.String("event"),
Ref: input.String("ref"),
Deploy: input.String("deploy-to"),
Target: input.String("branch"),
},
Repo: &drone.Repo{
Trusted: input.Bool("trusted"),
Timeout: int64(input.Duration("timeout").Seconds()),
Branch: input.String("branch"),
Name: input.String("name"),
},
Stage: &drone.Stage{
Name: input.String("pipeline"),
},
Netrc: &drone.Netrc{
Machine: input.String("netrc-machine"),
Login: input.String("netrc-username"),
Password: input.String("netrc-password"),
},
System: &drone.System{
Host: input.String("instance"),
},
},
Source: pipelineFile,
Include: input.StringSlice("include"),
Exclude: input.StringSlice("exclude"),
Clone: input.Bool("clone"),
Networks: input.StringSlice("network"),
Environ: readParams(input.String("env-file")),
Volumes: withVolumeSlice(input.StringSlice("volume")),
Secrets: readParams(input.String("secret-file")),
Config: input.String("registry"),
Privileged: input.StringSlice("privileged"),
}

return returnVal
}

// WithVolumeSlice is a transform function that adds a set of global volumes to the container that are defined in --volume=host:container format.
func withVolumeSlice(volumes []string) (to map[string]string) {
to = map[string]string{}
for _, s := range volumes {
parts := strings.Split(s, ":")
if len(parts) != 2 {
continue
}
key := parts[0]
val := parts[1]
to[key] = val
}
return to
}

// helper function reads secrets from a key-value file.
func readParams(path string) map[string]string {
data, _ := godotenv.Read(path)
return data
}
43 changes: 24 additions & 19 deletions backend/pkg/monitor/pipeline_monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,12 @@ func New(ctx context.Context, db *bun.DB, log *logrus.Logger, options ...Option)
filters.Add("type", events.ContainerEventType)
filters.Add("event", "start")
filters.Add("event", "die")
filters.Add("event", "kill")
filters.Add("event", "destroy")
filters.Add("scope", "local")
filters.Add("label", labelPipelineFile)
filters.Add("label", labelStageName)
filters.Add("label", labelStepName)
filters.Add("label", LabelPipelineFile)
filters.Add("label", LabelStageName)
filters.Add("label", LabelStepName)

//TODO add since flag to filter events since the app started

Expand Down Expand Up @@ -88,22 +90,23 @@ func (c *Config) MonitorAndLog() {

case msg := <-msgCh:
actor := msg.Actor
log.Debugf("Message \n%#v\n", msg)
go func(actor events.Actor, msg events.Message) {
log.Tracef("Actor \n%#v\n", actor)
pipelineFile := actor.Attributes[labelPipelineFile]
//log.Infof("Actor \n%#v\n", actor)
pipelineFile := actor.Attributes[LabelPipelineFile]
var includes, excludes []string
if v, ok := actor.Attributes[labelIncludes]; ok {
if v, ok := actor.Attributes[LabelIncludes]; ok {
if v != "" {
includes = strings.Split(v, ",")
}
}
if v, ok := actor.Attributes[labelExcludes]; ok {
if v, ok := actor.Attributes[LabelExcludes]; ok {
if v != "" {
excludes = strings.Split(v, ",")
}
}
stageName := actor.Attributes[labelStageName]
stepName := actor.Attributes[labelStepName]
stageName := actor.Attributes[LabelStageName]
stepName := actor.Attributes[LabelStepName]
var stage = &db.Stage{}
count, err := dbConn.NewSelect().
Model(stage).
Expand Down Expand Up @@ -133,8 +136,8 @@ func (c *Config) MonitorAndLog() {
}
switch msg.Status {
case "start":
log.Infof("Starting Step Name %s", stepName)
go c.writeLogs(pipelineLogPath, actor.Attributes)
log.Infof("Starting Step Name %s", stepName)
//Resetting the status of the steps
//All steps from the current step identified by stepName
//are set to status == db.None
Expand All @@ -150,19 +153,21 @@ func (c *Config) MonitorAndLog() {
log.Infof("Dying Step Name %s, attributes %#v", stepName, actor.Attributes)
stepIdx := getRunningStepIndex(stage, stepName)
var stepStatus db.Status
if actor.Attributes["exitCode"] == "0" {
switch actor.Attributes["exitCode"] {
case "0":
case "137":
stepStatus = db.Success
} else {
default:
stepStatus = db.Error
}
stage.Steps[stepIdx].Status = stepStatus
//update the overall stage status only if the current step is last step or any error occurred
c.updateStatuses(stage, (stepIdx == len(stage.Steps)-1 || stepStatus == db.Error))
c.updateStatuses(stage, stepIdx == len(stage.Steps)-1 || stepStatus == db.Error)
default:
//no requirement to handle other cases
}
} else {
c.MonitorErrors <- fmt.Errorf("unable to find stage %s ", stageName)
c.MonitorErrors <- fmt.Errorf("unable to find stage %s in pipeline %s", stageName, pipelineFile)
}
}(actor, msg)
}
Expand Down Expand Up @@ -213,7 +218,7 @@ func (c *Config) updateStatuses(stage *db.Stage, updateStage bool) {
dbConn := c.DB
log := c.Log
if err := dbConn.RunInTx(c.Ctx, &sql.TxOptions{}, func(ctx context.Context, tx bun.Tx) error {
log.Infof("Updating Status for stage %s of pipeline %s", stage.Name, stage.PipelineFile)
log.Infof("Updating Statuses for stage %s of pipeline %s", stage.Name, stage.PipelineFile)

if err := updateStepStatus(c.Ctx, dbConn, stage.Steps); err != nil {
return err
Expand Down Expand Up @@ -278,19 +283,19 @@ func (c *Config) writeLogs(pipelineLogPath string, attrs map[string]string) {
c.Log.Tracef("Actor Attributes %#v", attrs)
out, err := c.DockerCli.ContainerLogs(c.Ctx, attrs["name"], options)
if err != nil {
err := fmt.Errorf("error getting logs for container %s, %w ", attrs[labelStepName], err)
err := fmt.Errorf("error getting logs for container %s, %w ", attrs[LabelStepName], err)
log.Error(err)
c.MonitorErrors <- err
} else {
containerLogPath := path.Join(pipelineLogPath, fmt.Sprintf("%s.log", utils.Md5OfString(attrs[labelStepName])))
containerLogPath := path.Join(pipelineLogPath, fmt.Sprintf("%s.log", utils.Md5OfString(attrs[LabelStepName])))
f, err := os.OpenFile(containerLogPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
err := fmt.Errorf("error writing logs for container %s, %w ", attrs[labelStepName], err)
err := fmt.Errorf("error writing logs for container %s, %w ", attrs[LabelStepName], err)
log.Error(err)
c.MonitorErrors <- err
} else {
if _, err := io.Copy(f, out); err != nil {
err := fmt.Errorf("error copying logs for container %s, %w ", attrs[labelStepName], err)
err := fmt.Errorf("error copying logs for container %s, %w ", attrs[LabelStepName], err)
log.Error(err)
c.MonitorErrors <- err
}
Expand Down
21 changes: 15 additions & 6 deletions backend/pkg/monitor/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"github.com/uptrace/bun"
)

//Config configures the monitor to initialize
// Config configures the monitor to initialize
type Config struct {
Ctx context.Context
Log *logrus.Logger
Expand All @@ -29,9 +29,18 @@ type Monitor interface {
type Option func(*Config)

const (
labelPipelineFile = "io.drone.desktop.pipeline.file"
labelIncludes = "io.drone.desktop.pipeline.includes"
labelExcludes = "io.drone.desktop.pipeline.excludes"
labelStageName = "io.drone.stage.name"
labelStepName = "io.drone.step.name"
//LabelPipelineFile is to identify the pipeline file
LabelPipelineFile = "io.drone.desktop.pipeline.file"
//LabelIncludes is to hold list of included steps as comma separated string
LabelIncludes = "io.drone.desktop.pipeline.includes"
//LabelExcludes is to hold list of excluded steps as comma separated string
LabelExcludes = "io.drone.desktop.pipeline.excludes"
//LabelStageName is to identify the stage name
LabelStageName = "io.drone.stage.name"
//LabelStepName is to identify the step name
LabelStepName = "io.drone.step.name"
//LabelStepNumber is to identify the step number
LabelStepNumber = "io.drone.step.number"
//LabelService to identify if the step is a "Service"
LabelService = "io.drone.desktop.pipeline.service"
)
2 changes: 1 addition & 1 deletion backend/pkg/utils/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func TriggerUIRefresh(ctx context.Context, cli *client.Client, log *logrus.Logge
},
}, &container.HostConfig{
AutoRemove: true,
}, nil, nil, "")
}, nil, "")
if err != nil {
return err
}
Expand Down
14 changes: 7 additions & 7 deletions backend/pkg/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"github.com/sirupsen/logrus"
)

//LogSetup sets up the logging for the application
// LogSetup sets up the logging for the application
func LogSetup(out io.Writer, level string) *logrus.Logger {
lvl, err := logrus.ParseLevel(level)

Expand All @@ -25,15 +25,15 @@ func LogSetup(out io.Writer, level string) *logrus.Logger {
TimestampFormat: "2006-01-02 15:15:10",
},
Out: out,
ReportCaller: true,
ReportCaller: false,
Level: lvl,
}

return log
}

//LookupEnvOrString looks up an environment variable if not found
//returns defaultVal
// LookupEnvOrString looks up an environment variable if not found
// returns defaultVal
func LookupEnvOrString(envName, defaultVal string) string {
if val, ok := os.LookupEnv(envName); ok {
return val
Expand All @@ -42,9 +42,9 @@ func LookupEnvOrString(envName, defaultVal string) string {
return defaultVal
}

//Md5OfString returns the md5 has of the string
//Its ok to use md5 hashing here as it just used
//for consistent and sanitized naming
// Md5OfString returns the md5 has of the string
// Its ok to use md5 hashing here as it just used
// for consistent and sanitized naming
func Md5OfString(str string) string {
return fmt.Sprintf("%x", md5.Sum([]byte(str)))
}

0 comments on commit c0c5021

Please sign in to comment.