diff --git a/builder/oneandone/artifact.go b/builder/oneandone/artifact.go
new file mode 100644
index 000000000..52c3d456f
--- /dev/null
+++ b/builder/oneandone/artifact.go
@@ -0,0 +1,34 @@
+package oneandone
+
+import (
+ "fmt"
+)
+
+type Artifact struct {
+ snapshotId string
+ snapshotName string
+}
+
+func (*Artifact) BuilderId() string {
+ return BuilderId
+}
+
+func (a *Artifact) Files() []string {
+ return []string{}
+}
+
+func (*Artifact) Id() string {
+ return "Null"
+}
+
+func (a *Artifact) String() string {
+ return fmt.Sprintf("A snapshot was created: '%v', '%v'", a.snapshotId, a.snapshotName)
+}
+
+func (a *Artifact) State(name string) interface{} {
+ return nil
+}
+
+func (a *Artifact) Destroy() error {
+ return nil
+}
diff --git a/builder/oneandone/builder.go b/builder/oneandone/builder.go
new file mode 100644
index 000000000..6820558c4
--- /dev/null
+++ b/builder/oneandone/builder.go
@@ -0,0 +1,84 @@
+package oneandone
+
+import (
+ "fmt"
+ "github.com/mitchellh/multistep"
+ "github.com/mitchellh/packer/common"
+ "github.com/mitchellh/packer/helper/communicator"
+ "github.com/mitchellh/packer/packer"
+ "log"
+)
+
+const BuilderId = "packer.oneandone"
+
+type Builder struct {
+ config *Config
+ runner multistep.Runner
+}
+
+func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
+ c, warnings, errs := NewConfig(raws...)
+ if errs != nil {
+ return warnings, errs
+ }
+ b.config = c
+
+ return warnings, nil
+}
+
+func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
+
+ steps := []multistep.Step{
+ &StepCreateSSHKey{
+ Debug: b.config.PackerDebug,
+ DebugKeyPath: fmt.Sprintf("oneandone_%s", b.config.SnapshotName),
+ },
+ new(stepCreateServer),
+ &communicator.StepConnect{
+ Config: &b.config.Comm,
+ Host: commHost,
+ SSHConfig: sshConfig,
+ },
+ &common.StepProvision{},
+ new(stepTakeSnapshot),
+ }
+
+ state := new(multistep.BasicStateBag)
+
+ state.Put("config", b.config)
+ state.Put("hook", hook)
+ state.Put("ui", ui)
+ config := state.Get("config").(*Config)
+
+ if b.config.PackerDebug {
+ b.runner = &multistep.DebugRunner{
+ Steps: steps,
+ PauseFn: common.MultistepDebugFn(ui),
+ }
+ } else {
+ b.runner = &multistep.BasicRunner{Steps: steps}
+ }
+
+ b.runner.Run(state)
+
+ if rawErr, ok := state.GetOk("error"); ok {
+ return nil, rawErr.(error)
+ }
+
+ config.SnapshotName = state.Get("snapshot_name").(string)
+ snapshotId := state.Get("snapshot_id").(string)
+
+ artifact := &Artifact{
+ snapshotName: config.SnapshotName,
+ snapshotId: snapshotId,
+ }
+
+ return artifact, nil
+}
+
+func (b *Builder) Cancel() {
+ if b.runner != nil {
+ log.Println("Cancelling the step runner...")
+ b.runner.Cancel()
+ }
+}
diff --git a/builder/oneandone/builder_acc_test.go b/builder/oneandone/builder_acc_test.go
new file mode 100644
index 000000000..a15dce6d5
--- /dev/null
+++ b/builder/oneandone/builder_acc_test.go
@@ -0,0 +1,33 @@
+package oneandone
+
+import (
+ "os"
+ "testing"
+
+ builderT "github.com/mitchellh/packer/helper/builder/testing"
+)
+
+func TestBuilderAcc_basic(t *testing.T) {
+ builderT.Test(t, builderT.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ Builder: &Builder{},
+ Template: testBuilderAccBasic,
+ })
+}
+
+func testAccPreCheck(t *testing.T) {
+ if v := os.Getenv("ONEANDONE_TOKEN"); v == "" {
+ t.Fatal("ONEANDONE_TOKEN must be set for acceptance tests")
+ }
+}
+
+const testBuilderAccBasic = `
+{
+ "builders": [{
+ "type": "oneandone",
+ "disk_size": "50",
+ "snapshot_name": "test5",
+ "image" : "ubuntu1604-64min"
+ }]
+}
+`
diff --git a/builder/oneandone/builder_test.go b/builder/oneandone/builder_test.go
new file mode 100644
index 000000000..808caf46a
--- /dev/null
+++ b/builder/oneandone/builder_test.go
@@ -0,0 +1,55 @@
+package oneandone
+
+import (
+ "fmt"
+ "github.com/mitchellh/packer/packer"
+ "testing"
+)
+
+func testConfig() map[string]interface{} {
+ return map[string]interface{}{
+ "type": "oneandone",
+ "disk_size": "50",
+ "snapshot_name": "test5",
+ "image": "ubuntu1604-64min",
+ }
+}
+
+func TestImplementsBuilder(t *testing.T) {
+ var raw interface{}
+ raw = &Builder{}
+ if _, ok := raw.(packer.Builder); !ok {
+ t.Fatalf("Builder should be a builder")
+ }
+}
+
+func TestBuilder_Prepare_BadType(t *testing.T) {
+ b := &Builder{}
+ c := map[string]interface{}{
+ "api_key": []string{},
+ }
+
+ warns, err := b.Prepare(c)
+ if len(warns) > 0 {
+ t.Fatalf("bad: %#v", warns)
+ }
+ if err == nil {
+ fmt.Println(err)
+ fmt.Println(warns)
+ t.Fatalf("prepare should fail")
+ }
+}
+
+func TestBuilderPrepare_InvalidKey(t *testing.T) {
+ var b Builder
+ config := testConfig()
+
+ config["i_should_not_be_valid"] = true
+ warnings, err := b.Prepare(config)
+ if len(warnings) > 0 {
+ t.Fatalf("bad: %#v", warnings)
+ }
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
diff --git a/builder/oneandone/config.go b/builder/oneandone/config.go
new file mode 100644
index 000000000..5a8c97441
--- /dev/null
+++ b/builder/oneandone/config.go
@@ -0,0 +1,87 @@
+package oneandone
+
+import (
+ "github.com/1and1/oneandone-cloudserver-sdk-go"
+ "github.com/mitchellh/mapstructure"
+ "github.com/mitchellh/packer/common"
+ "github.com/mitchellh/packer/helper/communicator"
+ "github.com/mitchellh/packer/helper/config"
+ "github.com/mitchellh/packer/packer"
+ "github.com/mitchellh/packer/template/interpolate"
+ "os"
+)
+
+type Config struct {
+ common.PackerConfig `mapstructure:",squash"`
+ Comm communicator.Config `mapstructure:",squash"`
+
+ Token string `mapstructure:"token"`
+ Url string `mapstructure:"url"`
+ SSHKey string
+ SSHKey_path string `mapstructure:"ssh_key_path"`
+ SnapshotName string `mapstructure:"image_name"`
+ Image string `mapstructure:"source_image_name"`
+ ImagePassword string `mapstructure:"image_password"`
+ DiskSize int `mapstructure:"disk_size"`
+ Timeout int `mapstructure:"timeout"`
+ CommConfig communicator.Config `mapstructure:",squash"`
+ ctx interpolate.Context
+}
+
+func NewConfig(raws ...interface{}) (*Config, []string, error) {
+ var c Config
+
+ var md mapstructure.Metadata
+ err := config.Decode(&c, &config.DecodeOpts{
+ Metadata: &md,
+ Interpolate: true,
+ InterpolateContext: &c.ctx,
+ InterpolateFilter: &interpolate.RenderFilter{
+ Exclude: []string{
+ "run_command",
+ },
+ },
+ }, raws...)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var errs *packer.MultiError
+
+ if c.Comm.SSHUsername == "" {
+ c.Comm.SSHUsername = "root"
+ }
+ c.Comm.SSHPort = 22
+
+ if c.Token == "" {
+ c.Token = os.Getenv("ONEANDONE_TOKEN")
+ }
+
+ if c.Url == "" {
+ c.Url = oneandone.BaseUrl
+ }
+
+ if c.DiskSize == 0 {
+ c.DiskSize = 50
+ }
+
+ if c.Image == "" {
+ c.Image = "ubuntu1604-64std"
+ }
+
+ if c.Timeout == 0 {
+ c.Timeout = 600
+ }
+
+ if es := c.Comm.Prepare(&c.ctx); len(es) > 0 {
+ errs = packer.MultiErrorAppend(errs, es...)
+ }
+ c.Comm.SSHPort = 22
+
+ if errs != nil && len(errs.Errors) > 0 {
+ return nil, nil, errs
+ }
+ common.ScrubConfig(c, c.Token)
+
+ return &c, nil, nil
+}
diff --git a/builder/oneandone/ssh.go b/builder/oneandone/ssh.go
new file mode 100644
index 000000000..49a0b08b0
--- /dev/null
+++ b/builder/oneandone/ssh.go
@@ -0,0 +1,29 @@
+package oneandone
+
+import (
+ "fmt"
+ "github.com/mitchellh/multistep"
+ "golang.org/x/crypto/ssh"
+)
+
+func commHost(state multistep.StateBag) (string, error) {
+ ipAddress := state.Get("server_ip").(string)
+ return ipAddress, nil
+}
+
+func sshConfig(state multistep.StateBag) (*ssh.ClientConfig, error) {
+ config := state.Get("config").(*Config)
+ privateKey := state.Get("privateKey").(string)
+
+ signer, err := ssh.ParsePrivateKey([]byte(privateKey))
+ if err != nil {
+ return nil, fmt.Errorf("Error setting up SSH config: %s", err)
+ }
+
+ return &ssh.ClientConfig{
+ User: config.Comm.SSHUsername,
+ Auth: []ssh.AuthMethod{
+ ssh.PublicKeys(signer),
+ },
+ }, nil
+}
diff --git a/builder/oneandone/step_create_server.go b/builder/oneandone/step_create_server.go
new file mode 100644
index 000000000..9580a8bd6
--- /dev/null
+++ b/builder/oneandone/step_create_server.go
@@ -0,0 +1,117 @@
+package oneandone
+
+import (
+ "fmt"
+ "github.com/1and1/oneandone-cloudserver-sdk-go"
+ "github.com/mitchellh/multistep"
+ "github.com/mitchellh/packer/packer"
+ "strings"
+ "time"
+)
+
+type stepCreateServer struct{}
+
+func (s *stepCreateServer) Run(state multistep.StateBag) multistep.StepAction {
+ ui := state.Get("ui").(packer.Ui)
+ c := state.Get("config").(*Config)
+
+ c.SSHKey = state.Get("publicKey").(string)
+
+ token := oneandone.SetToken(c.Token)
+ //Create an API client
+ api := oneandone.New(token, c.Url)
+
+ // List server appliances
+ saps, _ := api.ListServerAppliances()
+
+ time.Sleep(time.Second * 10)
+
+ var sa oneandone.ServerAppliance
+ for _, a := range saps {
+
+ if a.Type == "IMAGE" && strings.Contains(strings.ToLower(a.Name), strings.ToLower(c.Image)) {
+ sa = a
+ break
+ }
+ }
+
+ c.SSHKey = state.Get("publicKey").(string)
+ if c.DiskSize < sa.MinHddSize {
+ ui.Error(fmt.Sprintf("Minimum required disk size %d", sa.MinHddSize))
+ }
+
+ ui.Say("Creating Server...")
+
+ // Create a server
+ req := oneandone.ServerRequest{
+ Name: c.SnapshotName,
+ Description: "Example server description.",
+ ApplianceId: sa.Id,
+ PowerOn: true,
+ SSHKey: c.SSHKey,
+ Hardware: oneandone.Hardware{
+ Vcores: 1,
+ CoresPerProcessor: 1,
+ Ram: 2,
+ Hdds: []oneandone.Hdd{
+ {
+ Size: c.DiskSize,
+ IsMain: true,
+ },
+ },
+ },
+ }
+
+ if c.ImagePassword != "" {
+ req.Password = c.ImagePassword
+ }
+ server_id, server, err := api.CreateServer(&req)
+
+ if err == nil {
+ // Wait until server is created and powered on for at most 60 x 10 seconds
+ err = api.WaitForState(server, "POWERED_ON", 1, c.Timeout)
+ } else {
+ ui.Error(err.Error())
+ return multistep.ActionHalt
+ }
+
+ // Get a server
+ server, err = api.GetServer(server_id)
+ if err != nil {
+ ui.Error(err.Error())
+ return multistep.ActionHalt
+ }
+
+ state.Put("server_id", server_id)
+
+ state.Put("server_ip", server.Ips[0].Ip)
+
+ return multistep.ActionContinue
+}
+
+func (s *stepCreateServer) Cleanup(state multistep.StateBag) {
+ c := state.Get("config").(*Config)
+ ui := state.Get("ui").(packer.Ui)
+
+ ui.Say("Removing Server...")
+
+ token := oneandone.SetToken(c.Token)
+ //Create an API client
+ api := oneandone.New(token, oneandone.BaseUrl)
+
+ serverId := state.Get("server_id").(string)
+
+ server, err := api.ShutdownServer(serverId, false)
+ if err != nil {
+ ui.Error(fmt.Sprintf("Error shutting down 1and1 server. Please destroy it manually: %s", serverId))
+ ui.Error(err.Error())
+ }
+ err = api.WaitForState(server, "POWERED_OFF", 1, c.Timeout)
+
+ server, err = api.DeleteServer(server.Id, false)
+
+ if err != nil {
+ ui.Error(fmt.Sprintf("Error deleting 1and1 server. Please destroy it manually: %s", serverId))
+ ui.Error(err.Error())
+ }
+}
diff --git a/builder/oneandone/step_create_sshkey.go b/builder/oneandone/step_create_sshkey.go
new file mode 100644
index 000000000..9ccdf054c
--- /dev/null
+++ b/builder/oneandone/step_create_sshkey.go
@@ -0,0 +1,105 @@
+package oneandone
+
+import (
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/x509"
+ "encoding/pem"
+ "fmt"
+ "os"
+
+ "github.com/mitchellh/multistep"
+ "github.com/mitchellh/packer/packer"
+ "golang.org/x/crypto/ssh"
+ "io/ioutil"
+)
+
+type StepCreateSSHKey struct {
+ Debug bool
+ DebugKeyPath string
+}
+
+func (s *StepCreateSSHKey) Run(state multistep.StateBag) multistep.StepAction {
+ ui := state.Get("ui").(packer.Ui)
+ c := state.Get("config").(*Config)
+
+ 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),
+ }
+
+ 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)))
+
+ 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
+}
+
+func (s *StepCreateSSHKey) Cleanup(state multistep.StateBag) {}
diff --git a/builder/oneandone/step_take_snapshot.go b/builder/oneandone/step_take_snapshot.go
new file mode 100644
index 000000000..8828c123d
--- /dev/null
+++ b/builder/oneandone/step_take_snapshot.go
@@ -0,0 +1,49 @@
+package oneandone
+
+import (
+ "github.com/1and1/oneandone-cloudserver-sdk-go"
+ "github.com/mitchellh/multistep"
+ "github.com/mitchellh/packer/packer"
+)
+
+type stepTakeSnapshot struct{}
+
+func (s *stepTakeSnapshot) Run(state multistep.StateBag) multistep.StepAction {
+ ui := state.Get("ui").(packer.Ui)
+ c := state.Get("config").(*Config)
+
+ ui.Say("Creating Snapshot...")
+
+ token := oneandone.SetToken(c.Token)
+ api := oneandone.New(token, c.Url)
+
+ serverId := state.Get("server_id").(string)
+
+ req := oneandone.ImageConfig{
+ Name: c.SnapshotName,
+ Description: "Packer image",
+ ServerId: serverId,
+ Frequency: "WEEKLY",
+ NumImages: 1,
+ }
+
+ img_id, img, err := api.CreateImage(&req)
+
+ if err != nil {
+ ui.Error(err.Error())
+ return multistep.ActionHalt
+ } else {
+ api.WaitForState(img, "ENABLED", 1, c.Timeout)
+ if err != nil {
+ ui.Error(err.Error())
+ return multistep.ActionHalt
+ }
+ }
+
+ state.Put("snapshot_id", img_id)
+ state.Put("snapshot_name", img.Name)
+ return multistep.ActionContinue
+}
+
+func (s *stepTakeSnapshot) Cleanup(state multistep.StateBag) {
+}
diff --git a/command/plugin.go b/command/plugin.go
index b20fa0674..dce7d9311 100644
--- a/command/plugin.go
+++ b/command/plugin.go
@@ -24,6 +24,7 @@ import (
filebuilder "github.com/mitchellh/packer/builder/file"
googlecomputebuilder "github.com/mitchellh/packer/builder/googlecompute"
nullbuilder "github.com/mitchellh/packer/builder/null"
+ oneandonebuilder "github.com/mitchellh/packer/builder/oneandone"
openstackbuilder "github.com/mitchellh/packer/builder/openstack"
parallelsisobuilder "github.com/mitchellh/packer/builder/parallels/iso"
parallelspvmbuilder "github.com/mitchellh/packer/builder/parallels/pvm"
@@ -79,6 +80,7 @@ var Builders = map[string]packer.Builder{
"file": new(filebuilder.Builder),
"googlecompute": new(googlecomputebuilder.Builder),
"null": new(nullbuilder.Builder),
+ "oneandone": new(oneandonebuilder.Builder),
"openstack": new(openstackbuilder.Builder),
"parallels-iso": new(parallelsisobuilder.Builder),
"parallels-pvm": new(parallelspvmbuilder.Builder),
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/LICENSE b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/LICENSE
new file mode 100644
index 000000000..9fb7e22bc
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/LICENSE
@@ -0,0 +1,202 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright (c) 2016 1&1 Internet SE
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/README.md b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/README.md
new file mode 100644
index 000000000..adb9cd19b
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/README.md
@@ -0,0 +1,2573 @@
+# 1&1 Cloudserver Go SDK
+
+The 1&1 Go SDK is a Go library designed for interaction with the 1&1 cloud platform over the REST API.
+
+This guide contains instructions on getting started with the library and automating various management tasks available through the 1&1 Cloud Panel UI.
+
+## Table of Contents
+
+- [Overview](#overview)
+- [Getting Started](#getting-started)
+ - [Installation](#installation)
+ - [Authentication](#authentication)
+- [Operations](#operations)
+ - [Servers](#servers)
+ - [Images](#images)
+ - [Shared Storages](#shared-storages)
+ - [Firewall Policies](#firewall-policies)
+ - [Load Balancers](#load-balancers)
+ - [Public IPs](#public-ips)
+ - [Private Networks](#private-networks)
+ - [VPNs](#vpns)
+ - [Monitoring Center](#monitoring-center)
+ - [Monitoring Policies](#monitoring-policies)
+ - [Logs](#logs)
+ - [Users](#users)
+ - [Roles](#roles)
+ - [Usages](#usages)
+ - [Server Appliances](#server-appliances)
+ - [DVD ISO](#dvd-iso)
+ - [Ping](#ping)
+ - [Pricing](#pricing)
+ - [Data Centers](#data-centers)
+- [Examples](#examples)
+- [Index](#index)
+
+## Overview
+
+This SDK is a wrapper for the 1&1 REST API written in Go(lang). All operations against the API are performed over SSL and authenticated using your 1&1 token key. The Go library facilitates the access to the REST API either within an instance running on 1&1 platform or directly across the Internet from any HTTPS-enabled application.
+
+For more information on the 1&1 Cloud Server SDK for Go, visit the [Community Portal](https://www.1and1.com/cloud-community/).
+
+## Getting Started
+
+Before you begin you will need to have signed up for a 1&1 account. The credentials you create during sign-up will be used to authenticate against the API.
+
+Install the Go language tools. Find the install package and instructions on the official Go website. Make sure that you have set up the `GOPATH` environment variable properly, as indicated in the instructions.
+
+### Installation
+
+The official Go library is available from the 1&1 GitHub account found here.
+
+Use the following Go command to download oneandone-cloudserver-sdk-go to your configured GOPATH:
+
+`go get github.com/1and1/oneandone-cloudserver-sdk-go`
+
+Import the library in your Go code:
+
+`import "github.com/1and1/oneandone-cloudserver-sdk-go"`
+
+### Authentication
+
+Set the authentication token and create the API client:
+
+```
+token := oneandone.SetToken("82ee732b8d47e451be5c6ad5b7b56c81")
+api := oneandone.New(token, oneandone.BaseUrl)
+```
+
+Refer to the [Examples](#examples) and [Operations](#operations) sections for additional information.
+
+## Operations
+
+### Servers
+
+**List all servers:**
+
+`servers, err := api.ListServers()`
+
+Alternatively, use the method with query parameters.
+
+`servers, err := api.ListServers(page, per_page, sort, query, fields)`
+
+To paginate the list of servers received in the response use `page` and `per_page` parameters. Set `per_page` to the number of servers that will be shown in each page. `page` indicates the current page. When set to an integer value that is less or equal to zero, the parameters are ignored by the framework.
+
+To receive the list of servers sorted in expected order pass a server property (e.g. `"name"`) in `sort` parameter.
+
+Use `query` parameter to search for a string in the response and return only the server instances that contain it.
+
+To retrieve a collection of servers containing only the requested fields pass a list of comma separated properties (e.g. `"id,name,description,hardware.ram"`) in `fields` parameter.
+
+If any of the parameters `sort`, `query` or `fields` is set to an empty string, it is ignored in the request.
+
+**Retrieve a single server:**
+
+`server, err := api.GetServer(server_id)`
+
+**List fixed-size server templates:**
+
+`fiss, err := api.ListFixedInstanceSizes()`
+
+**Retrieve information about a fixed-size server template:**
+
+`fis, err := api.GetFixedInstanceSize(fis_id)`
+
+**Retrieve information about a server's hardware:**
+
+`hardware, err := api.GetServerHardware(server_id)`
+
+**List a server's HDDs:**
+
+`hdds, err := api.ListServerHdds(server_id)`
+
+**Retrieve a single server HDD:**
+
+`hdd, err := api.GetServerHdd(server_id, hdd_id)`
+
+**Retrieve information about a server's image:**
+
+`image, err := api.GetServerImage(server_id)`
+
+**List a server's IPs:**
+
+`ips, err := api.ListServerIps(server_id)`
+
+**Retrieve information about a single server IP:**
+
+`ip, err := api.GetServerIp(server_id, ip_id)`
+
+**Retrieve information about a server's firewall policy:**
+
+`firewall, err := api.GetServerIpFirewallPolicy(server_id, ip_id)`
+
+**List all load balancers assigned to a server IP:**
+
+`lbs, err := api.ListServerIpLoadBalancers(server_id, ip_id)`
+
+**Retrieve information about a server's status:**
+
+`status, err := api.GetServerStatus(server_id)`
+
+**Retrieve information about the DVD loaded into the virtual DVD unit of a server:**
+
+`dvd, err := api.GetServerDvd(server_id)`
+
+**List a server's private networks:**
+
+`pns, err := api.ListServerPrivateNetworks(server_id)`
+
+**Retrieve information about a server's private network:**
+
+`pn, err := api.GetServerPrivateNetwork(server_id, pn_id)`
+
+**Retrieve information about a server's snapshot:**
+
+`snapshot, err := api.GetServerSnapshot(server_id)`
+
+**Create a server:**
+
+```
+req := oneandone.ServerRequest {
+ Name: "Server Name",
+ Description: "Server description.",
+ ApplianceId: server_appliance_id,
+ PowerOn: true,
+ Hardware: oneandone.Hardware {
+ Vcores: 1,
+ CoresPerProcessor: 1,
+ Ram: 2,
+ Hdds: []oneandone.Hdd {
+ oneandone.Hdd {
+ Size: 100,
+ IsMain: true,
+ },
+ },
+ },
+ }
+
+server_id, server, err := api.CreateServer(&req)
+```
+
+**Create a fixed-size server and return back the server's IP address and first password:**
+
+```
+req := oneandone.ServerRequest {
+ Name: server_name,
+ ApplianceId: server_appliance_id,
+ PowerOn: true_or_false,
+ Hardware: oneandone.Hardware {
+ FixedInsSizeId: fixed_instance_size_id,
+ },
+ }
+
+ip_address, password, err := api.CreateServerEx(&req, timeout)
+```
+
+**Update a server:**
+
+`server, err := api.RenameServer(server_id, new_name, new_desc)`
+
+**Delete a server:**
+
+`server, err := api.DeleteServer(server_id, keep_ips)`
+
+Set `keep_ips` parameter to `true` for keeping server IPs after deleting a server.
+
+**Update a server's hardware:**
+
+```
+hardware := oneandone.Hardware {
+ Vcores: 2,
+ CoresPerProcessor: 1,
+ Ram: 2,
+ }
+
+server, err := api.UpdateServerHardware(server_id, &hardware)
+```
+
+**Add new hard disk(s) to a server:**
+
+```
+hdds := oneandone.ServerHdds {
+ Hdds: []oneandone.Hdd {
+ {
+ Size: 50,
+ IsMain: false,
+ },
+ },
+ }
+
+server, err := api.AddServerHdds(server_id, &hdds)
+```
+
+**Resize a server's hard disk:**
+
+`server, err := api.ResizeServerHdd(server_id, hdd_id, new_size)`
+
+**Remove a server's hard disk:**
+
+`server, err := api.DeleteServerHdd(server_id, hdd_id)`
+
+**Load a DVD into the virtual DVD unit of a server:**
+
+`server, err := api.LoadServerDvd(server_id, dvd_id)`
+
+**Unload a DVD from the virtual DVD unit of a server:**
+
+`server, err := api.EjectServerDvd(server_id)`
+
+**Reinstall a new image into a server:**
+
+`server, err := api.ReinstallServerImage(server_id, image_id, password, fp_id)`
+
+**Assign a new IP to a server:**
+
+`server, err := api.AssignServerIp(server_id, ip_type)`
+
+**Release an IP and optionally remove it from a server:**
+
+`server, err := api.DeleteServerIp(server_id, ip_id, keep_ip)`
+
+Set `keep_ip` to true for releasing the IP without removing it.
+
+**Assign a new firewall policy to a server's IP:**
+
+`server, err := api.AssignServerIpFirewallPolicy(server_id, ip_id, fp_id)`
+
+**Remove a firewall policy from a server's IP:**
+
+`server, err := api.UnassignServerIpFirewallPolicy(server_id, ip_id)`
+
+**Assign a new load balancer to a server's IP:**
+
+`server, err := api.AssignServerIpLoadBalancer(server_id, ip_id, lb_id)`
+
+**Remove a load balancer from a server's IP:**
+
+`server, err := api.UnassignServerIpLoadBalancer(server_id, ip_id, lb_id)`
+
+**Start a server:**
+
+`server, err := api.StartServer(server_id)`
+
+**Reboot a server:**
+
+`server, err := api.RebootServer(server_id, is_hardware)`
+
+Set `is_hardware` to true for HARDWARE method of rebooting.
+
+Set `is_hardware` to false for SOFTWARE method of rebooting.
+
+**Shutdown a server:**
+
+`server, err := api.ShutdownServer(server_id, is_hardware)`
+
+Set `is_hardware` to true for HARDWARE method of powering off.
+
+Set `is_hardware` to false for SOFTWARE method of powering off.
+
+**Assign a private network to a server:**
+
+`server, err := api.AssignServerPrivateNetwork(server_id, pn_id)`
+
+**Remove a server's private network:**
+
+`server, err := api.RemoveServerPrivateNetwork(server_id, pn_id)`
+
+**Create a new server's snapshot:**
+
+`server, err := api.CreateServerSnapshot(server_id)`
+
+**Restore a server's snapshot:**
+
+`server, err := api.RestoreServerSnapshot(server_id, snapshot_id)`
+
+**Remove a server's snapshot:**
+
+`server, err := api.DeleteServerSnapshot(server_id, snapshot_id);`
+
+**Clone a server:**
+
+`server, err := api.CloneServer(server_id, new_name)`
+
+
+### Images
+
+**List all images:**
+
+`images, err = api.ListImages()`
+
+Alternatively, use the method with query parameters.
+
+`images, err = api.ListImages(page, per_page, sort, query, fields)`
+
+To paginate the list of images received in the response use `page` and `per_page` parameters. set `per_page` to the number of images that will be shown in each page. `page` indicates the current page. When set to an integer value that is less or equal to zero, the parameters are ignored by the framework.
+
+To receive the list of images sorted in expected order pass an image property (e.g. `"name"`) in `sort` parameter. Prefix the sorting attribute with `-` sign for sorting in descending order.
+
+Use `query` parameter to search for a string in the response and return only the elements that contain it.
+
+To retrieve a collection of images containing only the requested fields pass a list of comma separated properties (e.g. `"id,name,creation_date"`) in `fields` parameter.
+
+If any of the parameters `sort`, `query` or `fields` is set to an empty string, it is ignored in the request.
+
+**Retrieve a single image:**
+
+`image, err = api.GetImage(image_id)`
+
+
+**Create an image:**
+
+```
+request := oneandone.ImageConfig {
+ Name: image_name,
+ Description: image_description,
+ ServerId: server_id,
+ Frequency: image_frequenct,
+ NumImages: number_of_images,
+ }
+
+image_id, image, err = api.CreateImage(&request)
+```
+All fields except `Description` are required. `Frequency` may be set to `"ONCE"`, `"DAILY"` or `"WEEKLY"`.
+
+**Update an image:**
+
+
+`image, err = api.UpdateImage(image_id, new_name, new_description, new_frequenct)`
+
+If any of the parameters `new_name`, `new_description` or `new_frequenct` is set to an empty string, it is ignored in the request. `Frequency` may be set to `"ONCE"`, `"DAILY"` or `"WEEKLY"`.
+
+**Delete an image:**
+
+`image, err = api.DeleteImage(image_id)`
+
+### Shared Storages
+
+`ss, err := api.ListSharedStorages()`
+
+Alternatively, use the method with query parameters.
+
+`ss, err := api.ListSharedStorages(page, per_page, sort, query, fields)`
+
+To paginate the list of shared storages received in the response use `page` and `per_page` parameters. Set `per_page` to the number of volumes that will be shown in each page. `page` indicates the current page. When set to an integer value that is less or equal to zero, the parameters are ignored by the framework.
+
+To receive the list of shared storages sorted in expected order pass a volume property (e.g. `"name"`) in `sort` parameter. Prefix the sorting attribute with `-` sign for sorting in descending order.
+
+Use `query` parameter to search for a string in the response and return only the volume instances that contain it.
+
+To retrieve a collection of shared storages containing only the requested fields pass a list of comma separated properties (e.g. `"id,name,size,size_used"`) in `fields` parameter.
+
+If any of the parameters `sort`, `query` or `fields` is set to an empty string, it is ignored in the request.
+
+**Retrieve a shared storage:**
+
+`ss, err := api.GetSharedStorage(ss_id)`
+
+
+**Create a shared storage:**
+
+```
+request := oneandone.SharedStorageRequest {
+ Name: test_ss_name,
+ Description: test_ss_desc,
+ Size: oneandone.Int2Pointer(size),
+ }
+
+ss_id, ss, err := api.CreateSharedStorage(&request)
+
+```
+`Description` is optional parameter.
+
+
+**Update a shared storage:**
+
+```
+request := oneandone.SharedStorageRequest {
+ Name: new_name,
+ Description: new_desc,
+ Size: oneandone.Int2Pointer(new_size),
+ }
+
+ss, err := api.UpdateSharedStorage(ss_id, &request)
+```
+All request's parameters are optional.
+
+
+**Remove a shared storage:**
+
+`ss, err := api.DeleteSharedStorage(ss_id)`
+
+
+**List a shared storage servers:**
+
+`ss_servers, err := api.ListSharedStorageServers(ss_id)`
+
+
+**Retrieve a shared storage server:**
+
+`ss_server, err := api.GetSharedStorageServer(ss_id, server_id)`
+
+
+**Add servers to a shared storage:**
+
+```
+servers := []oneandone.SharedStorageServer {
+ {
+ Id: server_id,
+ Rights: permissions,
+ } ,
+ }
+
+ss, err := api.AddSharedStorageServers(ss_id, servers)
+```
+`Rights` may be set to `R` or `RW` string.
+
+
+**Remove a server from a shared storage:**
+
+`ss, err := api.DeleteSharedStorageServer(ss_id, server_id)`
+
+
+**Retrieve the credentials for accessing the shared storages:**
+
+`ss_credentials, err := api.GetSharedStorageCredentials()`
+
+
+**Change the password for accessing the shared storages:**
+
+`ss_credentials, err := api.UpdateSharedStorageCredentials(new_password)`
+
+
+### Firewall Policies
+
+**List firewall policies:**
+
+`firewalls, err := api.ListFirewallPolicies()`
+
+Alternatively, use the method with query parameters.
+
+`firewalls, err := api.ListFirewallPolicies(page, per_page, sort, query, fields)`
+
+To paginate the list of firewall policies received in the response use `page` and `per_page` parameters. Set `per_page` to the number of firewall policies that will be shown in each page. `page` indicates the current page. When set to an integer value that is less or equal to zero, the parameters are ignored by the framework.
+
+To receive the list of firewall policies sorted in expected order pass a firewall policy property (e.g. `"name"`) in `sort` parameter. Prefix the sorting attribute with `-` sign for sorting in descending order.
+
+Use `query` parameter to search for a string in the response and return only the firewall policy instances that contain it.
+
+To retrieve a collection of firewall policies containing only the requested fields pass a list of comma separated properties (e.g. `"id,name,creation_date"`) in `fields` parameter.
+
+If any of the parameters `sort`, `query` or `fields` is set to an empty string, it is ignored in the request.
+
+**Retrieve a single firewall policy:**
+
+`firewall, err := api.GetFirewallPolicy(fp_id)`
+
+
+**Create a firewall policy:**
+
+```
+request := oneandone.FirewallPolicyRequest {
+ Name: fp_name,
+ Description: fp_desc,
+ Rules: []oneandone.FirewallPolicyRule {
+ {
+ Protocol: protocol,
+ PortFrom: oneandone.Int2Pointer(port_from),
+ PortTo: oneandone.Int2Pointer(port_to),
+ SourceIp: source_ip,
+ },
+ },
+ }
+
+firewall_id, firewall, err := api.CreateFirewallPolicy(&request)
+```
+`SourceIp` and `Description` are optional parameters.
+
+
+**Update a firewall policy:**
+
+`firewall, err := api.UpdateFirewallPolicy(fp_id, fp_new_name, fp_new_description)`
+
+Passing an empty string in `fp_new_name` or `fp_new_description` skips updating the firewall policy name or description respectively.
+
+
+**Delete a firewall policy:**
+
+`firewall, err := api.DeleteFirewallPolicy(fp_id)`
+
+
+**List servers/IPs attached to a firewall policy:**
+
+`server_ips, err := api.ListFirewallPolicyServerIps(fp_id)`
+
+
+**Retrieve information about a server/IP assigned to a firewall policy:**
+
+`server_ip, err := api.GetFirewallPolicyServerIp(fp_id, ip_id)`
+
+
+**Add servers/IPs to a firewall policy:**
+
+`firewall, err := api.AddFirewallPolicyServerIps(fp_id, ip_ids)`
+
+`ip_ids` is a slice of IP ID's.
+
+
+**Remove a server/IP from a firewall policy:**
+
+`firewall, err := api.DeleteFirewallPolicyServerIp(fp_id, ip_id)`
+
+
+**List rules of a firewall policy:**
+
+`fp_rules, err := api.ListFirewallPolicyRules(fp_id)`
+
+
+**Retrieve information about a rule of a firewall policy:**
+
+`fp_rule, err := api.GetFirewallPolicyRule(fp_id, rule_id)`
+
+
+**Adds new rules to a firewall policy:**
+
+```
+fp_rules := []oneandone.FirewallPolicyRule {
+ {
+ Protocol: protocol1,
+ PortFrom: oneandone.Int2Pointer(port_from1),
+ PortTo: oneandone.Int2Pointer(port_to1),
+ SourceIp: source_ip,
+ },
+ {
+ Protocol: protocol2,
+ PortFrom: oneandone.Int2Pointer(port_from2),
+ PortTo: oneandone.Int2Pointer(port_to2),
+ },
+ }
+
+firewall, err := api.AddFirewallPolicyRules(fp_id, fp_rules)
+```
+
+**Remove a rule from a firewall policy:**
+
+`firewall, err := api.DeleteFirewallPolicyRule(fp_id, rule_id)`
+
+
+### Load Balancers
+
+**List load balancers:**
+
+`loadbalancers, err := api.ListLoadBalancers()`
+
+Alternatively, use the method with query parameters.
+
+`loadbalancers, err := api.ListLoadBalancers(page, per_page, sort, query, fields)`
+
+To paginate the list of load balancers received in the response use `page` and `per_page` parameters. Set `per_page` to the number of load balancers that will be shown in each page. `page` indicates the current page. When set to an integer value that is less or equal to zero, the parameters are ignored by the framework.
+
+To receive the list of load balancers sorted in expected order pass a load balancer property (e.g. `"name"`) in `sort` parameter. Prefix the sorting attribute with `-` sign for sorting in descending order.
+
+Use `query` parameter to search for a string in the response and return only the load balancer instances that contain it.
+
+To retrieve a collection of load balancers containing only the requested fields pass a list of comma separated properties (e.g. `"ip,name,method"`) in `fields` parameter.
+
+If any of the parameters `sort`, `query` or `fields` is set to an empty string, it is ignored in the request.
+
+**Retrieve a single load balancer:**
+
+`loadbalancer, err := api.GetLoadBalancer(lb_id)`
+
+
+**Create a load balancer:**
+
+```
+request := oneandone.LoadBalancerRequest {
+ Name: lb_name,
+ Description: lb_description,
+ Method: lb_method,
+ Persistence: oneandone.Bool2Pointer(true_or_false),
+ PersistenceTime: oneandone.Int2Pointer(seconds1),
+ HealthCheckTest: protocol1,
+ HealthCheckInterval: oneandone.Int2Pointer(seconds2),
+ HealthCheckPath: health_check_path,
+ HealthCheckPathParser: health_check_path_parser,
+ Rules: []oneandone.LoadBalancerRule {
+ {
+ Protocol: protocol1,
+ PortBalancer: lb_port,
+ PortServer: server_port,
+ Source: source_ip,
+ },
+ },
+ }
+
+loadbalancer_id, loadbalancer, err := api.CreateLoadBalancer(&request)
+```
+Optional parameters are `HealthCheckPath`, `HealthCheckPathParser`, `Source` and `Description`. Load balancer `Method` must be set to `"ROUND_ROBIN"` or `"LEAST_CONNECTIONS"`.
+
+**Update a load balancer:**
+```
+request := oneandone.LoadBalancerRequest {
+ Name: new_name,
+ Description: new_description,
+ Persistence: oneandone.Bool2Pointer(true_or_false),
+ PersistenceTime: oneandone.Int2Pointer(new_seconds1),
+ HealthCheckTest: new_protocol,
+ HealthCheckInterval: oneandone.Int2Pointer(new_seconds2),
+ HealthCheckPath: new_path,
+ HealthCheckPathParser: new_parser,
+ Method: new_lb_method,
+ }
+
+loadbalancer, err := api.UpdateLoadBalancer(lb_id, &request)
+```
+All updatable fields are optional.
+
+
+**Delete a load balancer:**
+
+`loadbalancer, err := api.DeleteLoadBalancer(lb_id)`
+
+
+**List servers/IPs attached to a load balancer:**
+
+`server_ips, err := api.ListLoadBalancerServerIps(lb_id)`
+
+
+**Retrieve information about a server/IP assigned to a load balancer:**
+
+`server_ip, err := api.GetLoadBalancerServerIp(lb_id, ip_id)`
+
+
+**Add servers/IPs to a load balancer:**
+
+`loadbalancer, err := api.AddLoadBalancerServerIps(lb_id, ip_ids)`
+
+`ip_ids` is a slice of IP ID's.
+
+
+**Remove a server/IP from a load balancer:**
+
+`loadbalancer, err := api.DeleteLoadBalancerServerIp(lb_id, ip_id)`
+
+
+**List rules of a load balancer:**
+
+`lb_rules, err := api.ListLoadBalancerRules(lb_id)`
+
+
+**Retrieve information about a rule of a load balancer:**
+
+`lb_rule, err := api.GetLoadBalancerRule(lb_id, rule_id)`
+
+
+**Adds new rules to a load balancer:**
+
+```
+lb_rules := []oneandone.LoadBalancerRule {
+ {
+ Protocol: protocol1,
+ PortBalancer: lb_port1,
+ PortServer: server_port1,
+ Source: source_ip,
+ },
+ {
+ Protocol: protocol2,
+ PortBalancer: lb_port2,
+ PortServer: server_port2,
+ },
+ }
+
+loadbalancer, err := api.AddLoadBalancerRules(lb_id, lb_rules)
+```
+
+**Remove a rule from a load balancer:**
+
+`loadbalancer, err := api.DeleteLoadBalancerRule(lb_id, rule_id)`
+
+
+### Public IPs
+
+**Retrieve a list of your public IPs:**
+
+`public_ips, err := api.ListPublicIps()`
+
+Alternatively, use the method with query parameters.
+
+`public_ips, err := api.ListPublicIps(page, per_page, sort, query, fields)`
+
+To paginate the list of public IPs received in the response use `page` and `per_page` parameters. Set `per_page` to the number of public IPs that will be shown in each page. `page` indicates the current page. When set to an integer value that is less or equal to zero, the parameters are ignored by the framework.
+
+To receive the list of public IPs sorted in expected order pass a public IP property (e.g. `"ip"`) in `sort` parameter. Prefix the sorting attribute with `-` sign for sorting in descending order.
+
+Use `query` parameter to search for a string in the response and return only the public IP instances that contain it.
+
+To retrieve a collection of public IPs containing only the requested fields pass a list of comma separated properties (e.g. `"id,ip,reverse_dns"`) in `fields` parameter.
+
+If any of the parameters `sort`, `query` or `fields` is set to an empty string, it is ignored in the request.
+
+
+**Retrieve a single public IP:**
+
+`public_ip, err := api.GetPublicIp(ip_id)`
+
+
+**Create a public IP:**
+
+`ip_id, public_ip, err := api.CreatePublicIp(ip_type, reverse_dns)`
+
+Both parameters are optional and may be left blank. `ip_type` may be set to `"IPV4"` or `"IPV6"`. Presently, only IPV4 is supported.
+
+**Update the reverse DNS of a public IP:**
+
+`public_ip, err := api.UpdatePublicIp(ip_id, reverse_dns)`
+
+If an empty string is passed in `reverse_dns,` it removes previous reverse dns of the public IP.
+
+**Remove a public IP:**
+
+`public_ip, err := api.DeletePublicIp(ip_id)`
+
+
+### Private Networks
+
+**List all private networks:**
+
+`private_nets, err := api.ListPrivateNetworks()`
+
+Alternatively, use the method with query parameters.
+
+`private_nets, err := api.ListPrivateNetworks(page, per_page, sort, query, fields)`
+
+To paginate the list of private networks received in the response use `page` and `per_page` parameters. Set `per_page` to the number of private networks that will be shown in each page. `page` indicates the current page. When set to an integer value that is less or equal to zero, the parameters are ignored by the framework.
+
+To receive the list of private networks sorted in expected order pass a private network property (e.g. `"-creation_date"`) in `sort` parameter. Prefix the sorting attribute with `-` sign for sorting in descending order.
+
+Use `query` parameter to search for a string in the response and return only the private network instances that contain it.
+
+To retrieve a collection of private networks containing only the requested fields pass a list of comma separated properties (e.g. `"id,name,creation_date"`) in `fields` parameter.
+
+If any of the parameters `sort`, `query` or `fields` is blank, it is ignored in the request.
+
+**Retrieve information about a private network:**
+
+`private_net, err := api.GetPrivateNetwork(pn_id)`
+
+**Create a new private network:**
+
+```
+request := oneandone.PrivateNetworkRequest {
+ Name: pn_name,
+ Description: pn_description,
+ NetworkAddress: network_address,
+ SubnetMask: subnet_mask,
+ }
+
+pnet_id, private_net, err := api.CreatePrivateNetwork(&request)
+```
+Private network `Name` is required parameter.
+
+
+**Modify a private network:**
+
+```
+request := oneandone.PrivateNetworkRequest {
+ Name: new_pn_name,
+ Description: new_pn_description,
+ NetworkAddress: new_network_address,
+ SubnetMask: new_subnet_mask,
+ }
+
+private_net, err := api.UpdatePrivateNetwork(pn_id, &request)
+```
+All parameters in the request are optional.
+
+
+**Delete a private network:**
+
+`private_net, err := api.DeletePrivateNetwork(pn_id)`
+
+
+**List all servers attached to a private network:**
+
+`servers, err = := api.ListPrivateNetworkServers(pn_id)`
+
+
+**Retrieve a server attached to a private network:**
+
+`server, err = := api.GetPrivateNetworkServer(pn_id, server_id)`
+
+
+**Attach servers to a private network:**
+
+`private_net, err := api.AttachPrivateNetworkServers(pn_id, server_ids)`
+
+`server_ids` is a slice of server ID's.
+
+*Note:* Servers cannot be attached to a private network if they currently have a snapshot.
+
+
+**Remove a server from a private network:**
+
+`private_net, err := api.DetachPrivateNetworkServer(pn_id, server_id)`
+
+*Note:* The server cannot be removed from a private network if it currently has a snapshot or it is powered on.
+
+
+### VPNs
+
+**List all VPNs:**
+
+`vpns, err := api.ListVPNs()`
+
+Alternatively, use the method with query parameters.
+
+`vpns, err := api.ListVPNs(page, per_page, sort, query, fields)`
+
+To paginate the list of VPNs received in the response use `page` and `per_page` parameters. Set ` per_page` to the number of VPNs that will be shown in each page. `page` indicates the current page. When set to an integer value that is less or equal to zero, the parameters are ignored by the framework.
+
+To receive the list of VPNs sorted in expected order pass a VPN property (e.g. `"name"`) in `sort` parameter. Prefix the sorting attribute with `-` sign for sorting in descending order.
+
+Use `query` parameter to search for a string in the response and return only the VPN instances that contain it.
+
+To retrieve a collection of VPNs containing only the requested fields pass a list of comma separated properties (e.g. `"id,name,creation_date"`) in `fields` parameter.
+
+If any of the parameters `sort`, `query` or `fields` is set to an empty string, it is ignored in the request.
+
+**Retrieve information about a VPN:**
+
+`vpn, err := api.GetVPN(vpn_id)`
+
+**Create a VPN:**
+
+`vpn, err := api.CreateVPN(vpn_name, vpn_description, datacenter_id)`
+
+**Modify a VPN:**
+
+`vpn, err := api.ModifyVPN(vpn_id, new_name, new_description)`
+
+**Delete a VPN:**
+
+`vpn, err := api.DeleteVPN(vpn_id)`
+
+**Retrieve a VPN's configuration file:**
+
+`base64_encoded_string, err := api.GetVPNConfigFile(vpn_id)`
+
+
+### Monitoring Center
+
+**List all usages and alerts of monitoring servers:**
+
+`server_usages, err := api.ListMonitoringServersUsages()`
+
+Alternatively, use the method with query parameters.
+
+`server_usages, err := api.ListMonitoringServersUsages(page, per_page, sort, query, fields)`
+
+To paginate the list of server usages received in the response use `page` and `per_page` parameters. Set `per_page` to the number of server usages that will be shown in each page. `page` indicates the current page. When set to an integer value that is less or equal to zero, the parameters are ignored by the framework.
+
+To receive the list of server usages sorted in expected order pass a server usage property (e.g. `"name"`) in `sort` parameter. Prefix the sorting attribute with `-` sign for sorting in descending order.
+
+Use `query` parameter to search for a string in the response and return only the usage instances that contain it.
+
+To retrieve a collection of server usages containing only the requested fields pass a list of comma separated properties (e.g. `"id,name,status.state"`) in `fields` parameter.
+
+If any of the parameters `sort`, `query` or `fields` is blank, it is ignored in the request.
+
+**Retrieve the usages and alerts for a monitoring server:**
+
+`server_usage, err := api.GetMonitoringServerUsage(server_id, period)`
+
+`period` may be set to `"LAST_HOUR"`, `"LAST_24H"`, `"LAST_7D"`, `"LAST_30D"`, `"LAST_365D"` or `"CUSTOM"`. If `period` is set to `"CUSTOM"`, the `start_date` and `end_date` parameters are required to be set in **RFC 3339** date/time format (e.g. `2015-13-12T00:01:00Z`).
+
+`server_usage, err := api.GetMonitoringServerUsage(server_id, period, start_date, end_date)`
+
+### Monitoring Policies
+
+**List all monitoring policies:**
+
+`mon_policies, err := api.ListMonitoringPolicies()`
+
+Alternatively, use the method with query parameters.
+
+`mon_policies, err := api.ListMonitoringPolicies(page, per_page, sort, query, fields)`
+
+To paginate the list of monitoring policies received in the response use `page` and `per_page` parameters. Set `per_page` to the number of monitoring policies that will be shown in each page. `page` indicates the current page. When set to an integer value that is less or equal to zero, the parameters are ignored by the framework.
+
+To receive the list of monitoring policies sorted in expected order pass a monitoring policy property (e.g. `"name"`) in `sort` parameter. Prefix the sorting attribute with `-` sign for sorting in descending order.
+
+Use `query` parameter to search for a string in the response and return only the monitoring policy instances that contain it.
+
+To retrieve a collection of monitoring policies containing only the requested fields pass a list of comma separated properties (e.g. `"id,name,creation_date"`) in `fields` parameter.
+
+If any of the parameters `sort`, `query` or `fields` is set to an empty string, it is ignored in the request.
+
+**Retrieve a single monitoring policy:**
+
+`mon_policy, err := api.GetMonitoringPolicy(mp_id)`
+
+
+**Create a monitoring policy:**
+
+```
+request := oneandone.MonitoringPolicy {
+ Name: mp_name,
+ Description: mp_desc,
+ Email: mp_mail,
+ Agent: true_or_false,
+ Thresholds: &oneandone.MonitoringThreshold {
+ Cpu: &oneandone.MonitoringLevel {
+ Warning: &oneandone.MonitoringValue {
+ Value: threshold_value,
+ Alert: true_or_false,
+ },
+ Critical: &oneandone.MonitoringValue {
+ Value: threshold_value,
+ Alert: true_or_false,
+ },
+ },
+ Ram: &oneandone.MonitoringLevel {
+ Warning: &oneandone.MonitoringValue {
+ Value: threshold_value,
+ Alert: true_or_false,
+ },
+ Critical: &oneandone.MonitoringValue {
+ Value: threshold_value,
+ Alert: true_or_false,
+ },
+ },
+ Disk: &oneandone.MonitoringLevel {
+ Warning: &oneandone.MonitoringValue {
+ Value: threshold_value,
+ Alert: true_or_false,
+ },
+ Critical: &oneandone.MonitoringValue {
+ Value: threshold_value,
+ Alert: true_or_false,
+ },
+ },
+ Transfer: &oneandone.MonitoringLevel {
+ Warning: &oneandone.MonitoringValue {
+ Value: threshold_value,
+ Alert: true_or_false,
+ },
+ Critical: &oneandone.MonitoringValue {
+ Value: threshold_value,
+ Alert: true_or_false,
+ },
+ },
+ InternalPing: &oneandone.MonitoringLevel {
+ Warning: &oneandone.MonitoringValue {
+ Value: threshold_value,
+ Alert: true_or_false,
+ },
+ Critical: &oneandone.MonitoringValue {
+ Value: threshold_value,
+ Alert: true_or_false,
+ },
+ },
+ },
+ Ports: []oneandone.MonitoringPort {
+ {
+ Protocol: protocol,
+ Port: port,
+ AlertIf: responding_or_not_responding,
+ EmailNotification: true_or_false,
+ },
+ },
+ Processes: []oneandone.MonitoringProcess {
+ {
+ Process: process_name,
+ AlertIf: running_or_not_running,
+ EmailNotification: true_or_false,
+ },
+ },
+ }
+
+mpolicy_id, mon_policy, err := api.CreateMonitoringPolicy(&request)
+```
+All fields, except `Description`, are required. `AlertIf` property accepts values `"RESPONDING"`/`"NOT_RESPONDING"` for ports, and `"RUNNING"`/`"NOT_RUNNING"` for processes.
+
+
+**Update a monitoring policy:**
+
+```
+request := oneandone.MonitoringPolicy {
+ Name: new_mp_name,
+ Description: new_mp_desc,
+ Email: new_mp_mail,
+ Thresholds: &oneandone.MonitoringThreshold {
+ Cpu: &oneandone.MonitoringLevel {
+ Warning: &oneandone.MonitoringValue {
+ Value: new_threshold_value,
+ Alert: true_or_false,
+ },
+ Critical: &oneandone.MonitoringValue {
+ Value: new_threshold_value,
+ Alert: true_or_false,
+ },
+ },
+ Ram: &oneandone.MonitoringLevel {
+ Warning: &oneandone.MonitoringValue {
+ Value: new_threshold_value,
+ Alert: true_or_false,
+ },
+ Critical: &oneandone.MonitoringValue {
+ Value: new_threshold_value,
+ Alert: true_or_false,
+ },
+ },
+ Disk: &oneandone.MonitoringLevel {
+ Warning: &oneandone.MonitoringValue {
+ Value: new_threshold_value,
+ Alert: true_or_false,
+ },
+ Critical: &oneandone.MonitoringValue {
+ Value: new_threshold_value,
+ Alert: true_or_false,
+ },
+ },
+ Transfer: &oneandone.MonitoringLevel {
+ Warning: &oneandone.MonitoringValue {
+ Value: new_threshold_value,
+ Alert: true_or_false,
+ },
+ Critical: &oneandone.MonitoringValue {
+ Value: new_threshold_value,
+ Alert: true_or_false,
+ },
+ },
+ InternalPing: &oneandone.MonitoringLevel {
+ Warning: &oneandone.MonitoringValue {
+ Value: new_threshold_value,
+ Alert: true_or_false,
+ },
+ Critical: &oneandone.MonitoringValue {
+ Value: new_threshold_value,
+ Alert: true_or_false,
+ },
+ },
+ },
+ }
+
+mon_policy, err := api.UpdateMonitoringPolicy(mp_id, &request)
+```
+All fields of the request are optional. When a threshold is specified in the request, the threshold fields are required.
+
+**Delete a monitoring policy:**
+
+`mon_policy, err := api.DeleteMonitoringPolicy(mp_id)`
+
+
+**List all ports of a monitoring policy:**
+
+`mp_ports, err := api.ListMonitoringPolicyPorts(mp_id)`
+
+
+**Retrieve information about a port of a monitoring policy:**
+
+`mp_port, err := api.GetMonitoringPolicyPort(mp_id, port_id)`
+
+
+**Add new ports to a monitoring policy:**
+
+```
+mp_ports := []oneandone.MonitoringPort {
+ {
+ Protocol: protocol1,
+ Port: port1,
+ AlertIf: responding_or_not_responding,
+ EmailNotification: true_or_false,
+ },
+ {
+ Protocol: protocol2,
+ Port: port2,
+ AlertIf: responding_or_not_responding,
+ EmailNotification: true_or_false,
+ },
+ }
+
+mon_policy, err := api.AddMonitoringPolicyPorts(mp_id, mp_ports)
+```
+Port properties are mandatory.
+
+
+**Modify a port of a monitoring policy:**
+
+```
+mp_port := oneandone.MonitoringPort {
+ Protocol: protocol,
+ Port: port,
+ AlertIf: responding_or_not_responding,
+ EmailNotification: true_or_false,
+ }
+
+mon_policy, err := api.ModifyMonitoringPolicyPort(mp_id, port_id, &mp_port)
+```
+*Note:* `Protocol` and `Port` cannot be changed.
+
+
+**Remove a port from a monitoring policy:**
+
+`mon_policy, err := api.DeleteMonitoringPolicyPort(mp_id, port_id)`
+
+
+**List the processes of a monitoring policy:**
+
+`mp_processes, err := api.ListMonitoringPolicyProcesses(mp_id)`
+
+
+**Retrieve information about a process of a monitoring policy:**
+
+`mp_process, err := api.GetMonitoringPolicyProcess(mp_id, process_id)`
+
+
+**Add new processes to a monitoring policy:**
+
+```
+processes := []oneandone.MonitoringProcess {
+ {
+ Process: process_name1,
+ AlertIf: running_or_not_running,
+ EmailNotification: true_or_false,
+ },
+ {
+ Process: process_name2,
+ AlertIf: running_or_not_running,
+ EmailNotification: true_or_false,
+ },
+ }
+
+mon_policy, err := api.AddMonitoringPolicyProcesses(mp_id, processes)
+```
+All properties of the `MonitoringProcess` instance are required.
+
+
+**Modify a process of a monitoring policy:**
+
+```
+process := oneandone.MonitoringProcess {
+ Process: process_name,
+ AlertIf: running_or_not_running,
+ EmailNotification: true_or_false,
+ }
+
+mon_policy, err := api.ModifyMonitoringPolicyProcess(mp_id, process_id, &process)
+```
+
+*Note:* Process name cannot be changed.
+
+**Remove a process from a monitoring policy:**
+
+`mon_policy, err := api.DeleteMonitoringPolicyProcess(mp_id, process_id)`
+
+**List all servers attached to a monitoring policy:**
+
+`mp_servers, err := api.ListMonitoringPolicyServers(mp_id)`
+
+**Retrieve information about a server attached to a monitoring policy:**
+
+`mp_server, err := api.GetMonitoringPolicyServer(mp_id, server_id)`
+
+**Attach servers to a monitoring policy:**
+
+`mon_policy, err := api.AttachMonitoringPolicyServers(mp_id, server_ids)`
+
+`server_ids` is a slice of server ID's.
+
+**Remove a server from a monitoring policy:**
+
+`mon_policy, err := api.RemoveMonitoringPolicyServer(mp_id, server_id)`
+
+
+### Logs
+
+**List all logs:**
+
+`logs, err := api.ListLogs(period, nil, nil)`
+
+`period` can be set to `"LAST_HOUR"`, `"LAST_24H"`, `"LAST_7D"`, `"LAST_30D"`, `"LAST_365D"` or `"CUSTOM"`. If `period` is set to `"CUSTOM"`, the `start_date` and `end_date` parameters are required to be set in **RFC 3339** date/time format (e.g. `2015-13-12T00:01:00Z`).
+
+`logs, err := api.ListLogs(period, start_date, end_date)`
+
+Additional query parameters can be used.
+
+`logs, err := api.ListLogs(period, start_date, end_date, page, per_page, sort, query, fields)`
+
+To paginate the list of logs received in the response use `page` and `per_page` parameters. Set ` per_page` to the number of logs that will be shown in each page. `page` indicates the current page. When set to an integer value that is less or equal to zero, the parameters are ignored by the framework.
+
+To receive the list of logs sorted in expected order pass a logs property (e.g. `"action"`) in `sort` parameter. Prefix the sorting attribute with `-` sign for sorting in descending order.
+
+Use `query` parameter to search for a string in the response and return only the logs instances that contain it.
+
+To retrieve a collection of logs containing only the requested fields pass a list of comma separated properties (e.g. `"id,action,type"`) in `fields` parameter.
+
+If any of the parameters `sort`, `query` or `fields` is set to an empty string, it is ignored in the request.
+
+**Retrieve a single log:**
+
+`log, err := api.GetLog(log_id)`
+
+
+### Users
+
+**List all users:**
+
+`users, err := api.ListUsers()`
+
+Alternatively, use the method with query parameters.
+
+`users, err := api.ListUsers(page, per_page, sort, query, fields)`
+
+To paginate the list of users received in the response use `page` and `per_page` parameters. Set ` per_page` to the number of users that will be shown in each page. `page` indicates the current page. When set to an integer value that is less or equal to zero, the parameters are ignored by the framework.
+
+To receive the list of users sorted in expected order pass a user property (e.g. `"name"`) in `sort` parameter. Prefix the sorting attribute with `-` sign for sorting in descending order.
+
+Use `query` parameter to search for a string in the response and return only the user instances that contain it.
+
+To retrieve a collection of users containing only the requested fields pass a list of comma separated properties (e.g. `"id,name,creation_date,email"`) in `fields` parameter.
+
+If any of the parameters `sort`, `query` or `fields` is set to an empty string, it is ignored in the request.
+
+**Retrieve information about a user:**
+
+`user, err := api.GetUser(user_id)`
+
+**Create a user:**
+
+```
+request := oneandone.UserRequest {
+ Name: username,
+ Description: user_description,
+ Password: password,
+ Email: user_email,
+ }
+
+user_id, user, err := api.CreateUser(&request)
+```
+
+`Name` and `Password` are required parameters. The password must contain at least 8 characters using uppercase letters, numbers and other special symbols.
+
+**Modify a user:**
+
+```
+request := oneandone.UserRequest {
+ Description: new_desc,
+ Email: new_mail,
+ Password: new_pass,
+ State: state,
+ }
+
+user, err := api.ModifyUser(user_id, &request)
+```
+
+All listed fields in the request are optional. `State` can be set to `"ACTIVE"` or `"DISABLED"`.
+
+**Delete a user:**
+
+`user, err := api.DeleteUser(user_id)`
+
+**Retrieve information about a user's API privileges:**
+
+`api_info, err := api.GetUserApi(user_id)`
+
+**Retrieve a user's API key:**
+
+`api_key, err := api.GetUserApiKey(user_id)`
+
+**List IP's from which API access is allowed for a user:**
+
+`allowed_ips, err := api.ListUserApiAllowedIps(user_id)`
+
+**Add new IP's to a user:**
+
+```
+user_ips := []string{ my_public_ip, "192.168.7.77", "10.81.12.101" }
+user, err := api.AddUserApiAlowedIps(user_id, user_ips)
+```
+
+**Remove an IP and forbid API access from it:**
+
+`user, err := api.RemoveUserApiAllowedIp(user_id, ip)`
+
+**Modify a user's API privileges:**
+
+`user, err := api.ModifyUserApi(user_id, is_active)`
+
+**Renew a user's API key:**
+
+`user, err := api.RenewUserApiKey(user_id)`
+
+**Retrieve current user permissions:**
+
+`permissions, err := api.GetCurrentUserPermissions()`
+
+
+### Roles
+
+**List all roles:**
+
+`roles, err := api.ListRoles()`
+
+Alternatively, use the method with query parameters.
+
+`roles, err := api.ListRoles(page, per_page, sort, query, fields)`
+
+To paginate the list of roles received in the response use `page` and `per_page` parameters. Set ` per_page` to the number of roles that will be shown in each page. `page` indicates the current page. When set to an integer value that is less or equal to zero, the parameters are ignored by the framework.
+
+To receive the list of roles sorted in expected order pass a role property (e.g. `"name"`) in `sort` parameter. Prefix the sorting attribute with `-` sign for sorting in descending order.
+
+Use `query` parameter to search for a string in the response and return only the role instances that contain it.
+
+To retrieve a collection of roles containing only the requested fields pass a list of comma separated properties (e.g. `"id,name,creation_date"`) in `fields` parameter.
+
+If any of the parameters `sort`, `query` or `fields` is set to an empty string, it is ignored in the request.
+
+**Retrieve information about a role:**
+
+`role, err := api.GetRole(role_id)`
+
+**Create a role:**
+
+`role, err := api.CreateRole(role_name)`
+
+**Clone a role:**
+
+`role, err := api.CloneRole(role_id, new_role_name)`
+
+**Modify a role:**
+
+`role, err := api.ModifyRole(role_id, new_name, new_description, new_state)`
+
+`ACTIVE` and `DISABLE` are valid values for the state.
+
+**Delete a role:**
+
+`role, err := api.DeleteRole(role_id)`
+
+**Retrieve information about a role's permissions:**
+
+`permissions, err := api.GetRolePermissions(role_id)`
+
+**Modify a role's permissions:**
+
+`role, err := api.ModifyRolePermissions(role_id, permissions)`
+
+**Assign users to a role:**
+
+`role, err := api.AssignRoleUsers(role_id, user_ids)`
+
+`user_ids` is a slice of user ID's.
+
+**List a role's users:**
+
+`users, err := api.ListRoleUsers(role_id)`
+
+**Retrieve information about a role's user:**
+
+`user, err := api.GetRoleUser(role_id, user_id)`
+
+**Remove a role's user:**
+
+`role, err := api.RemoveRoleUser(role_id, user_id)`
+
+
+### Usages
+
+**List your usages:**
+
+`usages, err := api.ListUsages(period, nil, nil)`
+
+`period` can be set to `"LAST_HOUR"`, `"LAST_24H"`, `"LAST_7D"`, `"LAST_30D"`, `"LAST_365D"` or `"CUSTOM"`. If `period` is set to `"CUSTOM"`, the `start_date` and `end_date` parameters are required to be set in **RFC 3339** date/time format (e.g. `2015-13-12T00:01:00Z`).
+
+`usages, err := api.ListUsages(period, start_date, end_date)`
+
+Additional query parameters can be used.
+
+`usages, err := api.ListUsages(period, start_date, end_date, page, per_page, sort, query, fields)`
+
+To paginate the list of usages received in the response use `page` and `per_page` parameters. Set ` per_page` to the number of usages that will be shown in each page. `page` indicates the current page. When set to an integer value that is less or equal to zero, the parameters are ignored by the framework.
+
+To receive the list of usages sorted in expected order pass a usages property (e.g. `"name"`) in `sort` parameter. Prefix the sorting attribute with `-` sign for sorting in descending order.
+
+Use `query` parameter to search for a string in the response and return only the usages instances that contain it.
+
+To retrieve a collection of usages containing only the requested fields pass a list of comma separated properties (e.g. `"id,name"`) in `fields` parameter.
+
+If any of the parameters `sort`, `query` or `fields` is set to an empty string, it is ignored in the request.
+
+
+### Server Appliances
+
+**List all the appliances that you can use to create a server:**
+
+`server_appliances, err := api.ListServerAppliances()`
+
+Alternatively, use the method with query parameters.
+
+`server_appliances, err := api.ListServerAppliances(page, per_page, sort, query, fields)`
+
+To paginate the list of server appliances received in the response use `page` and `per_page` parameters. Set `per_page` to the number of server appliances that will be shown in each page. `page` indicates the current page. When set to an integer value that is less or equal to zero, the parameters are ignored by the framework.
+
+To receive the list of server appliances sorted in expected order pass a server appliance property (e.g. `"os"`) in `sort` parameter. Prefix the sorting attribute with `-` sign for sorting in descending order.
+
+Use `query` parameter to search for a string in the response and return only the server appliance instances that contain it.
+
+To retrieve a collection of server appliances containing only the requested fields pass a list of comma separated properties (e.g. `"id,os,architecture"`) in `fields` parameter.
+
+If any of the parameters `sort`, `query` or `fields` is blank, it is ignored in the request.
+
+**Retrieve information about specific appliance:**
+
+`server_appliance, err := api.GetServerAppliance(appliance_id)`
+
+
+### DVD ISO
+
+**List all operative systems and tools that you can load into your virtual DVD unit:**
+
+`dvd_isos, err := api.ListDvdIsos()`
+
+Alternatively, use the method with query parameters.
+
+`dvd_isos, err := api.ListDvdIsos(page, per_page, sort, query, fields)`
+
+To paginate the list of ISO DVDs received in the response use `page` and `per_page` parameters. Set `per_page` to the number of ISO DVDs that will be shown in each page. `page` indicates the current page. When set to an integer value that is less or equal to zero, the parameters are ignored by the framework.
+
+To receive the list of ISO DVDs sorted in expected order pass a ISO DVD property (e.g. `"type"`) in `sort` parameter. Prefix the sorting attribute with `-` sign for sorting in descending order.
+
+Use `query` parameter to search for a string in the response and return only the ISO DVD instances that contain it.
+
+To retrieve a collection of ISO DVDs containing only the requested fields pass a list of comma separated properties (e.g. `"id,name,type"`) in `fields` parameter.
+
+If any of the parameters `sort`, `query` or `fields` is blank, it is ignored in the request.
+
+**Retrieve a specific ISO image:**
+
+`dvd_iso, err := api.GetDvdIso(dvd_id)`
+
+
+### Ping
+
+**Check if 1&1 REST API is running:**
+
+`response, err := api.Ping()`
+
+If the API is running, the response is a single-element slice `["PONG"]`.
+
+**Validate if 1&1 REST API is running and the authorization token is valid:**
+
+`response, err := api.PingAuth()`
+
+The response should be a single-element slice `["PONG"]` if the API is running and the token is valid.
+
+
+### Pricing
+
+**Show prices for all available resources in the Cloud Panel:**
+
+`pricing, err := api.GetPricing()`
+
+
+### Data Centers
+
+**List all 1&1 Cloud Server data centers:**
+
+`datacenters, err := api.ListDatacenters()`
+
+Here is another example of an alternative form of the list function that includes query parameters.
+
+`datacenters, err := api.ListDatacenters(0, 0, "country_code", "DE", "id,country_code")`
+
+**Retrieve a specific data center:**
+
+`datacenter, err := api.GetDatacenter(datacenter_id)`
+
+
+## Examples
+
+```Go
+package main
+
+import (
+ "fmt"
+ "github.com/1and1/oneandone-cloudserver-sdk-go"
+ "time"
+)
+
+func main() {
+ //Set an authentication token
+ token := oneandone.SetToken("82ee732b8d47e451be5c6ad5b7b56c81")
+ //Create an API client
+ api := oneandone.New(token, oneandone.BaseUrl)
+
+ // List server appliances
+ saps, err := api.ListServerAppliances()
+
+ var sa oneandone.ServerAppliance
+ for _, a := range saps {
+ if a.Type == "IMAGE" {
+ sa = a
+ }
+ }
+
+ // Create a server
+ req := oneandone.ServerRequest{
+ Name: "Example Server",
+ Description: "Example server description.",
+ ApplianceId: sa.Id,
+ PowerOn: true,
+ Hardware: oneandone.Hardware{
+ Vcores: 1,
+ CoresPerProcessor: 1,
+ Ram: 2,
+ Hdds: []oneandone.Hdd {
+ oneandone.Hdd {
+ Size: sa.MinHddSize,
+ IsMain: true,
+ },
+ },
+ },
+ }
+
+ server_id, server, err := api.CreateServer(&req)
+
+ if err == nil {
+ // Wait until server is created and powered on for at most 60 x 10 seconds
+ err = api.WaitForState(server, "POWERED_ON", 10, 60)
+ }
+
+ // Get the server
+ server, err = api.GetServer(server_id)
+
+ // Create a load balancer
+ lbr := oneandone.LoadBalancerRequest {
+ Name: "Load Balancer Example",
+ Description: "API created load balancer.",
+ Method: "ROUND_ROBIN",
+ Persistence: oneandone.Bool2Pointer(true),
+ PersistenceTime: oneandone.Int2Pointer(1200),
+ HealthCheckTest: "TCP",
+ HealthCheckInterval: oneandone.Int2Pointer(40),
+ Rules: []oneandone.LoadBalancerRule {
+ {
+ Protocol: "TCP",
+ PortBalancer: 80,
+ PortServer: 80,
+ Source: "0.0.0.0",
+ },
+ },
+ }
+
+ var lb *oneandone.LoadBalancer
+ var lb_id string
+
+ lb_id, lb, err = api.CreateLoadBalancer(&lbr)
+ if err != nil {
+ api.WaitForState(lb, "ACTIVE", 10, 30)
+ }
+
+ // Get the load balancer
+ lb, err = api.GetLoadBalancer(lb.Id)
+
+ // Assign the load balancer to server's IP
+ server, err = api.AssignServerIpLoadBalancer(server.Id, server.Ips[0].Id, lb_id)
+
+ // Create a firewall policy
+ fpr := oneandone.FirewallPolicyRequest{
+ Name: "Firewall Policy Example",
+ Description: "API created firewall policy.",
+ Rules: []oneandone.FirewallPolicyRule {
+ {
+ Protocol: "TCP",
+ PortFrom: oneandone.Int2Pointer(80),
+ PortTo: oneandone.Int2Pointer(80),
+ },
+ },
+ }
+
+ var fp *oneandone.FirewallPolicy
+
+ fp_id, fp, err = api.CreateFirewallPolicy(&fpr)
+ if err == nil {
+ api.WaitForState(fp, "ACTIVE", 10, 30)
+ }
+
+ // Get the firewall policy
+ fp, err = api.GetFirewallPolicy(fp_id)
+
+ // Add servers IPs to the firewall policy.
+ ips := []string{ server.Ips[0].Id }
+
+ fp, err = api.AddFirewallPolicyServerIps(fp.Id, ips)
+ if err == nil {
+ api.WaitForState(fp, "ACTIVE", 10, 60)
+ }
+
+ //Shutdown the server using 'SOFTWARE' method
+ server, err = api.ShutdownServer(server.Id, false)
+ if err != nil {
+ err = api.WaitForState(server, "POWERED_OFF", 5, 20)
+ }
+
+ // Delete the load balancer
+ lb, err = api.DeleteLoadBalancer(lb.Id)
+ if err != nil {
+ err = api.WaitUntilDeleted(lb)
+ }
+
+ // Delete the firewall policy
+ fp, err = api.DeleteFirewallPolicy(fp.Id)
+ if err != nil {
+ err = api.WaitUntilDeleted(fp)
+ }
+
+ // List usages in last 24h
+ var usages *oneandone.Usages
+ usages, err = api.ListUsages("LAST_24H", nil, nil)
+
+ fmt.Println(usages.Servers)
+
+ // List usages in last 5 hours
+ n := time.Now()
+ ed := time.Date(n.Year(), n.Month(), n.Day(), n.Hour(), n.Minute(), n.Second(), 0, time.UTC)
+ sd := ed.Add(-(time.Hour * 5))
+
+ usages, err = api.ListUsages("CUSTOM", &sd, &ed)
+
+ //Create a shared storage
+ ssr := oneandone.SharedStorageRequest {
+ Name: "Shared Storage Example",
+ Description: "API alocated 100 GB disk.",
+ Size: oneandone.Int2Pointer(100),
+ }
+
+ var ss *oneandone.SharedStorage
+ var ss_id string
+
+ ss_id, ss, err = api.CreateSharedStorage(&ssr)
+ if err != nil {
+ api.WaitForState(ss, "ACTIVE", 10, 30)
+ }
+
+ // List shared storages on page 1, 5 results per page and sort by 'name' field.
+ // Include only 'name', 'size' and 'minimum_size_allowed' fields in the result.
+ var shs []oneandone.SharedStorage
+ shs, err = api.ListSharedStorages(1, 5, "name", "", "name,size,minimum_size_allowed")
+
+ // List all shared storages that contain 'example' string
+ shs, err = api.ListSharedStorages(0, 0, "", "example", "")
+
+ // Delete the shared storage
+ ss, err = api.DeleteSharedStorage(ss_id)
+ if err == nil {
+ err = api.WaitUntilDeleted(ss)
+ }
+
+ // Delete the server
+ server, err = api.DeleteServer(server.Id, false)
+ if err == nil {
+ err = api.WaitUntilDeleted(server)
+ }
+}
+
+```
+The next example illustrates how to create a `TYPO3` application server of a fixed size with an initial password and a firewall policy that has just been created.
+
+```Go
+package main
+
+import "github.com/1and1/oneandone-cloudserver-sdk-go"
+
+func main() {
+ token := oneandone.SetToken("bde36026df9d548f699ea97e75a7e87f")
+ client := oneandone.New(token, oneandone.BaseUrl)
+
+ // Create a new firewall policy
+ fpr := oneandone.FirewallPolicyRequest{
+ Name: "HTTPS Traffic Policy",
+ Rules: []oneandone.FirewallPolicyRule{
+ {
+ Protocol: "TCP",
+ PortFrom: oneandone.Int2Pointer(443),
+ PortTo: oneandone.Int2Pointer(443),
+ },
+ },
+ }
+
+ _, fp, err := client.CreateFirewallPolicy(&fpr)
+ if fp != nil && err == nil {
+ client.WaitForState(fp, "ACTIVE", 5, 60)
+
+ // Look for the TYPO3 application appliance
+ saps, _ := client.ListServerAppliances(0, 0, "", "typo3", "")
+
+ var sa oneandone.ServerAppliance
+ for _, a := range saps {
+ if a.Type == "APPLICATION" {
+ sa = a
+ break
+ }
+ }
+
+ var fixed_flavours []oneandone.FixedInstanceInfo
+ var fixed_size_id string
+
+ fixed_flavours, err = client.ListFixedInstanceSizes()
+ for _, fl := range fixed_flavours {
+ //look for 'M' size
+ if fl.Name == "M" {
+ fixed_size_id = fl.Id
+ break
+ }
+ }
+
+ req := oneandone.ServerRequest{
+ Name: "TYPO3 Server",
+ ApplianceId: sa.Id,
+ PowerOn: true,
+ Password: "ucr_kXW8,.2SdMU",
+ Hardware: oneandone.Hardware{
+ FixedInsSizeId: fixed_size_id,
+ },
+ FirewallPolicyId: fp.Id,
+ }
+ _, server, _ := client.CreateServer(&req)
+ if server != nil {
+ client.WaitForState(server, "POWERED_ON", 10, 90)
+ }
+ }
+}
+```
+
+
+## Index
+
+```Go
+func New(token string, url string) *API
+```
+
+```Go
+func (api *API) AddFirewallPolicyRules(fp_id string, fp_rules []FirewallPolicyRule) (*FirewallPolicy, error)
+```
+
+```Go
+func (api *API) AddFirewallPolicyServerIps(fp_id string, ip_ids []string) (*FirewallPolicy, error)
+```
+
+```Go
+func (api *API) AddLoadBalancerRules(lb_id string, lb_rules []LoadBalancerRule) (*LoadBalancer, error)
+```
+
+```Go
+func (api *API) AddLoadBalancerServerIps(lb_id string, ip_ids []string) (*LoadBalancer, error)
+```
+
+```Go
+func (api *API) AddMonitoringPolicyPorts(mp_id string, mp_ports []MonitoringPort) (*MonitoringPolicy, error)
+```
+
+```Go
+func (api *API) AddMonitoringPolicyProcesses(mp_id string, mp_procs []MonitoringProcess) (*MonitoringPolicy, error)
+```
+
+```Go
+func (api *API) AddServerHdds(server_id string, hdds *ServerHdds) (*Server, error)
+```
+
+```Go
+func (api *API) AddSharedStorageServers(st_id string, servers []SharedStorageServer) (*SharedStorage, error)
+```
+
+```Go
+func (api *API) AddUserApiAlowedIps(user_id string, ips []string) (*User, error)
+```
+
+```Go
+func (api *API) AssignRoleUsers(role_id string, user_ids []string) (*Role, error)
+```
+
+```Go
+func (api *API) AssignServerIp(server_id string, ip_type string) (*Server, error)
+```
+
+```Go
+func (api *API) AssignServerIpFirewallPolicy(server_id string, ip_id string, fp_id string) (*Server, error)
+```
+
+```Go
+func (api *API) AssignServerIpLoadBalancer(server_id string, ip_id string, lb_id string) (*Server, error)
+```
+
+```Go
+func (api *API) AssignServerPrivateNetwork(server_id string, pn_id string) (*Server, error)
+```
+
+```Go
+func (api *API) AttachMonitoringPolicyServers(mp_id string, sids []string) (*MonitoringPolicy, error)
+```
+
+```Go
+func (api *API) AttachPrivateNetworkServers(pn_id string, sids []string) (*PrivateNetwork, error)
+```
+
+```Go
+func (api *API) CloneRole(role_id string, name string) (*Role, error)
+```
+
+```Go
+func (api *API) CloneServer(server_id string, new_name string, datacenter_id string) (*Server, error)
+```
+
+```Go
+func (api *API) CreateFirewallPolicy(fp_data *FirewallPolicyRequest) (string, *FirewallPolicy, error)
+```
+
+```Go
+func (api *API) CreateImage(request *ImageConfig) (string, *Image, error)
+```
+
+```Go
+func (api *API) CreateLoadBalancer(request *LoadBalancerRequest) (string, *LoadBalancer, error)
+```
+
+```Go
+func (api *API) CreateMonitoringPolicy(mp *MonitoringPolicy) (string, *MonitoringPolicy, error)
+```
+
+```Go
+func (api *API) CreatePrivateNetwork(request *PrivateNetworkRequest) (string, *PrivateNetwork, error)
+```
+
+```Go
+func (api *API) CreatePublicIp(ip_type string, reverse_dns string, datacenter_id string) (string, *PublicIp, error)
+```
+
+```Go
+func (api *API) CreateRole(name string) (string, *Role, error)
+```
+
+```Go
+func (api *API) CreateServer(request *ServerRequest) (string, *Server, error)
+```
+
+```Go
+func (api *API) CreateServerEx(request *ServerRequest, timeout int) (string, string, error)
+```
+
+```Go
+func (api *API) CreateServerSnapshot(server_id string) (*Server, error)
+```
+
+```Go
+func (api *API) CreateSharedStorage(request *SharedStorageRequest) (string, *SharedStorage, error)
+```
+
+```Go
+func (api *API) CreateUser(user *UserRequest) (string, *User, error)
+```
+
+```Go
+func (api *API) CreateVPN(name string, description string, datacenter_id string) (string, *VPN, error)
+```
+
+```Go
+func (api *API) DeleteFirewallPolicy(fp_id string) (*FirewallPolicy, error)
+```
+
+```Go
+func (api *API) DeleteFirewallPolicyRule(fp_id string, rule_id string) (*FirewallPolicy, error)
+```
+
+```Go
+func (api *API) DeleteFirewallPolicyServerIp(fp_id string, ip_id string) (*FirewallPolicy, error)
+```
+
+```Go
+func (api *API) DeleteImage(img_id string) (*Image, error)
+```
+
+```Go
+func (api *API) DeleteLoadBalancer(lb_id string) (*LoadBalancer, error)
+```
+
+```Go
+func (api *API) DeleteLoadBalancerRule(lb_id string, rule_id string) (*LoadBalancer, error)
+```
+
+```Go
+func (api *API) DeleteLoadBalancerServerIp(lb_id string, ip_id string) (*LoadBalancer, error)
+```
+
+```Go
+func (api *API) DeleteMonitoringPolicy(mp_id string) (*MonitoringPolicy, error)
+```
+
+```Go
+func (api *API) DeleteMonitoringPolicyPort(mp_id string, port_id string) (*MonitoringPolicy, error)
+```
+
+```Go
+func (api *API) DeleteMonitoringPolicyProcess(mp_id string, proc_id string) (*MonitoringPolicy, error)
+```
+
+```Go
+func (api *API) DeletePrivateNetwork(pn_id string) (*PrivateNetwork, error)
+```
+
+```Go
+func (api *API) DeletePublicIp(ip_id string) (*PublicIp, error)
+```
+
+```Go
+func (api *API) DeleteRole(role_id string) (*Role, error)
+```
+
+```Go
+func (api *API) DeleteServer(server_id string, keep_ips bool) (*Server, error)
+```
+
+```Go
+func (api *API) DeleteServerHdd(server_id string, hdd_id string) (*Server, error)
+```
+
+```Go
+func (api *API) DeleteServerIp(server_id string, ip_id string, keep_ip bool) (*Server, error)
+```
+
+```Go
+func (api *API) DeleteServerSnapshot(server_id string, snapshot_id string) (*Server, error)
+```
+
+```Go
+func (api *API) DeleteSharedStorage(ss_id string) (*SharedStorage, error)
+```
+
+```Go
+func (api *API) DeleteSharedStorageServer(st_id string, ser_id string) (*SharedStorage, error)
+```
+
+```Go
+func (api *API) DeleteUser(user_id string) (*User, error)
+```
+
+```Go
+func (api *API) DeleteVPN(vpn_id string) (*VPN, error)
+```
+
+```Go
+func (api *API) DetachPrivateNetworkServer(pn_id string, pns_id string) (*PrivateNetwork, error)
+```
+
+```Go
+func (api *API) EjectServerDvd(server_id string) (*Server, error)
+```
+
+```Go
+func (api *API) GetCurrentUserPermissions() (*Permissions, error)
+```
+
+```Go
+func (api *API) GetDatacenter(dc_id string) (*Datacenter, error)
+```
+
+```Go
+func (api *API) GetDvdIso(dvd_id string) (*DvdIso, error)
+```
+
+```Go
+func (api *API) GetFirewallPolicy(fp_id string) (*FirewallPolicy, error)
+```
+
+```Go
+func (api *API) GetFirewallPolicyRule(fp_id string, rule_id string) (*FirewallPolicyRule, error)
+```
+
+```Go
+func (api *API) GetFirewallPolicyServerIp(fp_id string, ip_id string) (*ServerIpInfo, error)
+```
+
+```Go
+func (api *API) GetFixedInstanceSize(fis_id string) (*FixedInstanceInfo, error)
+```
+
+```Go
+func (api *API) GetImage(img_id string) (*Image, error)
+```
+
+```Go
+func (api *API) GetLoadBalancer(lb_id string) (*LoadBalancer, error)
+```
+
+```Go
+func (api *API) GetLoadBalancerRule(lb_id string, rule_id string) (*LoadBalancerRule, error)
+```
+
+```Go
+func (api *API) GetLoadBalancerServerIp(lb_id string, ip_id string) (*ServerIpInfo, error)
+```
+
+```Go
+func (api *API) GetLog(log_id string) (*Log, error)
+```
+
+```Go
+func (api *API) GetMonitoringPolicy(mp_id string) (*MonitoringPolicy, error)
+```
+
+```Go
+func (api *API) GetMonitoringPolicyPort(mp_id string, port_id string) (*MonitoringPort, error)
+```
+
+```Go
+func (api *API) GetMonitoringPolicyProcess(mp_id string, proc_id string) (*MonitoringProcess, error)
+```
+
+```Go
+func (api *API) GetMonitoringPolicyServer(mp_id string, ser_id string) (*Identity, error)
+```
+
+```Go
+func (api *API) GetMonitoringServerUsage(ser_id string, period string, dates ...time.Time) (*MonServerUsageDetails, error)
+```
+
+```Go
+func (api *API) GetPricing() (*Pricing, error)
+```
+
+```Go
+func (api *API) GetPrivateNetwork(pn_id string) (*PrivateNetwork, error)
+```
+
+```Go
+func (api *API) GetPrivateNetworkServer(pn_id string, server_id string) (*Identity, error)
+```
+
+```Go
+func (api *API) GetPublicIp(ip_id string) (*PublicIp, error)
+```
+
+```Go
+func (api *API) GetRole(role_id string) (*Role, error)
+```
+
+```Go
+func (api *API) GetRolePermissions(role_id string) (*Permissions, error)
+```
+
+```Go
+func (api *API) GetRoleUser(role_id string, user_id string) (*Identity, error)
+```
+
+```Go
+func (api *API) GetServer(server_id string) (*Server, error)
+```
+
+```Go
+func (api *API) GetServerAppliance(sa_id string) (*ServerAppliance, error)
+```
+
+```Go
+func (api *API) GetServerDvd(server_id string) (*Identity, error)
+```
+
+```Go
+func (api *API) GetServerHardware(server_id string) (*Hardware, error)
+```
+
+```Go
+func (api *API) GetServerHdd(server_id string, hdd_id string) (*Hdd, error)
+```
+
+```Go
+func (api *API) GetServerImage(server_id string) (*Identity, error)
+```
+
+```Go
+func (api *API) GetServerIp(server_id string, ip_id string) (*ServerIp, error)
+```
+
+```Go
+func (api *API) GetServerIpFirewallPolicy(server_id string, ip_id string) (*Identity, error)
+```
+
+```Go
+func (api *API) GetServerPrivateNetwork(server_id string, pn_id string) (*PrivateNetwork, error)
+```
+
+```Go
+func (api *API) GetServerSnapshot(server_id string) (*ServerSnapshot, error)
+```
+
+```Go
+func (api *API) GetServerStatus(server_id string) (*Status, error)
+```
+
+```Go
+func (api *API) GetSharedStorage(ss_id string) (*SharedStorage, error)
+```
+
+```Go
+func (api *API) GetSharedStorageCredentials() ([]SharedStorageAccess, error)
+```
+
+```Go
+func (api *API) GetSharedStorageServer(st_id string, ser_id string) (*SharedStorageServer, error)
+```
+
+```Go
+func (api *API) GetUser(user_id string) (*User, error)
+```
+
+```Go
+func (api *API) GetUserApi(user_id string) (*UserApi, error)
+```
+
+```Go
+func (api *API) GetUserApiKey(user_id string) (*UserApiKey, error)
+```
+
+```Go
+func (api *API) GetVPN(vpn_id string) (*VPN, error)
+```
+
+```Go
+func (api *API) GetVPNConfigFile(vpn_id string) (string, error)
+```
+
+```Go
+func (api *API) ListDatacenters(args ...interface{}) ([]Datacenter, error)
+```
+
+```Go
+func (api *API) ListDvdIsos(args ...interface{}) ([]DvdIso, error)
+```
+
+```Go
+func (api *API) ListFirewallPolicies(args ...interface{}) ([]FirewallPolicy, error)
+```
+
+```Go
+func (api *API) ListFirewallPolicyRules(fp_id string) ([]FirewallPolicyRule, error)
+```
+
+```Go
+func (api *API) ListFirewallPolicyServerIps(fp_id string) ([]ServerIpInfo, error)
+```
+
+```Go
+func (api *API) ListFixedInstanceSizes() ([]FixedInstanceInfo, error)
+```
+
+```Go
+func (api *API) ListImages(args ...interface{}) ([]Image, error)
+```
+
+```Go
+func (api *API) ListLoadBalancerRules(lb_id string) ([]LoadBalancerRule, error)
+```
+
+```Go
+func (api *API) ListLoadBalancerServerIps(lb_id string) ([]ServerIpInfo, error)
+```
+
+```Go
+func (api *API) ListLoadBalancers(args ...interface{}) ([]LoadBalancer, error)
+```
+
+```Go
+func (api *API) ListLogs(period string, sd *time.Time, ed *time.Time, args ...interface{}) ([]Log, error)
+```
+
+```Go
+func (api *API) ListMonitoringPolicies(args ...interface{}) ([]MonitoringPolicy, error)
+```
+
+```Go
+func (api *API) ListMonitoringPolicyPorts(mp_id string) ([]MonitoringPort, error)
+```
+
+```Go
+func (api *API) ListMonitoringPolicyProcesses(mp_id string) ([]MonitoringProcess, error)
+```
+
+```Go
+func (api *API) ListMonitoringPolicyServers(mp_id string) ([]Identity, error)
+```
+
+```Go
+func (api *API) ListMonitoringServersUsages(args ...interface{}) ([]MonServerUsageSummary, error)
+```
+
+```Go
+func (api *API) ListPrivateNetworkServers(pn_id string) ([]Identity, error)
+```
+
+```Go
+func (api *API) ListPrivateNetworks(args ...interface{}) ([]PrivateNetwork, error)
+```
+
+```Go
+func (api *API) ListPublicIps(args ...interface{}) ([]PublicIp, error)
+```
+
+```Go
+func (api *API) ListRoleUsers(role_id string) ([]Identity, error)
+```
+
+```Go
+func (api *API) ListRoles(args ...interface{}) ([]Role, error)
+```
+
+```Go
+func (api *API) ListServerAppliances(args ...interface{}) ([]ServerAppliance, error)
+```
+
+```Go
+func (api *API) ListServerHdds(server_id string) ([]Hdd, error)
+```
+
+```Go
+func (api *API) ListServerIpLoadBalancers(server_id string, ip_id string) ([]Identity, error)
+```
+
+```Go
+func (api *API) ListServerIps(server_id string) ([]ServerIp, error)
+```
+
+```Go
+func (api *API) ListServerPrivateNetworks(server_id string) ([]Identity, error)
+```
+
+```Go
+func (api *API) ListServers(args ...interface{}) ([]Server, error)
+```
+
+```Go
+func (api *API) ListSharedStorageServers(st_id string) ([]SharedStorageServer, error)
+```
+
+```Go
+func (api *API) ListSharedStorages(args ...interface{}) ([]SharedStorage, error)
+```
+
+```Go
+func (api *API) ListUsages(period string, sd *time.Time, ed *time.Time, args ...interface{}) (*Usages, error)
+```
+
+```Go
+func (api *API) ListUserApiAllowedIps(user_id string) ([]string, error)
+```
+
+```Go
+func (api *API) ListUsers(args ...interface{}) ([]User, error)
+```
+
+```Go
+func (api *API) ListVPNs(args ...interface{}) ([]VPN, error)
+```
+
+```Go
+func (api *API) LoadServerDvd(server_id string, dvd_id string) (*Server, error)
+```
+
+```Go
+func (api *API) ModifyMonitoringPolicyPort(mp_id string, port_id string, mp_port *MonitoringPort) (*MonitoringPolicy, error)
+```
+
+```Go
+func (api *API) ModifyMonitoringPolicyProcess(mp_id string, proc_id string, mp_proc *MonitoringProcess) (*MonitoringPolicy, error)
+```
+
+```Go
+func (api *API) ModifyRole(role_id string, name string, description string, state string) (*Role, error)
+```
+
+```Go
+func (api *API) ModifyRolePermissions(role_id string, perm *Permissions) (*Role, error)
+```
+
+```Go
+func (api *API) ModifyUser(user_id string, user *UserRequest) (*User, error)
+```
+
+```Go
+func (api *API) ModifyUserApi(user_id string, active bool) (*User, error)
+```
+
+```Go
+func (api *API) ModifyVPN(vpn_id string, name string, description string) (*VPN, error)
+```
+
+```Go
+func (api *API) Ping() ([]string, error)
+```
+
+```Go
+func (api *API) PingAuth() ([]string, error)
+```
+
+```Go
+func (api *API) RebootServer(server_id string, is_hardware bool) (*Server, error)
+```
+
+```Go
+func (api *API) ReinstallServerImage(server_id string, image_id string, password string, fp_id string) (*Server, error)
+```
+
+```Go
+func (api *API) RemoveMonitoringPolicyServer(mp_id string, ser_id string) (*MonitoringPolicy, error)
+```
+
+```Go
+func (api *API) RemoveRoleUser(role_id string, user_id string) (*Role, error)
+```
+
+```Go
+func (api *API) RemoveServerPrivateNetwork(server_id string, pn_id string) (*Server, error)
+```
+
+```Go
+func (api *API) RemoveUserApiAllowedIp(user_id string, ip string) (*User, error)
+```
+
+```Go
+func (api *API) RenameServer(server_id string, new_name string, new_desc string) (*Server, error)
+```
+
+```Go
+func (api *API) RenewUserApiKey(user_id string) (*User, error)
+```
+
+```Go
+func (api *API) ResizeServerHdd(server_id string, hdd_id string, new_size int) (*Server, error)
+```
+
+```Go
+func (api *API) RestoreServerSnapshot(server_id string, snapshot_id string) (*Server, error)
+```
+
+```Go
+func (api *API) ShutdownServer(server_id string, is_hardware bool) (*Server, error)
+```
+
+```Go
+func (api *API) StartServer(server_id string) (*Server, error)
+```
+
+```Go
+func (api *API) UnassignServerIpFirewallPolicy(server_id string, ip_id string) (*Server, error)
+```
+
+```Go
+func (api *API) UnassignServerIpLoadBalancer(server_id string, ip_id string, lb_id string) (*Server, error)
+```
+
+```Go
+func (api *API) UpdateFirewallPolicy(fp_id string, fp_new_name string, fp_new_desc string) (*FirewallPolicy, error)
+```
+
+```Go
+func (api *API) UpdateImage(img_id string, new_name string, new_desc string, new_freq string) (*Image, error)
+```
+
+```Go
+func (api *API) UpdateLoadBalancer(lb_id string, request *LoadBalancerRequest) (*LoadBalancer, error)
+```
+
+```Go
+func (api *API) UpdateMonitoringPolicy(mp_id string, mp *MonitoringPolicy) (*MonitoringPolicy, error)
+```
+
+```Go
+func (api *API) UpdatePrivateNetwork(pn_id string, request *PrivateNetworkRequest) (*PrivateNetwork, error)
+```
+
+```Go
+func (api *API) UpdatePublicIp(ip_id string, reverse_dns string) (*PublicIp, error)
+```
+
+```Go
+func (api *API) UpdateServerHardware(server_id string, hardware *Hardware) (*Server, error)
+```
+
+```Go
+func (api *API) UpdateSharedStorage(ss_id string, request *SharedStorageRequest) (*SharedStorage, error)
+```
+
+```Go
+func (api *API) UpdateSharedStorageCredentials(new_pass string) ([]SharedStorageAccess, error)
+```
+
+```Go
+func (api *API) WaitForState(in ApiInstance, state string, sec time.Duration, count int) error
+```
+
+```Go
+func (api *API) WaitUntilDeleted(in ApiInstance) error
+```
+
+```Go
+func (fp *FirewallPolicy) GetState() (string, error)
+```
+
+```Go
+func (im *Image) GetState() (string, error)
+```
+
+```Go
+func (lb *LoadBalancer) GetState() (string, error)
+```
+
+```Go
+func (mp *MonitoringPolicy) GetState() (string, error)
+```
+
+```Go
+func (pn *PrivateNetwork) GetState() (string, error)
+```
+
+```Go
+func (ip *PublicIp) GetState() (string, error)
+```
+
+```Go
+func (role *Role) GetState() (string, error)
+```
+
+```Go
+func (s *Server) GetState() (string, error)
+```
+
+```Go
+func (ss *SharedStorage) GetState() (string, error)
+```
+
+```Go
+func (u *User) GetState() (string, error)
+```
+
+```Go
+func (u *User) GetState() (string, error)
+```
+
+```Go
+func (vpn *VPN) GetState() (string, error)
+```
+
+```Go
+func Bool2Pointer(input bool) *bool
+```
+
+```Go
+func Int2Pointer(input int) *int
+```
+
+```Go
+func (bp *BackupPerm) SetAll(value bool)
+```
+
+```Go
+func (fp *FirewallPerm) SetAll(value bool)
+```
+
+```Go
+func (imp *ImagePerm) SetAll(value bool)
+```
+
+```Go
+unc (inp *InvoicePerm) SetAll(value bool)
+```
+
+```Go
+func (ipp *IPPerm) SetAll(value bool)
+```
+
+```Go
+func (lbp *LoadBalancerPerm) SetAll(value bool)
+```
+
+```Go
+func (lp *LogPerm) SetAll(value bool)
+```
+
+```Go
+func (mcp *MonitorCenterPerm) SetAll(value bool)
+```
+
+```Go
+func (mpp *MonitorPolicyPerm) SetAll(value bool)
+```
+
+```Go
+func (p *Permissions) SetAll(v bool)
+```
+
+```Go
+func (pnp *PrivateNetworkPerm) SetAll(value bool)
+```
+
+```Go
+func (rp *RolePerm) SetAll(value bool)
+```
+
+```Go
+func (sp *ServerPerm) SetAll(value bool)
+```
+
+```Go
+func (ssp *SharedStoragePerm) SetAll(value bool)
+```
+
+```Go
+func (up *UsagePerm) SetAll(value bool)
+```
+
+```Go
+func (up *UserPerm) SetAll(value bool)
+```
+
+```Go
+func (vpnp *VPNPerm) SetAll(value bool)
+```
+
+```Go
+func SetBaseUrl(newbaseurl string) string
+```
+
+```Go
+func SetToken(newtoken string) string
+```
+
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/datacenters.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/datacenters.go
new file mode 100644
index 000000000..cf193fb88
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/datacenters.go
@@ -0,0 +1,36 @@
+package oneandone
+
+import "net/http"
+
+type Datacenter struct {
+ idField
+ CountryCode string `json:"country_code,omitempty"`
+ Location string `json:"location,omitempty"`
+}
+
+// GET /datacenters
+func (api *API) ListDatacenters(args ...interface{}) ([]Datacenter, error) {
+ url, err := processQueryParams(createUrl(api, datacenterPathSegment), args...)
+ if err != nil {
+ return nil, err
+ }
+ result := []Datacenter{}
+ err = api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+
+ return result, nil
+}
+
+// GET /datacenters/{datacenter_id}
+func (api *API) GetDatacenter(dc_id string) (*Datacenter, error) {
+ result := new(Datacenter)
+ url := createUrl(api, datacenterPathSegment, dc_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+
+ return result, nil
+}
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/dvdisos.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/dvdisos.go
new file mode 100644
index 000000000..ba54c3f7f
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/dvdisos.go
@@ -0,0 +1,48 @@
+package oneandone
+
+import "net/http"
+
+// Struct to describe a ISO image that can be used to boot a server.
+//
+// Values of this type describe ISO images that can be inserted into the servers virtual DVD drive.
+//
+//
+type DvdIso struct {
+ Identity
+ OsFamily string `json:"os_family,omitempty"`
+ Os string `json:"os,omitempty"`
+ OsVersion string `json:"os_version,omitempty"`
+ Type string `json:"type,omitempty"`
+ AvailableDatacenters []string `json:"available_datacenters,omitempty"`
+ Architecture interface{} `json:"os_architecture,omitempty"`
+ ApiPtr
+}
+
+// GET /dvd_isos
+func (api *API) ListDvdIsos(args ...interface{}) ([]DvdIso, error) {
+ url, err := processQueryParams(createUrl(api, dvdIsoPathSegment), args...)
+ if err != nil {
+ return nil, err
+ }
+ result := []DvdIso{}
+ err = api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ for index, _ := range result {
+ result[index].api = api
+ }
+ return result, nil
+}
+
+// GET /dvd_isos/{id}
+func (api *API) GetDvdIso(dvd_id string) (*DvdIso, error) {
+ result := new(DvdIso)
+ url := createUrl(api, dvdIsoPathSegment, dvd_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/errors.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/errors.go
new file mode 100644
index 000000000..08cc9c250
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/errors.go
@@ -0,0 +1,27 @@
+package oneandone
+
+import (
+ "fmt"
+)
+
+type errorResponse struct {
+ Type string `json:"type"`
+ Message string `json:"message"`
+}
+
+type apiError struct {
+ httpStatusCode int
+ message string
+}
+
+func (e apiError) Error() string {
+ return fmt.Sprintf("%d - %s", e.httpStatusCode, e.message)
+}
+
+func (e *apiError) HttpStatusCode() int {
+ return e.httpStatusCode
+}
+
+func (e *apiError) Message() string {
+ return e.message
+}
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/firewallpolicies.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/firewallpolicies.go
new file mode 100644
index 000000000..3e89c9b17
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/firewallpolicies.go
@@ -0,0 +1,208 @@
+package oneandone
+
+import (
+ "net/http"
+)
+
+type FirewallPolicy struct {
+ Identity
+ descField
+ DefaultPolicy uint8 `json:"default"`
+ CloudpanelId string `json:"cloudpanel_id,omitempty"`
+ CreationDate string `json:"creation_date,omitempty"`
+ State string `json:"state,omitempty"`
+ Rules []FirewallPolicyRule `json:"rules,omitempty"`
+ ServerIps []ServerIpInfo `json:"server_ips,omitempty"`
+ ApiPtr
+}
+
+type FirewallPolicyRule struct {
+ idField
+ Protocol string `json:"protocol,omitempty"`
+ PortFrom *int `json:"port_from,omitempty"`
+ PortTo *int `json:"port_to,omitempty"`
+ SourceIp string `json:"source,omitempty"`
+}
+
+type FirewallPolicyRequest struct {
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ Rules []FirewallPolicyRule `json:"rules,omitempty"`
+}
+
+// GET /firewall_policies
+func (api *API) ListFirewallPolicies(args ...interface{}) ([]FirewallPolicy, error) {
+ url, err := processQueryParams(createUrl(api, firewallPolicyPathSegment), args...)
+ if err != nil {
+ return nil, err
+ }
+ result := []FirewallPolicy{}
+ err = api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ for index, _ := range result {
+ result[index].api = api
+ }
+ return result, nil
+}
+
+// POST /firewall_policies
+func (api *API) CreateFirewallPolicy(fp_data *FirewallPolicyRequest) (string, *FirewallPolicy, error) {
+ result := new(FirewallPolicy)
+ url := createUrl(api, firewallPolicyPathSegment)
+ err := api.Client.Post(url, &fp_data, &result, http.StatusAccepted)
+ if err != nil {
+ return "", nil, err
+ }
+ result.api = api
+ return result.Id, result, nil
+}
+
+// GET /firewall_policies/{id}
+func (api *API) GetFirewallPolicy(fp_id string) (*FirewallPolicy, error) {
+ result := new(FirewallPolicy)
+ url := createUrl(api, firewallPolicyPathSegment, fp_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+
+}
+
+// DELETE /firewall_policies/{id}
+func (api *API) DeleteFirewallPolicy(fp_id string) (*FirewallPolicy, error) {
+ result := new(FirewallPolicy)
+ url := createUrl(api, firewallPolicyPathSegment, fp_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// PUT /firewall_policies/{id}
+func (api *API) UpdateFirewallPolicy(fp_id string, fp_new_name string, fp_new_desc string) (*FirewallPolicy, error) {
+ result := new(FirewallPolicy)
+ data := FirewallPolicyRequest{
+ Name: fp_new_name,
+ Description: fp_new_desc,
+ }
+ url := createUrl(api, firewallPolicyPathSegment, fp_id)
+ err := api.Client.Put(url, &data, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /firewall_policies/{id}/server_ips
+func (api *API) ListFirewallPolicyServerIps(fp_id string) ([]ServerIpInfo, error) {
+ result := []ServerIpInfo{}
+ url := createUrl(api, firewallPolicyPathSegment, fp_id, "server_ips")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// GET /firewall_policies/{id}/server_ips/{id}
+func (api *API) GetFirewallPolicyServerIp(fp_id string, ip_id string) (*ServerIpInfo, error) {
+ result := new(ServerIpInfo)
+ url := createUrl(api, firewallPolicyPathSegment, fp_id, "server_ips", ip_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// POST /firewall_policies/{id}/server_ips
+func (api *API) AddFirewallPolicyServerIps(fp_id string, ip_ids []string) (*FirewallPolicy, error) {
+ result := new(FirewallPolicy)
+ request := serverIps{
+ ServerIps: ip_ids,
+ }
+
+ url := createUrl(api, firewallPolicyPathSegment, fp_id, "server_ips")
+ err := api.Client.Post(url, &request, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// DELETE /firewall_policies/{id}/server_ips/{id}
+func (api *API) DeleteFirewallPolicyServerIp(fp_id string, ip_id string) (*FirewallPolicy, error) {
+ result := new(FirewallPolicy)
+ url := createUrl(api, firewallPolicyPathSegment, fp_id, "server_ips", ip_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /firewall_policies/{id}/rules
+func (api *API) ListFirewallPolicyRules(fp_id string) ([]FirewallPolicyRule, error) {
+ result := []FirewallPolicyRule{}
+ url := createUrl(api, firewallPolicyPathSegment, fp_id, "rules")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// POST /firewall_policies/{id}/rules
+func (api *API) AddFirewallPolicyRules(fp_id string, fp_rules []FirewallPolicyRule) (*FirewallPolicy, error) {
+ result := new(FirewallPolicy)
+ data := struct {
+ Rules []FirewallPolicyRule `json:"rules"`
+ }{fp_rules}
+ url := createUrl(api, firewallPolicyPathSegment, fp_id, "rules")
+ err := api.Client.Post(url, &data, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /firewall_policies/{id}/rules/{id}
+func (api *API) GetFirewallPolicyRule(fp_id string, rule_id string) (*FirewallPolicyRule, error) {
+ result := new(FirewallPolicyRule)
+ url := createUrl(api, firewallPolicyPathSegment, fp_id, "rules", rule_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// DELETE /firewall_policies/{id}/rules/{id}
+func (api *API) DeleteFirewallPolicyRule(fp_id string, rule_id string) (*FirewallPolicy, error) {
+ result := new(FirewallPolicy)
+ url := createUrl(api, firewallPolicyPathSegment, fp_id, "rules", rule_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+func (fp *FirewallPolicy) GetState() (string, error) {
+ in, err := fp.api.GetFirewallPolicy(fp.Id)
+ if in == nil {
+ return "", err
+ }
+ return in.State, err
+}
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/images.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/images.go
new file mode 100644
index 000000000..a3551cef7
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/images.go
@@ -0,0 +1,110 @@
+package oneandone
+
+import (
+ "net/http"
+)
+
+type Image struct {
+ idField
+ ImageConfig
+ MinHddSize int `json:"min_hdd_size"`
+ Architecture *int `json:"os_architecture"`
+ CloudPanelId string `json:"cloudpanel_id,omitempty"`
+ CreationDate string `json:"creation_date,omitempty"`
+ State string `json:"state,omitempty"`
+ OsImageType string `json:"os_image_type,omitempty"`
+ OsFamily string `json:"os_family,omitempty"`
+ Os string `json:"os,omitempty"`
+ OsVersion string `json:"os_version,omitempty"`
+ Type string `json:"type,omitempty"`
+ Licenses []License `json:"licenses,omitempty"`
+ Hdds []Hdd `json:"hdds,omitempty"`
+ Datacenter *Datacenter `json:"datacenter,omitempty"`
+ ApiPtr
+}
+
+type ImageConfig struct {
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ Frequency string `json:"frequency,omitempty"`
+ ServerId string `json:"server_id,omitempty"`
+ NumImages int `json:"num_images"`
+}
+
+// GET /images
+func (api *API) ListImages(args ...interface{}) ([]Image, error) {
+ url, err := processQueryParams(createUrl(api, imagePathSegment), args...)
+ if err != nil {
+ return nil, err
+ }
+ result := []Image{}
+ err = api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ for index, _ := range result {
+ result[index].api = api
+ }
+ return result, nil
+}
+
+// POST /images
+func (api *API) CreateImage(request *ImageConfig) (string, *Image, error) {
+ res := new(Image)
+ url := createUrl(api, imagePathSegment)
+ err := api.Client.Post(url, &request, &res, http.StatusAccepted)
+ if err != nil {
+ return "", nil, err
+ }
+ res.api = api
+ return res.Id, res, nil
+}
+
+// GET /images/{id}
+func (api *API) GetImage(img_id string) (*Image, error) {
+ result := new(Image)
+ url := createUrl(api, imagePathSegment, img_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// DELETE /images/{id}
+func (api *API) DeleteImage(img_id string) (*Image, error) {
+ result := new(Image)
+ url := createUrl(api, imagePathSegment, img_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// PUT /images/{id}
+func (api *API) UpdateImage(img_id string, new_name string, new_desc string, new_freq string) (*Image, error) {
+ result := new(Image)
+ req := struct {
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ Frequency string `json:"frequency,omitempty"`
+ }{Name: new_name, Description: new_desc, Frequency: new_freq}
+ url := createUrl(api, imagePathSegment, img_id)
+ err := api.Client.Put(url, &req, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+func (im *Image) GetState() (string, error) {
+ in, err := im.api.GetImage(im.Id)
+ if in == nil {
+ return "", err
+ }
+ return in.State, err
+}
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/loadbalancers.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/loadbalancers.go
new file mode 100644
index 000000000..c965a25a8
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/loadbalancers.go
@@ -0,0 +1,219 @@
+package oneandone
+
+import (
+ "net/http"
+)
+
+type LoadBalancer struct {
+ ApiPtr
+ idField
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ State string `json:"state,omitempty"`
+ CreationDate string `json:"creation_date,omitempty"`
+ Ip string `json:"ip,omitempty"`
+ HealthCheckTest string `json:"health_check_test,omitempty"`
+ HealthCheckInterval int `json:"health_check_interval"`
+ HealthCheckPath string `json:"health_check_path,omitempty"`
+ HealthCheckPathParser string `json:"health_check_path_parser,omitempty"`
+ Persistence bool `json:"persistence"`
+ PersistenceTime int `json:"persistence_time"`
+ Method string `json:"method,omitempty"`
+ Rules []LoadBalancerRule `json:"rules,omitempty"`
+ ServerIps []ServerIpInfo `json:"server_ips,omitempty"`
+ Datacenter *Datacenter `json:"datacenter,omitempty"`
+ CloudPanelId string `json:"cloudpanel_id,omitempty"`
+}
+
+type LoadBalancerRule struct {
+ idField
+ Protocol string `json:"protocol,omitempty"`
+ PortBalancer uint16 `json:"port_balancer"`
+ PortServer uint16 `json:"port_server"`
+ Source string `json:"source,omitempty"`
+}
+
+type LoadBalancerRequest struct {
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ DatacenterId string `json:"datacenter_id,omitempty"`
+ HealthCheckTest string `json:"health_check_test,omitempty"`
+ HealthCheckInterval *int `json:"health_check_interval"`
+ HealthCheckPath string `json:"health_check_path,omitempty"`
+ HealthCheckPathParser string `json:"health_check_path_parser,omitempty"`
+ Persistence *bool `json:"persistence"`
+ PersistenceTime *int `json:"persistence_time"`
+ Method string `json:"method,omitempty"`
+ Rules []LoadBalancerRule `json:"rules,omitempty"`
+}
+
+// GET /load_balancers
+func (api *API) ListLoadBalancers(args ...interface{}) ([]LoadBalancer, error) {
+ url, err := processQueryParams(createUrl(api, loadBalancerPathSegment), args...)
+ if err != nil {
+ return nil, err
+ }
+ result := []LoadBalancer{}
+ err = api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ for index, _ := range result {
+ result[index].api = api
+ }
+ return result, nil
+}
+
+// POST /load_balancers
+func (api *API) CreateLoadBalancer(request *LoadBalancerRequest) (string, *LoadBalancer, error) {
+ url := createUrl(api, loadBalancerPathSegment)
+ result := new(LoadBalancer)
+ err := api.Client.Post(url, &request, &result, http.StatusAccepted)
+ if err != nil {
+ return "", nil, err
+ }
+ result.api = api
+ return result.Id, result, nil
+}
+
+// GET /load_balancers/{id}
+func (api *API) GetLoadBalancer(lb_id string) (*LoadBalancer, error) {
+ url := createUrl(api, loadBalancerPathSegment, lb_id)
+ result := new(LoadBalancer)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// DELETE /load_balancers/{id}
+func (api *API) DeleteLoadBalancer(lb_id string) (*LoadBalancer, error) {
+ url := createUrl(api, loadBalancerPathSegment, lb_id)
+ result := new(LoadBalancer)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// PUT /load_balancers/{id}
+func (api *API) UpdateLoadBalancer(lb_id string, request *LoadBalancerRequest) (*LoadBalancer, error) {
+ url := createUrl(api, loadBalancerPathSegment, lb_id)
+ result := new(LoadBalancer)
+ err := api.Client.Put(url, &request, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /load_balancers/{id}/server_ips
+func (api *API) ListLoadBalancerServerIps(lb_id string) ([]ServerIpInfo, error) {
+ result := []ServerIpInfo{}
+ url := createUrl(api, loadBalancerPathSegment, lb_id, "server_ips")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// GET /load_balancers/{id}/server_ips/{id}
+func (api *API) GetLoadBalancerServerIp(lb_id string, ip_id string) (*ServerIpInfo, error) {
+ result := new(ServerIpInfo)
+ url := createUrl(api, loadBalancerPathSegment, lb_id, "server_ips", ip_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// POST /load_balancers/{id}/server_ips
+func (api *API) AddLoadBalancerServerIps(lb_id string, ip_ids []string) (*LoadBalancer, error) {
+ result := new(LoadBalancer)
+ request := serverIps{
+ ServerIps: ip_ids,
+ }
+ url := createUrl(api, loadBalancerPathSegment, lb_id, "server_ips")
+ err := api.Client.Post(url, &request, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// DELETE /load_balancers/{id}/server_ips/{id}
+func (api *API) DeleteLoadBalancerServerIp(lb_id string, ip_id string) (*LoadBalancer, error) {
+ result := new(LoadBalancer)
+ url := createUrl(api, loadBalancerPathSegment, lb_id, "server_ips", ip_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /load_balancers/{load_balancer_id}/rules
+func (api *API) ListLoadBalancerRules(lb_id string) ([]LoadBalancerRule, error) {
+ result := []LoadBalancerRule{}
+ url := createUrl(api, loadBalancerPathSegment, lb_id, "rules")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// POST /load_balancers/{load_balancer_id}/rules
+func (api *API) AddLoadBalancerRules(lb_id string, lb_rules []LoadBalancerRule) (*LoadBalancer, error) {
+ result := new(LoadBalancer)
+ data := struct {
+ Rules []LoadBalancerRule `json:"rules"`
+ }{lb_rules}
+ url := createUrl(api, loadBalancerPathSegment, lb_id, "rules")
+ err := api.Client.Post(url, &data, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /load_balancers/{load_balancer_id}/rules/{rule_id}
+func (api *API) GetLoadBalancerRule(lb_id string, rule_id string) (*LoadBalancerRule, error) {
+ result := new(LoadBalancerRule)
+ url := createUrl(api, loadBalancerPathSegment, lb_id, "rules", rule_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// DELETE /load_balancers/{load_balancer_id}/rules/{rule_id}
+func (api *API) DeleteLoadBalancerRule(lb_id string, rule_id string) (*LoadBalancer, error) {
+ result := new(LoadBalancer)
+ url := createUrl(api, loadBalancerPathSegment, lb_id, "rules", rule_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+func (lb *LoadBalancer) GetState() (string, error) {
+ in, err := lb.api.GetLoadBalancer(lb.Id)
+ if in == nil {
+ return "", err
+ }
+ return in.State, err
+}
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/logs.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/logs.go
new file mode 100644
index 000000000..b16ef31d5
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/logs.go
@@ -0,0 +1,50 @@
+package oneandone
+
+import (
+ "net/http"
+ "time"
+)
+
+type Log struct {
+ ApiPtr
+ idField
+ typeField
+ CloudPanelId string `json:"cloudpanel_id,omitempty"`
+ SiteId string `json:"site_id,omitempty"`
+ StartDate string `json:"start_date,omitempty"`
+ EndDate string `json:"end_date,omitempty"`
+ Action string `json:"action,omitempty"`
+ Duration int `json:"duration"`
+ Status *Status `json:"Status,omitempty"`
+ Resource *Identity `json:"resource,omitempty"`
+ User *Identity `json:"user,omitempty"`
+}
+
+// GET /logs
+func (api *API) ListLogs(period string, sd *time.Time, ed *time.Time, args ...interface{}) ([]Log, error) {
+ result := []Log{}
+ url, err := processQueryParamsExt(createUrl(api, logPathSegment), period, sd, ed, args...)
+ if err != nil {
+ return nil, err
+ }
+ err = api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ for index, _ := range result {
+ result[index].api = api
+ }
+ return result, nil
+}
+
+// GET /logs/{id}
+func (api *API) GetLog(log_id string) (*Log, error) {
+ result := new(Log)
+ url := createUrl(api, logPathSegment, log_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/monitoringcenter.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/monitoringcenter.go
new file mode 100644
index 000000000..86e899889
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/monitoringcenter.go
@@ -0,0 +1,158 @@
+package oneandone
+
+import (
+ "errors"
+ "net/http"
+ "time"
+)
+
+type MonServerUsageSummary struct {
+ Identity
+ Agent *monitoringAgent `json:"agent,omitempty"`
+ Alerts *monitoringAlerts `json:"alerts,omitempty"`
+ Status *monitoringStatus `json:"status,omitempty"`
+ ApiPtr
+}
+
+type MonServerUsageDetails struct {
+ Identity
+ Status *statusState `json:"status,omitempty"`
+ Agent *monitoringAgent `json:"agent,omitempty"`
+ Alerts *monitoringAlerts `json:"alerts,omitempty"`
+ CpuStatus *utilizationStatus `json:"cpu,omitempty"`
+ DiskStatus *utilizationStatus `json:"disk,omitempty"`
+ RamStatus *utilizationStatus `json:"ram,omitempty"`
+ PingStatus *pingStatus `json:"internal_ping,omitempty"`
+ TransferStatus *transferStatus `json:"transfer,omitempty"`
+ ApiPtr
+}
+
+type monitoringStatus struct {
+ State string `json:"state,omitempty"`
+ Cpu *statusState `json:"cpu,omitempty"`
+ Disk *statusState `json:"disk,omitempty"`
+ InternalPing *statusState `json:"internal_ping,omitempty"`
+ Ram *statusState `json:"ram,omitempty"`
+ Transfer *statusState `json:"transfer,omitempty"`
+}
+
+type utilizationStatus struct {
+ CriticalThreshold int `json:"critical,omitempty"`
+ WarningThreshold int `json:"warning,omitempty"`
+ Status string `json:"status,omitempty"`
+ Data []usageData `json:"data,omitempty"`
+ Unit *usageUnit `json:"unit,omitempty"`
+}
+
+type pingStatus struct {
+ CriticalThreshold int `json:"critical,omitempty"`
+ WarningThreshold int `json:"warning,omitempty"`
+ Status string `json:"status,omitempty"`
+ Data []pingData `json:"data,omitempty"`
+ Unit *pingUnit `json:"unit,omitempty"`
+}
+
+type transferStatus struct {
+ CriticalThreshold int `json:"critical,omitempty"`
+ WarningThreshold int `json:"warning,omitempty"`
+ Status string `json:"status,omitempty"`
+ Data []transferData `json:"data,omitempty"`
+ Unit *transferUnit `json:"unit,omitempty"`
+}
+
+type monitoringAgent struct {
+ AgentInstalled bool `json:"agent_installed"`
+ MissingAgentAlert bool `json:"missing_agent_alert"`
+ MonitoringNeedsAgent bool `json:"monitoring_needs_agent"`
+}
+
+type monitoringAlerts struct {
+ Ports *monitoringAlertInfo `json:"ports,omitempty"`
+ Process *monitoringAlertInfo `json:"process,omitempty"`
+ Resources *monitoringAlertInfo `json:"resources,omitempty"`
+}
+
+type monitoringAlertInfo struct {
+ Ok int `json:"ok"`
+ Warning int `json:"warning"`
+ Critical int `json:"critical"`
+}
+
+type usageData struct {
+ Date string `json:"date,omitempty"`
+ UsedPercent float32 `json:"used_percent"`
+}
+
+type usageUnit struct {
+ UsedPercent string `json:"used_percent,omitempty"`
+}
+
+type pingUnit struct {
+ PackagesLost string `json:"pl,omitempty"`
+ AccessTime string `json:"rta,omitempty"`
+}
+
+type pingData struct {
+ Date string `json:"date,omitempty"`
+ PackagesLost int `json:"pl"`
+ AccessTime float32 `json:"rta"`
+}
+
+type transferUnit struct {
+ Downstream string `json:"downstream,omitempty"`
+ Upstream string `json:"upstream,omitempty"`
+}
+
+type transferData struct {
+ Date string `json:"date,omitempty"`
+ Downstream int `json:"downstream"`
+ Upstream int `json:"upstream"`
+}
+
+// GET /monitoring_center
+func (api *API) ListMonitoringServersUsages(args ...interface{}) ([]MonServerUsageSummary, error) {
+ url, err := processQueryParams(createUrl(api, monitorCenterPathSegment), args...)
+ if err != nil {
+ return nil, err
+ }
+ result := []MonServerUsageSummary{}
+ err = api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ for index, _ := range result {
+ result[index].api = api
+ }
+ return result, nil
+}
+
+// GET /monitoring_center/{server_id}
+func (api *API) GetMonitoringServerUsage(ser_id string, period string, dates ...time.Time) (*MonServerUsageDetails, error) {
+ if period == "" {
+ return nil, errors.New("Time period must be provided.")
+ }
+
+ params := make(map[string]interface{}, len(dates)+1)
+ params["period"] = period
+
+ if len(dates) == 2 {
+ if dates[0].After(dates[1]) {
+ return nil, errors.New("Start date cannot be after end date.")
+ }
+
+ params["start_date"] = dates[0].Format(time.RFC3339)
+ params["end_date"] = dates[1].Format(time.RFC3339)
+
+ } else if len(dates) > 0 {
+ return nil, errors.New("Start and end dates must be provided.")
+ }
+ url := createUrl(api, monitorCenterPathSegment, ser_id)
+ url = appendQueryParams(url, params)
+ result := new(MonServerUsageDetails)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/monitoringpolicies.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/monitoringpolicies.go
new file mode 100644
index 000000000..4272461b6
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/monitoringpolicies.go
@@ -0,0 +1,305 @@
+package oneandone
+
+import (
+ "net/http"
+)
+
+type MonitoringPolicy struct {
+ ApiPtr
+ idField
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ State string `json:"state,omitempty"`
+ Default *int `json:"default,omitempty"`
+ CreationDate string `json:"creation_date,omitempty"`
+ Email string `json:"email,omitempty"`
+ Agent bool `json:"agent"`
+ Servers []Identity `json:"servers,omitempty"`
+ Thresholds *MonitoringThreshold `json:"thresholds,omitempty"`
+ Ports []MonitoringPort `json:"ports,omitempty"`
+ Processes []MonitoringProcess `json:"processes,omitempty"`
+ CloudPanelId string `json:"cloudpanel_id,omitempty"`
+}
+
+type MonitoringThreshold struct {
+ Cpu *MonitoringLevel `json:"cpu,omitempty"`
+ Ram *MonitoringLevel `json:"ram,omitempty"`
+ Disk *MonitoringLevel `json:"disk,omitempty"`
+ Transfer *MonitoringLevel `json:"transfer,omitempty"`
+ InternalPing *MonitoringLevel `json:"internal_ping,omitempty"`
+}
+
+type MonitoringLevel struct {
+ Warning *MonitoringValue `json:"warning,omitempty"`
+ Critical *MonitoringValue `json:"critical,omitempty"`
+}
+
+type MonitoringValue struct {
+ Value int `json:"value"`
+ Alert bool `json:"alert"`
+}
+
+type MonitoringPort struct {
+ idField
+ Protocol string `json:"protocol,omitempty"`
+ Port int `json:"port"`
+ AlertIf string `json:"alert_if,omitempty"`
+ EmailNotification bool `json:"email_notification"`
+}
+
+type MonitoringProcess struct {
+ idField
+ Process string `json:"process,omitempty"`
+ AlertIf string `json:"alert_if,omitempty"`
+ EmailNotification bool `json:"email_notification"`
+}
+
+// GET /monitoring_policies
+func (api *API) ListMonitoringPolicies(args ...interface{}) ([]MonitoringPolicy, error) {
+ url, err := processQueryParams(createUrl(api, monitorPolicyPathSegment), args...)
+ if err != nil {
+ return nil, err
+ }
+ result := []MonitoringPolicy{}
+ err = api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ for index, _ := range result {
+ result[index].api = api
+ }
+ return result, nil
+}
+
+// POST /monitoring_policies
+func (api *API) CreateMonitoringPolicy(mp *MonitoringPolicy) (string, *MonitoringPolicy, error) {
+ result := new(MonitoringPolicy)
+ url := createUrl(api, monitorPolicyPathSegment)
+ err := api.Client.Post(url, &mp, &result, http.StatusCreated)
+ if err != nil {
+ return "", nil, err
+ }
+ result.api = api
+ return result.Id, result, nil
+}
+
+// GET /monitoring_policies/{id}
+func (api *API) GetMonitoringPolicy(mp_id string) (*MonitoringPolicy, error) {
+ result := new(MonitoringPolicy)
+ url := createUrl(api, monitorPolicyPathSegment, mp_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// DELETE /monitoring_policies/{id}
+func (api *API) DeleteMonitoringPolicy(mp_id string) (*MonitoringPolicy, error) {
+ result := new(MonitoringPolicy)
+ url := createUrl(api, monitorPolicyPathSegment, mp_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// PUT /monitoring_policies/{id}
+func (api *API) UpdateMonitoringPolicy(mp_id string, mp *MonitoringPolicy) (*MonitoringPolicy, error) {
+ url := createUrl(api, monitorPolicyPathSegment, mp_id)
+ result := new(MonitoringPolicy)
+ err := api.Client.Put(url, &mp, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /monitoring_policies/{id}/ports
+func (api *API) ListMonitoringPolicyPorts(mp_id string) ([]MonitoringPort, error) {
+ result := []MonitoringPort{}
+ url := createUrl(api, monitorPolicyPathSegment, mp_id, "ports")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// POST /monitoring_policies/{id}/ports
+func (api *API) AddMonitoringPolicyPorts(mp_id string, mp_ports []MonitoringPort) (*MonitoringPolicy, error) {
+ result := new(MonitoringPolicy)
+ data := struct {
+ Ports []MonitoringPort `json:"ports"`
+ }{mp_ports}
+ url := createUrl(api, monitorPolicyPathSegment, mp_id, "ports")
+ err := api.Client.Post(url, &data, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /monitoring_policies/{id}/ports/{id}
+func (api *API) GetMonitoringPolicyPort(mp_id string, port_id string) (*MonitoringPort, error) {
+ result := new(MonitoringPort)
+ url := createUrl(api, monitorPolicyPathSegment, mp_id, "ports", port_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// DELETE /monitoring_policies/{id}/ports/{id}
+func (api *API) DeleteMonitoringPolicyPort(mp_id string, port_id string) (*MonitoringPolicy, error) {
+ result := new(MonitoringPolicy)
+ url := createUrl(api, monitorPolicyPathSegment, mp_id, "ports", port_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// PUT /monitoring_policies/{id}/ports/{id}
+func (api *API) ModifyMonitoringPolicyPort(mp_id string, port_id string, mp_port *MonitoringPort) (*MonitoringPolicy, error) {
+ url := createUrl(api, monitorPolicyPathSegment, mp_id, "ports", port_id)
+ result := new(MonitoringPolicy)
+ req := struct {
+ Ports *MonitoringPort `json:"ports"`
+ }{mp_port}
+ err := api.Client.Put(url, &req, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /monitoring_policies/{id}/processes
+func (api *API) ListMonitoringPolicyProcesses(mp_id string) ([]MonitoringProcess, error) {
+ result := []MonitoringProcess{}
+ url := createUrl(api, monitorPolicyPathSegment, mp_id, "processes")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// POST /monitoring_policies/{id}/processes
+func (api *API) AddMonitoringPolicyProcesses(mp_id string, mp_procs []MonitoringProcess) (*MonitoringPolicy, error) {
+ result := new(MonitoringPolicy)
+ request := struct {
+ Processes []MonitoringProcess `json:"processes"`
+ }{mp_procs}
+ url := createUrl(api, monitorPolicyPathSegment, mp_id, "processes")
+ err := api.Client.Post(url, &request, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /monitoring_policies/{id}/processes/{id}
+func (api *API) GetMonitoringPolicyProcess(mp_id string, proc_id string) (*MonitoringProcess, error) {
+ result := new(MonitoringProcess)
+ url := createUrl(api, monitorPolicyPathSegment, mp_id, "processes", proc_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// DELETE /monitoring_policies/{id}/processes/{id}
+func (api *API) DeleteMonitoringPolicyProcess(mp_id string, proc_id string) (*MonitoringPolicy, error) {
+ result := new(MonitoringPolicy)
+ url := createUrl(api, monitorPolicyPathSegment, mp_id, "processes", proc_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// PUT /monitoring_policies/{id}/processes/{id}
+func (api *API) ModifyMonitoringPolicyProcess(mp_id string, proc_id string, mp_proc *MonitoringProcess) (*MonitoringPolicy, error) {
+ url := createUrl(api, monitorPolicyPathSegment, mp_id, "processes", proc_id)
+ result := new(MonitoringPolicy)
+ req := struct {
+ Processes *MonitoringProcess `json:"processes"`
+ }{mp_proc}
+ err := api.Client.Put(url, &req, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /monitoring_policies/{id}/servers
+func (api *API) ListMonitoringPolicyServers(mp_id string) ([]Identity, error) {
+ result := []Identity{}
+ url := createUrl(api, monitorPolicyPathSegment, mp_id, "servers")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// POST /monitoring_policies/{id}/servers
+func (api *API) AttachMonitoringPolicyServers(mp_id string, sids []string) (*MonitoringPolicy, error) {
+ result := new(MonitoringPolicy)
+ request := servers{
+ Servers: sids,
+ }
+ url := createUrl(api, monitorPolicyPathSegment, mp_id, "servers")
+ err := api.Client.Post(url, &request, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /monitoring_policies/{id}/servers/{id}
+func (api *API) GetMonitoringPolicyServer(mp_id string, ser_id string) (*Identity, error) {
+ result := new(Identity)
+ url := createUrl(api, monitorPolicyPathSegment, mp_id, "servers", ser_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// DELETE /monitoring_policies/{id}/servers/{id}
+func (api *API) RemoveMonitoringPolicyServer(mp_id string, ser_id string) (*MonitoringPolicy, error) {
+ result := new(MonitoringPolicy)
+ url := createUrl(api, monitorPolicyPathSegment, mp_id, "servers", ser_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+func (mp *MonitoringPolicy) GetState() (string, error) {
+ in, err := mp.api.GetMonitoringPolicy(mp.Id)
+ if in == nil {
+ return "", err
+ }
+ return in.State, err
+}
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/oneandone.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/oneandone.go
new file mode 100644
index 000000000..e007fcb22
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/oneandone.go
@@ -0,0 +1,163 @@
+package oneandone
+
+import (
+ "errors"
+ "net/http"
+ "reflect"
+ "time"
+)
+
+// Struct to hold the required information for accessing the API.
+//
+// Instances of this type contain the URL of the endpoint to access the API as well as the API access token to be used.
+// They offer also all methods that allow to access the various objects that are returned by top level resources of
+// the API.
+type API struct {
+ Endpoint string
+ Client *restClient
+}
+
+type ApiPtr struct {
+ api *API
+}
+
+type idField struct {
+ Id string `json:"id,omitempty"`
+}
+
+type typeField struct {
+ Type string `json:"type,omitempty"`
+}
+
+type nameField struct {
+ Name string `json:"name,omitempty"`
+}
+
+type descField struct {
+ Description string `json:"description,omitempty"`
+}
+
+type countField struct {
+ Count int `json:"count,omitempty"`
+}
+
+type serverIps struct {
+ ServerIps []string `json:"server_ips"`
+}
+
+type servers struct {
+ Servers []string `json:"servers"`
+}
+
+type ApiInstance interface {
+ GetState() (string, error)
+}
+
+const (
+ datacenterPathSegment = "datacenters"
+ dvdIsoPathSegment = "dvd_isos"
+ firewallPolicyPathSegment = "firewall_policies"
+ imagePathSegment = "images"
+ loadBalancerPathSegment = "load_balancers"
+ logPathSegment = "logs"
+ monitorCenterPathSegment = "monitoring_center"
+ monitorPolicyPathSegment = "monitoring_policies"
+ pingPathSegment = "ping"
+ pingAuthPathSegment = "ping_auth"
+ pricingPathSegment = "pricing"
+ privateNetworkPathSegment = "private_networks"
+ publicIpPathSegment = "public_ips"
+ rolePathSegment = "roles"
+ serverPathSegment = "servers"
+ serverAppliancePathSegment = "server_appliances"
+ sharedStoragePathSegment = "shared_storages"
+ usagePathSegment = "usages"
+ userPathSegment = "users"
+ vpnPathSegment = "vpns"
+)
+
+// Struct to hold the status of an API object.
+//
+// Values of this type are used to represent the status of API objects like servers, firewall policies and the like.
+//
+// The value of the "State" field can represent fixed states like "ACTIVE" or "POWERED_ON" but also transitional
+// states like "POWERING_ON" or "CONFIGURING".
+//
+// For fixed states the "Percent" field is empty where as for transitional states it contains the progress of the
+// transition in percent.
+type Status struct {
+ State string `json:"state"`
+ Percent int `json:"percent"`
+}
+
+type statusState struct {
+ State string `json:"state,omitempty"`
+}
+
+type Identity struct {
+ idField
+ nameField
+}
+
+type License struct {
+ nameField
+}
+
+// Creates a new API instance.
+//
+// Explanations about given token and url information can be found online under the following url TODO add url!
+func New(token string, url string) *API {
+ api := new(API)
+ api.Endpoint = url
+ api.Client = newRestClient(token)
+ return api
+}
+
+// Converts a given integer value into a pointer of the same type.
+func Int2Pointer(input int) *int {
+ result := new(int)
+ *result = input
+ return result
+}
+
+// Converts a given boolean value into a pointer of the same type.
+func Bool2Pointer(input bool) *bool {
+ result := new(bool)
+ *result = input
+ return result
+}
+
+// Performs busy-waiting for types that implement ApiInstance interface.
+func (api *API) WaitForState(in ApiInstance, state string, sec time.Duration, count int) error {
+ if in != nil {
+ for i := 0; i < count; i++ {
+ s, err := in.GetState()
+ if err != nil {
+ return err
+ }
+ if s == state {
+ return nil
+ }
+ time.Sleep(sec * time.Second)
+ }
+ return errors.New(reflect.ValueOf(in).Type().String() + " operation timeout.")
+ }
+ return nil
+}
+
+// Waits until instance is deleted for types that implement ApiInstance interface.
+func (api *API) WaitUntilDeleted(in ApiInstance) error {
+ var err error
+ for in != nil {
+ _, err = in.GetState()
+ if err != nil {
+ if apiError, ok := err.(apiError); ok && apiError.httpStatusCode == http.StatusNotFound {
+ return nil
+ } else {
+ return err
+ }
+ }
+ time.Sleep(5 * time.Second)
+ }
+ return nil
+}
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/ping.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/ping.go
new file mode 100644
index 000000000..255608885
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/ping.go
@@ -0,0 +1,29 @@
+package oneandone
+
+import "net/http"
+
+// GET /ping
+// Returns "PONG" if API is running
+func (api *API) Ping() ([]string, error) {
+ url := createUrl(api, pingPathSegment)
+ result := []string{}
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+
+ return result, nil
+}
+
+// GET /ping_auth
+// Returns "PONG" if the API is running and the authentication token is valid
+func (api *API) PingAuth() ([]string, error) {
+ url := createUrl(api, pingAuthPathSegment)
+ result := []string{}
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+
+ return result, nil
+}
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/pricing.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/pricing.go
new file mode 100644
index 000000000..90eb2abd9
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/pricing.go
@@ -0,0 +1,40 @@
+package oneandone
+
+import "net/http"
+
+type Pricing struct {
+ Currency string `json:"currency,omitempty"`
+ Plan *pricingPlan `json:"pricing_plans,omitempty"`
+}
+
+type pricingPlan struct {
+ Image *pricingItem `json:"image,omitempty"`
+ PublicIPs []pricingItem `json:"public_ips,omitempty"`
+ Servers *serverPricing `json:"servers,omitempty"`
+ SharedStorage *pricingItem `json:"shared_storage,omitempty"`
+ SoftwareLicenses []pricingItem `json:"software_licences,omitempty"`
+}
+
+type serverPricing struct {
+ FixedServers []pricingItem `json:"fixed_servers,omitempty"`
+ FlexServers []pricingItem `json:"flexible_server,omitempty"`
+}
+
+type pricingItem struct {
+ Name string `json:"name,omitempty"`
+ GrossPrice string `json:"price_gross,omitempty"`
+ NetPrice string `json:"price_net,omitempty"`
+ Unit string `json:"unit,omitempty"`
+}
+
+// GET /pricing
+func (api *API) GetPricing() (*Pricing, error) {
+ result := new(Pricing)
+ url := createUrl(api, pricingPathSegment)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+
+ return result, nil
+}
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/privatenetworks.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/privatenetworks.go
new file mode 100644
index 000000000..667494e04
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/privatenetworks.go
@@ -0,0 +1,149 @@
+package oneandone
+
+import (
+ "net/http"
+)
+
+type PrivateNetwork struct {
+ Identity
+ descField
+ CloudpanelId string `json:"cloudpanel_id,omitempty"`
+ NetworkAddress string `json:"network_address,omitempty"`
+ SubnetMask string `json:"subnet_mask,omitempty"`
+ State string `json:"state,omitempty"`
+ SiteId string `json:"site_id,omitempty"`
+ CreationDate string `json:"creation_date,omitempty"`
+ Servers []Identity `json:"servers,omitempty"`
+ Datacenter *Datacenter `json:"datacenter,omitempty"`
+ ApiPtr
+}
+
+type PrivateNetworkRequest struct {
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ DatacenterId string `json:"datacenter_id,omitempty"`
+ NetworkAddress string `json:"network_address,omitempty"`
+ SubnetMask string `json:"subnet_mask,omitempty"`
+}
+
+// GET /private_networks
+func (api *API) ListPrivateNetworks(args ...interface{}) ([]PrivateNetwork, error) {
+ url, err := processQueryParams(createUrl(api, privateNetworkPathSegment), args...)
+ if err != nil {
+ return nil, err
+ }
+ result := []PrivateNetwork{}
+ err = api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ for index, _ := range result {
+ result[index].api = api
+ }
+ return result, nil
+}
+
+// POST /private_networks
+func (api *API) CreatePrivateNetwork(request *PrivateNetworkRequest) (string, *PrivateNetwork, error) {
+ result := new(PrivateNetwork)
+ url := createUrl(api, privateNetworkPathSegment)
+ err := api.Client.Post(url, &request, &result, http.StatusAccepted)
+ if err != nil {
+ return "", nil, err
+ }
+ result.api = api
+ return result.Id, result, nil
+}
+
+// GET /private_networks/{id}
+func (api *API) GetPrivateNetwork(pn_id string) (*PrivateNetwork, error) {
+ result := new(PrivateNetwork)
+ url := createUrl(api, privateNetworkPathSegment, pn_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// PUT /private_networks/{id}
+func (api *API) UpdatePrivateNetwork(pn_id string, request *PrivateNetworkRequest) (*PrivateNetwork, error) {
+ result := new(PrivateNetwork)
+ url := createUrl(api, privateNetworkPathSegment, pn_id)
+ err := api.Client.Put(url, &request, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// DELETE /private_networks/{id}
+func (api *API) DeletePrivateNetwork(pn_id string) (*PrivateNetwork, error) {
+ result := new(PrivateNetwork)
+ url := createUrl(api, privateNetworkPathSegment, pn_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /private_networks/{id}/servers
+func (api *API) ListPrivateNetworkServers(pn_id string) ([]Identity, error) {
+ result := []Identity{}
+ url := createUrl(api, privateNetworkPathSegment, pn_id, "servers")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// POST /private_networks/{id}/servers
+func (api *API) AttachPrivateNetworkServers(pn_id string, sids []string) (*PrivateNetwork, error) {
+ result := new(PrivateNetwork)
+ req := servers{
+ Servers: sids,
+ }
+ url := createUrl(api, privateNetworkPathSegment, pn_id, "servers")
+ err := api.Client.Post(url, &req, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /private_networks/{id}/servers/{id}
+func (api *API) GetPrivateNetworkServer(pn_id string, server_id string) (*Identity, error) {
+ result := new(Identity)
+ url := createUrl(api, privateNetworkPathSegment, pn_id, "servers", server_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// DELETE /private_networks/{id}/servers/{id}
+func (api *API) DetachPrivateNetworkServer(pn_id string, pns_id string) (*PrivateNetwork, error) {
+ result := new(PrivateNetwork)
+ url := createUrl(api, privateNetworkPathSegment, pn_id, "servers", pns_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+func (pn *PrivateNetwork) GetState() (string, error) {
+ in, err := pn.api.GetPrivateNetwork(pn.Id)
+ if in == nil {
+ return "", err
+ }
+ return in.State, err
+}
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/publicips.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/publicips.go
new file mode 100644
index 000000000..b0b6bd6ed
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/publicips.go
@@ -0,0 +1,108 @@
+package oneandone
+
+import "net/http"
+
+type PublicIp struct {
+ idField
+ typeField
+ IpAddress string `json:"ip,omitempty"`
+ AssignedTo *assignedTo `json:"assigned_to,omitempty"`
+ ReverseDns string `json:"reverse_dns,omitempty"`
+ IsDhcp *bool `json:"is_dhcp,omitempty"`
+ State string `json:"state,omitempty"`
+ SiteId string `json:"site_id,omitempty"`
+ CreationDate string `json:"creation_date,omitempty"`
+ Datacenter *Datacenter `json:"datacenter,omitempty"`
+ ApiPtr
+}
+
+type assignedTo struct {
+ Identity
+ typeField
+}
+
+const (
+ IpTypeV4 = "IPV4"
+ IpTypeV6 = "IPV6"
+)
+
+// GET /public_ips
+func (api *API) ListPublicIps(args ...interface{}) ([]PublicIp, error) {
+ url, err := processQueryParams(createUrl(api, publicIpPathSegment), args...)
+ if err != nil {
+ return nil, err
+ }
+ result := []PublicIp{}
+ err = api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ for index, _ := range result {
+ result[index].api = api
+ }
+ return result, nil
+}
+
+// POST /public_ips
+func (api *API) CreatePublicIp(ip_type string, reverse_dns string, datacenter_id string) (string, *PublicIp, error) {
+ res := new(PublicIp)
+ url := createUrl(api, publicIpPathSegment)
+ req := struct {
+ DatacenterId string `json:"datacenter_id,omitempty"`
+ ReverseDns string `json:"reverse_dns,omitempty"`
+ Type string `json:"type,omitempty"`
+ }{DatacenterId: datacenter_id, ReverseDns: reverse_dns, Type: ip_type}
+ err := api.Client.Post(url, &req, &res, http.StatusCreated)
+ if err != nil {
+ return "", nil, err
+ }
+ res.api = api
+ return res.Id, res, nil
+}
+
+// GET /public_ips/{id}
+func (api *API) GetPublicIp(ip_id string) (*PublicIp, error) {
+ result := new(PublicIp)
+ url := createUrl(api, publicIpPathSegment, ip_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// DELETE /public_ips/{id}
+func (api *API) DeletePublicIp(ip_id string) (*PublicIp, error) {
+ result := new(PublicIp)
+ url := createUrl(api, publicIpPathSegment, ip_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// PUT /public_ips/{id}
+func (api *API) UpdatePublicIp(ip_id string, reverse_dns string) (*PublicIp, error) {
+ result := new(PublicIp)
+ url := createUrl(api, publicIpPathSegment, ip_id)
+ req := struct {
+ ReverseDns string `json:"reverse_dns,omitempty"`
+ }{reverse_dns}
+ err := api.Client.Put(url, &req, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+func (ip *PublicIp) GetState() (string, error) {
+ in, err := ip.api.GetPublicIp(ip.Id)
+ if in == nil {
+ return "", err
+ }
+ return in.State, err
+}
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/restclient.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/restclient.go
new file mode 100644
index 000000000..b200a1089
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/restclient.go
@@ -0,0 +1,213 @@
+package oneandone
+
+import (
+ "bytes"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ p_url "net/url"
+ "time"
+)
+
+type restClient struct {
+ token string
+}
+
+func newRestClient(token string) *restClient {
+ restClient := new(restClient)
+ restClient.token = token
+ return restClient
+}
+
+func (c *restClient) Get(url string, result interface{}, expectedStatus int) error {
+ return c.doRequest(url, "GET", nil, result, expectedStatus)
+}
+
+func (c *restClient) Delete(url string, requestBody interface{}, result interface{}, expectedStatus int) error {
+ return c.doRequest(url, "DELETE", requestBody, result, expectedStatus)
+}
+
+func (c *restClient) Post(url string, requestBody interface{}, result interface{}, expectedStatus int) error {
+ return c.doRequest(url, "POST", requestBody, result, expectedStatus)
+}
+
+func (c *restClient) Put(url string, requestBody interface{}, result interface{}, expectedStatus int) error {
+ return c.doRequest(url, "PUT", requestBody, result, expectedStatus)
+}
+
+func (c *restClient) doRequest(url string, method string, requestBody interface{}, result interface{}, expectedStatus int) error {
+ var bodyData io.Reader
+ if requestBody != nil {
+ data, _ := json.Marshal(requestBody)
+ bodyData = bytes.NewBuffer(data)
+ }
+
+ request, err := http.NewRequest(method, url, bodyData)
+ if err != nil {
+ return err
+ }
+
+ request.Header.Add("X-Token", c.token)
+ request.Header.Add("Content-Type", "application/json")
+ client := http.Client{}
+ response, err := client.Do(request)
+ if err = isError(response, expectedStatus, err); err != nil {
+ return err
+ }
+
+ defer response.Body.Close()
+ body, err := ioutil.ReadAll(response.Body)
+ if err != nil {
+ return err
+ }
+ return c.unmarshal(body, result)
+}
+
+func (c *restClient) unmarshal(data []byte, result interface{}) error {
+ err := json.Unmarshal(data, result)
+ if err != nil {
+ // handle the case when the result is an empty array instead of an object
+ switch err.(type) {
+ case *json.UnmarshalTypeError:
+ var ra []interface{}
+ e := json.Unmarshal(data, &ra)
+ if e != nil {
+ return e
+ } else if len(ra) > 0 {
+ return err
+ }
+ return nil
+ default:
+ return err
+ }
+ }
+
+ return nil
+}
+
+func isError(response *http.Response, expectedStatus int, err error) error {
+ if err != nil {
+ return err
+ }
+ if response != nil {
+ if response.StatusCode == expectedStatus {
+ // we got a response with the expected HTTP status code, hence no error
+ return nil
+ }
+ body, _ := ioutil.ReadAll(response.Body)
+ // extract the API's error message to be returned later
+ er_resp := new(errorResponse)
+ err = json.Unmarshal(body, er_resp)
+ if err != nil {
+ return err
+ }
+
+ return apiError{response.StatusCode, fmt.Sprintf("Type: %s; Message: %s", er_resp.Type, er_resp.Message)}
+ }
+ return errors.New("Generic error - no response from the REST API service.")
+}
+
+func createUrl(api *API, sections ...interface{}) string {
+ url := api.Endpoint
+ for _, section := range sections {
+ url += "/" + fmt.Sprint(section)
+ }
+ return url
+}
+
+func makeParameterMap(args ...interface{}) (map[string]interface{}, error) {
+ qps := make(map[string]interface{}, len(args))
+ var is_true bool
+ var page, per_page int
+ var sort, query, fields string
+
+ for i, p := range args {
+ switch i {
+ case 0:
+ page, is_true = p.(int)
+ if !is_true {
+ return nil, errors.New("1st parameter must be a page number (integer).")
+ } else if page > 0 {
+ qps["page"] = page
+ }
+ case 1:
+ per_page, is_true = p.(int)
+ if !is_true {
+ return nil, errors.New("2nd parameter must be a per_page number (integer).")
+ } else if per_page > 0 {
+ qps["per_page"] = per_page
+ }
+ case 2:
+ sort, is_true = p.(string)
+ if !is_true {
+ return nil, errors.New("3rd parameter must be a sorting property string (e.g. 'name' or '-name').")
+ } else if sort != "" {
+ qps["sort"] = sort
+ }
+ case 3:
+ query, is_true = p.(string)
+ if !is_true {
+ return nil, errors.New("4th parameter must be a query string to look for the response.")
+ } else if query != "" {
+ qps["q"] = query
+ }
+ case 4:
+ fields, is_true = p.(string)
+ if !is_true {
+ return nil, errors.New("5th parameter must be fields properties string (e.g. 'id,name').")
+ } else if fields != "" {
+ qps["fields"] = fields
+ }
+ default:
+ return nil, errors.New("Wrong number of parameters.")
+ }
+ }
+ return qps, nil
+}
+
+func processQueryParams(url string, args ...interface{}) (string, error) {
+ if len(args) > 0 {
+ params, err := makeParameterMap(args...)
+ if err != nil {
+ return "", err
+ }
+ url = appendQueryParams(url, params)
+ }
+ return url, nil
+}
+
+func processQueryParamsExt(url string, period string, sd *time.Time, ed *time.Time, args ...interface{}) (string, error) {
+ var qm map[string]interface{}
+ var err error
+ if len(args) > 0 {
+ qm, err = makeParameterMap(args...)
+ if err != nil {
+ return "", err
+ }
+ } else {
+ qm = make(map[string]interface{}, 3)
+ }
+ qm["period"] = period
+ if sd != nil && ed != nil {
+ if sd.After(*ed) {
+ return "", errors.New("Start date cannot be after end date.")
+ }
+ qm["start_date"] = sd.Format(time.RFC3339)
+ qm["end_date"] = ed.Format(time.RFC3339)
+ }
+ url = appendQueryParams(url, qm)
+ return url, nil
+}
+
+func appendQueryParams(url string, params map[string]interface{}) string {
+ queryUrl, _ := p_url.Parse(url)
+ parameters := p_url.Values{}
+ for key, value := range params {
+ parameters.Add(key, fmt.Sprintf("%v", value))
+ }
+ queryUrl.RawQuery = parameters.Encode()
+ return queryUrl.String()
+}
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/roles.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/roles.go
new file mode 100644
index 000000000..e8aa44fee
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/roles.go
@@ -0,0 +1,595 @@
+package oneandone
+
+import "net/http"
+
+type Role struct {
+ Identity
+ descField
+ CreationDate string `json:"creation_date,omitempty"`
+ State string `json:"state,omitempty"`
+ Default *int `json:"default,omitempty"`
+ Permissions *Permissions `json:"permissions,omitempty"`
+ Users []Identity `json:"users,omitempty"`
+ ApiPtr
+}
+
+type Permissions struct {
+ Backups *BackupPerm `json:"backups,omitempty"`
+ Firewalls *FirewallPerm `json:"firewall_policies,omitempty"`
+ Images *ImagePerm `json:"images,omitempty"`
+ Invoice *InvoicePerm `json:"interactive_invoices,omitempty"`
+ IPs *IPPerm `json:"public_ips,omitempty"`
+ LoadBalancers *LoadBalancerPerm `json:"load_balancers,omitempty"`
+ Logs *LogPerm `json:"logs,omitempty"`
+ MonitorCenter *MonitorCenterPerm `json:"monitoring_center,omitempty"`
+ MonitorPolicies *MonitorPolicyPerm `json:"monitoring_policies,omitempty"`
+ PrivateNetworks *PrivateNetworkPerm `json:"private_networks,omitempty"`
+ Roles *RolePerm `json:"roles,omitempty"`
+ Servers *ServerPerm `json:"servers,omitempty"`
+ SharedStorage *SharedStoragePerm `json:"shared_storages,omitempty"`
+ Usages *UsagePerm `json:"usages,omitempty"`
+ Users *UserPerm `json:"users,omitempty"`
+ VPNs *VPNPerm `json:"vpn,omitempty"`
+}
+
+type BackupPerm struct {
+ Create bool `json:"create"`
+ Delete bool `json:"delete"`
+ Show bool `json:"show"`
+}
+
+type FirewallPerm struct {
+ Clone bool `json:"clone"`
+ Create bool `json:"create"`
+ Delete bool `json:"delete"`
+ ManageAttachedServerIPs bool `json:"manage_attached_server_ips"`
+ ManageRules bool `json:"manage_rules"`
+ SetDescription bool `json:"set_description"`
+ SetName bool `json:"set_name"`
+ Show bool `json:"show"`
+}
+
+type ImagePerm struct {
+ Create bool `json:"create"`
+ Delete bool `json:"delete"`
+ DisableAutoCreate bool `json:"disable_automatic_creation"`
+ SetDescription bool `json:"set_description"`
+ SetName bool `json:"set_name"`
+ Show bool `json:"show"`
+}
+
+type InvoicePerm struct {
+ Show bool `json:"show"`
+}
+
+type IPPerm struct {
+ Create bool `json:"create"`
+ Delete bool `json:"delete"`
+ Release bool `json:"release"`
+ SetReverseDNS bool `json:"set_reverse_dns"`
+ Show bool `json:"show"`
+}
+
+type LoadBalancerPerm struct {
+ Create bool `json:"create"`
+ Delete bool `json:"delete"`
+ ManageAttachedServerIPs bool `json:"manage_attached_server_ips"`
+ ManageRules bool `json:"manage_rules"`
+ Modify bool `json:"modify"`
+ SetDescription bool `json:"set_description"`
+ SetName bool `json:"set_name"`
+ Show bool `json:"show"`
+}
+
+type LogPerm struct {
+ Show bool `json:"show"`
+}
+
+type MonitorCenterPerm struct {
+ Show bool `json:"show"`
+}
+
+type MonitorPolicyPerm struct {
+ Clone bool `json:"clone"`
+ Create bool `json:"create"`
+ Delete bool `json:"delete"`
+ ManageAttachedServers bool `json:"manage_attached_servers"`
+ ManagePorts bool `json:"manage_ports"`
+ ManageProcesses bool `json:"manage_processes"`
+ ModifyResources bool `json:"modify_resources"`
+ SetDescription bool `json:"set_description"`
+ SetEmail bool `json:"set_email"`
+ SetName bool `json:"set_name"`
+ Show bool `json:"show"`
+}
+
+type PrivateNetworkPerm struct {
+ Create bool `json:"create"`
+ Delete bool `json:"delete"`
+ ManageAttachedServers bool `json:"manage_attached_servers"`
+ SetDescription bool `json:"set_description"`
+ SetName bool `json:"set_name"`
+ SetNetworkInfo bool `json:"set_network_info"`
+ Show bool `json:"show"`
+}
+
+type RolePerm struct {
+ Clone bool `json:"clone"`
+ Create bool `json:"create"`
+ Delete bool `json:"delete"`
+ ManageUsers bool `json:"manage_users"`
+ Modify bool `json:"modify"`
+ SetDescription bool `json:"set_description"`
+ SetName bool `json:"set_name"`
+ Show bool `json:"show"`
+}
+
+type ServerPerm struct {
+ AccessKVMConsole bool `json:"access_kvm_console"`
+ AssignIP bool `json:"assign_ip"`
+ Clone bool `json:"clone"`
+ Create bool `json:"create"`
+ Delete bool `json:"delete"`
+ ManageDVD bool `json:"manage_dvd"`
+ ManageSnapshot bool `json:"manage_snapshot"`
+ Reinstall bool `json:"reinstall"`
+ Resize bool `json:"resize"`
+ Restart bool `json:"restart"`
+ SetDescription bool `json:"set_description"`
+ SetName bool `json:"set_name"`
+ Show bool `json:"show"`
+ Shutdown bool `json:"shutdown"`
+ Start bool `json:"start"`
+}
+
+type SharedStoragePerm struct {
+ Access bool `json:"access"`
+ Create bool `json:"create"`
+ Delete bool `json:"delete"`
+ ManageAttachedServers bool `json:"manage_attached_servers"`
+ Resize bool `json:"resize"`
+ SetDescription bool `json:"set_description"`
+ SetName bool `json:"set_name"`
+ Show bool `json:"show"`
+}
+
+type UsagePerm struct {
+ Show bool `json:"show"`
+}
+
+type UserPerm struct {
+ ChangeRole bool `json:"change_role"`
+ Create bool `json:"create"`
+ Delete bool `json:"delete"`
+ Disable bool `json:"disable"`
+ Enable bool `json:"enable"`
+ ManageAPI bool `json:"manage_api"`
+ SetDescription bool `json:"set_description"`
+ SetEmail bool `json:"set_email"`
+ SetPassword bool `json:"set_password"`
+ Show bool `json:"show"`
+}
+
+type VPNPerm struct {
+ Create bool `json:"create"`
+ Delete bool `json:"delete"`
+ DownloadFile bool `json:"download_file"`
+ SetDescription bool `json:"set_description"`
+ SetName bool `json:"set_name"`
+ Show bool `json:"show"`
+}
+
+// GET /roles
+func (api *API) ListRoles(args ...interface{}) ([]Role, error) {
+ url, err := processQueryParams(createUrl(api, rolePathSegment), args...)
+ if err != nil {
+ return nil, err
+ }
+ result := []Role{}
+ err = api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ for _, role := range result {
+ role.api = api
+ }
+ return result, nil
+}
+
+// POST /roles
+func (api *API) CreateRole(name string) (string, *Role, error) {
+ result := new(Role)
+ url := createUrl(api, rolePathSegment)
+ req := struct {
+ Name string `json:"name"`
+ }{name}
+ err := api.Client.Post(url, &req, &result, http.StatusCreated)
+ if err != nil {
+ return "", nil, err
+ }
+ result.api = api
+ return result.Id, result, nil
+}
+
+// GET /roles/{role_id}
+func (api *API) GetRole(role_id string) (*Role, error) {
+ result := new(Role)
+ url := createUrl(api, rolePathSegment, role_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// PUT /roles/{role_id}
+func (api *API) ModifyRole(role_id string, name string, description string, state string) (*Role, error) {
+ result := new(Role)
+ url := createUrl(api, rolePathSegment, role_id)
+ req := struct {
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ State string `json:"state,omitempty"`
+ }{Name: name, Description: description, State: state}
+ err := api.Client.Put(url, &req, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// DELETE /roles/{role_id}
+func (api *API) DeleteRole(role_id string) (*Role, error) {
+ result := new(Role)
+ url := createUrl(api, rolePathSegment, role_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /roles/{role_id}/permissions
+func (api *API) GetRolePermissions(role_id string) (*Permissions, error) {
+ result := new(Permissions)
+ url := createUrl(api, rolePathSegment, role_id, "permissions")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// PUT /roles/{role_id}/permissions
+func (api *API) ModifyRolePermissions(role_id string, perm *Permissions) (*Role, error) {
+ result := new(Role)
+ url := createUrl(api, rolePathSegment, role_id, "permissions")
+ err := api.Client.Put(url, &perm, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /roles/{role_id}/users
+func (api *API) ListRoleUsers(role_id string) ([]Identity, error) {
+ result := []Identity{}
+ url := createUrl(api, rolePathSegment, role_id, "users")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// POST /roles/{role_id}/users
+func (api *API) AssignRoleUsers(role_id string, user_ids []string) (*Role, error) {
+ result := new(Role)
+ url := createUrl(api, rolePathSegment, role_id, "users")
+ req := struct {
+ Users []string `json:"users"`
+ }{user_ids}
+ err := api.Client.Post(url, &req, &result, http.StatusCreated)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /roles/{role_id}/users/{user_id}
+func (api *API) GetRoleUser(role_id string, user_id string) (*Identity, error) {
+ result := new(Identity)
+ url := createUrl(api, rolePathSegment, role_id, "users", user_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// DELETE /roles/{role_id}/users/{user_id}
+func (api *API) RemoveRoleUser(role_id string, user_id string) (*Role, error) {
+ result := new(Role)
+ url := createUrl(api, rolePathSegment, role_id, "users", user_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// POST /roles/{role_id}/clone
+func (api *API) CloneRole(role_id string, name string) (*Role, error) {
+ result := new(Role)
+ url := createUrl(api, rolePathSegment, role_id, "clone")
+ req := struct {
+ Name string `json:"name"`
+ }{name}
+ err := api.Client.Post(url, &req, &result, http.StatusCreated)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+func (role *Role) GetState() (string, error) {
+ in, err := role.api.GetRole(role.Id)
+ if in == nil {
+ return "", err
+ }
+ return in.State, err
+}
+
+// Sets all backups' permissions
+func (bp *BackupPerm) SetAll(value bool) {
+ bp.Create = value
+ bp.Delete = value
+ bp.Show = value
+}
+
+// Sets all firewall policies' permissions
+func (fp *FirewallPerm) SetAll(value bool) {
+ fp.Clone = value
+ fp.Create = value
+ fp.Delete = value
+ fp.ManageAttachedServerIPs = value
+ fp.ManageRules = value
+ fp.SetDescription = value
+ fp.SetName = value
+ fp.Show = value
+}
+
+// Sets all images' permissions
+func (imp *ImagePerm) SetAll(value bool) {
+ imp.Create = value
+ imp.Delete = value
+ imp.DisableAutoCreate = value
+ imp.SetDescription = value
+ imp.SetName = value
+ imp.Show = value
+}
+
+// Sets all invoice's permissions
+func (inp *InvoicePerm) SetAll(value bool) {
+ inp.Show = value
+}
+
+// Sets all IPs' permissions
+func (ipp *IPPerm) SetAll(value bool) {
+ ipp.Create = value
+ ipp.Delete = value
+ ipp.Release = value
+ ipp.SetReverseDNS = value
+ ipp.Show = value
+}
+
+// Sets all load balancers' permissions
+func (lbp *LoadBalancerPerm) SetAll(value bool) {
+ lbp.Create = value
+ lbp.Delete = value
+ lbp.ManageAttachedServerIPs = value
+ lbp.ManageRules = value
+ lbp.Modify = value
+ lbp.SetDescription = value
+ lbp.SetName = value
+ lbp.Show = value
+}
+
+// Sets all logs' permissions
+func (lp *LogPerm) SetAll(value bool) {
+ lp.Show = value
+}
+
+// Sets all monitoring center's permissions
+func (mcp *MonitorCenterPerm) SetAll(value bool) {
+ mcp.Show = value
+}
+
+// Sets all monitoring policies' permissions
+func (mpp *MonitorPolicyPerm) SetAll(value bool) {
+ mpp.Clone = value
+ mpp.Create = value
+ mpp.Delete = value
+ mpp.ManageAttachedServers = value
+ mpp.ManagePorts = value
+ mpp.ManageProcesses = value
+ mpp.ModifyResources = value
+ mpp.SetDescription = value
+ mpp.SetEmail = value
+ mpp.SetName = value
+ mpp.Show = value
+}
+
+// Sets all private networks' permissions
+func (pnp *PrivateNetworkPerm) SetAll(value bool) {
+ pnp.Create = value
+ pnp.Delete = value
+ pnp.ManageAttachedServers = value
+ pnp.SetDescription = value
+ pnp.SetName = value
+ pnp.SetNetworkInfo = value
+ pnp.Show = value
+}
+
+// Sets all roles' permissions
+func (rp *RolePerm) SetAll(value bool) {
+ rp.Clone = value
+ rp.Create = value
+ rp.Delete = value
+ rp.ManageUsers = value
+ rp.Modify = value
+ rp.SetDescription = value
+ rp.SetName = value
+ rp.Show = value
+}
+
+// Sets all servers' permissions
+func (sp *ServerPerm) SetAll(value bool) {
+ sp.AccessKVMConsole = value
+ sp.AssignIP = value
+ sp.Clone = value
+ sp.Create = value
+ sp.Delete = value
+ sp.ManageDVD = value
+ sp.ManageSnapshot = value
+ sp.Reinstall = value
+ sp.Resize = value
+ sp.Restart = value
+ sp.SetDescription = value
+ sp.SetName = value
+ sp.Show = value
+ sp.Shutdown = value
+ sp.Start = value
+}
+
+// Sets all shared storages' permissions
+func (ssp *SharedStoragePerm) SetAll(value bool) {
+ ssp.Access = value
+ ssp.Create = value
+ ssp.Delete = value
+ ssp.ManageAttachedServers = value
+ ssp.Resize = value
+ ssp.SetDescription = value
+ ssp.SetName = value
+ ssp.Show = value
+}
+
+// Sets all usages' permissions
+func (up *UsagePerm) SetAll(value bool) {
+ up.Show = value
+}
+
+// Sets all users' permissions
+func (up *UserPerm) SetAll(value bool) {
+ up.ChangeRole = value
+ up.Create = value
+ up.Delete = value
+ up.Disable = value
+ up.Enable = value
+ up.ManageAPI = value
+ up.SetDescription = value
+ up.SetEmail = value
+ up.SetPassword = value
+ up.Show = value
+}
+
+// Sets all VPNs' permissions
+func (vpnp *VPNPerm) SetAll(value bool) {
+ vpnp.Create = value
+ vpnp.Delete = value
+ vpnp.DownloadFile = value
+ vpnp.SetDescription = value
+ vpnp.SetName = value
+ vpnp.Show = value
+}
+
+// Sets all available permissions
+func (p *Permissions) SetAll(v bool) {
+ if p.Backups == nil {
+ p.Backups = &BackupPerm{v, v, v}
+ } else {
+ p.Backups.SetAll(v)
+ }
+ if p.Firewalls == nil {
+ p.Firewalls = &FirewallPerm{v, v, v, v, v, v, v, v}
+ } else {
+ p.Firewalls.SetAll(v)
+ }
+ if p.Images == nil {
+ p.Images = &ImagePerm{v, v, v, v, v, v}
+ } else {
+ p.Images.SetAll(v)
+ }
+ if p.Invoice == nil {
+ p.Invoice = &InvoicePerm{v}
+ } else {
+ p.Invoice.SetAll(v)
+ }
+ if p.IPs == nil {
+ p.IPs = &IPPerm{v, v, v, v, v}
+ } else {
+ p.IPs.SetAll(v)
+ }
+ if p.LoadBalancers == nil {
+ p.LoadBalancers = &LoadBalancerPerm{v, v, v, v, v, v, v, v}
+ } else {
+ p.LoadBalancers.SetAll(v)
+ }
+ if p.Logs == nil {
+ p.Logs = &LogPerm{v}
+ } else {
+ p.Logs.SetAll(v)
+ }
+ if p.MonitorCenter == nil {
+ p.MonitorCenter = &MonitorCenterPerm{v}
+ } else {
+ p.MonitorCenter.SetAll(v)
+ }
+ if p.MonitorPolicies == nil {
+ p.MonitorPolicies = &MonitorPolicyPerm{v, v, v, v, v, v, v, v, v, v, v}
+ } else {
+ p.MonitorPolicies.SetAll(v)
+ }
+ if p.PrivateNetworks == nil {
+ p.PrivateNetworks = &PrivateNetworkPerm{v, v, v, v, v, v, v}
+ } else {
+ p.PrivateNetworks.SetAll(v)
+ }
+ if p.Roles == nil {
+ p.Roles = &RolePerm{v, v, v, v, v, v, v, v}
+ } else {
+ p.Roles.SetAll(v)
+ }
+ if p.Servers == nil {
+ p.Servers = &ServerPerm{v, v, v, v, v, v, v, v, v, v, v, v, v, v, v}
+ } else {
+ p.Servers.SetAll(v)
+ }
+ if p.SharedStorage == nil {
+ p.SharedStorage = &SharedStoragePerm{v, v, v, v, v, v, v, v}
+ } else {
+ p.SharedStorage.SetAll(v)
+ }
+ if p.Usages == nil {
+ p.Usages = &UsagePerm{v}
+ } else {
+ p.Usages.SetAll(v)
+ }
+ if p.Users == nil {
+ p.Users = &UserPerm{v, v, v, v, v, v, v, v, v, v}
+ } else {
+ p.Users.SetAll(v)
+ }
+ if p.VPNs == nil {
+ p.VPNs = &VPNPerm{v, v, v, v, v, v}
+ } else {
+ p.VPNs.SetAll(v)
+ }
+}
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/serverappliances.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/serverappliances.go
new file mode 100644
index 000000000..03c45f3d8
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/serverappliances.go
@@ -0,0 +1,48 @@
+package oneandone
+
+import "net/http"
+
+type ServerAppliance struct {
+ Identity
+ typeField
+ OsInstallBase string `json:"os_installation_base,omitempty"`
+ OsFamily string `json:"os_family,omitempty"`
+ Os string `json:"os,omitempty"`
+ OsVersion string `json:"os_version,omitempty"`
+ Version string `json:"version,omitempty"`
+ MinHddSize int `json:"min_hdd_size"`
+ Architecture interface{} `json:"os_architecture"`
+ Licenses interface{} `json:"licenses,omitempty"`
+ Categories []string `json:"categories,omitempty"`
+ // AvailableDatacenters []string `json:"available_datacenters,omitempty"`
+ ApiPtr
+}
+
+// GET /server_appliances
+func (api *API) ListServerAppliances(args ...interface{}) ([]ServerAppliance, error) {
+ url, err := processQueryParams(createUrl(api, serverAppliancePathSegment), args...)
+ if err != nil {
+ return nil, err
+ }
+ res := []ServerAppliance{}
+ err = api.Client.Get(url, &res, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ for index, _ := range res {
+ res[index].api = api
+ }
+ return res, nil
+}
+
+// GET /server_appliances/{id}
+func (api *API) GetServerAppliance(sa_id string) (*ServerAppliance, error) {
+ res := new(ServerAppliance)
+ url := createUrl(api, serverAppliancePathSegment, sa_id)
+ err := api.Client.Get(url, &res, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ // res.api = api
+ return res, nil
+}
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/servers.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/servers.go
new file mode 100644
index 000000000..18fad51a2
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/servers.go
@@ -0,0 +1,808 @@
+package oneandone
+
+import (
+ "encoding/json"
+ "errors"
+ "math/big"
+ "net/http"
+)
+
+type Server struct {
+ ApiPtr
+ Identity
+ descField
+ CloudPanelId string `json:"cloudpanel_id,omitempty"`
+ CreationDate string `json:"creation_date,omitempty"`
+ FirstPassword string `json:"first_password,omitempty"`
+ Datacenter *Datacenter `json:"datacenter,omitempty"`
+ Status *Status `json:"status,omitempty"`
+ Hardware *Hardware `json:"hardware,omitempty"`
+ Image *Identity `json:"image,omitempty"`
+ Dvd *Identity `json:"dvd,omitempty"`
+ MonPolicy *Identity `json:"monitoring_policy,omitempty"`
+ Snapshot *ServerSnapshot `json:"snapshot,omitempty"`
+ Ips []ServerIp `json:"ips,omitempty"`
+ PrivateNets []Identity `json:"private_networks,omitempty"`
+ Alerts *ServerAlerts `json:"-"`
+ AlertsRaw *json.RawMessage `json:"alerts,omitempty"`
+}
+
+type Hardware struct {
+ Vcores int `json:"vcore,omitempty"`
+ CoresPerProcessor int `json:"cores_per_processor"`
+ Ram float32 `json:"ram"`
+ Hdds []Hdd `json:"hdds,omitempty"`
+ FixedInsSizeId string `json:"fixed_instance_size_id,omitempty"`
+ ApiPtr
+}
+
+type ServerHdds struct {
+ Hdds []Hdd `json:"hdds,omitempty"`
+}
+
+type Hdd struct {
+ idField
+ Size int `json:"size,omitempty"`
+ IsMain bool `json:"is_main,omitempty"`
+ ApiPtr
+}
+
+type serverDeployImage struct {
+ idField
+ Password string `json:"password,omitempty"`
+ Firewall *Identity `json:"firewall_policy,omitempty"`
+}
+
+type ServerIp struct {
+ idField
+ typeField
+ Ip string `json:"ip,omitempty"`
+ ReverseDns string `json:"reverse_dns,omitempty"`
+ Firewall *Identity `json:"firewall_policy,omitempty"`
+ LoadBalancers []Identity `json:"load_balancers,omitempty"`
+ ApiPtr
+}
+
+type ServerIpInfo struct {
+ idField // IP id
+ Ip string `json:"ip,omitempty"`
+ ServerName string `json:"server_name,omitempty"`
+}
+
+type ServerSnapshot struct {
+ idField
+ CreationDate string `json:"creation_date,omitempty"`
+ DeletionDate string `json:"deletion_date,omitempty"`
+}
+
+type ServerAlerts struct {
+ AlertSummary []serverAlertSummary
+ AlertDetails *serverAlertDetails
+}
+
+type serverAlertSummary struct {
+ countField
+ typeField
+}
+
+type serverAlertDetails struct {
+ Criticals []ServerAlert `json:"critical,omitempty"`
+ Warnings []ServerAlert `json:"warning,omitempty"`
+}
+
+type ServerAlert struct {
+ typeField
+ descField
+ Date string `json:"date"`
+}
+
+type ServerRequest struct {
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ Hardware Hardware `json:"hardware"`
+ ApplianceId string `json:"appliance_id,omitempty"`
+ Password string `json:"password,omitempty"`
+ PowerOn bool `json:"power_on"`
+ FirewallPolicyId string `json:"firewall_policy_id,omitempty"`
+ IpId string `json:"ip_id,omitempty"`
+ LoadBalancerId string `json:"load_balancer_id,omitempty"`
+ MonitoringPolicyId string `json:"monitoring_policy_id,omitempty"`
+ DatacenterId string `json:"datacenter_id,omitempty"`
+ SSHKey string `json:"rsa_key,omitempty"`
+}
+
+type ServerAction struct {
+ Action string `json:"action,omitempty"`
+ Method string `json:"method,omitempty"`
+}
+
+type FixedInstanceInfo struct {
+ Identity
+ Hardware *Hardware `json:"hardware,omitempty"`
+ ApiPtr
+}
+
+// GET /servers
+func (api *API) ListServers(args ...interface{}) ([]Server, error) {
+ url, err := processQueryParams(createUrl(api, serverPathSegment), args...)
+ if err != nil {
+ return nil, err
+ }
+ result := []Server{}
+ err = api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ for _, s := range result {
+ s.api = api
+ s.decodeRaws()
+ }
+ return result, nil
+}
+
+// POST /servers
+func (api *API) CreateServer(request *ServerRequest) (string, *Server, error) {
+ result := new(Server)
+ url := createUrl(api, serverPathSegment)
+ insert2map := func(hasht map[string]interface{}, key string, value string) {
+ if key != "" && value != "" {
+ hasht[key] = value
+ }
+ }
+ req := make(map[string]interface{})
+ hw := make(map[string]interface{})
+ req["name"] = request.Name
+ req["description"] = request.Description
+ req["appliance_id"] = request.ApplianceId
+ req["power_on"] = request.PowerOn
+ insert2map(req, "password", request.Password)
+ insert2map(req, "firewall_policy_id", request.FirewallPolicyId)
+ insert2map(req, "ip_id", request.IpId)
+ insert2map(req, "load_balancer_id", request.LoadBalancerId)
+ insert2map(req, "monitoring_policy_id", request.MonitoringPolicyId)
+ insert2map(req, "datacenter_id", request.DatacenterId)
+ insert2map(req, "rsa_key", request.SSHKey)
+ req["hardware"] = hw
+ if request.Hardware.FixedInsSizeId != "" {
+ hw["fixed_instance_size_id"] = request.Hardware.FixedInsSizeId
+ } else {
+ hw["vcore"] = request.Hardware.Vcores
+ hw["cores_per_processor"] = request.Hardware.CoresPerProcessor
+ hw["ram"] = request.Hardware.Ram
+ hw["hdds"] = request.Hardware.Hdds
+ }
+ err := api.Client.Post(url, &req, &result, http.StatusAccepted)
+ if err != nil {
+ return "", nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result.Id, result, nil
+}
+
+// This is a wraper function for `CreateServer` that returns the server's IP address and first password.
+// The function waits at most `timeout` seconds for the server to be created.
+// The initial `POST /servers` response does not contain the IP address, so we need to wait
+// until the server is created.
+func (api *API) CreateServerEx(request *ServerRequest, timeout int) (string, string, error) {
+ id, server, err := api.CreateServer(request)
+ if server != nil && err == nil {
+ count := timeout / 5
+ if request.PowerOn {
+ err = api.WaitForState(server, "POWERED_ON", 5, count)
+ } else {
+ err = api.WaitForState(server, "POWERED_OFF", 5, count)
+ }
+ if err != nil {
+ return "", "", err
+ }
+ server, err := api.GetServer(id)
+ if server != nil && err == nil && server.Ips[0].Ip != "" {
+ if server.FirstPassword != "" {
+ return server.Ips[0].Ip, server.FirstPassword, nil
+ }
+ if request.Password != "" {
+ return server.Ips[0].Ip, request.Password, nil
+ }
+ // should never reach here
+ return "", "", errors.New("No server's password was found.")
+ }
+ }
+ return "", "", err
+}
+
+// GET /servers/{id}
+func (api *API) GetServer(server_id string) (*Server, error) {
+ result := new(Server)
+ url := createUrl(api, serverPathSegment, server_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// GET /servers/fixed_instance_sizes
+func (api *API) ListFixedInstanceSizes() ([]FixedInstanceInfo, error) {
+ result := []FixedInstanceInfo{}
+ url := createUrl(api, serverPathSegment, "fixed_instance_sizes")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ for index, _ := range result {
+ result[index].api = api
+ }
+ return result, nil
+}
+
+// GET /servers/fixed_instance_sizes/{fixed_instance_size_id}
+func (api *API) GetFixedInstanceSize(fis_id string) (*FixedInstanceInfo, error) {
+ result := new(FixedInstanceInfo)
+ url := createUrl(api, serverPathSegment, "fixed_instance_sizes", fis_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// DELETE /servers/{id}
+func (api *API) DeleteServer(server_id string, keep_ips bool) (*Server, error) {
+ result := new(Server)
+ url := createUrl(api, serverPathSegment, server_id)
+ pm := make(map[string]interface{}, 1)
+ pm["keep_ips"] = keep_ips
+ url = appendQueryParams(url, pm)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// PUT /servers/{id}
+func (api *API) RenameServer(server_id string, new_name string, new_desc string) (*Server, error) {
+ data := struct {
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ }{Name: new_name, Description: new_desc}
+ result := new(Server)
+ url := createUrl(api, serverPathSegment, server_id)
+ err := api.Client.Put(url, &data, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// GET /servers/{server_id}/hardware
+func (api *API) GetServerHardware(server_id string) (*Hardware, error) {
+ result := new(Hardware)
+ url := createUrl(api, serverPathSegment, server_id, "hardware")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// PUT /servers/{server_id}/hardware
+func (api *API) UpdateServerHardware(server_id string, hardware *Hardware) (*Server, error) {
+ var vc, cpp *int
+ var ram *float32
+ if hardware.Vcores > 0 {
+ vc = new(int)
+ *vc = hardware.Vcores
+ }
+ if hardware.CoresPerProcessor > 0 {
+ cpp = new(int)
+ *cpp = hardware.CoresPerProcessor
+ }
+ if big.NewFloat(float64(hardware.Ram)).Cmp(big.NewFloat(0)) != 0 {
+ ram = new(float32)
+ *ram = hardware.Ram
+ }
+ req := struct {
+ VCores *int `json:"vcore,omitempty"`
+ Cpp *int `json:"cores_per_processor,omitempty"`
+ Ram *float32 `json:"ram,omitempty"`
+ Flavor string `json:"fixed_instance_size_id,omitempty"`
+ }{VCores: vc, Cpp: cpp, Ram: ram, Flavor: hardware.FixedInsSizeId}
+
+ result := new(Server)
+ url := createUrl(api, serverPathSegment, server_id, "hardware")
+ err := api.Client.Put(url, &req, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// GET /servers/{id}/hardware/hdds
+func (api *API) ListServerHdds(server_id string) ([]Hdd, error) {
+ result := []Hdd{}
+ url := createUrl(api, serverPathSegment, server_id, "hardware/hdds")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ for index, _ := range result {
+ result[index].api = api
+ }
+ return result, nil
+}
+
+// POST /servers/{id}/hardware/hdds
+func (api *API) AddServerHdds(server_id string, hdds *ServerHdds) (*Server, error) {
+ result := new(Server)
+ url := createUrl(api, serverPathSegment, server_id, "hardware/hdds")
+ err := api.Client.Post(url, &hdds, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// GET /servers/{id}/hardware/hdds/{id}
+func (api *API) GetServerHdd(server_id string, hdd_id string) (*Hdd, error) {
+ result := new(Hdd)
+ url := createUrl(api, serverPathSegment, server_id, "hardware/hdds", hdd_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// DELETE /servers/{id}/hardware/hdds/{id}
+func (api *API) DeleteServerHdd(server_id string, hdd_id string) (*Server, error) {
+ result := new(Server)
+ url := createUrl(api, serverPathSegment, server_id, "hardware/hdds", hdd_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// PUT /servers/{id}/hardware/hdds/{id}
+func (api *API) ResizeServerHdd(server_id string, hdd_id string, new_size int) (*Server, error) {
+ data := Hdd{Size: new_size}
+ result := new(Server)
+ url := createUrl(api, serverPathSegment, server_id, "hardware/hdds", hdd_id)
+ err := api.Client.Put(url, &data, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// GET /servers/{id}/image
+func (api *API) GetServerImage(server_id string) (*Identity, error) {
+ result := new(Identity)
+ url := createUrl(api, serverPathSegment, server_id, "image")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// PUT /servers/{id}/image
+func (api *API) ReinstallServerImage(server_id string, image_id string, password string, fp_id string) (*Server, error) {
+ data := new(serverDeployImage)
+ data.Id = image_id
+ data.Password = password
+ if fp_id != "" {
+ fp := new(Identity)
+ fp.Id = fp_id
+ data.Firewall = fp
+ }
+
+ result := new(Server)
+ url := createUrl(api, serverPathSegment, server_id, "image")
+ err := api.Client.Put(url, &data, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// GET /servers/{id}/ips
+func (api *API) ListServerIps(server_id string) ([]ServerIp, error) {
+ result := []ServerIp{}
+ url := createUrl(api, serverPathSegment, server_id, "ips")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ for index, _ := range result {
+ result[index].api = api
+ }
+ return result, nil
+}
+
+// POST /servers/{id}/ips
+func (api *API) AssignServerIp(server_id string, ip_type string) (*Server, error) {
+ data := typeField{Type: ip_type}
+ result := new(Server)
+ url := createUrl(api, serverPathSegment, server_id, "ips")
+ err := api.Client.Post(url, &data, &result, http.StatusCreated)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// GET /servers/{id}/ips/{id}
+func (api *API) GetServerIp(server_id string, ip_id string) (*ServerIp, error) {
+ result := new(ServerIp)
+ url := createUrl(api, serverPathSegment, server_id, "ips", ip_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// DELETE /servers/{id}/ips/{id}
+func (api *API) DeleteServerIp(server_id string, ip_id string, keep_ip bool) (*Server, error) {
+ result := new(Server)
+ url := createUrl(api, serverPathSegment, server_id, "ips", ip_id)
+ qm := make(map[string]interface{}, 1)
+ qm["keep_ip"] = keep_ip
+ url = appendQueryParams(url, qm)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /servers/{id}/status
+func (api *API) GetServerStatus(server_id string) (*Status, error) {
+ result := new(Status)
+ url := createUrl(api, serverPathSegment, server_id, "status")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// PUT /servers/{id}/status/action (action = REBOOT)
+func (api *API) RebootServer(server_id string, is_hardware bool) (*Server, error) {
+ result := new(Server)
+ request := ServerAction{}
+ request.Action = "REBOOT"
+ if is_hardware {
+ request.Method = "HARDWARE"
+ } else {
+ request.Method = "SOFTWARE"
+ }
+ url := createUrl(api, serverPathSegment, server_id, "status", "action")
+ err := api.Client.Put(url, &request, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// PUT /servers/{id}/status/action (action = POWER_OFF)
+func (api *API) ShutdownServer(server_id string, is_hardware bool) (*Server, error) {
+ result := new(Server)
+ request := ServerAction{}
+ request.Action = "POWER_OFF"
+ if is_hardware {
+ request.Method = "HARDWARE"
+ } else {
+ request.Method = "SOFTWARE"
+ }
+ url := createUrl(api, serverPathSegment, server_id, "status", "action")
+ err := api.Client.Put(url, &request, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// PUT /servers/{id}/status/action (action = POWER_ON)
+func (api *API) StartServer(server_id string) (*Server, error) {
+ result := new(Server)
+ request := ServerAction{}
+ request.Action = "POWER_ON"
+ url := createUrl(api, serverPathSegment, server_id, "status", "action")
+ err := api.Client.Put(url, &request, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// GET /servers/{id}/dvd
+func (api *API) GetServerDvd(server_id string) (*Identity, error) {
+ result := new(Identity)
+ url := createUrl(api, serverPathSegment, server_id, "dvd")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// DELETE /servers/{id}/dvd
+func (api *API) EjectServerDvd(server_id string) (*Server, error) {
+ result := new(Server)
+ url := createUrl(api, serverPathSegment, server_id, "dvd")
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// PUT /servers/{id}/dvd
+func (api *API) LoadServerDvd(server_id string, dvd_id string) (*Server, error) {
+ request := Identity{}
+ request.Id = dvd_id
+ result := new(Server)
+ url := createUrl(api, serverPathSegment, server_id, "dvd")
+ err := api.Client.Put(url, &request, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// GET /servers/{id}/private_networks
+func (api *API) ListServerPrivateNetworks(server_id string) ([]Identity, error) {
+ result := []Identity{}
+ url := createUrl(api, serverPathSegment, server_id, "private_networks")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// POST /servers/{id}/private_networks
+func (api *API) AssignServerPrivateNetwork(server_id string, pn_id string) (*Server, error) {
+ req := new(Identity)
+ req.Id = pn_id
+ result := new(Server)
+ url := createUrl(api, serverPathSegment, server_id, "private_networks")
+ err := api.Client.Post(url, &req, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// GET /servers/{id}/private_networks/{id}
+func (api *API) GetServerPrivateNetwork(server_id string, pn_id string) (*PrivateNetwork, error) {
+ result := new(PrivateNetwork)
+ url := createUrl(api, serverPathSegment, server_id, "private_networks", pn_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// DELETE /servers/{id}/private_networks/{id}
+func (api *API) RemoveServerPrivateNetwork(server_id string, pn_id string) (*Server, error) {
+ result := new(Server)
+ url := createUrl(api, serverPathSegment, server_id, "private_networks", pn_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// GET /servers/{server_id}/ips/{ip_id}/load_balancers
+func (api *API) ListServerIpLoadBalancers(server_id string, ip_id string) ([]Identity, error) {
+ result := []Identity{}
+ url := createUrl(api, serverPathSegment, server_id, "ips", ip_id, "load_balancers")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// POST /servers/{server_id}/ips/{ip_id}/load_balancers
+func (api *API) AssignServerIpLoadBalancer(server_id string, ip_id string, lb_id string) (*Server, error) {
+ req := struct {
+ LbId string `json:"load_balancer_id"`
+ }{lb_id}
+ result := new(Server)
+ url := createUrl(api, serverPathSegment, server_id, "ips", ip_id, "load_balancers")
+ err := api.Client.Post(url, &req, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// DELETE /servers/{server_id}/ips/{ip_id}/load_balancers
+func (api *API) UnassignServerIpLoadBalancer(server_id string, ip_id string, lb_id string) (*Server, error) {
+ result := new(Server)
+ url := createUrl(api, serverPathSegment, server_id, "ips", ip_id, "load_balancers", lb_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// GET /servers/{server_id}/ips/{ip_id}/firewall_policy
+func (api *API) GetServerIpFirewallPolicy(server_id string, ip_id string) (*Identity, error) {
+ result := new(Identity)
+ url := createUrl(api, serverPathSegment, server_id, "ips", ip_id, "firewall_policy")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// PUT /servers/{server_id}/ips/{ip_id}/firewall_policy
+func (api *API) AssignServerIpFirewallPolicy(server_id string, ip_id string, fp_id string) (*Server, error) {
+ req := idField{fp_id}
+ result := new(Server)
+ url := createUrl(api, serverPathSegment, server_id, "ips", ip_id, "firewall_policy")
+ err := api.Client.Put(url, &req, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// DELETE /servers/{server_id}/ips/{ip_id}/firewall_policy
+func (api *API) UnassignServerIpFirewallPolicy(server_id string, ip_id string) (*Server, error) {
+ result := new(Server)
+ url := createUrl(api, serverPathSegment, server_id, "ips", ip_id, "firewall_policy")
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// GET /servers/{id}/snapshots
+func (api *API) GetServerSnapshot(server_id string) (*ServerSnapshot, error) {
+ result := new(ServerSnapshot)
+ url := createUrl(api, serverPathSegment, server_id, "snapshots")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// POST /servers/{id}/snapshots
+func (api *API) CreateServerSnapshot(server_id string) (*Server, error) {
+ result := new(Server)
+ url := createUrl(api, serverPathSegment, server_id, "snapshots")
+ err := api.Client.Post(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// PUT /servers/{server_id}/snapshots/{snapshot_id}
+func (api *API) RestoreServerSnapshot(server_id string, snapshot_id string) (*Server, error) {
+ result := new(Server)
+ url := createUrl(api, serverPathSegment, server_id, "snapshots", snapshot_id)
+ err := api.Client.Put(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// DELETE /servers/{server_id}/snapshots/{snapshot_id}
+func (api *API) DeleteServerSnapshot(server_id string, snapshot_id string) (*Server, error) {
+ result := new(Server)
+ url := createUrl(api, serverPathSegment, server_id, "snapshots", snapshot_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+// POST /servers/{server_id}/clone
+func (api *API) CloneServer(server_id string, new_name string, datacenter_id string) (*Server, error) {
+ data := struct {
+ Name string `json:"name"`
+ DatacenterId string `json:"datacenter_id,omitempty"`
+ }{Name: new_name, DatacenterId: datacenter_id}
+ result := new(Server)
+ url := createUrl(api, serverPathSegment, server_id, "clone")
+ err := api.Client.Post(url, &data, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ result.decodeRaws()
+ return result, nil
+}
+
+func (s *Server) GetState() (string, error) {
+ st, err := s.api.GetServerStatus(s.Id)
+ if st == nil {
+ return "", err
+ }
+ return st.State, err
+}
+
+func (server *Server) decodeRaws() {
+ if server.AlertsRaw != nil {
+ server.Alerts = new(ServerAlerts)
+ var sad serverAlertDetails
+ if err := json.Unmarshal(*server.AlertsRaw, &sad); err == nil {
+ server.Alerts.AlertDetails = &sad
+ return
+ }
+ var sams []serverAlertSummary
+ if err := json.Unmarshal(*server.AlertsRaw, &sams); err == nil {
+ server.Alerts.AlertSummary = sams
+ }
+ }
+}
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/setup.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/setup.go
new file mode 100644
index 000000000..7d910c653
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/setup.go
@@ -0,0 +1,19 @@
+package oneandone
+
+// The base url for 1&1 Cloud Server REST API.
+var BaseUrl = "https://cloudpanel-api.1and1.com/v1"
+
+// Authentication token
+var Token string
+
+// SetBaseUrl is intended to set the REST base url. BaseUrl is declared in setup.go
+func SetBaseUrl(newbaseurl string) string {
+ BaseUrl = newbaseurl
+ return BaseUrl
+}
+
+// SetToken is used to set authentication Token for the REST service. Token is declared in setup.go
+func SetToken(newtoken string) string {
+ Token = newtoken
+ return Token
+}
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/sharedstorages.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/sharedstorages.go
new file mode 100644
index 000000000..fdb2a7bfd
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/sharedstorages.go
@@ -0,0 +1,190 @@
+package oneandone
+
+import (
+ "net/http"
+)
+
+type SharedStorage struct {
+ Identity
+ descField
+ Size int `json:"size"`
+ MinSizeAllowed int `json:"minimum_size_allowed"`
+ SizeUsed string `json:"size_used,omitempty"`
+ State string `json:"state,omitempty"`
+ CloudPanelId string `json:"cloudpanel_id,omitempty"`
+ SiteId string `json:"site_id,omitempty"`
+ CifsPath string `json:"cifs_path,omitempty"`
+ NfsPath string `json:"nfs_path,omitempty"`
+ CreationDate string `json:"creation_date,omitempty"`
+ Servers []SharedStorageServer `json:"servers,omitempty"`
+ Datacenter *Datacenter `json:"datacenter,omitempty"`
+ ApiPtr
+}
+
+type SharedStorageServer struct {
+ Id string `json:"id,omitempty"`
+ Name string `json:"name,omitempty"`
+ Rights string `json:"rights,omitempty"`
+}
+
+type SharedStorageRequest struct {
+ DatacenterId string `json:"datacenter_id,omitempty"`
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ Size *int `json:"size"`
+}
+
+type SharedStorageAccess struct {
+ State string `json:"state,omitempty"`
+ KerberosContentFile string `json:"kerberos_content_file,omitempty"`
+ UserDomain string `json:"user_domain,omitempty"`
+ SiteId string `json:"site_id,omitempty"`
+ NeedsPasswordReset int `json:"needs_password_reset"`
+}
+
+// GET /shared_storages
+func (api *API) ListSharedStorages(args ...interface{}) ([]SharedStorage, error) {
+ url, err := processQueryParams(createUrl(api, sharedStoragePathSegment), args...)
+ if err != nil {
+ return nil, err
+ }
+ result := []SharedStorage{}
+ err = api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ for index, _ := range result {
+ result[index].api = api
+ }
+ return result, nil
+}
+
+// POST /shared_storages
+func (api *API) CreateSharedStorage(request *SharedStorageRequest) (string, *SharedStorage, error) {
+ result := new(SharedStorage)
+ url := createUrl(api, sharedStoragePathSegment)
+ err := api.Client.Post(url, request, &result, http.StatusAccepted)
+ if err != nil {
+ return "", nil, err
+ }
+ result.api = api
+ return result.Id, result, nil
+}
+
+// GET /shared_storages/{id}
+func (api *API) GetSharedStorage(ss_id string) (*SharedStorage, error) {
+ result := new(SharedStorage)
+ url := createUrl(api, sharedStoragePathSegment, ss_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// DELETE /shared_storages/{id}
+func (api *API) DeleteSharedStorage(ss_id string) (*SharedStorage, error) {
+ result := new(SharedStorage)
+ url := createUrl(api, sharedStoragePathSegment, ss_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// PUT /shared_storages/{id}
+func (api *API) UpdateSharedStorage(ss_id string, request *SharedStorageRequest) (*SharedStorage, error) {
+ result := new(SharedStorage)
+ url := createUrl(api, sharedStoragePathSegment, ss_id)
+ err := api.Client.Put(url, &request, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /shared_storages/{id}/servers
+func (api *API) ListSharedStorageServers(st_id string) ([]SharedStorageServer, error) {
+ result := []SharedStorageServer{}
+ url := createUrl(api, sharedStoragePathSegment, st_id, "servers")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// POST /shared_storages/{id}/servers
+func (api *API) AddSharedStorageServers(st_id string, servers []SharedStorageServer) (*SharedStorage, error) {
+ result := new(SharedStorage)
+ req := struct {
+ Servers []SharedStorageServer `json:"servers"`
+ }{servers}
+ url := createUrl(api, sharedStoragePathSegment, st_id, "servers")
+ err := api.Client.Post(url, &req, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /shared_storages/{id}/servers/{id}
+func (api *API) GetSharedStorageServer(st_id string, ser_id string) (*SharedStorageServer, error) {
+ result := new(SharedStorageServer)
+ url := createUrl(api, sharedStoragePathSegment, st_id, "servers", ser_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// DELETE /shared_storages/{id}/servers/{id}
+func (api *API) DeleteSharedStorageServer(st_id string, ser_id string) (*SharedStorage, error) {
+ result := new(SharedStorage)
+ url := createUrl(api, sharedStoragePathSegment, st_id, "servers", ser_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /shared_storages/access
+func (api *API) GetSharedStorageCredentials() ([]SharedStorageAccess, error) {
+ result := []SharedStorageAccess{}
+ url := createUrl(api, sharedStoragePathSegment, "access")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// PUT /shared_storages/access
+func (api *API) UpdateSharedStorageCredentials(new_pass string) ([]SharedStorageAccess, error) {
+ result := []SharedStorageAccess{}
+ req := struct {
+ Password string `json:"password"`
+ }{new_pass}
+ url := createUrl(api, sharedStoragePathSegment, "access")
+ err := api.Client.Put(url, &req, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+func (ss *SharedStorage) GetState() (string, error) {
+ in, err := ss.api.GetSharedStorage(ss.Id)
+ if in == nil {
+ return "", err
+ }
+ return in.State, err
+}
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/usages.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/usages.go
new file mode 100644
index 000000000..e56c9f2ef
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/usages.go
@@ -0,0 +1,52 @@
+package oneandone
+
+import (
+ "net/http"
+ "time"
+)
+
+type Usages struct {
+ Images []usage `json:"IMAGES,omitempty"`
+ LoadBalancers []usage `json:"LOAD BALANCERS,omitempty"`
+ PublicIPs []usage `json:"PUBLIC IP,omitempty"`
+ Servers []usage `json:"SERVERS,omitempty"`
+ SharedStorages []usage `json:"SHARED STORAGE,omitempty"`
+ ApiPtr
+}
+
+type usage struct {
+ Identity
+ Site int `json:"site"`
+ Services []usageService `json:"services,omitempty"`
+}
+
+type usageService struct {
+ AverageAmmount string `json:"avg_amount,omitempty"`
+ Unit string `json:"unit,omitempty"`
+ Usage int `json:"usage"`
+ Details []usageDetails `json:"detail,omitempty"`
+ typeField
+}
+
+type usageDetails struct {
+ AverageAmmount string `json:"avg_amount,omitempty"`
+ StartDate string `json:"start_date,omitempty"`
+ EndDate string `json:"end_date,omitempty"`
+ Unit string `json:"unit,omitempty"`
+ Usage int `json:"usage,omitempty"`
+}
+
+// GET /usages
+func (api *API) ListUsages(period string, sd *time.Time, ed *time.Time, args ...interface{}) (*Usages, error) {
+ result := new(Usages)
+ url, err := processQueryParamsExt(createUrl(api, usagePathSegment), period, sd, ed, args...)
+ if err != nil {
+ return nil, err
+ }
+ err = api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/users.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/users.go
new file mode 100644
index 000000000..782d07a50
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/users.go
@@ -0,0 +1,205 @@
+package oneandone
+
+import "net/http"
+
+type User struct {
+ Identity
+ descField
+ CreationDate string `json:"creation_date,omitempty"`
+ Email string `json:"email,omitempty"`
+ State string `json:"state,omitempty"`
+ Role *Identity `json:"role,omitempty"`
+ Api *UserApi `json:"api,omitempty"`
+ ApiPtr
+}
+
+type UserApi struct {
+ Active bool `json:"active"`
+ AllowedIps []string `json:"allowed_ips,omitempty"`
+ UserApiKey
+ ApiPtr
+}
+
+type UserApiKey struct {
+ Key string `json:"key,omitempty"`
+}
+
+type UserRequest struct {
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ Password string `json:"password,omitempty"`
+ Email string `json:"email,omitempty"`
+ State string `json:"state,omitempty"`
+}
+
+// GET /users
+func (api *API) ListUsers(args ...interface{}) ([]User, error) {
+ url, err := processQueryParams(createUrl(api, userPathSegment), args...)
+ if err != nil {
+ return nil, err
+ }
+ result := []User{}
+ err = api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ for index, _ := range result {
+ result[index].api = api
+ }
+ return result, nil
+}
+
+// POST /users
+func (api *API) CreateUser(user *UserRequest) (string, *User, error) {
+ result := new(User)
+ url := createUrl(api, userPathSegment)
+ err := api.Client.Post(url, &user, &result, http.StatusCreated)
+ if err != nil {
+ return "", nil, err
+ }
+ result.api = api
+ return result.Id, result, nil
+}
+
+// GET /users/{id}
+func (api *API) GetUser(user_id string) (*User, error) {
+ result := new(User)
+ url := createUrl(api, userPathSegment, user_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// DELETE /users/{id}
+func (api *API) DeleteUser(user_id string) (*User, error) {
+ result := new(User)
+ url := createUrl(api, userPathSegment, user_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// PUT /users/{id}
+func (api *API) ModifyUser(user_id string, user *UserRequest) (*User, error) {
+ result := new(User)
+ url := createUrl(api, userPathSegment, user_id)
+ err := api.Client.Put(url, &user, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /users/{id}/api
+func (api *API) GetUserApi(user_id string) (*UserApi, error) {
+ result := new(UserApi)
+ url := createUrl(api, userPathSegment, user_id, "api")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// PUT /users/{id}/api
+func (api *API) ModifyUserApi(user_id string, active bool) (*User, error) {
+ result := new(User)
+ req := struct {
+ Active bool `json:"active"`
+ }{active}
+ url := createUrl(api, userPathSegment, user_id, "api")
+ err := api.Client.Put(url, &req, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /users/{id}/api/key
+func (api *API) GetUserApiKey(user_id string) (*UserApiKey, error) {
+ result := new(UserApiKey)
+ url := createUrl(api, userPathSegment, user_id, "api/key")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// PUT /users/{id}/api/key
+func (api *API) RenewUserApiKey(user_id string) (*User, error) {
+ result := new(User)
+ url := createUrl(api, userPathSegment, user_id, "api/key")
+ err := api.Client.Put(url, nil, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /users/{id}/api/ips
+func (api *API) ListUserApiAllowedIps(user_id string) ([]string, error) {
+ result := []string{}
+ url := createUrl(api, userPathSegment, user_id, "api/ips")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// POST /users/{id}/api/ips
+func (api *API) AddUserApiAlowedIps(user_id string, ips []string) (*User, error) {
+ result := new(User)
+ req := struct {
+ Ips []string `json:"ips"`
+ }{ips}
+ url := createUrl(api, userPathSegment, user_id, "api/ips")
+ err := api.Client.Post(url, &req, &result, http.StatusCreated)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// DELETE /users/{id}/api/ips/{ip}
+func (api *API) RemoveUserApiAllowedIp(user_id string, ip string) (*User, error) {
+ result := new(User)
+ url := createUrl(api, userPathSegment, user_id, "api/ips", ip)
+ err := api.Client.Delete(url, nil, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /users/{id}/api/ips
+func (api *API) GetCurrentUserPermissions() (*Permissions, error) {
+ result := new(Permissions)
+ url := createUrl(api, userPathSegment, "current_user_permissions")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+func (u *User) GetState() (string, error) {
+ in, err := u.api.GetUser(u.Id)
+ if in == nil {
+ return "", err
+ }
+ return in.State, err
+}
diff --git a/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/vpns.go b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/vpns.go
new file mode 100644
index 000000000..723a85459
--- /dev/null
+++ b/vendor/github.com/1and1/oneandone-cloudserver-sdk-go/vpns.go
@@ -0,0 +1,114 @@
+package oneandone
+
+import "net/http"
+
+type VPN struct {
+ Identity
+ descField
+ typeField
+ CloudPanelId string `json:"cloudpanel_id,omitempty"`
+ CreationDate string `json:"creation_date,omitempty"`
+ State string `json:"state,omitempty"`
+ IPs []string `json:"ips,omitempty"`
+ Datacenter *Datacenter `json:"datacenter,omitempty"`
+ ApiPtr
+}
+
+type configZipFile struct {
+ Base64String string `json:"config_zip_file"`
+}
+
+// GET /vpns
+func (api *API) ListVPNs(args ...interface{}) ([]VPN, error) {
+ url, err := processQueryParams(createUrl(api, vpnPathSegment), args...)
+ if err != nil {
+ return nil, err
+ }
+ result := []VPN{}
+ err = api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ for _, vpn := range result {
+ vpn.api = api
+ }
+ return result, nil
+}
+
+// POST /vpns
+func (api *API) CreateVPN(name string, description string, datacenter_id string) (string, *VPN, error) {
+ res := new(VPN)
+ url := createUrl(api, vpnPathSegment)
+ req := struct {
+ Name string `json:"name"`
+ Description string `json:"description,omitempty"`
+ DatacenterId string `json:"datacenter_id,omitempty"`
+ }{Name: name, Description: description, DatacenterId: datacenter_id}
+ err := api.Client.Post(url, &req, &res, http.StatusAccepted)
+ if err != nil {
+ return "", nil, err
+ }
+ res.api = api
+ return res.Id, res, nil
+}
+
+// GET /vpns/{vpn_id}
+func (api *API) GetVPN(vpn_id string) (*VPN, error) {
+ result := new(VPN)
+ url := createUrl(api, vpnPathSegment, vpn_id)
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// PUT /vpns/{vpn_id}
+func (api *API) ModifyVPN(vpn_id string, name string, description string) (*VPN, error) {
+ result := new(VPN)
+ url := createUrl(api, vpnPathSegment, vpn_id)
+ req := struct {
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ }{Name: name, Description: description}
+ err := api.Client.Put(url, &req, &result, http.StatusOK)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// DELETE /vpns/{vpn_id}
+func (api *API) DeleteVPN(vpn_id string) (*VPN, error) {
+ result := new(VPN)
+ url := createUrl(api, vpnPathSegment, vpn_id)
+ err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
+ if err != nil {
+ return nil, err
+ }
+ result.api = api
+ return result, nil
+}
+
+// GET /vpns/{vpn_id}/configuration_file
+// Returns VPN configuration files (in a zip arhive) as a base64 encoded string
+func (api *API) GetVPNConfigFile(vpn_id string) (string, error) {
+ result := new(configZipFile)
+ url := createUrl(api, vpnPathSegment, vpn_id, "configuration_file")
+ err := api.Client.Get(url, &result, http.StatusOK)
+ if err != nil {
+ return "", err
+ }
+
+ return result.Base64String, nil
+}
+
+func (vpn *VPN) GetState() (string, error) {
+ in, err := vpn.api.GetVPN(vpn.Id)
+ if in == nil {
+ return "", err
+ }
+ return in.State, err
+}
diff --git a/vendor/vendor.json b/vendor/vendor.json
index ad34e1c7a..981743752 100644
--- a/vendor/vendor.json
+++ b/vendor/vendor.json
@@ -2,6 +2,12 @@
"comment": "",
"ignore": "test appengine",
"package": [
+ {
+ "checksumSHA1": "aABATU51PlDHfGeSe5cc9udwSXg=",
+ "path": "github.com/1and1/oneandone-cloudserver-sdk-go",
+ "revision": "5678f03fc801525df794f953aa82f5ad7555a2ef",
+ "revisionTime": "2016-08-11T22:04:02Z"
+ },
{
"checksumSHA1": "/WG++Jij8INZ80tER+FAiIDMmws=",
"comment": "v3.1.0-beta",
diff --git a/website/source/docs/builders/oneandone.html.md b/website/source/docs/builders/oneandone.html.md
new file mode 100644
index 000000000..47b845e46
--- /dev/null
+++ b/website/source/docs/builders/oneandone.html.md
@@ -0,0 +1,58 @@
+---
+description: |
+ The 1&1 builder is able to create images for 1&1 cloud.
+layout: docs
+page_title: 1&1 Builder
+...
+
+# 1&1 Builder
+
+Type: `oneandone`
+
+The 1&1 Builder is able to create virtual machines for [One](https://www.1and1.com/).
+
+## Configuration Reference
+
+There are many configuration options available for the builder. They are
+segmented below into two categories: required and optional parameters. Within
+each category, the available configuration keys are alphabetized.
+
+In addition to the options listed here, a
+[communicator](/docs/templates/communicator.html) can be configured for this
+builder.
+
+### Required
+
+- `source_image_name` (string) - 1&1 Server Appliance name of type `IMAGE`. Defaults to `ubuntu1604-64std`
+
+- `token` (string) - 1&1 REST API Token. This can be specified via environment variable `ONEANDONE_TOKEN`
+
+### Optional
+
+- `disk_size` (string) - Amount of disk space for this image in GB. Defaults to "50"
+
+- `image_password` (string) - Password for the server images.
+
+- `image_name` (string) - Resulting image. If "image_name" is not provided Packer will generate it
+
+- `timeout` (string) - An approximate limit on how long Packer will continue making status requests while waiting for the build to complete. Default value "600".
+
+- `url` (string) - Endpoint for the 1&1 REST API. Default URL "https://cloudpanel-api.1and1.com/v1"
+
+
+## Example
+
+Here is a basic example:
+
+```json
+{
+ "builders":[
+ {
+ "type":"oneandone",
+ "disk_size":"50",
+ "image_name":"test5",
+ "source_image_name":"ubuntu1604-64min"
+ }
+ ]
+}
+```
\ No newline at end of file