plugin/step/bundle/bundle.go (83 lines of code) (raw):
package bundle
/*
Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
import (
"context"
"os"
"os/exec"
"time"
"github.com/facebookincubator/go2chef/util/temp"
"github.com/facebookincubator/go2chef"
"github.com/mitchellh/mapstructure"
)
// TypeName is the name of this step plugin
const TypeName = "go2chef.step.bundle"
// Bundle represents an executable bundle of files that
// can be downloaded from a go2chef.Source
type Bundle struct {
BundleName string `mapstructure:"name"`
source go2chef.Source
logger go2chef.Logger
downloadPath string
ConfigName string `mapstructure:"config_name"`
TimeoutSeconds int `mapstructure:"timeout_seconds"`
}
func (b *Bundle) String() string {
return "<" + TypeName + ":" + b.BundleName + ">"
}
// Name returns the name of this bundle step
func (b *Bundle) Name() string {
return b.BundleName
}
// Type returns "bundle"
func (b *Bundle) Type() string {
return TypeName
}
// SetName sets the name of this bundle step
func (b *Bundle) SetName(n string) {
b.BundleName = n
}
// Download fetches resources required for this bundle's execution
func (b *Bundle) Download() error {
b.logger.Debugf(1, "%s: downloading bundle", b.Name())
tmpdir, err := temp.Dir("", "go2chef-bundle")
if err != nil {
return err
}
if err := b.source.DownloadToPath(tmpdir); err != nil {
return err
}
b.downloadPath = tmpdir
b.logger.Debugf(1, "%s: downloaded bundle to %s", b.Name(), b.downloadPath)
return nil
}
// Execute loads the bundle.json and executes the command specified therein
func (b *Bundle) Execute() error {
entryPoint, err := findEntrypoint(b.downloadPath)
if err != nil {
return err
}
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(b.TimeoutSeconds)*time.Second)
defer cancel()
var cmd *exec.Cmd
cmd = commandForPath(entryPoint, ctx)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Dir = b.downloadPath
if err := cmd.Run(); err != nil {
return err
}
return nil
}
// Loader provides an instantiation function for this step
func Loader(config map[string]interface{}) (go2chef.Step, error) {
source, err := go2chef.GetSourceFromStepConfig(config)
if err != nil {
return nil, err
}
b := &Bundle{
source: source,
logger: go2chef.GetGlobalLogger(),
ConfigName: "bundle.json",
TimeoutSeconds: 300,
}
if err := mapstructure.Decode(config, b); err != nil {
return nil, err
}
b.source.SetName(b.Name() + "-source")
return b, nil
}
func init() {
go2chef.RegisterStep(TypeName, Loader)
}
var _ go2chef.Step = &Bundle{}
var _ go2chef.StepLoader = Loader