github.com/justinjmoses/evergreen@v0.0.0-20170530173719-1d50e381ff0d/alerts/alerts_activation.go (about)

     1  package alerts
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/evergreen-ci/evergreen/model"
     7  	"github.com/evergreen-ci/evergreen/model/alert"
     8  	"github.com/evergreen-ci/evergreen/model/host"
     9  	"github.com/evergreen-ci/evergreen/model/task"
    10  	"github.com/evergreen-ci/evergreen/model/version"
    11  	"gopkg.in/mgo.v2/bson"
    12  )
    13  
    14  func RunLastRevisionNotFoundTrigger(proj *model.ProjectRef, v *version.Version) error {
    15  	ctx := triggerContext{
    16  		projectRef: proj,
    17  		version:    v,
    18  	}
    19  	trigger := LastRevisionNotFound{}
    20  	// only one trigger to act on for now
    21  	shouldExec, err := trigger.ShouldExecute(ctx)
    22  	if err != nil {
    23  		return err
    24  	}
    25  	if !shouldExec {
    26  		return nil
    27  	}
    28  	err = alert.EnqueueAlertRequest(&alert.AlertRequest{
    29  		Id:        bson.NewObjectId(),
    30  		Trigger:   trigger.Id(),
    31  		VersionId: v.Id,
    32  		CreatedAt: time.Now(),
    33  	})
    34  
    35  	if err != nil {
    36  		return err
    37  	}
    38  	return storeTriggerBookkeeping(ctx, []Trigger{trigger})
    39  }
    40  
    41  // RunTaskTriggers queues alerts for any active triggers on the tasks's state change.
    42  func RunTaskFailureTriggers(taskId string) error {
    43  	t, err := task.FindOne(task.ById(taskId))
    44  	if err != nil {
    45  		return err
    46  	}
    47  	ctx, err := getTaskTriggerContext(t)
    48  	if err != nil {
    49  		return err
    50  	}
    51  	activeTriggers, err := getActiveTaskFailureTriggers(*ctx)
    52  	if err != nil {
    53  		return err
    54  	}
    55  	for _, trigger := range activeTriggers {
    56  		req := &alert.AlertRequest{
    57  			Id:        bson.NewObjectId(),
    58  			Trigger:   trigger.Id(),
    59  			TaskId:    t.Id,
    60  			HostId:    t.HostId,
    61  			Execution: t.Execution,
    62  			BuildId:   t.BuildId,
    63  			VersionId: t.Version,
    64  			ProjectId: t.Project,
    65  			PatchId:   "",
    66  			CreatedAt: time.Now(),
    67  		}
    68  		err := alert.EnqueueAlertRequest(req)
    69  		if err != nil {
    70  			return err
    71  		}
    72  		err = storeTriggerBookkeeping(*ctx, []Trigger{trigger})
    73  		if err != nil {
    74  			return err
    75  		}
    76  	}
    77  	return nil
    78  }
    79  
    80  func RunHostProvisionFailTriggers(h *host.Host) error {
    81  	ctx := triggerContext{host: h}
    82  	trigger := &ProvisionFailed{}
    83  	// only one provision failure trigger to act on for now
    84  	shouldExec, err := trigger.ShouldExecute(ctx)
    85  	if err != nil {
    86  		return err
    87  	}
    88  	if !shouldExec {
    89  		return nil
    90  	}
    91  
    92  	err = alert.EnqueueAlertRequest(&alert.AlertRequest{
    93  		Id:        bson.NewObjectId(),
    94  		Trigger:   trigger.Id(),
    95  		HostId:    h.Id,
    96  		CreatedAt: time.Now(),
    97  	})
    98  	if err != nil {
    99  		return err
   100  	}
   101  	return storeTriggerBookkeeping(ctx, []Trigger{trigger})
   102  }
   103  
   104  func RunSpawnWarningTriggers(host *host.Host) error {
   105  	ctx := triggerContext{host: host}
   106  	for _, trigger := range SpawnWarningTriggers {
   107  		shouldExec, err := trigger.ShouldExecute(ctx)
   108  		if err != nil {
   109  			return err
   110  		}
   111  		if shouldExec {
   112  			err := alert.EnqueueAlertRequest(&alert.AlertRequest{
   113  				Id:        bson.NewObjectId(),
   114  				Trigger:   trigger.Id(),
   115  				HostId:    host.Id,
   116  				CreatedAt: time.Now(),
   117  			})
   118  			if err != nil {
   119  				return err
   120  			}
   121  			err = storeTriggerBookkeeping(ctx, []Trigger{trigger})
   122  			if err != nil {
   123  				return err
   124  			}
   125  		}
   126  	}
   127  	return nil
   128  }
   129  
   130  func getTaskTriggerContext(t *task.Task) (*triggerContext, error) {
   131  	ctx := triggerContext{task: t}
   132  	t, err := task.FindOne(task.ByBeforeRevisionWithStatuses(t.RevisionOrderNumber, task.CompletedStatuses, t.BuildVariant,
   133  		t.DisplayName, t.Project).
   134  		Sort([]string{"-" + task.RevisionOrderNumberKey}))
   135  	if err != nil {
   136  		return nil, err
   137  	}
   138  	if t != nil {
   139  		ctx.previousCompleted = t
   140  	}
   141  	return &ctx, nil
   142  }
   143  
   144  // getActiveTaskTriggers returns a list of the triggers that should be executed for the given task,
   145  // by testing the result of each one's ShouldExecute method.
   146  func getActiveTaskFailureTriggers(ctx triggerContext) ([]Trigger, error) {
   147  	if ctx.task == nil {
   148  		return nil, nil
   149  	}
   150  
   151  	activeTriggers := []Trigger{}
   152  	for _, trigger := range AvailableTaskFailTriggers {
   153  		shouldExec, err := trigger.ShouldExecute(ctx)
   154  		if err != nil {
   155  			return nil, err
   156  		}
   157  		if shouldExec {
   158  			activeTriggers = append(activeTriggers, trigger)
   159  		}
   160  	}
   161  	return activeTriggers, nil
   162  }
   163  
   164  // storeTriggerBookkeeping runs through any trigger bookkeeping that must be done in order to
   165  // "remember" the state of the trigger for previous executions.
   166  func storeTriggerBookkeeping(ctx triggerContext, triggers []Trigger) error {
   167  	for _, trigger := range triggers {
   168  		alertRecord := trigger.CreateAlertRecord(ctx)
   169  		if alertRecord == nil {
   170  			continue
   171  		}
   172  
   173  		err := alertRecord.Insert()
   174  		if err != nil {
   175  			return err
   176  		}
   177  	}
   178  	return nil
   179  }