Merge pull request #7945 from ahilsend/hcloud-image-filter
feat(builder/hcloud): allow selecting image based on filters
This commit is contained in:
commit
17d9a85895
@ -25,10 +25,11 @@ type Config struct {
|
||||
Endpoint string `mapstructure:"endpoint"`
|
||||
PollInterval time.Duration `mapstructure:"poll_interval"`
|
||||
|
||||
ServerName string `mapstructure:"server_name"`
|
||||
Location string `mapstructure:"location"`
|
||||
ServerType string `mapstructure:"server_type"`
|
||||
Image string `mapstructure:"image"`
|
||||
ServerName string `mapstructure:"server_name"`
|
||||
Location string `mapstructure:"location"`
|
||||
ServerType string `mapstructure:"server_type"`
|
||||
Image string `mapstructure:"image"`
|
||||
ImageFilter *imageFilter `mapstructure:"image_filter"`
|
||||
|
||||
SnapshotName string `mapstructure:"snapshot_name"`
|
||||
SnapshotLabels map[string]string `mapstructure:"snapshot_labels"`
|
||||
@ -41,6 +42,11 @@ type Config struct {
|
||||
ctx interpolate.Context
|
||||
}
|
||||
|
||||
type imageFilter struct {
|
||||
WithSelector []string `mapstructure:"with_selector"`
|
||||
MostRecent bool `mapstructure:"most_recent"`
|
||||
}
|
||||
|
||||
func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||
c := new(Config)
|
||||
|
||||
@ -108,9 +114,18 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||
errs, errors.New("server type is required"))
|
||||
}
|
||||
|
||||
if c.Image == "" {
|
||||
if c.Image == "" && c.ImageFilter == nil {
|
||||
errs = packer.MultiErrorAppend(
|
||||
errs, errors.New("image is required"))
|
||||
errs, errors.New("image or image_filter is required"))
|
||||
}
|
||||
if c.ImageFilter != nil {
|
||||
if len(c.ImageFilter.WithSelector) == 0 {
|
||||
errs = packer.MultiErrorAppend(
|
||||
errs, errors.New("image_filter.with_selector is required when specifying filter"))
|
||||
} else if c.Image != "" {
|
||||
errs = packer.MultiErrorAppend(
|
||||
errs, errors.New("only one of image or image_filter can be specified"))
|
||||
}
|
||||
}
|
||||
|
||||
if c.UserData != "" && c.UserDataFile != "" {
|
||||
|
@ -3,8 +3,9 @@ package hcloud
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"io/ioutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
@ -50,10 +51,24 @@ func (s *stepCreateServer) Run(ctx context.Context, state multistep.StateBag) mu
|
||||
sshKeys = append(sshKeys, sshKey)
|
||||
}
|
||||
|
||||
var image *hcloud.Image
|
||||
if c.Image != "" {
|
||||
image = &hcloud.Image{Name: c.Image}
|
||||
} else {
|
||||
var err error
|
||||
image, err = getImageWithSelectors(ctx, client, c)
|
||||
if err != nil {
|
||||
ui.Error(err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
ui.Message(fmt.Sprintf("Using image %s with ID %d", image.Description, image.ID))
|
||||
}
|
||||
|
||||
serverCreateResult, _, err := client.Server.Create(ctx, hcloud.ServerCreateOpts{
|
||||
Name: c.ServerName,
|
||||
ServerType: &hcloud.ServerType{Name: c.ServerType},
|
||||
Image: &hcloud.Image{Name: c.Image},
|
||||
Image: image,
|
||||
SSHKeys: sshKeys,
|
||||
Location: &hcloud.Location{Name: c.Location},
|
||||
UserData: userData,
|
||||
@ -185,3 +200,32 @@ func waitForAction(ctx context.Context, client *hcloud.Client, action *hcloud.Ac
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getImageWithSelectors(ctx context.Context, client *hcloud.Client, c *Config) (*hcloud.Image, error) {
|
||||
var allImages []*hcloud.Image
|
||||
|
||||
var selector = strings.Join(c.ImageFilter.WithSelector, ",")
|
||||
opts := hcloud.ImageListOpts{
|
||||
ListOpts: hcloud.ListOpts{LabelSelector: selector},
|
||||
Status: []hcloud.ImageStatus{hcloud.ImageStatusAvailable},
|
||||
}
|
||||
|
||||
allImages, err := client.Image.AllWithOpts(ctx, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(allImages) == 0 {
|
||||
return nil, fmt.Errorf("no image found for selector %q", selector)
|
||||
}
|
||||
if len(allImages) > 1 {
|
||||
if !c.ImageFilter.MostRecent {
|
||||
return nil, fmt.Errorf("more than one image found for selector %q", selector)
|
||||
}
|
||||
|
||||
sort.Slice(allImages, func(i, j int) bool {
|
||||
return allImages[i].Created.After(allImages[j].Created)
|
||||
})
|
||||
}
|
||||
|
||||
return allImages[0], nil
|
||||
}
|
||||
|
2
go.mod
2
go.mod
@ -60,7 +60,7 @@ require (
|
||||
github.com/hashicorp/serf v0.8.2 // indirect
|
||||
github.com/hashicorp/vault v1.1.0
|
||||
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d
|
||||
github.com/hetznercloud/hcloud-go v1.12.0
|
||||
github.com/hetznercloud/hcloud-go v1.15.1
|
||||
github.com/hyperonecom/h1-client-go v0.0.0-20190122232013-cf38e8387775
|
||||
github.com/jdcloud-api/jdcloud-sdk-go v1.9.1-0.20190605102154-3d81a50ca961
|
||||
github.com/joyent/triton-go v0.0.0-20180116165742-545edbe0d564
|
||||
|
4
go.sum
4
go.sum
@ -211,8 +211,8 @@ github.com/hashicorp/vault v1.1.0 h1:v79NUgO5xCZnXVzUkIqFOXtP8YhpnHAi1fk3eo9cuOE
|
||||
github.com/hashicorp/vault v1.1.0/go.mod h1:KfSyffbKxoVyspOdlaGVjIuwLobi07qD1bAbosPMpP0=
|
||||
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=
|
||||
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
||||
github.com/hetznercloud/hcloud-go v1.12.0 h1:ugZO8a8ADekqSWi7xWlcs6pxr4QE0tw5VnyjXcL5n28=
|
||||
github.com/hetznercloud/hcloud-go v1.12.0/go.mod h1:g5pff0YNAZywQaivY/CmhUYFVp7oP0nu3MiODC2W4Hw=
|
||||
github.com/hetznercloud/hcloud-go v1.15.1 h1:G8Q+xyAqQ5IUY7yq4HKZgkabFa0S/VXJXq3TGCeT8JM=
|
||||
github.com/hetznercloud/hcloud-go v1.15.1/go.mod h1:8lR3yHBHZWy2uGcUi9Ibt4UOoop2wrVdERJgCtxsF3Q=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/hyperonecom/h1-client-go v0.0.0-20190122232013-cf38e8387775 h1:MIteIoIQ5nFoOmwEHPDsqng8d0dtKj3lCnQCwGvtxXc=
|
||||
|
18
vendor/github.com/hetznercloud/hcloud-go/hcloud/action.go
generated
vendored
18
vendor/github.com/hetznercloud/hcloud-go/hcloud/action.go
generated
vendored
@ -3,6 +3,7 @@ package hcloud
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/hetznercloud/hcloud-go/hcloud/schema"
|
||||
@ -95,11 +96,24 @@ func (c *ActionClient) GetByID(ctx context.Context, id int) (*Action, *Response,
|
||||
// ActionListOpts specifies options for listing actions.
|
||||
type ActionListOpts struct {
|
||||
ListOpts
|
||||
Status []ActionStatus
|
||||
Sort []string
|
||||
}
|
||||
|
||||
func (l ActionListOpts) values() url.Values {
|
||||
vals := l.ListOpts.values()
|
||||
for _, status := range l.Status {
|
||||
vals.Add("status", string(status))
|
||||
}
|
||||
for _, sort := range l.Sort {
|
||||
vals.Add("sort", sort)
|
||||
}
|
||||
return vals
|
||||
}
|
||||
|
||||
// List returns a list of actions for a specific page.
|
||||
func (c *ActionClient) List(ctx context.Context, opts ActionListOpts) ([]*Action, *Response, error) {
|
||||
path := "/actions?" + valuesForListOpts(opts.ListOpts).Encode()
|
||||
path := "/actions?" + opts.values().Encode()
|
||||
req, err := c.client.NewRequest(ctx, "GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@ -170,7 +184,7 @@ func (c *ActionClient) WatchProgress(ctx context.Context, action *Action) (<-cha
|
||||
|
||||
a, _, err := c.GetByID(ctx, action.ID)
|
||||
if err != nil {
|
||||
errCh <- ctx.Err()
|
||||
errCh <- err
|
||||
return
|
||||
}
|
||||
|
||||
|
41
vendor/github.com/hetznercloud/hcloud-go/hcloud/client.go
generated
vendored
41
vendor/github.com/hetznercloud/hcloud-go/hcloud/client.go
generated
vendored
@ -9,6 +9,7 @@ import (
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -55,6 +56,7 @@ type Client struct {
|
||||
applicationName string
|
||||
applicationVersion string
|
||||
userAgent string
|
||||
debugWriter io.Writer
|
||||
|
||||
Action ActionClient
|
||||
Datacenter DatacenterClient
|
||||
@ -62,6 +64,7 @@ type Client struct {
|
||||
Image ImageClient
|
||||
ISO ISOClient
|
||||
Location LocationClient
|
||||
Network NetworkClient
|
||||
Pricing PricingClient
|
||||
Server ServerClient
|
||||
ServerType ServerTypeClient
|
||||
@ -111,6 +114,14 @@ func WithApplication(name, version string) ClientOption {
|
||||
}
|
||||
}
|
||||
|
||||
// WithDebugWriter configures a Client to print debug information to the given
|
||||
// writer. To, for example, print debug information on stderr, set it to os.Stderr.
|
||||
func WithDebugWriter(debugWriter io.Writer) ClientOption {
|
||||
return func(client *Client) {
|
||||
client.debugWriter = debugWriter
|
||||
}
|
||||
}
|
||||
|
||||
// NewClient creates a new client.
|
||||
func NewClient(options ...ClientOption) *Client {
|
||||
client := &Client{
|
||||
@ -132,6 +143,7 @@ func NewClient(options ...ClientOption) *Client {
|
||||
client.Image = ImageClient{client: client}
|
||||
client.ISO = ISOClient{client: client}
|
||||
client.Location = LocationClient{client: client}
|
||||
client.Network = NetworkClient{client: client}
|
||||
client.Pricing = PricingClient{client: client}
|
||||
client.Server = ServerClient{client: client}
|
||||
client.ServerType = ServerTypeClient{client: client}
|
||||
@ -167,7 +179,6 @@ func (c *Client) Do(r *http.Request, v interface{}) (*Response, error) {
|
||||
return nil, err
|
||||
}
|
||||
response := &Response{Response: resp}
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
resp.Body.Close()
|
||||
@ -176,6 +187,20 @@ func (c *Client) Do(r *http.Request, v interface{}) (*Response, error) {
|
||||
resp.Body.Close()
|
||||
resp.Body = ioutil.NopCloser(bytes.NewReader(body))
|
||||
|
||||
if c.debugWriter != nil {
|
||||
dumpReq, err := httputil.DumpRequest(r, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Fprintf(c.debugWriter, "--- Request:\n%s\n\n", dumpReq)
|
||||
|
||||
dumpResp, err := httputil.DumpResponse(resp, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Fprintf(c.debugWriter, "--- Response:\n%s\n\n", dumpResp)
|
||||
}
|
||||
|
||||
if err = response.readMeta(body); err != nil {
|
||||
return response, fmt.Errorf("hcloud: error reading response meta data: %s", err)
|
||||
}
|
||||
@ -314,16 +339,16 @@ type ListOpts struct {
|
||||
LabelSelector string // Label selector for filtering by labels
|
||||
}
|
||||
|
||||
func valuesForListOpts(opts ListOpts) url.Values {
|
||||
func (l ListOpts) values() url.Values {
|
||||
vals := url.Values{}
|
||||
if opts.Page > 0 {
|
||||
vals.Add("page", strconv.Itoa(opts.Page))
|
||||
if l.Page > 0 {
|
||||
vals.Add("page", strconv.Itoa(l.Page))
|
||||
}
|
||||
if opts.PerPage > 0 {
|
||||
vals.Add("per_page", strconv.Itoa(opts.PerPage))
|
||||
if l.PerPage > 0 {
|
||||
vals.Add("per_page", strconv.Itoa(l.PerPage))
|
||||
}
|
||||
if len(opts.LabelSelector) > 0 {
|
||||
vals.Add("label_selector", opts.LabelSelector)
|
||||
if len(l.LabelSelector) > 0 {
|
||||
vals.Add("label_selector", l.LabelSelector)
|
||||
}
|
||||
return vals
|
||||
}
|
||||
|
30
vendor/github.com/hetznercloud/hcloud-go/hcloud/datacenter.go
generated
vendored
30
vendor/github.com/hetznercloud/hcloud-go/hcloud/datacenter.go
generated
vendored
@ -49,22 +49,11 @@ func (c *DatacenterClient) GetByID(ctx context.Context, id int) (*Datacenter, *R
|
||||
|
||||
// GetByName retrieves an datacenter by its name. If the datacenter does not exist, nil is returned.
|
||||
func (c *DatacenterClient) GetByName(ctx context.Context, name string) (*Datacenter, *Response, error) {
|
||||
path := "/datacenters?name=" + url.QueryEscape(name)
|
||||
req, err := c.client.NewRequest(ctx, "GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
datacenters, response, err := c.List(ctx, DatacenterListOpts{Name: name})
|
||||
if len(datacenters) == 0 {
|
||||
return nil, response, err
|
||||
}
|
||||
|
||||
var body schema.DatacenterListResponse
|
||||
resp, err := c.client.Do(req, &body)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if len(body.Datacenters) == 0 {
|
||||
return nil, resp, nil
|
||||
}
|
||||
return DatacenterFromSchema(body.Datacenters[0]), resp, nil
|
||||
return datacenters[0], response, err
|
||||
}
|
||||
|
||||
// Get retrieves a datacenter by its ID if the input can be parsed as an integer, otherwise it
|
||||
@ -79,11 +68,20 @@ func (c *DatacenterClient) Get(ctx context.Context, idOrName string) (*Datacente
|
||||
// DatacenterListOpts specifies options for listing datacenters.
|
||||
type DatacenterListOpts struct {
|
||||
ListOpts
|
||||
Name string
|
||||
}
|
||||
|
||||
func (l DatacenterListOpts) values() url.Values {
|
||||
vals := l.ListOpts.values()
|
||||
if l.Name != "" {
|
||||
vals.Add("name", l.Name)
|
||||
}
|
||||
return vals
|
||||
}
|
||||
|
||||
// List returns a list of datacenters for a specific page.
|
||||
func (c *DatacenterClient) List(ctx context.Context, opts DatacenterListOpts) ([]*Datacenter, *Response, error) {
|
||||
path := "/datacenters?" + valuesForListOpts(opts.ListOpts).Encode()
|
||||
path := "/datacenters?" + opts.values().Encode()
|
||||
req, err := c.client.NewRequest(ctx, "GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
2
vendor/github.com/hetznercloud/hcloud-go/hcloud/error.go
generated
vendored
2
vendor/github.com/hetznercloud/hcloud-go/hcloud/error.go
generated
vendored
@ -20,6 +20,8 @@ const (
|
||||
ErrorCodeUniquenessError ErrorCode = "uniqueness_error" // One or more fields must be unique
|
||||
ErrorCodeProtected ErrorCode = "protected" // The actions you are trying is protected
|
||||
ErrorCodeMaintenance ErrorCode = "maintenance" // Cannot perform operation due to maintenance
|
||||
ErrorCodeConflict ErrorCode = "conflict" // The resource has changed during the request, please retry
|
||||
ErrorCodeServerAlreadyAttached ErrorCode = "server_already_attached" // The server is already attached to the resource
|
||||
|
||||
// Deprecated error codes
|
||||
|
||||
|
9
vendor/github.com/hetznercloud/hcloud-go/hcloud/floating_ip.go
generated
vendored
9
vendor/github.com/hetznercloud/hcloud-go/hcloud/floating_ip.go
generated
vendored
@ -7,6 +7,8 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/hetznercloud/hcloud-go/hcloud/schema"
|
||||
)
|
||||
@ -15,6 +17,7 @@ import (
|
||||
type FloatingIP struct {
|
||||
ID int
|
||||
Description string
|
||||
Created time.Time
|
||||
IP net.IP
|
||||
Network *net.IPNet
|
||||
Type FloatingIPType
|
||||
@ -74,9 +77,13 @@ type FloatingIPListOpts struct {
|
||||
ListOpts
|
||||
}
|
||||
|
||||
func (l FloatingIPListOpts) values() url.Values {
|
||||
return l.ListOpts.values()
|
||||
}
|
||||
|
||||
// List returns a list of Floating IPs for a specific page.
|
||||
func (c *FloatingIPClient) List(ctx context.Context, opts FloatingIPListOpts) ([]*FloatingIP, *Response, error) {
|
||||
path := "/floating_ips?" + valuesForListOpts(opts.ListOpts).Encode()
|
||||
path := "/floating_ips?" + opts.values().Encode()
|
||||
req, err := c.client.NewRequest(ctx, "GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
2
vendor/github.com/hetznercloud/hcloud-go/hcloud/hcloud.go
generated
vendored
2
vendor/github.com/hetznercloud/hcloud-go/hcloud/hcloud.go
generated
vendored
@ -2,4 +2,4 @@
|
||||
package hcloud
|
||||
|
||||
// Version is the library's version following Semantic Versioning.
|
||||
const Version = "1.12.0"
|
||||
const Version = "1.15.1"
|
||||
|
48
vendor/github.com/hetznercloud/hcloud-go/hcloud/image.go
generated
vendored
48
vendor/github.com/hetznercloud/hcloud-go/hcloud/image.go
generated
vendored
@ -91,22 +91,11 @@ func (c *ImageClient) GetByID(ctx context.Context, id int) (*Image, *Response, e
|
||||
|
||||
// GetByName retrieves an image by its name. If the image does not exist, nil is returned.
|
||||
func (c *ImageClient) GetByName(ctx context.Context, name string) (*Image, *Response, error) {
|
||||
path := "/images?name=" + url.QueryEscape(name)
|
||||
req, err := c.client.NewRequest(ctx, "GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
images, response, err := c.List(ctx, ImageListOpts{Name: name})
|
||||
if len(images) == 0 {
|
||||
return nil, response, err
|
||||
}
|
||||
|
||||
var body schema.ImageListResponse
|
||||
resp, err := c.client.Do(req, &body)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if len(body.Images) == 0 {
|
||||
return nil, resp, nil
|
||||
}
|
||||
return ImageFromSchema(body.Images[0]), resp, nil
|
||||
return images[0], response, err
|
||||
}
|
||||
|
||||
// Get retrieves an image by its ID if the input can be parsed as an integer, otherwise it
|
||||
@ -121,11 +110,36 @@ func (c *ImageClient) Get(ctx context.Context, idOrName string) (*Image, *Respon
|
||||
// ImageListOpts specifies options for listing images.
|
||||
type ImageListOpts struct {
|
||||
ListOpts
|
||||
Type []ImageType
|
||||
BoundTo *Server
|
||||
Name string
|
||||
Sort []string
|
||||
Status []ImageStatus
|
||||
}
|
||||
|
||||
func (l ImageListOpts) values() url.Values {
|
||||
vals := l.ListOpts.values()
|
||||
for _, typ := range l.Type {
|
||||
vals.Add("type", string(typ))
|
||||
}
|
||||
if l.BoundTo != nil {
|
||||
vals.Add("bound_to", strconv.Itoa(l.BoundTo.ID))
|
||||
}
|
||||
if l.Name != "" {
|
||||
vals.Add("name", l.Name)
|
||||
}
|
||||
for _, sort := range l.Sort {
|
||||
vals.Add("sort", sort)
|
||||
}
|
||||
for _, status := range l.Status {
|
||||
vals.Add("status", string(status))
|
||||
}
|
||||
return vals
|
||||
}
|
||||
|
||||
// List returns a list of images for a specific page.
|
||||
func (c *ImageClient) List(ctx context.Context, opts ImageListOpts) ([]*Image, *Response, error) {
|
||||
path := "/images?" + valuesForListOpts(opts.ListOpts).Encode()
|
||||
path := "/images?" + opts.values().Encode()
|
||||
req, err := c.client.NewRequest(ctx, "GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@ -145,7 +159,7 @@ func (c *ImageClient) List(ctx context.Context, opts ImageListOpts) ([]*Image, *
|
||||
|
||||
// All returns all images.
|
||||
func (c *ImageClient) All(ctx context.Context) ([]*Image, error) {
|
||||
return c.AllWithOpts(ctx, ImageListOpts{ListOpts{PerPage: 50}})
|
||||
return c.AllWithOpts(ctx, ImageListOpts{ListOpts: ListOpts{PerPage: 50}})
|
||||
}
|
||||
|
||||
// AllWithOpts returns all images for the given options.
|
||||
|
30
vendor/github.com/hetznercloud/hcloud-go/hcloud/iso.go
generated
vendored
30
vendor/github.com/hetznercloud/hcloud-go/hcloud/iso.go
generated
vendored
@ -60,22 +60,11 @@ func (c *ISOClient) GetByID(ctx context.Context, id int) (*ISO, *Response, error
|
||||
|
||||
// GetByName retrieves an ISO by its name.
|
||||
func (c *ISOClient) GetByName(ctx context.Context, name string) (*ISO, *Response, error) {
|
||||
path := "/isos?name=" + url.QueryEscape(name)
|
||||
req, err := c.client.NewRequest(ctx, "GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
isos, response, err := c.List(ctx, ISOListOpts{Name: name})
|
||||
if len(isos) == 0 {
|
||||
return nil, response, err
|
||||
}
|
||||
|
||||
var body schema.ISOListResponse
|
||||
resp, err := c.client.Do(req, &body)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if len(body.ISOs) == 0 {
|
||||
return nil, resp, nil
|
||||
}
|
||||
return ISOFromSchema(body.ISOs[0]), resp, nil
|
||||
return isos[0], response, err
|
||||
}
|
||||
|
||||
// Get retrieves an ISO by its ID if the input can be parsed as an integer, otherwise it retrieves an ISO by its name.
|
||||
@ -89,11 +78,20 @@ func (c *ISOClient) Get(ctx context.Context, idOrName string) (*ISO, *Response,
|
||||
// ISOListOpts specifies options for listing isos.
|
||||
type ISOListOpts struct {
|
||||
ListOpts
|
||||
Name string
|
||||
}
|
||||
|
||||
func (l ISOListOpts) values() url.Values {
|
||||
vals := l.ListOpts.values()
|
||||
if l.Name != "" {
|
||||
vals.Add("name", l.Name)
|
||||
}
|
||||
return vals
|
||||
}
|
||||
|
||||
// List returns a list of ISOs for a specific page.
|
||||
func (c *ISOClient) List(ctx context.Context, opts ISOListOpts) ([]*ISO, *Response, error) {
|
||||
path := "/isos?" + valuesForListOpts(opts.ListOpts).Encode()
|
||||
path := "/isos?" + opts.values().Encode()
|
||||
req, err := c.client.NewRequest(ctx, "GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
31
vendor/github.com/hetznercloud/hcloud-go/hcloud/location.go
generated
vendored
31
vendor/github.com/hetznercloud/hcloud-go/hcloud/location.go
generated
vendored
@ -18,6 +18,7 @@ type Location struct {
|
||||
City string
|
||||
Latitude float64
|
||||
Longitude float64
|
||||
NetworkZone NetworkZone
|
||||
}
|
||||
|
||||
// LocationClient is a client for the location API.
|
||||
@ -45,22 +46,11 @@ func (c *LocationClient) GetByID(ctx context.Context, id int) (*Location, *Respo
|
||||
|
||||
// GetByName retrieves an location by its name. If the location does not exist, nil is returned.
|
||||
func (c *LocationClient) GetByName(ctx context.Context, name string) (*Location, *Response, error) {
|
||||
path := "/locations?name=" + url.QueryEscape(name)
|
||||
req, err := c.client.NewRequest(ctx, "GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
locations, response, err := c.List(ctx, LocationListOpts{Name: name})
|
||||
if len(locations) == 0 {
|
||||
return nil, response, err
|
||||
}
|
||||
|
||||
var body schema.LocationListResponse
|
||||
resp, err := c.client.Do(req, &body)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if len(body.Locations) == 0 {
|
||||
return nil, resp, nil
|
||||
}
|
||||
return LocationFromSchema(body.Locations[0]), resp, nil
|
||||
return locations[0], response, err
|
||||
}
|
||||
|
||||
// Get retrieves a location by its ID if the input can be parsed as an integer, otherwise it
|
||||
@ -75,11 +65,20 @@ func (c *LocationClient) Get(ctx context.Context, idOrName string) (*Location, *
|
||||
// LocationListOpts specifies options for listing location.
|
||||
type LocationListOpts struct {
|
||||
ListOpts
|
||||
Name string
|
||||
}
|
||||
|
||||
func (l LocationListOpts) values() url.Values {
|
||||
vals := l.ListOpts.values()
|
||||
if l.Name != "" {
|
||||
vals.Add("name", l.Name)
|
||||
}
|
||||
return vals
|
||||
}
|
||||
|
||||
// List returns a list of locations for a specific page.
|
||||
func (c *LocationClient) List(ctx context.Context, opts LocationListOpts) ([]*Location, *Response, error) {
|
||||
path := "/locations?" + valuesForListOpts(opts.ListOpts).Encode()
|
||||
path := "/locations?" + opts.values().Encode()
|
||||
req, err := c.client.NewRequest(ctx, "GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
445
vendor/github.com/hetznercloud/hcloud-go/hcloud/network.go
generated
vendored
Normal file
445
vendor/github.com/hetznercloud/hcloud-go/hcloud/network.go
generated
vendored
Normal file
@ -0,0 +1,445 @@
|
||||
package hcloud
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/hetznercloud/hcloud-go/hcloud/schema"
|
||||
)
|
||||
|
||||
// NetworkZone specifies a network zone.
|
||||
type NetworkZone string
|
||||
|
||||
// List of available Network Zones.
|
||||
const (
|
||||
NetworkZoneEUCentral NetworkZone = "eu-central"
|
||||
)
|
||||
|
||||
// NetworkSubnetType specifies a type of a subnet.
|
||||
type NetworkSubnetType string
|
||||
|
||||
// List of available network subnet types.
|
||||
const (
|
||||
NetworkSubnetTypeServer NetworkSubnetType = "server"
|
||||
)
|
||||
|
||||
// Network represents a network in the Hetzner Cloud.
|
||||
type Network struct {
|
||||
ID int
|
||||
Name string
|
||||
Created time.Time
|
||||
IPRange *net.IPNet
|
||||
Subnets []NetworkSubnet
|
||||
Routes []NetworkRoute
|
||||
Servers []*Server
|
||||
Protection NetworkProtection
|
||||
Labels map[string]string
|
||||
}
|
||||
|
||||
// NetworkSubnet represents a subnet of a network in the Hetzner Cloud.
|
||||
type NetworkSubnet struct {
|
||||
Type NetworkSubnetType
|
||||
IPRange *net.IPNet
|
||||
NetworkZone NetworkZone
|
||||
Gateway net.IP
|
||||
}
|
||||
|
||||
// NetworkRoute represents a route of a network.
|
||||
type NetworkRoute struct {
|
||||
Destination *net.IPNet
|
||||
Gateway net.IP
|
||||
}
|
||||
|
||||
// NetworkProtection represents the protection level of a network.
|
||||
type NetworkProtection struct {
|
||||
Delete bool
|
||||
}
|
||||
|
||||
// NetworkClient is a client for the network API.
|
||||
type NetworkClient struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// GetByID retrieves a network by its ID. If the network does not exist, nil is returned.
|
||||
func (c *NetworkClient) GetByID(ctx context.Context, id int) (*Network, *Response, error) {
|
||||
req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/networks/%d", id), nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var body schema.NetworkGetResponse
|
||||
resp, err := c.client.Do(req, &body)
|
||||
if err != nil {
|
||||
if IsError(err, ErrorCodeNotFound) {
|
||||
return nil, resp, nil
|
||||
}
|
||||
return nil, nil, err
|
||||
}
|
||||
return NetworkFromSchema(body.Network), resp, nil
|
||||
}
|
||||
|
||||
// GetByName retrieves a network by its name. If the network does not exist, nil is returned.
|
||||
func (c *NetworkClient) GetByName(ctx context.Context, name string) (*Network, *Response, error) {
|
||||
Networks, response, err := c.List(ctx, NetworkListOpts{Name: name})
|
||||
if len(Networks) == 0 {
|
||||
return nil, response, err
|
||||
}
|
||||
return Networks[0], response, err
|
||||
}
|
||||
|
||||
// Get retrieves a network by its ID if the input can be parsed as an integer, otherwise it
|
||||
// retrieves a network by its name. If the network does not exist, nil is returned.
|
||||
func (c *NetworkClient) Get(ctx context.Context, idOrName string) (*Network, *Response, error) {
|
||||
if id, err := strconv.Atoi(idOrName); err == nil {
|
||||
return c.GetByID(ctx, int(id))
|
||||
}
|
||||
return c.GetByName(ctx, idOrName)
|
||||
}
|
||||
|
||||
// NetworkListOpts specifies options for listing networks.
|
||||
type NetworkListOpts struct {
|
||||
ListOpts
|
||||
Name string
|
||||
}
|
||||
|
||||
func (l NetworkListOpts) values() url.Values {
|
||||
vals := l.ListOpts.values()
|
||||
if l.Name != "" {
|
||||
vals.Add("name", l.Name)
|
||||
}
|
||||
return vals
|
||||
}
|
||||
|
||||
// List returns a list of networks for a specific page.
|
||||
func (c *NetworkClient) List(ctx context.Context, opts NetworkListOpts) ([]*Network, *Response, error) {
|
||||
path := "/networks?" + opts.values().Encode()
|
||||
req, err := c.client.NewRequest(ctx, "GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var body schema.NetworkListResponse
|
||||
resp, err := c.client.Do(req, &body)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
Networks := make([]*Network, 0, len(body.Networks))
|
||||
for _, s := range body.Networks {
|
||||
Networks = append(Networks, NetworkFromSchema(s))
|
||||
}
|
||||
return Networks, resp, nil
|
||||
}
|
||||
|
||||
// All returns all networks.
|
||||
func (c *NetworkClient) All(ctx context.Context) ([]*Network, error) {
|
||||
return c.AllWithOpts(ctx, NetworkListOpts{ListOpts: ListOpts{PerPage: 50}})
|
||||
}
|
||||
|
||||
// AllWithOpts returns all networks for the given options.
|
||||
func (c *NetworkClient) AllWithOpts(ctx context.Context, opts NetworkListOpts) ([]*Network, error) {
|
||||
var allNetworks []*Network
|
||||
|
||||
_, err := c.client.all(func(page int) (*Response, error) {
|
||||
opts.Page = page
|
||||
Networks, resp, err := c.List(ctx, opts)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
allNetworks = append(allNetworks, Networks...)
|
||||
return resp, nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return allNetworks, nil
|
||||
}
|
||||
|
||||
// Delete deletes a network.
|
||||
func (c *NetworkClient) Delete(ctx context.Context, network *Network) (*Response, error) {
|
||||
req, err := c.client.NewRequest(ctx, "DELETE", fmt.Sprintf("/networks/%d", network.ID), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.client.Do(req, nil)
|
||||
}
|
||||
|
||||
// NetworkUpdateOpts specifies options for updating a network.
|
||||
type NetworkUpdateOpts struct {
|
||||
Name string
|
||||
Labels map[string]string
|
||||
}
|
||||
|
||||
// Update updates a network.
|
||||
func (c *NetworkClient) Update(ctx context.Context, network *Network, opts NetworkUpdateOpts) (*Network, *Response, error) {
|
||||
reqBody := schema.NetworkUpdateRequest{
|
||||
Name: opts.Name,
|
||||
}
|
||||
if opts.Labels != nil {
|
||||
reqBody.Labels = &opts.Labels
|
||||
}
|
||||
reqBodyData, err := json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
path := fmt.Sprintf("/networks/%d", network.ID)
|
||||
req, err := c.client.NewRequest(ctx, "PUT", path, bytes.NewReader(reqBodyData))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
respBody := schema.NetworkUpdateResponse{}
|
||||
resp, err := c.client.Do(req, &respBody)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return NetworkFromSchema(respBody.Network), resp, nil
|
||||
}
|
||||
|
||||
// NetworkCreateOpts specifies options for creating a new network.
|
||||
type NetworkCreateOpts struct {
|
||||
Name string
|
||||
IPRange *net.IPNet
|
||||
Subnets []NetworkSubnet
|
||||
Routes []NetworkRoute
|
||||
Labels map[string]string
|
||||
}
|
||||
|
||||
// Validate checks if options are valid.
|
||||
func (o NetworkCreateOpts) Validate() error {
|
||||
if o.Name == "" {
|
||||
return errors.New("missing name")
|
||||
}
|
||||
if o.IPRange == nil || o.IPRange.String() == "" {
|
||||
return errors.New("missing IP range")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create creates a new network.
|
||||
func (c *NetworkClient) Create(ctx context.Context, opts NetworkCreateOpts) (*Network, *Response, error) {
|
||||
if err := opts.Validate(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
reqBody := schema.NetworkCreateRequest{
|
||||
Name: opts.Name,
|
||||
IPRange: opts.IPRange.String(),
|
||||
}
|
||||
for _, subnet := range opts.Subnets {
|
||||
reqBody.Subnets = append(reqBody.Subnets, schema.NetworkSubnet{
|
||||
Type: string(subnet.Type),
|
||||
IPRange: subnet.IPRange.String(),
|
||||
NetworkZone: string(subnet.NetworkZone),
|
||||
})
|
||||
}
|
||||
for _, route := range opts.Routes {
|
||||
reqBody.Routes = append(reqBody.Routes, schema.NetworkRoute{
|
||||
Destination: route.Destination.String(),
|
||||
Gateway: route.Gateway.String(),
|
||||
})
|
||||
}
|
||||
if opts.Labels != nil {
|
||||
reqBody.Labels = &opts.Labels
|
||||
}
|
||||
reqBodyData, err := json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
req, err := c.client.NewRequest(ctx, "POST", "/networks", bytes.NewReader(reqBodyData))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
respBody := schema.NetworkCreateResponse{}
|
||||
resp, err := c.client.Do(req, &respBody)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return NetworkFromSchema(respBody.Network), resp, nil
|
||||
}
|
||||
|
||||
// NetworkChangeIPRangeOpts specifies options for changing the IP range of a network.
|
||||
type NetworkChangeIPRangeOpts struct {
|
||||
IPRange *net.IPNet
|
||||
}
|
||||
|
||||
// ChangeIPRange changes the IP range of a network.
|
||||
func (c *NetworkClient) ChangeIPRange(ctx context.Context, network *Network, opts NetworkChangeIPRangeOpts) (*Action, *Response, error) {
|
||||
reqBody := schema.NetworkActionChangeIPRangeRequest{
|
||||
IPRange: opts.IPRange.String(),
|
||||
}
|
||||
reqBodyData, err := json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
path := fmt.Sprintf("/networks/%d/actions/change_ip_range", network.ID)
|
||||
req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
respBody := schema.NetworkActionChangeIPRangeResponse{}
|
||||
resp, err := c.client.Do(req, &respBody)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return ActionFromSchema(respBody.Action), resp, nil
|
||||
}
|
||||
|
||||
// NetworkAddSubnetOpts specifies options for adding a subnet to a network.
|
||||
type NetworkAddSubnetOpts struct {
|
||||
Subnet NetworkSubnet
|
||||
}
|
||||
|
||||
// AddSubnet adds a subnet to a network.
|
||||
func (c *NetworkClient) AddSubnet(ctx context.Context, network *Network, opts NetworkAddSubnetOpts) (*Action, *Response, error) {
|
||||
reqBody := schema.NetworkActionAddSubnetRequest{
|
||||
Type: string(opts.Subnet.Type),
|
||||
IPRange: opts.Subnet.IPRange.String(),
|
||||
NetworkZone: string(opts.Subnet.NetworkZone),
|
||||
}
|
||||
reqBodyData, err := json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
path := fmt.Sprintf("/networks/%d/actions/add_subnet", network.ID)
|
||||
req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
respBody := schema.NetworkActionAddSubnetResponse{}
|
||||
resp, err := c.client.Do(req, &respBody)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return ActionFromSchema(respBody.Action), resp, nil
|
||||
}
|
||||
|
||||
// NetworkDeleteSubnetOpts specifies options for deleting a subnet from a network.
|
||||
type NetworkDeleteSubnetOpts struct {
|
||||
Subnet NetworkSubnet
|
||||
}
|
||||
|
||||
// DeleteSubnet deletes a subnet from a network.
|
||||
func (c *NetworkClient) DeleteSubnet(ctx context.Context, network *Network, opts NetworkDeleteSubnetOpts) (*Action, *Response, error) {
|
||||
reqBody := schema.NetworkActionDeleteSubnetRequest{
|
||||
IPRange: opts.Subnet.IPRange.String(),
|
||||
}
|
||||
reqBodyData, err := json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
path := fmt.Sprintf("/networks/%d/actions/delete_subnet", network.ID)
|
||||
req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
respBody := schema.NetworkActionDeleteSubnetResponse{}
|
||||
resp, err := c.client.Do(req, &respBody)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return ActionFromSchema(respBody.Action), resp, nil
|
||||
}
|
||||
|
||||
// NetworkAddRouteOpts specifies options for adding a route to a network.
|
||||
type NetworkAddRouteOpts struct {
|
||||
Route NetworkRoute
|
||||
}
|
||||
|
||||
// AddRoute adds a route to a network.
|
||||
func (c *NetworkClient) AddRoute(ctx context.Context, network *Network, opts NetworkAddRouteOpts) (*Action, *Response, error) {
|
||||
reqBody := schema.NetworkActionAddRouteRequest{
|
||||
Destination: opts.Route.Destination.String(),
|
||||
Gateway: opts.Route.Gateway.String(),
|
||||
}
|
||||
reqBodyData, err := json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
path := fmt.Sprintf("/networks/%d/actions/add_route", network.ID)
|
||||
req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
respBody := schema.NetworkActionAddSubnetResponse{}
|
||||
resp, err := c.client.Do(req, &respBody)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return ActionFromSchema(respBody.Action), resp, nil
|
||||
}
|
||||
|
||||
// NetworkDeleteRouteOpts specifies options for deleting a route from a network.
|
||||
type NetworkDeleteRouteOpts struct {
|
||||
Route NetworkRoute
|
||||
}
|
||||
|
||||
// DeleteRoute deletes a route from a network.
|
||||
func (c *NetworkClient) DeleteRoute(ctx context.Context, network *Network, opts NetworkDeleteRouteOpts) (*Action, *Response, error) {
|
||||
reqBody := schema.NetworkActionDeleteRouteRequest{
|
||||
Destination: opts.Route.Destination.String(),
|
||||
Gateway: opts.Route.Gateway.String(),
|
||||
}
|
||||
reqBodyData, err := json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
path := fmt.Sprintf("/networks/%d/actions/delete_route", network.ID)
|
||||
req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
respBody := schema.NetworkActionDeleteSubnetResponse{}
|
||||
resp, err := c.client.Do(req, &respBody)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return ActionFromSchema(respBody.Action), resp, nil
|
||||
}
|
||||
|
||||
// NetworkChangeProtectionOpts specifies options for changing the resource protection level of a network.
|
||||
type NetworkChangeProtectionOpts struct {
|
||||
Delete *bool
|
||||
}
|
||||
|
||||
// ChangeProtection changes the resource protection level of a network.
|
||||
func (c *NetworkClient) ChangeProtection(ctx context.Context, network *Network, opts NetworkChangeProtectionOpts) (*Action, *Response, error) {
|
||||
reqBody := schema.NetworkActionChangeProtectionRequest{
|
||||
Delete: opts.Delete,
|
||||
}
|
||||
reqBodyData, err := json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
path := fmt.Sprintf("/networks/%d/actions/change_protection", network.ID)
|
||||
req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
respBody := schema.NetworkActionChangeProtectionResponse{}
|
||||
resp, err := c.client.Do(req, &respBody)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return ActionFromSchema(respBody.Action), resp, err
|
||||
}
|
68
vendor/github.com/hetznercloud/hcloud-go/hcloud/schema.go
generated
vendored
68
vendor/github.com/hetznercloud/hcloud-go/hcloud/schema.go
generated
vendored
@ -50,6 +50,7 @@ func FloatingIPFromSchema(s schema.FloatingIP) *FloatingIP {
|
||||
ID: s.ID,
|
||||
Type: FloatingIPType(s.Type),
|
||||
HomeLocation: LocationFromSchema(s.HomeLocation),
|
||||
Created: s.Created,
|
||||
Blocked: s.Blocked,
|
||||
Protection: FloatingIPProtection{
|
||||
Delete: s.Protection.Delete,
|
||||
@ -98,6 +99,7 @@ func LocationFromSchema(s schema.Location) *Location {
|
||||
City: s.City,
|
||||
Latitude: s.Latitude,
|
||||
Longitude: s.Longitude,
|
||||
NetworkZone: NetworkZone(s.NetworkZone),
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,6 +164,9 @@ func ServerFromSchema(s schema.Server) *Server {
|
||||
for _, id := range s.Volumes {
|
||||
server.Volumes = append(server.Volumes, &Volume{ID: id})
|
||||
}
|
||||
for _, privNet := range s.PrivateNet {
|
||||
server.PrivateNet = append(server.PrivateNet, ServerPrivateNetFromSchema(privNet))
|
||||
}
|
||||
return server
|
||||
}
|
||||
|
||||
@ -202,6 +207,19 @@ func ServerPublicNetIPv6FromSchema(s schema.ServerPublicNetIPv6) ServerPublicNet
|
||||
return ipv6
|
||||
}
|
||||
|
||||
// ServerPrivateNetFromSchema converts a schema.ServerPrivateNet to a ServerPrivateNet.
|
||||
func ServerPrivateNetFromSchema(s schema.ServerPrivateNet) ServerPrivateNet {
|
||||
n := ServerPrivateNet{
|
||||
Network: &Network{ID: s.Network},
|
||||
IP: net.ParseIP(s.IP),
|
||||
MACAddress: s.MACAddress,
|
||||
}
|
||||
for _, ip := range s.AliasIPs {
|
||||
n.Aliases = append(n.Aliases, net.ParseIP(ip))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// ServerTypeFromSchema converts a schema.ServerType to a ServerType.
|
||||
func ServerTypeFromSchema(s schema.ServerType) *ServerType {
|
||||
st := &ServerType{
|
||||
@ -311,6 +329,56 @@ func VolumeFromSchema(s schema.Volume) *Volume {
|
||||
return v
|
||||
}
|
||||
|
||||
// NetworkFromSchema converts a schema.Network to a Network.
|
||||
func NetworkFromSchema(s schema.Network) *Network {
|
||||
n := &Network{
|
||||
ID: s.ID,
|
||||
Name: s.Name,
|
||||
Created: s.Created,
|
||||
Protection: NetworkProtection{
|
||||
Delete: s.Protection.Delete,
|
||||
},
|
||||
Labels: map[string]string{},
|
||||
}
|
||||
|
||||
_, n.IPRange, _ = net.ParseCIDR(s.IPRange)
|
||||
|
||||
for _, subnet := range s.Subnets {
|
||||
n.Subnets = append(n.Subnets, NetworkSubnetFromSchema(subnet))
|
||||
}
|
||||
for _, route := range s.Routes {
|
||||
n.Routes = append(n.Routes, NetworkRouteFromSchema(route))
|
||||
}
|
||||
for _, serverID := range s.Servers {
|
||||
n.Servers = append(n.Servers, &Server{ID: serverID})
|
||||
}
|
||||
for key, value := range s.Labels {
|
||||
n.Labels[key] = value
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
// NetworkSubnetFromSchema converts a schema.NetworkSubnet to a NetworkSubnet.
|
||||
func NetworkSubnetFromSchema(s schema.NetworkSubnet) NetworkSubnet {
|
||||
sn := NetworkSubnet{
|
||||
Type: NetworkSubnetType(s.Type),
|
||||
NetworkZone: NetworkZone(s.NetworkZone),
|
||||
Gateway: net.ParseIP(s.Gateway),
|
||||
}
|
||||
_, sn.IPRange, _ = net.ParseCIDR(s.IPRange)
|
||||
return sn
|
||||
}
|
||||
|
||||
// NetworkRouteFromSchema converts a schema.NetworkRoute to a NetworkRoute.
|
||||
func NetworkRouteFromSchema(s schema.NetworkRoute) NetworkRoute {
|
||||
r := NetworkRoute{
|
||||
Gateway: net.ParseIP(s.Gateway),
|
||||
}
|
||||
_, r.Destination, _ = net.ParseCIDR(s.Destination)
|
||||
return r
|
||||
}
|
||||
|
||||
// PaginationFromSchema converts a schema.MetaPagination to a Pagination.
|
||||
func PaginationFromSchema(s schema.MetaPagination) Pagination {
|
||||
return Pagination{
|
||||
|
3
vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/floating_ip.go
generated
vendored
3
vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/floating_ip.go
generated
vendored
@ -1,9 +1,12 @@
|
||||
package schema
|
||||
|
||||
import "time"
|
||||
|
||||
// FloatingIP defines the schema of a Floating IP.
|
||||
type FloatingIP struct {
|
||||
ID int `json:"id"`
|
||||
Description *string `json:"description"`
|
||||
Created time.Time `json:"created"`
|
||||
IP string `json:"ip"`
|
||||
Type string `json:"type"`
|
||||
Server *int `json:"server"`
|
||||
|
1
vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/location.go
generated
vendored
1
vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/location.go
generated
vendored
@ -9,6 +9,7 @@ type Location struct {
|
||||
City string `json:"city"`
|
||||
Latitude float64 `json:"latitude"`
|
||||
Longitude float64 `json:"longitude"`
|
||||
NetworkZone string `json:"network_zone"`
|
||||
}
|
||||
|
||||
// LocationGetResponse defines the schema of the response when retrieving a single location.
|
||||
|
150
vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/network.go
generated
vendored
Normal file
150
vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/network.go
generated
vendored
Normal file
@ -0,0 +1,150 @@
|
||||
package schema
|
||||
|
||||
import "time"
|
||||
|
||||
// Network defines the schema of a network.
|
||||
type Network struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Created time.Time `json:"created"`
|
||||
IPRange string `json:"ip_range"`
|
||||
Subnets []NetworkSubnet `json:"subnets"`
|
||||
Routes []NetworkRoute `json:"routes"`
|
||||
Servers []int `json:"servers"`
|
||||
Protection NetworkProtection `json:"protection"`
|
||||
Labels map[string]string `json:"labels"`
|
||||
}
|
||||
|
||||
// NetworkSubnet represents a subnet of a network.
|
||||
type NetworkSubnet struct {
|
||||
Type string `json:"type"`
|
||||
IPRange string `json:"ip_range"`
|
||||
NetworkZone string `json:"network_zone"`
|
||||
Gateway string `json:"gateway"`
|
||||
}
|
||||
|
||||
// NetworkRoute represents a route of a network.
|
||||
type NetworkRoute struct {
|
||||
Destination string `json:"destination"`
|
||||
Gateway string `json:"gateway"`
|
||||
}
|
||||
|
||||
// NetworkProtection represents the protection level of a network.
|
||||
type NetworkProtection struct {
|
||||
Delete bool `json:"delete"`
|
||||
}
|
||||
|
||||
// NetworkUpdateRequest defines the schema of the request to update a network.
|
||||
type NetworkUpdateRequest struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Labels *map[string]string `json:"labels,omitempty"`
|
||||
}
|
||||
|
||||
// NetworkUpdateResponse defines the schema of the response when updating a network.
|
||||
type NetworkUpdateResponse struct {
|
||||
Network Network `json:"network"`
|
||||
}
|
||||
|
||||
// NetworkListResponse defines the schema of the response when
|
||||
// listing networks.
|
||||
type NetworkListResponse struct {
|
||||
Networks []Network `json:"networks"`
|
||||
}
|
||||
|
||||
// NetworkGetResponse defines the schema of the response when
|
||||
// retrieving a single network.
|
||||
type NetworkGetResponse struct {
|
||||
Network Network `json:"network"`
|
||||
}
|
||||
|
||||
// NetworkCreateRequest defines the schema of the request to create a network.
|
||||
type NetworkCreateRequest struct {
|
||||
Name string `json:"name"`
|
||||
IPRange string `json:"ip_range"`
|
||||
Subnets []NetworkSubnet `json:"subnets,omitempty"`
|
||||
Routes []NetworkRoute `json:"routes,omitempty"`
|
||||
Labels *map[string]string `json:"labels,omitempty"`
|
||||
}
|
||||
|
||||
// NetworkCreateResponse defines the schema of the response when
|
||||
// creating a network.
|
||||
type NetworkCreateResponse struct {
|
||||
Network Network `json:"network"`
|
||||
}
|
||||
|
||||
// NetworkActionChangeIPRangeRequest defines the schema of the request to
|
||||
// change the IP range of a network.
|
||||
type NetworkActionChangeIPRangeRequest struct {
|
||||
IPRange string `json:"ip_range"`
|
||||
}
|
||||
|
||||
// NetworkActionChangeIPRangeResponse defines the schema of the response when
|
||||
// changing the IP range of a network.
|
||||
type NetworkActionChangeIPRangeResponse struct {
|
||||
Action Action `json:"action"`
|
||||
}
|
||||
|
||||
// NetworkActionAddSubnetRequest defines the schema of the request to
|
||||
// add a subnet to a network.
|
||||
type NetworkActionAddSubnetRequest struct {
|
||||
Type string `json:"type"`
|
||||
IPRange string `json:"ip_range,omitempty"`
|
||||
NetworkZone string `json:"network_zone"`
|
||||
Gateway string `json:"gateway"`
|
||||
}
|
||||
|
||||
// NetworkActionAddSubnetResponse defines the schema of the response when
|
||||
// adding a subnet to a network.
|
||||
type NetworkActionAddSubnetResponse struct {
|
||||
Action Action `json:"action"`
|
||||
}
|
||||
|
||||
// NetworkActionDeleteSubnetRequest defines the schema of the request to
|
||||
// delete a subnet from a network.
|
||||
type NetworkActionDeleteSubnetRequest struct {
|
||||
IPRange string `json:"ip_range"`
|
||||
}
|
||||
|
||||
// NetworkActionDeleteSubnetResponse defines the schema of the response when
|
||||
// deleting a subnet from a network.
|
||||
type NetworkActionDeleteSubnetResponse struct {
|
||||
Action Action `json:"action"`
|
||||
}
|
||||
|
||||
// NetworkActionAddRouteRequest defines the schema of the request to
|
||||
// add a route to a network.
|
||||
type NetworkActionAddRouteRequest struct {
|
||||
Destination string `json:"destination"`
|
||||
Gateway string `json:"gateway"`
|
||||
}
|
||||
|
||||
// NetworkActionAddRouteResponse defines the schema of the response when
|
||||
// adding a route to a network.
|
||||
type NetworkActionAddRouteResponse struct {
|
||||
Action Action `json:"action"`
|
||||
}
|
||||
|
||||
// NetworkActionDeleteRouteRequest defines the schema of the request to
|
||||
// delete a route from a network.
|
||||
type NetworkActionDeleteRouteRequest struct {
|
||||
Destination string `json:"destination"`
|
||||
Gateway string `json:"gateway"`
|
||||
}
|
||||
|
||||
// NetworkActionDeleteRouteResponse defines the schema of the response when
|
||||
// deleting a route from a network.
|
||||
type NetworkActionDeleteRouteResponse struct {
|
||||
Action Action `json:"action"`
|
||||
}
|
||||
|
||||
// NetworkActionChangeProtectionRequest defines the schema of the request to
|
||||
// change the resource protection of a network.
|
||||
type NetworkActionChangeProtectionRequest struct {
|
||||
Delete *bool `json:"delete,omitempty"`
|
||||
}
|
||||
|
||||
// NetworkActionChangeProtectionResponse defines the schema of the response when
|
||||
// changing the resource protection of a network.
|
||||
type NetworkActionChangeProtectionResponse struct {
|
||||
Action Action `json:"action"`
|
||||
}
|
91
vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/server.go
generated
vendored
91
vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/server.go
generated
vendored
@ -4,24 +4,25 @@ import "time"
|
||||
|
||||
// Server defines the schema of a server.
|
||||
type Server struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Status string `json:"status"`
|
||||
Created time.Time `json:"created"`
|
||||
PublicNet ServerPublicNet `json:"public_net"`
|
||||
ServerType ServerType `json:"server_type"`
|
||||
IncludedTraffic uint64 `json:"included_traffic"`
|
||||
OutgoingTraffic *uint64 `json:"outgoing_traffic"`
|
||||
IngoingTraffic *uint64 `json:"ingoing_traffic"`
|
||||
BackupWindow *string `json:"backup_window"`
|
||||
RescueEnabled bool `json:"rescue_enabled"`
|
||||
ISO *ISO `json:"iso"`
|
||||
Locked bool `json:"locked"`
|
||||
Datacenter Datacenter `json:"datacenter"`
|
||||
Image *Image `json:"image"`
|
||||
Protection ServerProtection `json:"protection"`
|
||||
Labels map[string]string `json:"labels"`
|
||||
Volumes []int `json:"volumes"`
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Status string `json:"status"`
|
||||
Created time.Time `json:"created"`
|
||||
PublicNet ServerPublicNet `json:"public_net"`
|
||||
PrivateNet []ServerPrivateNet `json:"private_net"`
|
||||
ServerType ServerType `json:"server_type"`
|
||||
IncludedTraffic uint64 `json:"included_traffic"`
|
||||
OutgoingTraffic *uint64 `json:"outgoing_traffic"`
|
||||
IngoingTraffic *uint64 `json:"ingoing_traffic"`
|
||||
BackupWindow *string `json:"backup_window"`
|
||||
RescueEnabled bool `json:"rescue_enabled"`
|
||||
ISO *ISO `json:"iso"`
|
||||
Locked bool `json:"locked"`
|
||||
Datacenter Datacenter `json:"datacenter"`
|
||||
Image *Image `json:"image"`
|
||||
Protection ServerProtection `json:"protection"`
|
||||
Labels map[string]string `json:"labels"`
|
||||
Volumes []int `json:"volumes"`
|
||||
}
|
||||
|
||||
// ServerProtection defines the schema of a server's resource protection.
|
||||
@ -61,6 +62,14 @@ type ServerPublicNetIPv6DNSPtr struct {
|
||||
DNSPtr string `json:"dns_ptr"`
|
||||
}
|
||||
|
||||
// ServerPrivateNet defines the schema of a server's private network information.
|
||||
type ServerPrivateNet struct {
|
||||
Network int `json:"network"`
|
||||
IP string `json:"ip"`
|
||||
AliasIPs []string `json:"alias_ips"`
|
||||
MACAddress string `json:"mac_address"`
|
||||
}
|
||||
|
||||
// ServerGetResponse defines the schema of the response when
|
||||
// retrieving a single server.
|
||||
type ServerGetResponse struct {
|
||||
@ -87,6 +96,7 @@ type ServerCreateRequest struct {
|
||||
Labels *map[string]string `json:"labels,omitempty"`
|
||||
Automount *bool `json:"automount,omitempty"`
|
||||
Volumes []int `json:"volumes,omitempty"`
|
||||
Networks []int `json:"networks,omitempty"`
|
||||
}
|
||||
|
||||
// ServerCreateResponse defines the schema of the response when
|
||||
@ -291,13 +301,54 @@ type ServerActionChangeDNSPtrResponse struct {
|
||||
Action Action `json:"action"`
|
||||
}
|
||||
|
||||
// ServerActionChangeProtectionRequest defines the schema of the request to change the resource protection of a server.
|
||||
// ServerActionChangeProtectionRequest defines the schema of the request to
|
||||
// change the resource protection of a server.
|
||||
type ServerActionChangeProtectionRequest struct {
|
||||
Rebuild *bool `json:"rebuild,omitempty"`
|
||||
Delete *bool `json:"delete,omitempty"`
|
||||
}
|
||||
|
||||
// ServerActionChangeProtectionResponse defines the schema of the response when changing the resource protection of a server.
|
||||
// ServerActionChangeProtectionResponse defines the schema of the response when
|
||||
// changing the resource protection of a server.
|
||||
type ServerActionChangeProtectionResponse struct {
|
||||
Action Action `json:"action"`
|
||||
}
|
||||
|
||||
// ServerActionAttachToNetworkRequest defines the schema for the request to
|
||||
// attach a network to a server.
|
||||
type ServerActionAttachToNetworkRequest struct {
|
||||
Network int `json:"network"`
|
||||
IP *string `json:"ip,omitempty"`
|
||||
AliasIPs []*string `json:"alias_ips,omitempty"`
|
||||
}
|
||||
|
||||
// ServerActionAttachToNetworkResponse defines the schema of the response when
|
||||
// creating an attach_to_network server action.
|
||||
type ServerActionAttachToNetworkResponse struct {
|
||||
Action Action `json:"action"`
|
||||
}
|
||||
|
||||
// ServerActionDetachFromNetworkRequest defines the schema for the request to
|
||||
// detach a network from a server.
|
||||
type ServerActionDetachFromNetworkRequest struct {
|
||||
Network int `json:"network"`
|
||||
}
|
||||
|
||||
// ServerActionDetachFromNetworkResponse defines the schema of the response when
|
||||
// creating a detach_from_network server action.
|
||||
type ServerActionDetachFromNetworkResponse struct {
|
||||
Action Action `json:"action"`
|
||||
}
|
||||
|
||||
// ServerActionChangeAliasIPsRequest defines the schema for the request to
|
||||
// change a server's alias IPs in a network.
|
||||
type ServerActionChangeAliasIPsRequest struct {
|
||||
Network int `json:"network"`
|
||||
AliasIPs []string `json:"alias_ips"`
|
||||
}
|
||||
|
||||
// ServerActionChangeAliasIPsResponse defines the schema of the response when
|
||||
// creating an change_alias_ips server action.
|
||||
type ServerActionChangeAliasIPsResponse struct {
|
||||
Action Action `json:"action"`
|
||||
}
|
||||
|
172
vendor/github.com/hetznercloud/hcloud-go/hcloud/server.go
generated
vendored
172
vendor/github.com/hetznercloud/hcloud-go/hcloud/server.go
generated
vendored
@ -21,6 +21,7 @@ type Server struct {
|
||||
Status ServerStatus
|
||||
Created time.Time
|
||||
PublicNet ServerPublicNet
|
||||
PrivateNet []ServerPrivateNet
|
||||
ServerType *ServerType
|
||||
Datacenter *Datacenter
|
||||
IncludedTraffic uint64
|
||||
@ -53,6 +54,24 @@ const (
|
||||
|
||||
// ServerStatusRunning is the status when a server is running.
|
||||
ServerStatusRunning ServerStatus = "running"
|
||||
|
||||
// ServerStatusStarting is the status when a server is being started.
|
||||
ServerStatusStarting ServerStatus = "starting"
|
||||
|
||||
// ServerStatusStopping is the status when a server is being stopped.
|
||||
ServerStatusStopping ServerStatus = "stopping"
|
||||
|
||||
// ServerStatusMigrating is the status when a server is being migrated.
|
||||
ServerStatusMigrating ServerStatus = "migrating"
|
||||
|
||||
// ServerStatusRebuilding is the status when a server is being rebuilt.
|
||||
ServerStatusRebuilding ServerStatus = "rebuilding"
|
||||
|
||||
// ServerStatusDeleting is the status when a server is being deleted.
|
||||
ServerStatusDeleting ServerStatus = "deleting"
|
||||
|
||||
// ServerStatusUnknown is the status when a server's state is unknown.
|
||||
ServerStatusUnknown ServerStatus = "unknown"
|
||||
)
|
||||
|
||||
// ServerPublicNet represents a server's public network.
|
||||
@ -77,6 +96,14 @@ type ServerPublicNetIPv6 struct {
|
||||
DNSPtr map[string]string
|
||||
}
|
||||
|
||||
// ServerPrivateNet defines the schema of a server's private network information.
|
||||
type ServerPrivateNet struct {
|
||||
Network *Network
|
||||
IP net.IP
|
||||
Aliases []net.IP
|
||||
MACAddress string
|
||||
}
|
||||
|
||||
// DNSPtrForIP returns the reverse dns pointer of the ip address.
|
||||
func (s *ServerPublicNetIPv6) DNSPtrForIP(ip net.IP) string {
|
||||
return s.DNSPtr[ip.String()]
|
||||
@ -115,24 +142,13 @@ func (c *ServerClient) GetByID(ctx context.Context, id int) (*Server, *Response,
|
||||
return ServerFromSchema(body.Server), resp, nil
|
||||
}
|
||||
|
||||
// GetByName retreives a server by its name. If the server does not exist, nil is returned.
|
||||
// GetByName retrieves a server by its name. If the server does not exist, nil is returned.
|
||||
func (c *ServerClient) GetByName(ctx context.Context, name string) (*Server, *Response, error) {
|
||||
path := "/servers?name=" + url.QueryEscape(name)
|
||||
req, err := c.client.NewRequest(ctx, "GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
servers, response, err := c.List(ctx, ServerListOpts{Name: name})
|
||||
if len(servers) == 0 {
|
||||
return nil, response, err
|
||||
}
|
||||
|
||||
var body schema.ServerListResponse
|
||||
resp, err := c.client.Do(req, &body)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if len(body.Servers) == 0 {
|
||||
return nil, resp, nil
|
||||
}
|
||||
return ServerFromSchema(body.Servers[0]), resp, nil
|
||||
return servers[0], response, err
|
||||
}
|
||||
|
||||
// Get retrieves a server by its ID if the input can be parsed as an integer, otherwise it
|
||||
@ -147,11 +163,24 @@ func (c *ServerClient) Get(ctx context.Context, idOrName string) (*Server, *Resp
|
||||
// ServerListOpts specifies options for listing servers.
|
||||
type ServerListOpts struct {
|
||||
ListOpts
|
||||
Name string
|
||||
Status []ServerStatus
|
||||
}
|
||||
|
||||
func (l ServerListOpts) values() url.Values {
|
||||
vals := l.ListOpts.values()
|
||||
if l.Name != "" {
|
||||
vals.Add("name", l.Name)
|
||||
}
|
||||
for _, status := range l.Status {
|
||||
vals.Add("status", string(status))
|
||||
}
|
||||
return vals
|
||||
}
|
||||
|
||||
// List returns a list of servers for a specific page.
|
||||
func (c *ServerClient) List(ctx context.Context, opts ServerListOpts) ([]*Server, *Response, error) {
|
||||
path := "/servers?" + valuesForListOpts(opts.ListOpts).Encode()
|
||||
path := "/servers?" + opts.values().Encode()
|
||||
req, err := c.client.NewRequest(ctx, "GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@ -171,7 +200,7 @@ func (c *ServerClient) List(ctx context.Context, opts ServerListOpts) ([]*Server
|
||||
|
||||
// All returns all servers.
|
||||
func (c *ServerClient) All(ctx context.Context) ([]*Server, error) {
|
||||
return c.AllWithOpts(ctx, ServerListOpts{ListOpts{PerPage: 50}})
|
||||
return c.AllWithOpts(ctx, ServerListOpts{ListOpts: ListOpts{PerPage: 50}})
|
||||
}
|
||||
|
||||
// AllWithOpts returns all servers for the given options.
|
||||
@ -207,6 +236,7 @@ type ServerCreateOpts struct {
|
||||
Labels map[string]string
|
||||
Automount *bool
|
||||
Volumes []*Volume
|
||||
Networks []*Network
|
||||
}
|
||||
|
||||
// Validate checks if options are valid.
|
||||
@ -264,6 +294,9 @@ func (c *ServerClient) Create(ctx context.Context, opts ServerCreateOpts) (Serve
|
||||
for _, volume := range opts.Volumes {
|
||||
reqBody.Volumes = append(reqBody.Volumes, volume.ID)
|
||||
}
|
||||
for _, network := range opts.Networks {
|
||||
reqBody.Networks = append(reqBody.Networks, network.ID)
|
||||
}
|
||||
|
||||
if opts.Location != nil {
|
||||
if opts.Location.ID != 0 {
|
||||
@ -763,7 +796,7 @@ type ServerChangeProtectionOpts struct {
|
||||
}
|
||||
|
||||
// ChangeProtection changes the resource protection level of a server.
|
||||
func (c *ServerClient) ChangeProtection(ctx context.Context, image *Server, opts ServerChangeProtectionOpts) (*Action, *Response, error) {
|
||||
func (c *ServerClient) ChangeProtection(ctx context.Context, server *Server, opts ServerChangeProtectionOpts) (*Action, *Response, error) {
|
||||
reqBody := schema.ServerActionChangeProtectionRequest{
|
||||
Rebuild: opts.Rebuild,
|
||||
Delete: opts.Delete,
|
||||
@ -773,7 +806,7 @@ func (c *ServerClient) ChangeProtection(ctx context.Context, image *Server, opts
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
path := fmt.Sprintf("/servers/%d/actions/change_protection", image.ID)
|
||||
path := fmt.Sprintf("/servers/%d/actions/change_protection", server.ID)
|
||||
req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@ -786,3 +819,102 @@ func (c *ServerClient) ChangeProtection(ctx context.Context, image *Server, opts
|
||||
}
|
||||
return ActionFromSchema(respBody.Action), resp, err
|
||||
}
|
||||
|
||||
// ServerAttachToNetworkOpts specifies options for attaching a server to a network.
|
||||
type ServerAttachToNetworkOpts struct {
|
||||
Network *Network
|
||||
IP net.IP
|
||||
AliasIPs []net.IP
|
||||
}
|
||||
|
||||
// AttachToNetwork attaches a server to a network.
|
||||
func (c *ServerClient) AttachToNetwork(ctx context.Context, server *Server, opts ServerAttachToNetworkOpts) (*Action, *Response, error) {
|
||||
reqBody := schema.ServerActionAttachToNetworkRequest{
|
||||
Network: opts.Network.ID,
|
||||
}
|
||||
if opts.IP != nil {
|
||||
reqBody.IP = String(opts.IP.String())
|
||||
}
|
||||
for _, aliasIP := range opts.AliasIPs {
|
||||
reqBody.AliasIPs = append(reqBody.AliasIPs, String(aliasIP.String()))
|
||||
}
|
||||
reqBodyData, err := json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
path := fmt.Sprintf("/servers/%d/actions/attach_to_network", server.ID)
|
||||
req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
respBody := schema.ServerActionAttachToNetworkResponse{}
|
||||
resp, err := c.client.Do(req, &respBody)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return ActionFromSchema(respBody.Action), resp, err
|
||||
}
|
||||
|
||||
// ServerDetachFromNetworkOpts specifies options for detaching a server from a network.
|
||||
type ServerDetachFromNetworkOpts struct {
|
||||
Network *Network
|
||||
}
|
||||
|
||||
// DetachFromNetwork detaches a server from a network.
|
||||
func (c *ServerClient) DetachFromNetwork(ctx context.Context, server *Server, opts ServerDetachFromNetworkOpts) (*Action, *Response, error) {
|
||||
reqBody := schema.ServerActionDetachFromNetworkRequest{
|
||||
Network: opts.Network.ID,
|
||||
}
|
||||
reqBodyData, err := json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
path := fmt.Sprintf("/servers/%d/actions/detach_from_network", server.ID)
|
||||
req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
respBody := schema.ServerActionDetachFromNetworkResponse{}
|
||||
resp, err := c.client.Do(req, &respBody)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return ActionFromSchema(respBody.Action), resp, err
|
||||
}
|
||||
|
||||
// ServerChangeAliasIPsOpts specifies options for changing the alias ips of an already attached network.
|
||||
type ServerChangeAliasIPsOpts struct {
|
||||
Network *Network
|
||||
AliasIPs []net.IP
|
||||
}
|
||||
|
||||
// ChangeAliasIPs changes a server's alias IPs in a network.
|
||||
func (c *ServerClient) ChangeAliasIPs(ctx context.Context, server *Server, opts ServerChangeAliasIPsOpts) (*Action, *Response, error) {
|
||||
reqBody := schema.ServerActionChangeAliasIPsRequest{
|
||||
Network: opts.Network.ID,
|
||||
AliasIPs: []string{},
|
||||
}
|
||||
for _, aliasIP := range opts.AliasIPs {
|
||||
reqBody.AliasIPs = append(reqBody.AliasIPs, aliasIP.String())
|
||||
}
|
||||
reqBodyData, err := json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
path := fmt.Sprintf("/servers/%d/actions/change_alias_ips", server.ID)
|
||||
req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
respBody := schema.ServerActionDetachFromNetworkResponse{}
|
||||
resp, err := c.client.Do(req, &respBody)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return ActionFromSchema(respBody.Action), resp, err
|
||||
}
|
||||
|
30
vendor/github.com/hetznercloud/hcloud-go/hcloud/server_type.go
generated
vendored
30
vendor/github.com/hetznercloud/hcloud-go/hcloud/server_type.go
generated
vendored
@ -69,22 +69,11 @@ func (c *ServerTypeClient) GetByID(ctx context.Context, id int) (*ServerType, *R
|
||||
|
||||
// GetByName retrieves a server type by its name. If the server type does not exist, nil is returned.
|
||||
func (c *ServerTypeClient) GetByName(ctx context.Context, name string) (*ServerType, *Response, error) {
|
||||
path := "/server_types?name=" + url.QueryEscape(name)
|
||||
req, err := c.client.NewRequest(ctx, "GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
serverTypes, response, err := c.List(ctx, ServerTypeListOpts{Name: name})
|
||||
if len(serverTypes) == 0 {
|
||||
return nil, response, err
|
||||
}
|
||||
|
||||
var body schema.ServerTypeListResponse
|
||||
resp, err := c.client.Do(req, &body)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if len(body.ServerTypes) == 0 {
|
||||
return nil, resp, nil
|
||||
}
|
||||
return ServerTypeFromSchema(body.ServerTypes[0]), resp, nil
|
||||
return serverTypes[0], response, err
|
||||
}
|
||||
|
||||
// Get retrieves a server type by its ID if the input can be parsed as an integer, otherwise it
|
||||
@ -99,11 +88,20 @@ func (c *ServerTypeClient) Get(ctx context.Context, idOrName string) (*ServerTyp
|
||||
// ServerTypeListOpts specifies options for listing server types.
|
||||
type ServerTypeListOpts struct {
|
||||
ListOpts
|
||||
Name string
|
||||
}
|
||||
|
||||
func (l ServerTypeListOpts) values() url.Values {
|
||||
vals := l.ListOpts.values()
|
||||
if l.Name != "" {
|
||||
vals.Add("name", l.Name)
|
||||
}
|
||||
return vals
|
||||
}
|
||||
|
||||
// List returns a list of server types for a specific page.
|
||||
func (c *ServerTypeClient) List(ctx context.Context, opts ServerTypeListOpts) ([]*ServerType, *Response, error) {
|
||||
path := "/server_types?" + valuesForListOpts(opts.ListOpts).Encode()
|
||||
path := "/server_types?" + opts.values().Encode()
|
||||
req, err := c.client.NewRequest(ctx, "GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
55
vendor/github.com/hetznercloud/hcloud-go/hcloud/ssh_key.go
generated
vendored
55
vendor/github.com/hetznercloud/hcloud-go/hcloud/ssh_key.go
generated
vendored
@ -46,42 +46,20 @@ func (c *SSHKeyClient) GetByID(ctx context.Context, id int) (*SSHKey, *Response,
|
||||
|
||||
// GetByName retrieves a SSH key by its name. If the SSH key does not exist, nil is returned.
|
||||
func (c *SSHKeyClient) GetByName(ctx context.Context, name string) (*SSHKey, *Response, error) {
|
||||
path := "/ssh_keys?name=" + url.QueryEscape(name)
|
||||
req, err := c.client.NewRequest(ctx, "GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
sshKeys, response, err := c.List(ctx, SSHKeyListOpts{Name: name})
|
||||
if len(sshKeys) == 0 {
|
||||
return nil, response, err
|
||||
}
|
||||
|
||||
var body schema.SSHKeyListResponse
|
||||
resp, err := c.client.Do(req, &body)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if len(body.SSHKeys) == 0 {
|
||||
return nil, resp, nil
|
||||
}
|
||||
return SSHKeyFromSchema(body.SSHKeys[0]), resp, nil
|
||||
return sshKeys[0], response, err
|
||||
}
|
||||
|
||||
// GetByFingerprint retreives a SSH key by its fingerprint. If the SSH key does not exist, nil is returned.
|
||||
func (c *SSHKeyClient) GetByFingerprint(ctx context.Context, fingerprint string) (*SSHKey, *Response, error) {
|
||||
path := "/ssh_keys?fingerprint=" + url.QueryEscape(fingerprint)
|
||||
req, err := c.client.NewRequest(ctx, "GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
sshKeys, response, err := c.List(ctx, SSHKeyListOpts{Fingerprint: fingerprint})
|
||||
if len(sshKeys) == 0 {
|
||||
return nil, response, err
|
||||
}
|
||||
|
||||
var body schema.SSHKeyListResponse
|
||||
resp, err := c.client.Do(req, &body)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if len(body.SSHKeys) == 0 {
|
||||
return nil, resp, nil
|
||||
}
|
||||
return SSHKeyFromSchema(body.SSHKeys[0]), resp, nil
|
||||
return sshKeys[0], response, err
|
||||
}
|
||||
|
||||
// Get retrieves a SSH key by its ID if the input can be parsed as an integer, otherwise it
|
||||
@ -96,11 +74,24 @@ func (c *SSHKeyClient) Get(ctx context.Context, idOrName string) (*SSHKey, *Resp
|
||||
// SSHKeyListOpts specifies options for listing SSH keys.
|
||||
type SSHKeyListOpts struct {
|
||||
ListOpts
|
||||
Name string
|
||||
Fingerprint string
|
||||
}
|
||||
|
||||
func (l SSHKeyListOpts) values() url.Values {
|
||||
vals := l.ListOpts.values()
|
||||
if l.Name != "" {
|
||||
vals.Add("name", l.Name)
|
||||
}
|
||||
if l.Fingerprint != "" {
|
||||
vals.Add("fingerprint", l.Fingerprint)
|
||||
}
|
||||
return vals
|
||||
}
|
||||
|
||||
// List returns a list of SSH keys for a specific page.
|
||||
func (c *SSHKeyClient) List(ctx context.Context, opts SSHKeyListOpts) ([]*SSHKey, *Response, error) {
|
||||
path := "/ssh_keys?" + valuesForListOpts(opts.ListOpts).Encode()
|
||||
path := "/ssh_keys?" + opts.values().Encode()
|
||||
req, err := c.client.NewRequest(ctx, "GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@ -120,7 +111,7 @@ func (c *SSHKeyClient) List(ctx context.Context, opts SSHKeyListOpts) ([]*SSHKey
|
||||
|
||||
// All returns all SSH keys.
|
||||
func (c *SSHKeyClient) All(ctx context.Context) ([]*SSHKey, error) {
|
||||
return c.AllWithOpts(ctx, SSHKeyListOpts{ListOpts{PerPage: 50}})
|
||||
return c.AllWithOpts(ctx, SSHKeyListOpts{ListOpts: ListOpts{PerPage: 50}})
|
||||
}
|
||||
|
||||
// AllWithOpts returns all SSH keys with the given options.
|
||||
|
47
vendor/github.com/hetznercloud/hcloud-go/hcloud/volume.go
generated
vendored
47
vendor/github.com/hetznercloud/hcloud-go/hcloud/volume.go
generated
vendored
@ -36,6 +36,17 @@ type VolumeClient struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// VolumeStatus specifies a volume's status.
|
||||
type VolumeStatus string
|
||||
|
||||
const (
|
||||
// VolumeStatusCreating is the status when a volume is being created.
|
||||
VolumeStatusCreating VolumeStatus = "creating"
|
||||
|
||||
// VolumeStatusAvailable is the status when a volume is available.
|
||||
VolumeStatusAvailable VolumeStatus = "available"
|
||||
)
|
||||
|
||||
// GetByID retrieves a volume by its ID. If the volume does not exist, nil is returned.
|
||||
func (c *VolumeClient) GetByID(ctx context.Context, id int) (*Volume, *Response, error) {
|
||||
req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/volumes/%d", id), nil)
|
||||
@ -56,22 +67,11 @@ func (c *VolumeClient) GetByID(ctx context.Context, id int) (*Volume, *Response,
|
||||
|
||||
// GetByName retrieves a volume by its name. If the volume does not exist, nil is returned.
|
||||
func (c *VolumeClient) GetByName(ctx context.Context, name string) (*Volume, *Response, error) {
|
||||
path := "/volumes?name=" + url.QueryEscape(name)
|
||||
req, err := c.client.NewRequest(ctx, "GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
volumes, response, err := c.List(ctx, VolumeListOpts{Name: name})
|
||||
if len(volumes) == 0 {
|
||||
return nil, response, err
|
||||
}
|
||||
|
||||
var body schema.VolumeListResponse
|
||||
resp, err := c.client.Do(req, &body)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if len(body.Volumes) == 0 {
|
||||
return nil, resp, nil
|
||||
}
|
||||
return VolumeFromSchema(body.Volumes[0]), resp, nil
|
||||
return volumes[0], response, err
|
||||
}
|
||||
|
||||
// Get retrieves a volume by its ID if the input can be parsed as an integer, otherwise it
|
||||
@ -86,11 +86,24 @@ func (c *VolumeClient) Get(ctx context.Context, idOrName string) (*Volume, *Resp
|
||||
// VolumeListOpts specifies options for listing volumes.
|
||||
type VolumeListOpts struct {
|
||||
ListOpts
|
||||
Name string
|
||||
Status []VolumeStatus
|
||||
}
|
||||
|
||||
func (l VolumeListOpts) values() url.Values {
|
||||
vals := l.ListOpts.values()
|
||||
if l.Name != "" {
|
||||
vals.Add("name", l.Name)
|
||||
}
|
||||
for _, status := range l.Status {
|
||||
vals.Add("status", string(status))
|
||||
}
|
||||
return vals
|
||||
}
|
||||
|
||||
// List returns a list of volumes for a specific page.
|
||||
func (c *VolumeClient) List(ctx context.Context, opts VolumeListOpts) ([]*Volume, *Response, error) {
|
||||
path := "/volumes?" + valuesForListOpts(opts.ListOpts).Encode()
|
||||
path := "/volumes?" + opts.values().Encode()
|
||||
req, err := c.client.NewRequest(ctx, "GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@ -110,7 +123,7 @@ func (c *VolumeClient) List(ctx context.Context, opts VolumeListOpts) ([]*Volume
|
||||
|
||||
// All returns all volumes.
|
||||
func (c *VolumeClient) All(ctx context.Context) ([]*Volume, error) {
|
||||
return c.AllWithOpts(ctx, VolumeListOpts{ListOpts{PerPage: 50}})
|
||||
return c.AllWithOpts(ctx, VolumeListOpts{ListOpts: ListOpts{PerPage: 50}})
|
||||
}
|
||||
|
||||
// AllWithOpts returns all volumes with the given options.
|
||||
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@ -295,7 +295,7 @@ github.com/hashicorp/vault/helper/compressutil
|
||||
github.com/hashicorp/vault/helper/strutil
|
||||
# github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d
|
||||
github.com/hashicorp/yamux
|
||||
# github.com/hetznercloud/hcloud-go v1.12.0
|
||||
# github.com/hetznercloud/hcloud-go v1.15.1
|
||||
github.com/hetznercloud/hcloud-go/hcloud
|
||||
github.com/hetznercloud/hcloud-go/hcloud/schema
|
||||
# github.com/hyperonecom/h1-client-go v0.0.0-20190122232013-cf38e8387775
|
||||
|
@ -38,7 +38,8 @@ builder.
|
||||
- `token` (string) - The client TOKEN to use to access your account. It can
|
||||
also be specified via environment variable `HCLOUD_TOKEN`, if set.
|
||||
|
||||
- `image` (string) - ID or name of image to launch server from.
|
||||
- `image` (string) - ID or name of image to launch server from. Alternatively
|
||||
you can use `image_filter`.
|
||||
|
||||
- `location` (string) - The name of the location to launch the server in.
|
||||
|
||||
@ -51,6 +52,34 @@ builder.
|
||||
using a Hetzner Cloud API compatible service. It can also be specified via
|
||||
environment variable `HCLOUD_ENDPOINT`.
|
||||
|
||||
- `image_filter` (object) - Filters used to populate the `filter`
|
||||
field. Example:
|
||||
|
||||
``` json
|
||||
{
|
||||
"image_filter": {
|
||||
"with_selector": [
|
||||
"name==my-image"
|
||||
],
|
||||
"most_recent": true
|
||||
}
|
||||
```
|
||||
|
||||
This selects the most recent image with the label `name==my-image`. NOTE:
|
||||
This will fail unless *exactly* one AMI is returned. In the above example,
|
||||
`most_recent` will cause this to succeed by selecting the newest image.
|
||||
|
||||
- `with_selector` (list of strings) - label selectors used to select an
|
||||
`image`. NOTE: This will fail unless *exactly* one image is returned.
|
||||
Check the official hcloud docs on
|
||||
[Label Selectors](https://docs.hetzner.cloud/#overview-label-selector)
|
||||
for more info.
|
||||
|
||||
- `most_recent` (boolean) - Selects the newest created image when true.
|
||||
This is most useful if you base your image on another packer build image.
|
||||
|
||||
You may set this in place of `image`, but not both.
|
||||
|
||||
- `server_name` (string) - The name assigned to the server. The Hetzner Cloud
|
||||
sets the hostname of the machine to this value.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user