Update packer to Use ProfitBricks Image Alias feature

This commit is contained in:
Ali Bazlamit 2017-08-10 16:15:53 +03:00
parent eec162ee3c
commit c67d118523
25 changed files with 3209 additions and 603 deletions

View File

@ -76,7 +76,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
}
if c.PBUrl == "" {
c.PBUrl = "https://api.profitbricks.com/rest/v2"
c.PBUrl = "https://api.profitbricks.com/cloudapi/v4"
}
if c.Cores == 0 {

View File

@ -26,16 +26,18 @@ func (s *stepCreateServer) Run(state multistep.StateBag) multistep.StepAction {
}
ui.Say("Creating Virtual Data Center...")
img := s.getImageId(c.Image, c)
alias := ""
if img == "" {
alias = s.getImageAlias(c.Image, c.Region, ui)
}
datacenter := profitbricks.Datacenter{
Properties: profitbricks.DatacenterProperties{
Name: c.SnapshotName,
Location: c.Region,
},
Entities: profitbricks.DatacenterEntities{
Servers: &profitbricks.Servers{
Items: []profitbricks.Server{
{
}
server := profitbricks.Server{
Properties: profitbricks.ServerProperties{
Name: c.SnapshotName,
Ram: c.Ram,
@ -49,23 +51,20 @@ func (s *stepCreateServer) Run(state multistep.StateBag) multistep.StepAction {
Type: c.DiskType,
Size: c.DiskSize,
Name: c.SnapshotName,
ImageAlias: alias,
Image: img,
},
},
},
},
},
},
},
},
},
}
if c.SSHKey != "" {
datacenter.Entities.Servers.Items[0].Entities.Volumes.Items[0].Properties.SshKeys = []string{c.SSHKey}
server.Entities.Volumes.Items[0].Properties.SshKeys = []string{c.SSHKey}
}
if c.Comm.SSHPassword != "" {
datacenter.Entities.Servers.Items[0].Entities.Volumes.Items[0].Properties.ImagePassword = c.Comm.SSHPassword
server.Entities.Volumes.Items[0].Properties.ImagePassword = c.Comm.SSHPassword
}
datacenter = profitbricks.CompositeCreateDatacenter(datacenter)
@ -94,8 +93,20 @@ func (s *stepCreateServer) Run(state multistep.StateBag) multistep.StepAction {
state.Put("datacenter_id", datacenter.Id)
lan := profitbricks.CreateLan(datacenter.Id, profitbricks.Lan{
Properties: profitbricks.LanProperties{
server = profitbricks.CreateServer(datacenter.Id, server)
if server.StatusCode > 299 {
ui.Error(fmt.Sprintf("Error occurred %s", parseErrorMessage(server.Response)))
return multistep.ActionHalt
}
err = s.waitTillProvisioned(server.Headers.Get("Location"), *c)
if err != nil {
ui.Error(fmt.Sprintf("Error occurred while creating a server %s", err.Error()))
return multistep.ActionHalt
}
lan := profitbricks.CreateLan(datacenter.Id, profitbricks.CreateLanRequest{
Properties: profitbricks.CreateLanProperties{
Public: true,
Name: c.SnapshotName,
},
@ -113,8 +124,8 @@ func (s *stepCreateServer) Run(state multistep.StateBag) multistep.StepAction {
}
lanId, _ := strconv.Atoi(lan.Id)
nic := profitbricks.CreateNic(datacenter.Id, datacenter.Entities.Servers.Items[0].Id, profitbricks.Nic{
Properties: profitbricks.NicProperties{
nic := profitbricks.CreateNic(datacenter.Id, server.Id, profitbricks.Nic{
Properties: &profitbricks.NicProperties{
Name: c.SnapshotName,
Lan: lanId,
Dhcp: true,
@ -132,9 +143,9 @@ func (s *stepCreateServer) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionHalt
}
state.Put("volume_id", datacenter.Entities.Servers.Items[0].Entities.Volumes.Items[0].Id)
state.Put("volume_id", server.Entities.Volumes.Items[0].Id)
server := profitbricks.GetServer(datacenter.Id, datacenter.Entities.Servers.Items[0].Id)
server = profitbricks.GetServer(datacenter.Id, server.Id)
state.Put("server_ip", server.Entities.Nics.Items[0].Properties.Ips[0])
@ -225,6 +236,25 @@ func (d *stepCreateServer) getImageId(imageName string, c *Config) string {
return ""
}
func (d *stepCreateServer) getImageAlias(imageAlias string, location string, ui packer.Ui) string {
if imageAlias == "" {
return ""
}
locations := profitbricks.GetLocation(location)
if len(locations.Properties.ImageAliases) > 0 {
for _, i := range locations.Properties.ImageAliases {
alias := ""
if i != "" {
alias = i
}
if alias != "" && strings.ToLower(alias) == strings.ToLower(imageAlias) {
return alias
}
}
}
return ""
}
func parseErrorMessage(raw string) (toreturn string) {
var tmp map[string]interface{}
json.Unmarshal([]byte(raw), &tmp)

View File

@ -22,7 +22,7 @@ func (s *stepTakeSnapshot) Run(state multistep.StateBag) multistep.StepAction {
dcId := state.Get("datacenter_id").(string)
volumeId := state.Get("volume_id").(string)
snapshot := profitbricks.CreateSnapshot(dcId, volumeId, c.SnapshotName)
snapshot := profitbricks.CreateSnapshot(dcId, volumeId, c.SnapshotName, "")
state.Put("snapshotname", c.SnapshotName)

View File

@ -1,33 +0,0 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
*.prof
/.idea/
.idea/compiler.xml
.idea/copyright/
.idea/encodings.xml
.idea/misc.xml
.idea/modules.xml
.idea/profitbricks-sdk-go.iml
.idea/vcs.xml
.idea/workspace.xml

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
package profitbricks
// Endpoint is the base url for REST requests.
var Endpoint = "https://api.profitbricks.com/rest/v2"
var Endpoint = "https://api.profitbricks.com/cloudapi/v4"
// Username for authentication .
var Username string
@ -11,7 +11,9 @@ var Passwd string
// SetEndpoint is used to set the REST Endpoint. Endpoint is declared in config.go
func SetEndpoint(newendpoint string) string {
if newendpoint != "" {
Endpoint = newendpoint
}
return Endpoint
}
@ -21,3 +23,7 @@ func SetAuth(u, p string) {
Username = u
Passwd = p
}
func SetUserAgent(userAgent string) {
AgentHeader = userAgent
}

View File

@ -0,0 +1,60 @@
package profitbricks
import (
"encoding/json"
"net/http"
"strconv"
)
type ContractResources struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Properties ContractResourcesProperties `json:"properties,omitempty"`
Response string `json:"Response,omitempty"`
Headers *http.Header `json:"headers,omitempty"`
StatusCode int `json:"headers,omitempty"`
}
type ContractResourcesProperties struct {
PBContractNumber string `json:"PB-Contract-Number,omitempty"`
Owner string `json:"owner,omitempty"`
Status string `json:"status,omitempty"`
ResourceLimits *ResourcesLimits `json:"resourceLimits,omitempty"`
}
type ResourcesLimits struct {
CoresPerServer int32 `json:"coresPerServer,omitempty"`
CoresPerContract int32 `json:"coresPerContract,omitempty"`
CoresProvisioned int32 `json:"coresProvisioned,omitempty"`
RamPerServer int32 `json:"ramPerServer,omitempty"`
RamPerContract int32 `json:"ramPerContract,omitempty"`
RamProvisioned int32 `json:"ramProvisioned,omitempty"`
HddLimitPerVolume int64 `json:"hddLimitPerVolume,omitempty"`
HddLimitPerContract int64 `json:"hddLimitPerContract,omitempty"`
HddVolumeProvisioned int64 `json:"hddVolumeProvisioned,omitempty"`
SsdLimitPerVolume int64 `json:"ssdLimitPerVolume,omitempty"`
SsdLimitPerContract int64 `json:"ssdLimitPerContract,omitempty"`
SsdVolumeProvisioned int64 `json:"ssdVolumeProvisioned,omitempty"`
ReservableIps int32 `json:"reservableIps,omitempty"`
ReservedIpsOnContract int32 `json:"reservedIpsOnContract,omitempty"`
ReservedIpsInUse int32 `json:"reservedIpsInUse,omitempty"`
}
func GetContractResources() ContractResources {
path := contract_resource_path()
url := mk_url(path) + `?depth=` + Depth + `&pretty=` + strconv.FormatBool(Pretty)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Content-Type", FullHeader)
resp := do(req)
return toContractResources(resp)
}
func toContractResources(resp Resp) ContractResources {
var col ContractResources
json.Unmarshal(resp.Body, &col)
col.Response = string(resp.Body)
col.Headers = &resp.Headers
col.StatusCode = resp.StatusCode
return col
}

View File

@ -11,7 +11,7 @@ type Datacenter struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Metadata *DatacenterElementMetadata `json:"metadata,omitempty"`
Metadata *Metadata `json:"metadata,omitempty"`
Properties DatacenterProperties `json:"properties,omitempty"`
Entities DatacenterEntities `json:"entities,omitempty"`
Response string `json:"Response,omitempty"`
@ -19,7 +19,7 @@ type Datacenter struct {
StatusCode int `json:"headers,omitempty"`
}
type DatacenterElementMetadata struct {
type Metadata struct {
CreatedDate time.Time `json:"createdDate,omitempty"`
CreatedBy string `json:"createdBy,omitempty"`
Etag string `json:"etag,omitempty"`

View File

@ -10,7 +10,7 @@ type FirewallRule struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Metadata *DatacenterElementMetadata `json:"metadata,omitempty"`
Metadata *Metadata `json:"metadata,omitempty"`
Properties FirewallruleProperties `json:"properties,omitempty"`
Response string `json:"Response,omitempty"`
Headers *http.Header `json:"headers,omitempty"`
@ -20,13 +20,13 @@ type FirewallRule struct {
type FirewallruleProperties struct {
Name string `json:"name,omitempty"`
Protocol string `json:"protocol,omitempty"`
SourceMac string `json:"sourceMac,omitempty"`
SourceIp string `json:"sourceIp,omitempty"`
TargetIp string `json:"targetIp,omitempty"`
IcmpCode int `json:"icmpCode,omitempty"`
IcmpType int `json:"icmpType,omitempty"`
PortRangeStart int `json:"portRangeStart,omitempty"`
PortRangeEnd int `json:"portRangeEnd,omitempty"`
SourceMac *string `json:"sourceMac,omitempty"`
SourceIp *string `json:"sourceIp,omitempty"`
TargetIp *string `json:"targetIp,omitempty"`
IcmpCode *int `json:"icmpCode,omitempty"`
IcmpType *int `json:"icmpType,omitempty"`
PortRangeStart *int `json:"portRangeStart,omitempty"`
PortRangeEnd *int `json:"portRangeEnd,omitempty"`
}
type FirewallRules struct {

View File

@ -9,7 +9,7 @@ type Image struct {
Id string `json:"id,omitempty"`
Type string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Metadata *DatacenterElementMetadata `json:"metadata,omitempty"`
Metadata *Metadata `json:"metadata,omitempty"`
Properties ImageProperties `json:"properties,omitempty"`
Response string `json:"Response,omitempty"`
Headers *http.Header `json:"headers,omitempty"`

View File

@ -10,7 +10,7 @@ type IpBlock struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Metadata *DatacenterElementMetadata `json:"metadata,omitempty"`
Metadata *Metadata `json:"metadata,omitempty"`
Properties IpBlockProperties `json:"properties,omitempty"`
Response string `json:"Response,omitempty"`
Headers *http.Header `json:"headers,omitempty"`
@ -18,6 +18,7 @@ type IpBlock struct {
}
type IpBlockProperties struct {
Name string `json:"name,omitempty"`
Ips []string `json:"ips,omitempty"`
Location string `json:"location,omitempty"`
Size int `json:"size,omitempty"`

View File

@ -6,11 +6,28 @@ import (
"net/http"
)
type CreateLanRequest struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Metadata *Metadata `json:"metadata,omitempty"`
Properties CreateLanProperties `json:"properties,omitempty"`
Entities *LanEntities `json:"entities,omitempty"`
Response string `json:"Response,omitempty"`
Headers *http.Header `json:"headers,omitempty"`
StatusCode int `json:"headers,omitempty"`
}
type CreateLanProperties struct {
Name string `json:"name,omitempty"`
Public bool `json:"public,omitempty"`
}
type Lan struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Metadata *DatacenterElementMetadata `json:"metadata,omitempty"`
Metadata *Metadata `json:"metadata,omitempty"`
Properties LanProperties `json:"properties,omitempty"`
Entities *LanEntities `json:"entities,omitempty"`
Response string `json:"Response,omitempty"`
@ -21,12 +38,18 @@ type Lan struct {
type LanProperties struct {
Name string `json:"name,omitempty"`
Public bool `json:"public,omitempty"`
IpFailover []IpFailover `json:"ipFailover"`
}
type LanEntities struct {
Nics *LanNics `json:"nics,omitempty"`
}
type IpFailover struct {
NicUuid string `json:"nicUuid,omitempty"`
Ip string `json:"ip,omitempty"`
}
type LanNics struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
@ -55,7 +78,7 @@ func ListLans(dcid string) Lans {
// CreateLan creates a lan in the datacenter
// from a jason []byte and returns a Instance struct
func CreateLan(dcid string, request Lan) Lan {
func CreateLan(dcid string, request CreateLanRequest) Lan {
obj, _ := json.Marshal(request)
path := lan_col_path(dcid)
url := mk_url(path)

View File

@ -10,7 +10,7 @@ type Loadbalancer struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Metadata *DatacenterElementMetadata `json:"metadata,omitempty"`
Metadata *Metadata `json:"metadata,omitempty"`
Properties LoadbalancerProperties `json:"properties,omitempty"`
Entities LoadbalancerEntities `json:"entities,omitempty"`
Response string `json:"Response,omitempty"`

View File

@ -9,8 +9,8 @@ type Location struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Metadata DatacenterElementMetadata `json:"metadata,omitempty"`
Properties Properties `json:"properties,omitempty"`
Metadata Metadata `json:"metadata,omitempty"`
Properties LocationProperties `json:"properties,omitempty"`
Response string `json:"Response,omitempty"`
Headers *http.Header `json:"headers,omitempty"`
StatusCode int `json:"headers,omitempty"`
@ -26,8 +26,10 @@ type Locations struct {
StatusCode int `json:"headers,omitempty"`
}
type Properties struct {
type LocationProperties struct {
Name string `json:"name,omitempty"`
Features []string `json:"features,omitempty"`
ImageAliases []string `json:"imageAliases,omitempty"`
}
// ListLocations returns location collection data
@ -38,6 +40,14 @@ func ListLocations() Locations {
return toLocations(do(req))
}
// GetRegionalLocations returns a list of available locations in a specific region
func GetRegionalLocations(regid string) Locations {
url := mk_url(location_reg_path(regid)) + `?depth=` + Depth
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Content-Type", FullHeader)
return toLocations(do(req))
}
// GetLocation returns location data
func GetLocation(locid string) Location {
url := mk_url(location_path(locid)) + `?depth=` + Depth

View File

@ -10,8 +10,8 @@ type Nic struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Metadata *DatacenterElementMetadata `json:"metadata,omitempty"`
Properties NicProperties `json:"properties,omitempty"`
Metadata *Metadata `json:"metadata,omitempty"`
Properties *NicProperties `json:"properties,omitempty"`
Entities *NicEntities `json:"entities,omitempty"`
Response string `json:"Response,omitempty"`
Headers *http.Header `json:"headers,omitempty"`
@ -22,9 +22,10 @@ type NicProperties struct {
Name string `json:"name,omitempty"`
Mac string `json:"mac,omitempty"`
Ips []string `json:"ips,omitempty"`
Dhcp bool `json:"dhcp,omitempty"`
Dhcp bool `json:"dhcp"`
Lan int `json:"lan,omitempty"`
FirewallActive bool `json:"firewallActive,omitempty"`
Nat bool `json:"nat,omitempty"`
}
type NicEntities struct {
@ -56,8 +57,8 @@ func ListNics(dcid, srvid string) Nics {
// CreateNic creates a nic on a server
// from a jason []byte and returns a Instance struct
func CreateNic(dcid string, srvid string, request Nic) Nic {
obj, _ := json.Marshal(request)
func CreateNic(dcid string, srvid string, nic Nic) Nic {
obj, _ := json.Marshal(nic)
path := nic_col_path(dcid, srvid)
url := mk_url(path) + `?depth=` + Depth
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(obj))

View File

@ -45,19 +45,9 @@ func location_path(locid string) string {
return location_col_path() + slash(locid)
}
// request_col_path returns the string "/requests"
func request_col_path() string {
return slash("requests")
}
// request_path returns the string "/requests/<requestid>"
func request_path(requestid string) string {
return request_col_path() + slash(requestid)
}
// request_status_path returns the string "/requests<requestid>/status"
func request_status_path(requestid string) string {
return request_path(requestid) + slash("status")
// location_path returns the string "/locations/<regid>"
func location_reg_path(regid string) string {
return location_col_path() + slash(regid)
}
// snapshot_col_path returns the string "/snapshots"
@ -65,11 +55,6 @@ func snapshot_col_path() string {
return slash("snapshots")
}
// snapshot_path returns the string "/snapshots/<snapid>"
func snapshot_path(snapid string) string {
return snapshot_col_path() + slash(snapid)
}
// lan_col_path returns the string "/datacenters/<dcid>/lans"
func lan_col_path(dcid string) string {
return dc_path(dcid) + slash("lans")
@ -115,12 +100,6 @@ func volume_path(dcid, volid string) string {
return volume_col_path(dcid) + slash(volid)
}
// lan_nic_col_path returns the string /datacenters/<dcid>/lans/<lanid>/nics
func lan_nic_col(dcid, lanid string) string {
return lan_path(dcid, lanid) + slash("nics")
}
// balnic_col_path returns the string "/loadbalancers/<lbalid>/balancednics"
func balnic_col_path(dcid, lbalid string) string {
return lbal_path(dcid, lbalid) + slash("balancednics")
@ -171,3 +150,67 @@ func fwrule_col_path(dcid, srvid, nicid string) string {
func fwrule_path(dcid, srvid, nicid, fwruleid string) string {
return fwrule_col_path(dcid, srvid, nicid) + slash(fwruleid)
}
// contract_resource_path returns the string "/contracts"
func contract_resource_path() string {
return slash("contracts")
}
func um() string {
return slash("um")
}
// um_groups returns the string "/groups"
func um_groups() string {
return um() + slash("groups")
}
// um_group_path returns the string "/groups/groupid"
func um_group_path(grpid string) string {
return um_groups() + slash(grpid)
}
// um_group_shares returns the string "groups/{groupId}/shares"
func um_group_shares(grpid string) string {
return um() + slash("groups") + slash(grpid) + slash("shares")
}
// um_group_share_path returns the string "groups/{groupId}/shares/{resourceId}"
func um_group_share_path(grpid string, resourceid string) string {
return um() + slash("groups") + slash(grpid) + slash("shares") + slash(resourceid)
}
// um_group_users returns the string "/groups/groupid/users"
func um_group_users(grpid string) string {
return um() + slash("groups") + slash(grpid) + slash("users")
}
// um_group_users_path returns the string "/groups/groupid/users/userid"
func um_group_users_path(grpid string, usrid string) string {
return um() + slash("groups") + slash(grpid) + slash("users") + slash(usrid)
}
// um_users returns the string "/users"
func um_users() string {
return um() + slash("users")
}
// um_users returns the string "/users/usrid"
func um_users_path(usrid string) string {
return um() + slash("users") + slash(usrid)
}
// um_resources returns the string "/resources"
func um_resources() string {
return um() + slash("resources")
}
// um_resources_type returns the string "/resources/resourceType"
func um_resources_type(restype string) string {
return um() + slash("resources") + slash(restype)
}
// um_resources_type_path returns the string "resources/{resourceType}/{resourceId}"
func um_resources_type_path(restype string, resourceid string) string {
return um() + slash("resources") + slash(restype) + slash(resourceid)
}

View File

@ -9,15 +9,18 @@ import (
)
//FullHeader is the standard header to include with all http requests except is_patch and is_command
const FullHeader = "application/vnd.profitbricks.resource+json"
const FullHeader = "application/json"
var AgentHeader = "profitbricks-sdk-go/3.0.1"
//PatchHeader is used with is_patch .
const PatchHeader = "application/vnd.profitbricks.partial-properties+json"
const PatchHeader = "application/json"
//CommandHeader is used with is_command
const CommandHeader = "application/x-www-form-urlencoded"
var Depth = "5"
var Pretty = true
// SetDepth is used to set Depth
func SetDepth(newdepth string) string {
@ -25,6 +28,12 @@ func SetDepth(newdepth string) string {
return Depth
}
// SetDepth is used to set Depth
func SetPretty(pretty bool) bool {
Pretty = pretty
return Pretty
}
// mk_url either:
// returns the path (if it`s a full url)
// or
@ -32,7 +41,8 @@ func SetDepth(newdepth string) string {
func mk_url(path string) string {
if strings.HasPrefix(path, "http") {
//REMOVE AFTER TESTING
path := strings.Replace(path, "https://api.profitbricks.com/rest/v2", Endpoint, 1)
//FIXME @jasmin Is this still relevant?
path := strings.Replace(path, "https://api.profitbricks.com/cloudapi/v3", Endpoint, 1)
// END REMOVE
return path
}
@ -48,6 +58,7 @@ func mk_url(path string) string {
func do(req *http.Request) Resp {
client := &http.Client{}
req.SetBasicAuth(Username, Passwd)
req.Header.Add("User-Agent", AgentHeader)
resp, err := client.Do(req)
if err != nil {
panic(err)
@ -67,6 +78,7 @@ func is_delete(path string) Resp {
url := mk_url(path)
req, _ := http.NewRequest("DELETE", url, nil)
req.Header.Add("Content-Type", FullHeader)
req.Header.Add("User-Agent", AgentHeader)
return do(req)
}
@ -76,5 +88,6 @@ func is_command(path string, jason string) Resp {
body := json.RawMessage(jason)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(body))
req.Header.Add("Content-Type", CommandHeader)
req.Header.Add("User-Agent", AgentHeader)
return do(req)
}

View File

@ -3,6 +3,7 @@ package profitbricks
import (
"encoding/json"
"net/http"
"time"
)
type RequestStatus struct {
@ -26,6 +27,55 @@ type RequestTarget struct {
Status string `json:"status,omitempty"`
}
type Requests struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Items []Request `json:"items,omitempty"`
Response string `json:"Response,omitempty"`
Headers *http.Header `json:"headers,omitempty"`
StatusCode int `json:"headers,omitempty"`
}
type Request struct {
ID string `json:"id"`
Type string `json:"type"`
Href string `json:"href"`
Metadata struct {
CreatedDate time.Time `json:"createdDate"`
CreatedBy string `json:"createdBy"`
Etag string `json:"etag"`
RequestStatus struct {
ID string `json:"id"`
Type string `json:"type"`
Href string `json:"href"`
} `json:"requestStatus"`
} `json:"metadata"`
Properties struct {
Method string `json:"method"`
Headers interface{} `json:"headers"`
Body interface{} `json:"body"`
URL string `json:"url"`
} `json:"properties"`
Response string `json:"Response,omitempty"`
Headers *http.Header `json:"headers,omitempty"`
StatusCode int `json:"headers,omitempty"`
}
func ListRequests() Requests {
url := mk_url("/requests") + `?depth=` + Depth
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Content-Type", FullHeader)
return toRequests(do(req))
}
func GetRequest(req_id string) Request {
url := mk_url("/requests/"+req_id) + `?depth=` + Depth
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Content-Type", FullHeader)
return toRequest(do(req))
}
func GetRequestStatus(path string) RequestStatus {
url := mk_url(path) + `?depth=` + Depth
req, _ := http.NewRequest("GET", url, nil)
@ -41,3 +91,21 @@ func toRequestStatus(resp Resp) RequestStatus {
server.StatusCode = resp.StatusCode
return server
}
func toRequests(resp Resp) Requests {
var server Requests
json.Unmarshal(resp.Body, &server)
server.Response = string(resp.Body)
server.Headers = &resp.Headers
server.StatusCode = resp.StatusCode
return server
}
func toRequest(resp Resp) Request {
var server Request
json.Unmarshal(resp.Body, &server)
server.Response = string(resp.Body)
server.Headers = &resp.Headers
server.StatusCode = resp.StatusCode
return server
}

View File

@ -15,13 +15,6 @@ func MkJson(i interface{}) string {
return string(jason)
}
// MetaData is a map for metadata returned in a Resp.Body
type StringMap map[string]string
type StringIfaceMap map[string]interface{}
type StringCollectionMap map[string]Collection
// Resp is the struct returned by all Rest request functions
type Resp struct {
Req *http.Request
@ -37,25 +30,3 @@ func (r *Resp) PrintHeaders() {
}
}
type Id_Type_Href struct {
Id string `json:"id"`
Type string `json:"type"`
Href string `json:"href"`
}
type MetaData StringIfaceMap
type Instance struct {
Id_Type_Href
MetaData StringMap `json:"metaData,omitempty"`
Properties StringIfaceMap `json:"properties,omitempty"`
Entities StringCollectionMap `json:"entities,omitempty"`
Resp Resp `json:"-"`
}
type Collection struct {
Id_Type_Href
Items []Instance `json:"items,omitempty"`
Resp Resp `json:"-"`
}

View File

@ -3,7 +3,6 @@ package profitbricks
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
@ -11,7 +10,7 @@ type Server struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Metadata *DatacenterElementMetadata `json:"metadata,omitempty"`
Metadata *Metadata `json:"metadata,omitempty"`
Properties ServerProperties `json:"properties,omitempty"`
Entities *ServerEntities `json:"entities,omitempty"`
Response string `json:"Response,omitempty"`
@ -81,7 +80,6 @@ func GetServer(dcid, srvid string) Server {
path := server_path(dcid, srvid)
url := mk_url(path) + `?depth=` + Depth
req, _ := http.NewRequest("GET", url, nil)
fmt.Println(path)
req.Header.Add("Content-Type", FullHeader)
return toServer(do(req))
}

View File

@ -10,7 +10,7 @@ type Snapshot struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Metadata DatacenterElementMetadata `json:"metadata,omitempty"`
Metadata Metadata `json:"metadata,omitempty"`
Properties SnapshotProperties `json:"properties,omitempty"`
Response string `json:"Response,omitempty"`
Headers *http.Header `json:"headers,omitempty"`

View File

@ -2,9 +2,48 @@ package profitbricks
import (
"fmt"
"os"
"strings"
"time"
)
func mkVolume(dcID string) string {
var request = Volume{
Properties: VolumeProperties{
Size: 2,
Name: "Volume Test",
Type: "HDD",
ImagePassword: "test1234",
ImageAlias: "ubuntu:latest",
},
}
resp := CreateVolume(dcID, request)
waitTillProvisioned(resp.Headers.Get("Location"))
return resp.Id
}
func mkipid(name string) string {
var obj = IpBlock{
Properties: IpBlockProperties{
Name: "GO SDK Test",
Size: 1,
Location: "us/las",
},
}
resp := ReserveIpBlock(obj)
return resp.Id
}
func mksnapshotId(name string, dcId string) string {
svolumeId := mkVolume(dcId)
resp := CreateSnapshot(dcId, svolumeId, name, "description")
waitTillProvisioned(resp.Headers.Get("Location"))
return resp.Id
}
func mkdcid(name string) string {
request := Datacenter{
Properties: DatacenterProperties{
@ -14,11 +53,6 @@ func mkdcid(name string) string {
},
}
dc := CreateDatacenter(request)
fmt.Println("===========================")
fmt.Println("Created a DC " + name)
fmt.Println("Created a DC id " + dc.Id)
fmt.Println(dc.StatusCode)
fmt.Println("===========================")
return dc.Id
}
@ -31,42 +65,82 @@ func mksrvid(srv_dcid string) string {
},
}
srv := CreateServer(srv_dcid, req)
fmt.Println("===========================")
fmt.Println("Created a server " + srv.Id)
fmt.Println(srv.StatusCode)
fmt.Println("===========================")
waitTillProvisioned(srv.Headers.Get("Location"))
return srv.Id
}
func mknic(lbal_dcid, serverid string) string {
var request = Nic{
Properties: NicProperties{
Name: "GO SDK Original Nic",
Properties: &NicProperties{
Lan: 1,
Name: "GO SDK Test",
Nat: false,
Dhcp: true,
FirewallActive: true,
Ips: []string{"10.0.0.1"},
},
}
resp := CreateNic(lbal_dcid, serverid, request)
fmt.Println("===========================")
fmt.Println("created a nic at server " + serverid)
waitTillProvisioned(resp.Headers.Get("Location"))
return resp.Id
}
fmt.Println("created a nic with id " + resp.Id)
fmt.Println(resp.StatusCode)
fmt.Println("===========================")
func mknic_custom(lbal_dcid, serverid string, lanid int, ips []string) string {
var request = Nic{
Properties: &NicProperties{
Lan: lanid,
Name: "GO SDK Test",
Nat: false,
Dhcp: true,
FirewallActive: true,
Ips: ips,
},
}
resp := CreateNic(lbal_dcid, serverid, request)
waitTillProvisioned(resp.Headers.Get("Location"))
return resp.Id
}
func waitTillProvisioned(path string) {
waitCount := 20
fmt.Println(path)
waitCount := 120
for i := 0; i < waitCount; i++ {
request := GetRequestStatus(path)
if request.Metadata.Status == "DONE" {
break
}
time.Sleep(10 * time.Second)
time.Sleep(1 * time.Second)
i++
}
}
func getImageId(location string, imageName string, imageType string) string {
if imageName == "" {
return ""
}
SetAuth(os.Getenv("PROFITBRICKS_USERNAME"), os.Getenv("PROFITBRICKS_PASSWORD"))
images := ListImages()
if images.StatusCode > 299 {
fmt.Printf("Error while fetching the list of images %s", images.Response)
}
if len(images.Items) > 0 {
for _, i := range images.Items {
imgName := ""
if i.Properties.Name != "" {
imgName = i.Properties.Name
}
if imageType == "SSD" {
imageType = "HDD"
}
if imgName != "" && strings.Contains(strings.ToLower(imgName), strings.ToLower(imageName)) && i.Properties.ImageType == imageType && i.Properties.Location == location && i.Properties.Public == true {
return i.Id
}
}
}
return ""
}

View File

@ -0,0 +1,402 @@
package profitbricks
import (
"bytes"
"encoding/json"
"net/http"
"strconv"
)
type Groups struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Items []Group `json:"items,omitempty"`
Response string `json:"Response,omitempty"`
Headers *http.Header `json:"headers,omitempty"`
StatusCode int `json:"headers,omitempty"`
}
type Group struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Properties GroupProperties `json:"properties,omitempty"`
Entities *GroupEntities `json:"entities,omitempty"`
Response string `json:"Response,omitempty"`
Headers *http.Header `json:"headers,omitempty"`
StatusCode int `json:"headers,omitempty"`
}
type GroupProperties struct {
Name string `json:"name,omitempty"`
CreateDataCenter *bool `json:"createDataCenter,omitempty"`
CreateSnapshot *bool `json:"createSnapshot,omitempty"`
ReserveIp *bool `json:"reserveIp,omitempty"`
AccessActivityLog *bool `json:"accessActivityLog,omitempty"`
}
type GroupEntities struct {
Users Users `json:"users,omitempty"`
Resources Resources `json:"resources,omitempty"`
}
type Users struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Items []User `json:"items,omitempty"`
Response string `json:"Response,omitempty"`
Headers *http.Header `json:"headers,omitempty"`
StatusCode int `json:"headers,omitempty"`
}
type User struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Metadata *Metadata `json:"metadata,omitempty"`
Properties *UserProperties `json:"properties,omitempty"`
Entities *UserEntities `json:"entities,omitempty"`
Response string `json:"Response,omitempty"`
Headers *http.Header `json:"headers,omitempty"`
StatusCode int `json:"headers,omitempty"`
}
type UserProperties struct {
Firstname string `json:"firstname,omitempty"`
Lastname string `json:"lastname,omitempty"`
Email string `json:"email,omitempty"`
Password string `json:"password,omitempty"`
Administrator bool `json:"administrator,omitempty"`
ForceSecAuth bool `json:"forceSecAuth,omitempty"`
SecAuthActive bool `json:"secAuthActive,omitempty"`
}
type UserEntities struct {
Groups Groups `json:"groups,omitempty"`
Owns Owns `json:"owns,omitempty"`
}
type Resources struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Items []Resource `json:"items,omitempty"`
Response string `json:"Response,omitempty"`
Headers *http.Header `json:"headers,omitempty"`
StatusCode int `json:"headers,omitempty"`
}
type Resource struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Metadata *Metadata `json:"metadata,omitempty"`
Entities *ResourceEntities `json:"entities,omitempty"`
Response string `json:"Response,omitempty"`
Headers *http.Header `json:"headers,omitempty"`
StatusCode int `json:"headers,omitempty"`
}
type ResourceEntities struct {
Groups Groups `json:"groups,omitempty"`
}
type Owns struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Items []Entity `json:"items,omitempty"`
Response string `json:"Response,omitempty"`
Headers *http.Header `json:"headers,omitempty"`
StatusCode int `json:"headers,omitempty"`
}
type Entity struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Metadata *Metadata `json:"metadata,omitempty"`
Response string `json:"Response,omitempty"`
Headers *http.Header `json:"headers,omitempty"`
StatusCode int `json:"headers,omitempty"`
}
type Shares struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Items []Share `json:"items,omitempty"`
Response string `json:"Response,omitempty"`
Headers *http.Header `json:"headers,omitempty"`
StatusCode int `json:"headers,omitempty"`
}
type Share struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Properties ShareProperties `json:"properties,omitempty"`
Response string `json:"Response,omitempty"`
Headers *http.Header `json:"headers,omitempty"`
StatusCode int `json:"headers,omitempty"`
}
type ShareProperties struct {
EditPrivilege *bool `json:"editPrivilege,omitempty"`
SharePrivilege *bool `json:"sharePrivilege,omitempty"`
}
//Group fucntions
func ListGroups() Groups {
path := um_groups()
url := mk_url(path) + `?depth=` + Depth + `&pretty=` + strconv.FormatBool(Pretty)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Content-Type", FullHeader)
resp := do(req)
return toGroups(resp)
}
func GetGroup(groupid string) Group {
path := um_group_path(groupid)
url := mk_url(path) + `?depth=` + Depth + `&pretty=` + strconv.FormatBool(Pretty)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Content-Type", FullHeader)
return toGroup(do(req))
}
func CreateGroup(grp Group) Group {
obj, _ := json.Marshal(grp)
path := um_groups()
url := mk_url(path)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(obj))
req.Header.Add("Content-Type", FullHeader)
return toGroup(do(req))
}
func UpdateGroup(groupid string, obj Group) Group {
jason_patch := []byte(MkJson(obj))
path := um_group_path(groupid)
url := mk_url(path) + `?depth=` + Depth
req, _ := http.NewRequest("PUT", url, bytes.NewBuffer(jason_patch))
req.Header.Add("Content-Type", PatchHeader)
return toGroup(do(req))
}
func DeleteGroup(groupid string) Resp {
path := um_group_path(groupid)
return is_delete(path)
}
func toGroup(resp Resp) Group {
var grp Group
json.Unmarshal(resp.Body, &grp)
grp.Response = string(resp.Body)
grp.Headers = &resp.Headers
grp.StatusCode = resp.StatusCode
return grp
}
func toGroups(resp Resp) Groups {
var col Groups
json.Unmarshal(resp.Body, &col)
col.Response = string(resp.Body)
col.Headers = &resp.Headers
col.StatusCode = resp.StatusCode
return col
}
//Shares functions
func ListShares(grpid string) Shares {
path := um_group_shares(grpid)
url := mk_url(path) + `?depth=` + Depth + `&pretty=` + strconv.FormatBool(Pretty)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Content-Type", FullHeader)
resp := do(req)
return toShares(resp)
}
func GetShare(groupid string, resourceid string) Share {
path := um_group_share_path(groupid, resourceid)
url := mk_url(path) + `?depth=` + Depth + `&pretty=` + strconv.FormatBool(Pretty)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Content-Type", FullHeader)
return toShare(do(req))
}
func AddShare(share Share, groupid string, resourceid string) Share {
obj, _ := json.Marshal(share)
path := um_group_share_path(groupid, resourceid)
url := mk_url(path)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(obj))
req.Header.Add("Content-Type", FullHeader)
return toShare(do(req))
}
func UpdateShare(groupid string, resourceid string, obj Share) Share {
jason_patch := []byte(MkJson(obj))
path := um_group_share_path(groupid, resourceid)
url := mk_url(path) + `?depth=` + Depth
req, _ := http.NewRequest("PUT", url, bytes.NewBuffer(jason_patch))
req.Header.Add("Content-Type", PatchHeader)
return toShare(do(req))
}
func DeleteShare(groupid string, resourceid string) Resp {
path := um_group_share_path(groupid, resourceid)
return is_delete(path)
}
func toShare(resp Resp) Share {
var shr Share
json.Unmarshal(resp.Body, &shr)
shr.Response = string(resp.Body)
shr.Headers = &resp.Headers
shr.StatusCode = resp.StatusCode
return shr
}
func toShares(resp Resp) Shares {
var col Shares
json.Unmarshal(resp.Body, &col)
col.Response = string(resp.Body)
col.Headers = &resp.Headers
col.StatusCode = resp.StatusCode
return col
}
//Users in a group
func ListGroupUsers(groupid string) Users {
path := um_group_users(groupid)
url := mk_url(path) + `?depth=` + Depth + `&pretty=` + strconv.FormatBool(Pretty)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Content-Type", FullHeader)
resp := do(req)
return toUsers(resp)
}
func AddUserToGroup(groupid string, userid string) User {
var usr User
usr.Id = userid
obj, _ := json.Marshal(usr)
path := um_group_users(groupid)
url := mk_url(path)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(obj))
req.Header.Add("Content-Type", FullHeader)
return toUser(do(req))
}
func DeleteUserFromGroup(groupid string, userid string) Resp {
path := um_group_users_path(groupid, userid)
return is_delete(path)
}
func toUser(resp Resp) User {
var usr User
json.Unmarshal(resp.Body, &usr)
usr.Response = string(resp.Body)
usr.Headers = &resp.Headers
usr.StatusCode = resp.StatusCode
return usr
}
func toUsers(resp Resp) Users {
var col Users
json.Unmarshal(resp.Body, &col)
col.Response = string(resp.Body)
col.Headers = &resp.Headers
col.StatusCode = resp.StatusCode
return col
}
//Users
func ListUsers() Users {
path := um_users()
url := mk_url(path) + `?depth=` + Depth + `&pretty=` + strconv.FormatBool(Pretty)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Content-Type", FullHeader)
resp := do(req)
return toUsers(resp)
}
func GetUser(usrid string) User {
path := um_users_path(usrid)
url := mk_url(path) + `?depth=` + Depth + `&pretty=` + strconv.FormatBool(Pretty)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Content-Type", FullHeader)
return toUser(do(req))
}
func CreateUser(usr User) User {
obj, _ := json.Marshal(usr)
path := um_users()
url := mk_url(path)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(obj))
req.Header.Add("Content-Type", FullHeader)
return toUser(do(req))
}
func UpdateUser(userid string, obj User) User {
jason_patch := []byte(MkJson(obj))
path := um_users_path(userid)
url := mk_url(path)
req, _ := http.NewRequest("PUT", url, bytes.NewBuffer(jason_patch))
req.Header.Add("Content-Type", PatchHeader)
return toUser(do(req))
}
func DeleteUser(groupid string) Resp {
path := um_users_path(groupid)
return is_delete(path)
}
//Resources
func ListResources() Resources {
path := um_resources()
url := mk_url(path) + `?depth=` + Depth + `&pretty=` + strconv.FormatBool(Pretty)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Content-Type", FullHeader)
resp := do(req)
return toResources(resp)
}
func GetResourceByType(resourcetype string, resourceid string) Resource {
path := um_resources_type_path(resourcetype, resourceid)
url := mk_url(path) + `?depth=` + Depth + `&pretty=` + strconv.FormatBool(Pretty)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Content-Type", FullHeader)
resp := do(req)
return toResource(resp)
}
func ListResourcesByType(resourcetype string) Resources {
path := um_resources_type(resourcetype)
url := mk_url(path) + `?depth=` + Depth + `&pretty=` + strconv.FormatBool(Pretty)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Content-Type", FullHeader)
resp := do(req)
return toResources(resp)
}
func toResources(resp Resp) Resources {
var col Resources
json.Unmarshal(resp.Body, &col)
col.Response = string(resp.Body)
col.Headers = &resp.Headers
col.StatusCode = resp.StatusCode
return col
}
func toResource(resp Resp) Resource {
var col Resource
json.Unmarshal(resp.Body, &col)
col.Response = string(resp.Body)
col.Headers = &resp.Headers
col.StatusCode = resp.StatusCode
return col
}

View File

@ -4,13 +4,14 @@ import (
"bytes"
"encoding/json"
"net/http"
"net/url"
)
type Volume struct {
Id string `json:"id,omitempty"`
Type_ string `json:"type,omitempty"`
Href string `json:"href,omitempty"`
Metadata *DatacenterElementMetadata `json:"metadata,omitempty"`
Metadata *Metadata `json:"metadata,omitempty"`
Properties VolumeProperties `json:"properties,omitempty"`
Response string `json:"Response,omitempty"`
Headers *http.Header `json:"headers,omitempty"`
@ -21,7 +22,9 @@ type VolumeProperties struct {
Name string `json:"name,omitempty"`
Type string `json:"type,omitempty"`
Size int `json:"size,omitempty"`
AvailabilityZone string `json:"availabilityZone,omitempty"`
Image string `json:"image,omitempty"`
ImageAlias string `json:"imageAlias,omitempty"`
ImagePassword string `json:"imagePassword,omitempty"`
SshKeys []string `json:"sshKeys,omitempty"`
Bus string `json:"bus,omitempty"`
@ -95,12 +98,14 @@ func DeleteVolume(dcid, volid string) Resp {
return is_delete(path)
}
func CreateSnapshot(dcid string, volid string, name string) Snapshot {
func CreateSnapshot(dcid string, volid string, name string, description string) Snapshot {
var path = volume_path(dcid, volid)
path = path + "/create-snapshot"
url := mk_url(path)
body := json.RawMessage("name=" + name)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(body))
req_url := mk_url(path)
data := url.Values{}
data.Set("name", name)
data.Add("description", description)
req, _ := http.NewRequest("POST", req_url, bytes.NewBufferString(data.Encode()))
req.Header.Add("Content-Type", CommandHeader)
return toSnapshot(do(req))
}

6
vendor/vendor.json vendored
View File

@ -854,6 +854,12 @@
"path": "github.com/pmezard/go-difflib/difflib",
"revision": "792786c7400a136282c1664665ae0a8db921c6c2"
},
{
"checksumSHA1": "Kq0fF7R65dDcGReuhf47O3LQgrY=",
"path": "github.com/profitbricks/profitbricks-sdk-go",
"revision": "7bdb11aecb0e457ea23c86898c6b49bfc0eb4bb1",
"revisionTime": "2017-08-01T13:52:49Z"
},
{
"checksumSHA1": "TvF3ym5sZVNqGlUOS9HgOIl/sZM=",
"path": "github.com/satori/go.uuid",