Cleaned up the code

This commit is contained in:
jasminSPC 2016-07-07 10:28:46 +02:00
parent 478181d7f4
commit d575cd62ec
7 changed files with 209 additions and 105 deletions

View File

@ -31,7 +31,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
steps := []multistep.Step{
&StepCreateSSHKey{
Debug: b.config.PackerDebug,
DebugKeyPath: fmt.Sprintf("pb_%s.pem", b.config.ServerName),
DebugKeyPath: fmt.Sprintf("pb_%s", b.config.SnapshotName),
},
new(stepCreateServer),
&communicator.StepConnect{

View File

@ -81,7 +81,7 @@ func TestBuilderPrepare_Servername(t *testing.T) {
t.Fatalf("should not have error: %s", err)
}
if b.config.ServerName != expected {
t.Errorf("found %s, expected %s", b.config.ServerName, expected)
if b.config.SnapshotName != expected {
t.Errorf("found %s, expected %s", b.config.SnapshotName, expected)
}
}

View File

@ -13,23 +13,25 @@ import (
type Config struct {
common.PackerConfig `mapstructure:",squash"`
Comm communicator.Config `mapstructure:",squash"`
Comm communicator.Config `mapstructure:",squash"`
PBUsername string `mapstructure:"pbusername"`
PBPassword string `mapstructure:"pbpassword"`
PBUrl string `mapstructure:"pburl"`
PBUsername string `mapstructure:"username"`
PBPassword string `mapstructure:"password"`
PBUrl string `mapstructure:"url"`
Region string `mapstructure:"region"`
Image string `mapstructure:"image"`
SSHKey string `mapstructure:"sshkey"`
ServerName string `mapstructure:"servername"`
DiskSize int `mapstructure:"disksize"`
DiskType string `mapstructure:"disktype"`
Cores int `mapstructure:"cores"`
Ram int `mapstructure:"ram"`
Region string `mapstructure:"region"`
Image string `mapstructure:"image"`
SSHKey string
SSHKey_path string `mapstructure:"sshkey_path"`
SnapshotName string `mapstructure:"snapshot_name"`
SnapshotPassword string `mapstructure:"snapshot_password"`
DiskSize int `mapstructure:"disksize"`
DiskType string `mapstructure:"disktype"`
Cores int `mapstructure:"cores"`
Ram int `mapstructure:"ram"`
CommConfig communicator.Config `mapstructure:",squash"`
ctx interpolate.Context
CommConfig communicator.Config `mapstructure:",squash"`
ctx interpolate.Context
}
func NewConfig(raws ...interface{}) (*Config, []string, error) {
@ -57,12 +59,22 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
}
c.Comm.SSHPort = 22
if c.PBUsername == ""{
c.PBUsername = os.Getenv("PROFITBRICKS_USERNAME")
if c.SnapshotName == "" {
def, err := interpolate.Render("packer-{{timestamp}}", nil)
if err != nil {
panic(err)
}
// Default to packer-{{ unix timestamp (utc) }}
c.SnapshotName = def
}
if c.PBPassword == ""{
c.PBPassword = os.Getenv("PROFITBRICKS_PASSWORD")
if c.PBUsername == "" {
c.PBUsername = os.Getenv("PROFITBRICKS_USERNAME")
}
if c.PBPassword == "" {
c.PBPassword = os.Getenv("PROFITBRICKS_PASSWORD")
}
if c.PBUrl == "" {
@ -108,11 +120,6 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
errs, errors.New("ProfitBricks password is required"))
}
if c.ServerName == "" {
errs = packer.MultiErrorAppend(
errs, errors.New("Server Name is required"))
}
if errs != nil && len(errs.Errors) > 0 {
return nil, nil, errs
}

View File

@ -22,11 +22,11 @@ func (s *stepCreateServer) Run(state multistep.StateBag) multistep.StepAction {
profitbricks.SetAuth(c.PBUsername, c.PBPassword)
ui.Say("Creating Virutal datacenter...")
ui.Say("Creating Virutal Data Center...")
datacenter := profitbricks.CreateDatacenter(profitbricks.CreateDatacenterRequest{
DCProperties: profitbricks.DCProperties{
Name: c.ServerName,
Name: c.SnapshotName,
Location: c.Region,
},
})
@ -45,7 +45,7 @@ func (s *stepCreateServer) Run(state multistep.StateBag) multistep.StepAction {
server := profitbricks.CreateServer(datacenter.Id, profitbricks.CreateServerRequest{
ServerProperties: profitbricks.ServerProperties{
Name: c.ServerName,
Name: c.SnapshotName,
Ram: c.Ram,
Cores: c.Cores,
},
@ -68,10 +68,11 @@ func (s *stepCreateServer) Run(state multistep.StateBag) multistep.StepAction {
volume := profitbricks.CreateVolume(datacenter.Id, profitbricks.CreateVolumeRequest{
VolumeProperties: profitbricks.VolumeProperties{
Size: c.DiskSize,
Name: c.ServerName,
Name: c.SnapshotName,
Image: img,
Type: c.DiskType,
SshKey: []string{c.SSHKey},
ImagePassword: c.SnapshotPassword,
},
})
@ -91,7 +92,7 @@ func (s *stepCreateServer) Run(state multistep.StateBag) multistep.StepAction {
lan := profitbricks.CreateLan(datacenter.Id, profitbricks.CreateLanRequest{
LanProperties: profitbricks.LanProperties{
Public: true,
Name: c.ServerName,
Name: c.SnapshotName,
},
})
@ -107,7 +108,7 @@ func (s *stepCreateServer) Run(state multistep.StateBag) multistep.StepAction {
nic := profitbricks.CreateNic(datacenter.Id, server.Id, profitbricks.NicCreateRequest{
NicProperties: profitbricks.NicProperties{
Name: c.ServerName,
Name: c.SnapshotName,
Lan: lan.Id,
Dhcp: true,
},

View File

@ -11,6 +11,7 @@ import (
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"golang.org/x/crypto/ssh"
"io/ioutil"
)
type StepCreateSSHKey struct {
@ -20,46 +21,83 @@ type StepCreateSSHKey struct {
func (s *StepCreateSSHKey) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
c := state.Get("config").(*Config)
ui.Say("Creating temporary SSH key for instance...")
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
err := fmt.Errorf("Error creating temporary ssh key: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
if (c.SSHKey_path == "") {
ui.Say("Creating temporary SSH key for instance...")
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
err := fmt.Errorf("Error creating temporary ssh key: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
priv_blk := pem.Block{
Type: "RSA PRIVATE KEY",
Headers: nil,
Bytes: x509.MarshalPKCS1PrivateKey(priv),
}
priv_blk := pem.Block{
Type: "RSA PRIVATE KEY",
Headers: nil,
Bytes: x509.MarshalPKCS1PrivateKey(priv),
}
pub, err := ssh.NewPublicKey(&priv.PublicKey)
if err != nil {
err := fmt.Errorf("Error creating temporary ssh key: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
state.Put("privateKey", string(pem.EncodeToMemory(&priv_blk)))
state.Put("publicKey", string(ssh.MarshalAuthorizedKey(pub)))
pub, err := ssh.NewPublicKey(&priv.PublicKey)
if err != nil {
err := fmt.Errorf("Error creating temporary ssh key: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
state.Put("privateKey", string(pem.EncodeToMemory(&priv_blk)))
state.Put("publicKey", string(ssh.MarshalAuthorizedKey(pub)))
if s.Debug {
ui.Message(fmt.Sprintf("Saving key for debug purposes: %s", s.DebugKeyPath))
ui.Message(fmt.Sprintf("Saving key to: %s", s.DebugKeyPath))
f, err := os.Create(s.DebugKeyPath)
if err != nil {
state.Put("error", fmt.Errorf("Error saving debug key: %s", err))
return multistep.ActionHalt
}
f.Chmod(os.FileMode(int(0700)))
err = pem.Encode(f, &priv_blk)
f.Close()
if err != nil {
state.Put("error", fmt.Errorf("Error saving debug key: %s", err))
return multistep.ActionHalt
}
} else {
ui.Say(c.SSHKey_path)
pemBytes, err := ioutil.ReadFile(c.SSHKey_path)
if (err != nil) {
ui.Error(err.Error())
return multistep.ActionHalt
}
block, _ := pem.Decode(pemBytes)
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
err := fmt.Errorf("Error creating temporary ssh key: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
priv_blk := pem.Block{
Type: "RSA PRIVATE KEY",
Headers: nil,
Bytes: x509.MarshalPKCS1PrivateKey(priv),
}
pub, err := ssh.NewPublicKey(&priv.PublicKey)
if err != nil {
err := fmt.Errorf("Error creating temporary ssh key: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
state.Put("privateKey", string(pem.EncodeToMemory(&priv_blk)))
state.Put("publicKey", string(ssh.MarshalAuthorizedKey(pub)))
}
return multistep.ActionContinue
}

View File

@ -23,9 +23,9 @@ func (s *stepTakeSnapshot) Run(state multistep.StateBag) multistep.StepAction {
dcId := state.Get("datacenter_id").(string)
volumeId := state.Get("volume_id").(string)
snapshot := profitbricks.CreateSnapshot(dcId, volumeId, c.ServerName+"Snapshot")
snapshot := profitbricks.CreateSnapshot(dcId, volumeId, c.SnapshotName)
state.Put("snapshotname", c.ServerName+"Snapshot")
state.Put("snapshotname", c.SnapshotName)
err := s.checkForErrors(snapshot)
if err != nil {

View File

@ -1,71 +1,66 @@
---
description: |
The `profitbricks` Packer builder is able to create new images for use with
ProfitBricks. The builder takes a source image, runs any provisioning necessary
on the image after launching it, then snapshots it into a reusable image. This
reusable image can then be used as the foundation for new servers that are
launched within ProfitBricks.
layout: docs
page_title: ProfitBricks Builder
...
# Profitbricks packer builder
# ProfitBricks Builder
This builder plugin extends packer.io to support building images for ProfitBricks.
Type: `profitbricks`
You can check out Packer [here](https://packer.io).
The `profitbricks` Packer builder is able to create new images for use with
[ProfitBricks](https://www.profitbricks.com). The builder takes a source image,
runs any provisioning necessary on the image after launching it, then snapshots
it into a reusable image. This reusable image can then be used as the foundation
for new servers that are launched within ProfitBricks.
The builder does *not* manage images. Once it creates an image, it is up to you
to either use it or delete it.
## Dependencies
* Packer >= v0.10.1 (https://packer.io)
* Golang (tested with 1.6)
* Godep >= v62
## Configuration Reference
There are many configuration options available for the builder. They are
divided into two categories: required and optional parameters. Within
each category, the available configuration keys are alphabetized.
## Install Go
In addition to the options listed here, a
[communicator](/docs/templates/communicator.html) can be configured for this
builder.
Follow these instructions to install Go(lang) on your system:
* https://golang.org/doc/install
### Required:
## Install Packer
- `pbpasswrod` (string) - ProfitBricks password. It
can also be specified via the environment variable `PROFITBRICKS_PASSWORD`,
if set.
- `pbusername` (string) - ProfitBricks username. It
can also be specified via the environment variable `PROFITBRICKS_USERNAME`,
if set.
Follow these instructions to install Packer:
* https://www.packer.io/intro/getting-started/setup.html
- `servername` (string) - The name of the server that will be created.
## Compile the plugin
### Optional:
Once you have installed Packer, you must compile this plugin and install the
resulting binary.
- `cores` (int) - Number of server cores. Default value is 4.
```shell
go get https://github.com/profitbricks/packer-builder-profitbricks
cd $GOPATH/src/github.com/profitbricks/packer-builder-profitbricks
make install
```
- `disksize` (string) - Desired disk size. Default value is 50GB.
If the build is successful, you should now have the `packer-builder-profitbricks`
binary in:
- `disktype` (string) - Desired disk type. The default value is "HDD".
* Linux/Mac: the `~/.packer.d/plugins` directory.
* Windows: the `%APPDATA%/packer.d/plugins` directory.
- `image` (string) - ProfitBricks volume image. The default value is `Ubuntu-16.04`.
If this binary is in the right location, you are ready to get started with Packer.
- `pburl` (string) - ProfitBricks REST Url.
## Download the plugin
- `ram` (int) - RAM size for the server. The default value is 2048.
Alternatively, you can download prebuilt binaries from https://github.com/profitbricks/packer-builder-profitbricks/releases/tag/v1.0.0.
- `region` (string) - ProfitBricks region. The default value is "us/las".
After you have downloaded the binary for your operating system:
## Basic Example
* Linux/Mac: Place the binary in the `~/.packer.d/plugins` directory.
* Windows: Place the binary in the `%APPDATA%/packer.d/plugins` directory.
Here is a basic example. It is completely valid as soon as you enter your own
access tokens:
## Example
``` {.javascript}
Once you have set everything up, you are ready to start with an example.
To get a quick start run:
```shell
cd $GOPATH/src/github.com/profitbricks/packer-builder-profitbricks
```
There you will find example `config.json`
```
{
"builders": [
{
@ -77,3 +72,66 @@ access tokens:
}
}
```
To validate `config.json` run:
```shell
packer validate config.json
```
Or if you want to get suggestions on how to fix your config, run:
```shell
packer fix config.json
```
To build a ProfitBricks Packer image run:
```shell
packer build config.json
==> profitbricks: Creating temporary SSH key for instance...
==> profitbricks: Creating Virutal Data Center...
==> profitbricks: Creating ProfitBricks server...
==> profitbricks: Creating a volume
==> profitbricks: Creating a LAN
==> profitbricks: Creating a NIC
==> profitbricks: Waiting for SSH to become available...
==> profitbricks: Creating ProfitBricks snapshot...
==> profitbricks: Removing Virtual Data Center
Build 'profitbricks' finished.
==> Builds finished. The artifacts of successful builds are:
--> profitbricks: A snapshot was created: 'packerSnapshot'
```
## Available config parameters
Required parameters:
```shell
"type" - Builder type
"username" - ProfitBricks username
"password" - ProfitiBricks password
```
Optional parameters:
```shell
"snapshot_password" - Snapshot password
"snapshot_name" - Snapshot name. If snapshot name is not provided Packer will generate it
"sshkey_path" - Path to private SSHkey. If no path to the key is provided Packer will create one under the name [snapshot_name]
"url" - ProfitBricks REST Url
"image" - ProfitBricks volume image
"region" - ProfitBricks region default value "us/las"
"disksize" - Desired disk size default value 50gb
"disktype" - Desired disk type default value "HDD"
"cores" - Number of server cores default value 4
"ram" - RAM size for the server default value "2048"
```
## Support
You are welcome to contact us with questions or comments at [ProfitBricks DevOps Central](https://devops.profitbricks.com/). Please report any issues via [GitHub's issue tracker](https://github.com/profitbricks/docker-machine-driver-profitbricks/issues).