github.com/askholme/packer@v0.7.2-0.20140924152349-70d9566a6852/post-processor/docker-push/post-processor.go (about)

     1  package dockerpush
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/mitchellh/packer/builder/docker"
     6  	"github.com/mitchellh/packer/common"
     7  	"github.com/mitchellh/packer/packer"
     8  	"github.com/mitchellh/packer/post-processor/docker-import"
     9  	"strings"
    10  )
    11  
    12  type Config struct {
    13  	common.PackerConfig `mapstructure:",squash"`
    14  
    15  	Login         bool
    16  	LoginEmail    string `mapstructure:"login_email"`
    17  	LoginUsername string `mapstructure:"login_username"`
    18  	LoginPassword string `mapstructure:"login_password"`
    19  	LoginServer   string `mapstructure:"login_server"`
    20  
    21  	tpl *packer.ConfigTemplate
    22  }
    23  
    24  type PostProcessor struct {
    25  	Driver docker.Driver
    26  
    27  	config Config
    28  }
    29  
    30  func (p *PostProcessor) Configure(raws ...interface{}) error {
    31  	_, err := common.DecodeConfig(&p.config, raws...)
    32  	if err != nil {
    33  		return err
    34  	}
    35  
    36  	p.config.tpl, err = packer.NewConfigTemplate()
    37  	if err != nil {
    38  		return err
    39  	}
    40  	p.config.tpl.UserVars = p.config.PackerUserVars
    41  
    42  	// Accumulate any errors
    43  	errs := new(packer.MultiError)
    44  
    45  	// Process templates
    46  	templates := map[string]*string{
    47  		"login_email":    &p.config.LoginEmail,
    48  		"login_username": &p.config.LoginUsername,
    49  		"login_password": &p.config.LoginPassword,
    50  		"login_server":   &p.config.LoginServer,
    51  	}
    52  
    53  	for n, ptr := range templates {
    54  		var err error
    55  		*ptr, err = p.config.tpl.Process(*ptr, nil)
    56  		if err != nil {
    57  			errs = packer.MultiErrorAppend(
    58  				errs, fmt.Errorf("Error processing %s: %s", n, err))
    59  		}
    60  	}
    61  
    62  	if len(errs.Errors) > 0 {
    63  		return errs
    64  	}
    65  
    66  	return nil
    67  }
    68  
    69  func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) {
    70  	if artifact.BuilderId() != dockerimport.BuilderId {
    71  		err := fmt.Errorf(
    72  			"Unknown artifact type: %s\nCan only import from docker-import artifacts.",
    73  			artifact.BuilderId())
    74  		return nil, false, err
    75  	}
    76  
    77  	driver := p.Driver
    78  	if driver == nil {
    79  		// If no driver is set, then we use the real driver
    80  		driver = &docker.DockerDriver{Tpl: p.config.tpl, Ui: ui}
    81  	}
    82  
    83  	if p.config.Login {
    84  		ui.Message("Logging in...")
    85  		err := driver.Login(
    86  			p.config.LoginServer,
    87  			p.config.LoginEmail,
    88  			p.config.LoginUsername,
    89  			p.config.LoginPassword)
    90  		if err != nil {
    91  			return nil, false, fmt.Errorf(
    92  				"Error logging in to Docker: %s", err)
    93  		}
    94  
    95  		defer func() {
    96  			ui.Message("Logging out...")
    97  			if err := driver.Logout(p.config.LoginServer); err != nil {
    98  				ui.Error(fmt.Sprintf("Error logging out: %s", err))
    99  			}
   100  		}()
   101  	}
   102  
   103  	// Get the name. We strip off any tags from the name because the
   104  	// push doesn't use those.
   105  	name := artifact.Id()
   106  
   107  	if i := strings.Index(name, "/"); i >= 0 {
   108  		// This should always be true because the / is required. But we have
   109  		// to get the index to this so we don't accidentally strip off the port
   110  		if j := strings.Index(name[i:], ":"); j >= 0 {
   111  			name = name[:i+j]
   112  		}
   113  	}
   114  
   115  	ui.Message("Pushing: " + name)
   116  	if err := driver.Push(name); err != nil {
   117  		return nil, false, err
   118  	}
   119  
   120  	return nil, false, nil
   121  }