github.com/iqoqo/nomad@v0.11.3-0.20200911112621-d7021c74d101/client/allocrunner/taskrunner/artifact_hook.go (about)

     1  package taskrunner
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	log "github.com/hashicorp/go-hclog"
     8  	"github.com/hashicorp/nomad/client/allocrunner/interfaces"
     9  	"github.com/hashicorp/nomad/client/allocrunner/taskrunner/getter"
    10  	ti "github.com/hashicorp/nomad/client/allocrunner/taskrunner/interfaces"
    11  	"github.com/hashicorp/nomad/nomad/structs"
    12  )
    13  
    14  // artifactHook downloads artifacts for a task.
    15  type artifactHook struct {
    16  	eventEmitter ti.EventEmitter
    17  	logger       log.Logger
    18  }
    19  
    20  func newArtifactHook(e ti.EventEmitter, logger log.Logger) *artifactHook {
    21  	h := &artifactHook{
    22  		eventEmitter: e,
    23  	}
    24  	h.logger = logger.Named(h.Name())
    25  	return h
    26  }
    27  
    28  func (*artifactHook) Name() string {
    29  	// Copied in client/state when upgrading from <0.9 schemas, so if you
    30  	// change it here you also must change it there.
    31  	return "artifacts"
    32  }
    33  
    34  func (h *artifactHook) Prestart(ctx context.Context, req *interfaces.TaskPrestartRequest, resp *interfaces.TaskPrestartResponse) error {
    35  	if len(req.Task.Artifacts) == 0 {
    36  		resp.Done = true
    37  		return nil
    38  	}
    39  
    40  	// Initialize hook state to store download progress
    41  	resp.State = make(map[string]string, len(req.Task.Artifacts))
    42  
    43  	h.eventEmitter.EmitEvent(structs.NewTaskEvent(structs.TaskDownloadingArtifacts))
    44  
    45  	for _, artifact := range req.Task.Artifacts {
    46  		aid := artifact.Hash()
    47  		if req.PreviousState[aid] != "" {
    48  			h.logger.Trace("skipping already downloaded artifact", "artifact", artifact.GetterSource)
    49  			resp.State[aid] = req.PreviousState[aid]
    50  			continue
    51  		}
    52  
    53  		h.logger.Debug("downloading artifact", "artifact", artifact.GetterSource)
    54  		//XXX add ctx to GetArtifact to allow cancelling long downloads
    55  		if err := getter.GetArtifact(req.TaskEnv, artifact, req.TaskDir.Dir); err != nil {
    56  			wrapped := structs.NewRecoverableError(
    57  				fmt.Errorf("failed to download artifact %q: %v", artifact.GetterSource, err),
    58  				true,
    59  			)
    60  			herr := NewHookError(wrapped, structs.NewTaskEvent(structs.TaskArtifactDownloadFailed).SetDownloadError(wrapped))
    61  
    62  			return herr
    63  		}
    64  
    65  		// Mark artifact as downloaded to avoid re-downloading due to
    66  		// retries caused by subsequent artifacts failing. Any
    67  		// non-empty value works.
    68  		resp.State[aid] = "1"
    69  	}
    70  
    71  	resp.Done = true
    72  	return nil
    73  }