github.com/billybanfield/evergreen@v0.0.0-20170525200750-eeee692790f7/plugin/builtin/expansions/expansions_plugin.go (about)

     1  package expansions
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"path/filepath"
     7  
     8  	"github.com/evergreen-ci/evergreen/model"
     9  	"github.com/evergreen-ci/evergreen/plugin"
    10  	"github.com/mitchellh/mapstructure"
    11  	"github.com/mongodb/grip/slogger"
    12  	"github.com/pkg/errors"
    13  )
    14  
    15  func init() {
    16  	plugin.Publish(&ExpansionsPlugin{})
    17  }
    18  
    19  const (
    20  	ExpansionsPluginName = "expansions"
    21  	UpdateVarsCmdName    = "update"
    22  )
    23  
    24  // ExpansionsPlugin handles updating expansions in a task at runtime.
    25  type ExpansionsPlugin struct{}
    26  
    27  // Name fulfills the Plugin interface.
    28  func (self *ExpansionsPlugin) Name() string {
    29  	return ExpansionsPluginName
    30  }
    31  
    32  // GetRoutes registers the API handler for fetching expansion variables
    33  // from the API server.
    34  func (self *ExpansionsPlugin) GetAPIHandler() http.Handler {
    35  	r := http.NewServeMux()
    36  	r.HandleFunc(fmt.Sprintf("/%v", FetchVarsRoute), FetchVarsHandler) // GET
    37  	r.HandleFunc("/", http.NotFound)
    38  	return r
    39  }
    40  
    41  func (self *ExpansionsPlugin) Configure(map[string]interface{}) error {
    42  	return nil
    43  }
    44  
    45  // NewCommand fulfills the Plugin interface.
    46  func (self *ExpansionsPlugin) NewCommand(cmdName string) (plugin.Command, error) {
    47  	if cmdName == UpdateVarsCmdName {
    48  		return &UpdateCommand{}, nil
    49  	} else if cmdName == FetchVarsCmdname {
    50  		return &FetchVarsCommand{}, nil
    51  	}
    52  	return nil, &plugin.ErrUnknownCommand{cmdName}
    53  }
    54  
    55  // UpdateCommand reads in a set of new expansions and updates the
    56  // task's expansions at runtime. UpdateCommand can take a list
    57  // of update expansion pairs and/or a file of expansion pairs
    58  type UpdateCommand struct {
    59  	// Key-value pairs for updating the task's parameters with
    60  	Updates []PutCommandParams `mapstructure:"updates"`
    61  
    62  	// Filename for a yaml file containing expansion updates
    63  	// in the form of
    64  	//   "expansion_key: expansions_value"
    65  	YamlFile string `mapstructure:"file"`
    66  }
    67  
    68  // PutCommandParams are pairings of expansion names
    69  // and the value they expand to
    70  type PutCommandParams struct {
    71  	// The name of the expansion
    72  	Key string
    73  
    74  	// The expanded value
    75  	Value string
    76  
    77  	// Can optionally concat a string to the end of the current value
    78  	Concat string
    79  }
    80  
    81  func (self *UpdateCommand) Name() string {
    82  	return UpdateVarsCmdName
    83  }
    84  
    85  func (self *UpdateCommand) Plugin() string {
    86  	return ExpansionsPluginName
    87  }
    88  
    89  // ParseParams validates the input to the UpdateCommand, returning and error
    90  // if something is incorrect. Fulfills Command interface.
    91  func (self *UpdateCommand) ParseParams(params map[string]interface{}) error {
    92  	err := mapstructure.Decode(params, self)
    93  	if err != nil {
    94  		return err
    95  	}
    96  
    97  	for _, item := range self.Updates {
    98  		if item.Key == "" {
    99  			return errors.Errorf("error parsing '%v' params: key must not be "+
   100  				"a blank string", self.Name())
   101  		}
   102  	}
   103  
   104  	return nil
   105  }
   106  
   107  func (self *UpdateCommand) ExecuteUpdates(conf *model.TaskConfig) error {
   108  	for _, update := range self.Updates {
   109  		if update.Concat == "" {
   110  			newValue, err := conf.Expansions.ExpandString(update.Value)
   111  
   112  			if err != nil {
   113  				return err
   114  			}
   115  			conf.Expansions.Put(update.Key, newValue)
   116  		} else {
   117  			newValue, err := conf.Expansions.ExpandString(update.Concat)
   118  			if err != nil {
   119  				return err
   120  			}
   121  
   122  			oldValue := conf.Expansions.Get(update.Key)
   123  			conf.Expansions.Put(update.Key, oldValue+newValue)
   124  		}
   125  	}
   126  
   127  	return nil
   128  }
   129  
   130  // Execute updates the expansions. Fulfills Command interface.
   131  func (self *UpdateCommand) Execute(pluginLogger plugin.Logger,
   132  	pluginCom plugin.PluginCommunicator, conf *model.TaskConfig, stop chan bool) error {
   133  
   134  	err := self.ExecuteUpdates(conf)
   135  	if err != nil {
   136  		return err
   137  	}
   138  
   139  	if self.YamlFile != "" {
   140  		self.YamlFile, err = conf.Expansions.ExpandString(self.YamlFile)
   141  		if err != nil {
   142  			return err
   143  		}
   144  
   145  		pluginLogger.LogTask(slogger.INFO, "Updating expansions with keys from file: %v", self.YamlFile)
   146  		filename := filepath.Join(conf.WorkDir, self.YamlFile)
   147  		err := conf.Expansions.UpdateFromYaml(filename)
   148  		if err != nil {
   149  			return err
   150  		}
   151  	}
   152  	return nil
   153  
   154  }