Cleaned up the code
This commit is contained in:
parent
478181d7f4
commit
d575cd62ec
|
@ -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{
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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).
|
||||
|
|
Loading…
Reference in New Issue