github.com/kikitux/packer@v0.10.1-0.20160322154024-6237df566f9f/builder/azure/arm/config.go (about)

     1  // Copyright (c) Microsoft Corporation. All rights reserved.
     2  // Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
     3  
     4  package arm
     5  
     6  import (
     7  	"encoding/base64"
     8  	"fmt"
     9  	"io/ioutil"
    10  	"time"
    11  
    12  	"golang.org/x/crypto/ssh"
    13  
    14  	"github.com/Azure/azure-sdk-for-go/arm/compute"
    15  	"github.com/Azure/go-autorest/autorest/to"
    16  
    17  	"github.com/mitchellh/packer/common"
    18  	"github.com/mitchellh/packer/helper/communicator"
    19  	"github.com/mitchellh/packer/helper/config"
    20  	"github.com/mitchellh/packer/packer"
    21  	"github.com/mitchellh/packer/template/interpolate"
    22  )
    23  
    24  const (
    25  	DefaultUserName = "packer"
    26  	DefaultVMSize   = "Standard_A1"
    27  )
    28  
    29  type Config struct {
    30  	common.PackerConfig `mapstructure:",squash"`
    31  
    32  	// Authentication via OAUTH
    33  	ClientID       string `mapstructure:"client_id"`
    34  	ClientSecret   string `mapstructure:"client_secret"`
    35  	TenantID       string `mapstructure:"tenant_id"`
    36  	SubscriptionID string `mapstructure:"subscription_id"`
    37  
    38  	// Capture
    39  	CaptureNamePrefix    string `mapstructure:"capture_name_prefix"`
    40  	CaptureContainerName string `mapstructure:"capture_container_name"`
    41  
    42  	// Compute
    43  	ImagePublisher string `mapstructure:"image_publisher"`
    44  	ImageOffer     string `mapstructure:"image_offer"`
    45  	ImageSku       string `mapstructure:"image_sku"`
    46  	Location       string `mapstructure:"location"`
    47  	VMSize         string `mapstructure:"vm_size"`
    48  
    49  	// Deployment
    50  	ResourceGroupName string `mapstructure:"resource_group_name"`
    51  	StorageAccount    string `mapstructure:"storage_account"`
    52  
    53  	// Runtime Values
    54  	UserName             string
    55  	Password             string
    56  	tmpAdminPassword     string
    57  	tmpResourceGroupName string
    58  	tmpComputeName       string
    59  	tmpDeploymentName    string
    60  	tmpOSDiskName        string
    61  
    62  	// Authentication with the VM via SSH
    63  	sshAuthorizedKey string
    64  	sshPrivateKey    string
    65  
    66  	Comm communicator.Config `mapstructure:",squash"`
    67  	ctx  *interpolate.Context
    68  }
    69  
    70  // If we ever feel the need to support more templates consider moving this
    71  // method to its own factory class.
    72  func (c *Config) toTemplateParameters() *TemplateParameters {
    73  	return &TemplateParameters{
    74  		AdminUsername:      &TemplateParameter{c.UserName},
    75  		AdminPassword:      &TemplateParameter{c.Password},
    76  		DnsNameForPublicIP: &TemplateParameter{c.tmpComputeName},
    77  		ImageOffer:         &TemplateParameter{c.ImageOffer},
    78  		ImagePublisher:     &TemplateParameter{c.ImagePublisher},
    79  		ImageSku:           &TemplateParameter{c.ImageSku},
    80  		OSDiskName:         &TemplateParameter{c.tmpOSDiskName},
    81  		SshAuthorizedKey:   &TemplateParameter{c.sshAuthorizedKey},
    82  		StorageAccountName: &TemplateParameter{c.StorageAccount},
    83  		VMSize:             &TemplateParameter{c.VMSize},
    84  		VMName:             &TemplateParameter{c.tmpComputeName},
    85  	}
    86  }
    87  
    88  func (c *Config) toVirtualMachineCaptureParameters() *compute.VirtualMachineCaptureParameters {
    89  	return &compute.VirtualMachineCaptureParameters{
    90  		DestinationContainerName: &c.CaptureContainerName,
    91  		VhdPrefix:                &c.CaptureNamePrefix,
    92  		OverwriteVhds:            to.BoolPtr(false),
    93  	}
    94  }
    95  
    96  func newConfig(raws ...interface{}) (*Config, []string, error) {
    97  	var c Config
    98  
    99  	err := config.Decode(&c, &config.DecodeOpts{
   100  		Interpolate:        true,
   101  		InterpolateContext: c.ctx,
   102  	}, raws...)
   103  
   104  	if err != nil {
   105  		return nil, nil, err
   106  	}
   107  
   108  	provideDefaultValues(&c)
   109  	setRuntimeValues(&c)
   110  	setUserNamePassword(&c)
   111  
   112  	err = setSshValues(&c)
   113  	if err != nil {
   114  		return nil, nil, err
   115  	}
   116  
   117  	var errs *packer.MultiError
   118  	errs = packer.MultiErrorAppend(errs, c.Comm.Prepare(c.ctx)...)
   119  
   120  	assertRequiredParametersSet(&c, errs)
   121  	if errs != nil && len(errs.Errors) > 0 {
   122  		return nil, nil, errs
   123  	}
   124  
   125  	return &c, nil, nil
   126  }
   127  
   128  func setSshValues(c *Config) error {
   129  	if c.Comm.SSHTimeout == 0 {
   130  		c.Comm.SSHTimeout = 20 * time.Minute
   131  	}
   132  
   133  	if c.Comm.SSHPrivateKey != "" {
   134  		privateKeyBytes, err := ioutil.ReadFile(c.Comm.SSHPrivateKey)
   135  		if err != nil {
   136  			panic(err)
   137  		}
   138  		signer, err := ssh.ParsePrivateKey(privateKeyBytes)
   139  		if err != nil {
   140  			panic(err)
   141  		}
   142  
   143  		publicKey := signer.PublicKey()
   144  		c.sshAuthorizedKey = fmt.Sprintf("%s %s packer Azure Deployment%s",
   145  			publicKey.Type(),
   146  			base64.StdEncoding.EncodeToString(publicKey.Marshal()),
   147  			time.Now().Format(time.RFC3339))
   148  		c.sshPrivateKey = string(privateKeyBytes)
   149  
   150  	} else {
   151  		sshKeyPair, err := NewOpenSshKeyPair()
   152  		if err != nil {
   153  			return err
   154  		}
   155  
   156  		c.sshAuthorizedKey = sshKeyPair.AuthorizedKey()
   157  		c.sshPrivateKey = sshKeyPair.PrivateKey()
   158  	}
   159  
   160  	return nil
   161  }
   162  
   163  func setRuntimeValues(c *Config) {
   164  	var tempName = NewTempName()
   165  
   166  	c.tmpAdminPassword = tempName.AdminPassword
   167  	c.tmpComputeName = tempName.ComputeName
   168  	c.tmpDeploymentName = tempName.DeploymentName
   169  	// c.tmpResourceGroupName = c.ResourceGroupName
   170  	c.tmpResourceGroupName = tempName.ResourceGroupName
   171  	c.tmpOSDiskName = tempName.OSDiskName
   172  }
   173  
   174  func setUserNamePassword(c *Config) {
   175  	if c.Comm.SSHUsername == "" {
   176  		c.Comm.SSHUsername = DefaultUserName
   177  	}
   178  
   179  	c.UserName = c.Comm.SSHUsername
   180  
   181  	if c.Comm.SSHPassword != "" {
   182  		c.Password = c.Comm.SSHPassword
   183  	} else {
   184  		c.Password = c.tmpAdminPassword
   185  	}
   186  }
   187  
   188  func provideDefaultValues(c *Config) {
   189  	if c.VMSize == "" {
   190  		c.VMSize = DefaultVMSize
   191  	}
   192  }
   193  
   194  func assertRequiredParametersSet(c *Config, errs *packer.MultiError) {
   195  	/////////////////////////////////////////////
   196  	// Authentication via OAUTH
   197  
   198  	if c.ClientID == "" {
   199  		errs = packer.MultiErrorAppend(errs, fmt.Errorf("A client_id must be specified"))
   200  	}
   201  
   202  	if c.ClientSecret == "" {
   203  		errs = packer.MultiErrorAppend(errs, fmt.Errorf("A client_secret must be specified"))
   204  	}
   205  
   206  	if c.TenantID == "" {
   207  		errs = packer.MultiErrorAppend(errs, fmt.Errorf("A tenant_id must be specified"))
   208  	}
   209  
   210  	if c.SubscriptionID == "" {
   211  		errs = packer.MultiErrorAppend(errs, fmt.Errorf("A subscription_id must be specified"))
   212  	}
   213  
   214  	/////////////////////////////////////////////
   215  	// Capture
   216  	if c.CaptureContainerName == "" {
   217  		errs = packer.MultiErrorAppend(errs, fmt.Errorf("An capture_container_name must be specified"))
   218  	}
   219  
   220  	if c.CaptureNamePrefix == "" {
   221  		errs = packer.MultiErrorAppend(errs, fmt.Errorf("An capture_name_prefix must be specified"))
   222  	}
   223  
   224  	/////////////////////////////////////////////
   225  	// Compute
   226  
   227  	if c.ImagePublisher == "" {
   228  		errs = packer.MultiErrorAppend(errs, fmt.Errorf("A image_publisher must be specified"))
   229  	}
   230  
   231  	if c.ImageOffer == "" {
   232  		errs = packer.MultiErrorAppend(errs, fmt.Errorf("A image_offer must be specified"))
   233  	}
   234  
   235  	if c.ImageSku == "" {
   236  		errs = packer.MultiErrorAppend(errs, fmt.Errorf("A image_sku must be specified"))
   237  	}
   238  
   239  	if c.Location == "" {
   240  		errs = packer.MultiErrorAppend(errs, fmt.Errorf("A location must be specified"))
   241  	}
   242  
   243  	/////////////////////////////////////////////
   244  	// Deployment
   245  
   246  	if c.StorageAccount == "" {
   247  		errs = packer.MultiErrorAppend(errs, fmt.Errorf("A storage_account must be specified"))
   248  	}
   249  }