mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-10-31 13:50:01 +00:00 
			
		
		
		
	Update vendor dir and Godeps.json with new Godep
This commit is contained in:
		| @@ -1 +0,0 @@ | ||||
| package defsecrules | ||||
| @@ -1,143 +0,0 @@ | ||||
| package defsecrules | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"testing" | ||||
|  | ||||
| 	th "github.com/rackspace/gophercloud/testhelper" | ||||
| 	fake "github.com/rackspace/gophercloud/testhelper/client" | ||||
| ) | ||||
|  | ||||
| const rootPath = "/os-security-group-default-rules" | ||||
|  | ||||
| func mockListRulesResponse(t *testing.T) { | ||||
| 	th.Mux.HandleFunc(rootPath, func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "GET") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		w.WriteHeader(http.StatusOK) | ||||
|  | ||||
| 		fmt.Fprintf(w, ` | ||||
| { | ||||
|   "security_group_default_rules": [ | ||||
|     { | ||||
|       "from_port": 80, | ||||
|       "id": "{ruleID}", | ||||
|       "ip_protocol": "TCP", | ||||
|       "ip_range": { | ||||
|         "cidr": "10.10.10.0/24" | ||||
|       }, | ||||
|       "to_port": 80 | ||||
|     } | ||||
|   ] | ||||
| } | ||||
|       `) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func mockCreateRuleResponse(t *testing.T) { | ||||
| 	th.Mux.HandleFunc(rootPath, func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "POST") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) | ||||
|  | ||||
| 		th.TestJSONRequest(t, r, ` | ||||
| { | ||||
|   "security_group_default_rule": { | ||||
|     "ip_protocol": "TCP", | ||||
|     "from_port": 80, | ||||
|     "to_port": 80, | ||||
|     "cidr": "10.10.12.0/24" | ||||
|   } | ||||
| } | ||||
| 	`) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		w.WriteHeader(http.StatusOK) | ||||
|  | ||||
| 		fmt.Fprintf(w, ` | ||||
| { | ||||
|   "security_group_default_rule": { | ||||
|     "from_port": 80, | ||||
|     "id": "{ruleID}", | ||||
|     "ip_protocol": "TCP", | ||||
|     "ip_range": { | ||||
|       "cidr": "10.10.12.0/24" | ||||
|     }, | ||||
|     "to_port": 80 | ||||
|   } | ||||
| } | ||||
| `) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func mockCreateRuleResponseICMPZero(t *testing.T) { | ||||
| 	th.Mux.HandleFunc(rootPath, func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "POST") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) | ||||
|  | ||||
| 		th.TestJSONRequest(t, r, ` | ||||
| { | ||||
|   "security_group_default_rule": { | ||||
|     "ip_protocol": "ICMP", | ||||
|     "from_port": 0, | ||||
|     "to_port": 0, | ||||
|     "cidr": "10.10.12.0/24" | ||||
|   } | ||||
| } | ||||
| 	`) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		w.WriteHeader(http.StatusOK) | ||||
|  | ||||
| 		fmt.Fprintf(w, ` | ||||
| { | ||||
|   "security_group_default_rule": { | ||||
|     "from_port": 0, | ||||
|     "id": "{ruleID}", | ||||
|     "ip_protocol": "ICMP", | ||||
|     "ip_range": { | ||||
|       "cidr": "10.10.12.0/24" | ||||
|     }, | ||||
|     "to_port": 0 | ||||
|   } | ||||
| } | ||||
| `) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func mockGetRuleResponse(t *testing.T, ruleID string) { | ||||
| 	url := rootPath + "/" + ruleID | ||||
| 	th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "GET") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		w.WriteHeader(http.StatusOK) | ||||
|  | ||||
| 		fmt.Fprintf(w, ` | ||||
| { | ||||
|   "security_group_default_rule": { | ||||
|     "id": "{ruleID}", | ||||
|     "from_port": 80, | ||||
|     "to_port": 80, | ||||
|     "ip_protocol": "TCP", | ||||
|     "ip_range": { | ||||
|       "cidr": "10.10.12.0/24" | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 			`) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func mockDeleteRuleResponse(t *testing.T, ruleID string) { | ||||
| 	url := rootPath + "/" + ruleID | ||||
| 	th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "DELETE") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		w.WriteHeader(http.StatusNoContent) | ||||
| 	}) | ||||
| } | ||||
| @@ -1,96 +0,0 @@ | ||||
| package defsecrules | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/rackspace/gophercloud" | ||||
| 	"github.com/rackspace/gophercloud/pagination" | ||||
| ) | ||||
|  | ||||
| // List will return a collection of default rules. | ||||
| func List(client *gophercloud.ServiceClient) pagination.Pager { | ||||
| 	createPage := func(r pagination.PageResult) pagination.Page { | ||||
| 		return DefaultRulePage{pagination.SinglePageBase(r)} | ||||
| 	} | ||||
|  | ||||
| 	return pagination.NewPager(client, rootURL(client), createPage) | ||||
| } | ||||
|  | ||||
| // CreateOpts represents the configuration for adding a new default rule. | ||||
| type CreateOpts struct { | ||||
| 	// Required - the lower bound of the port range that will be opened. | ||||
| 	FromPort int `json:"from_port"` | ||||
|  | ||||
| 	// Required - the upper bound of the port range that will be opened. | ||||
| 	ToPort int `json:"to_port"` | ||||
|  | ||||
| 	// Required - the protocol type that will be allowed, e.g. TCP. | ||||
| 	IPProtocol string `json:"ip_protocol"` | ||||
|  | ||||
| 	// ONLY required if FromGroupID is blank. This represents the IP range that | ||||
| 	// will be the source of network traffic to your security group. Use | ||||
| 	// 0.0.0.0/0 to allow all IP addresses. | ||||
| 	CIDR string `json:"cidr,omitempty"` | ||||
| } | ||||
|  | ||||
| // CreateOptsBuilder builds the create rule options into a serializable format. | ||||
| type CreateOptsBuilder interface { | ||||
| 	ToRuleCreateMap() (map[string]interface{}, error) | ||||
| } | ||||
|  | ||||
| // ToRuleCreateMap builds the create rule options into a serializable format. | ||||
| func (opts CreateOpts) ToRuleCreateMap() (map[string]interface{}, error) { | ||||
| 	rule := make(map[string]interface{}) | ||||
|  | ||||
| 	if opts.FromPort == 0 && strings.ToUpper(opts.IPProtocol) != "ICMP" { | ||||
| 		return rule, errors.New("A FromPort must be set") | ||||
| 	} | ||||
| 	if opts.ToPort == 0 && strings.ToUpper(opts.IPProtocol) != "ICMP" { | ||||
| 		return rule, errors.New("A ToPort must be set") | ||||
| 	} | ||||
| 	if opts.IPProtocol == "" { | ||||
| 		return rule, errors.New("A IPProtocol must be set") | ||||
| 	} | ||||
| 	if opts.CIDR == "" { | ||||
| 		return rule, errors.New("A CIDR must be set") | ||||
| 	} | ||||
|  | ||||
| 	rule["from_port"] = opts.FromPort | ||||
| 	rule["to_port"] = opts.ToPort | ||||
| 	rule["ip_protocol"] = opts.IPProtocol | ||||
| 	rule["cidr"] = opts.CIDR | ||||
|  | ||||
| 	return map[string]interface{}{"security_group_default_rule": rule}, nil | ||||
| } | ||||
|  | ||||
| // Create is the operation responsible for creating a new default rule. | ||||
| func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { | ||||
| 	var result CreateResult | ||||
|  | ||||
| 	reqBody, err := opts.ToRuleCreateMap() | ||||
| 	if err != nil { | ||||
| 		result.Err = err | ||||
| 		return result | ||||
| 	} | ||||
|  | ||||
| 	_, result.Err = client.Post(rootURL(client), reqBody, &result.Body, &gophercloud.RequestOpts{ | ||||
| 		OkCodes: []int{200}, | ||||
| 	}) | ||||
|  | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // Get will return details for a particular default rule. | ||||
| func Get(client *gophercloud.ServiceClient, id string) GetResult { | ||||
| 	var result GetResult | ||||
| 	_, result.Err = client.Get(resourceURL(client, id), &result.Body, nil) | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // Delete will permanently delete a default rule from the project. | ||||
| func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult { | ||||
| 	var result gophercloud.ErrResult | ||||
| 	_, result.Err = client.Delete(resourceURL(client, id), nil) | ||||
| 	return result | ||||
| } | ||||
| @@ -1,69 +0,0 @@ | ||||
| package defsecrules | ||||
|  | ||||
| import ( | ||||
| 	"github.com/mitchellh/mapstructure" | ||||
|  | ||||
| 	"github.com/rackspace/gophercloud" | ||||
| 	"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups" | ||||
| 	"github.com/rackspace/gophercloud/pagination" | ||||
| ) | ||||
|  | ||||
| // DefaultRule represents a default rule - which is identical to a | ||||
| // normal security rule. | ||||
| type DefaultRule secgroups.Rule | ||||
|  | ||||
| // DefaultRulePage is a single page of a DefaultRule collection. | ||||
| type DefaultRulePage struct { | ||||
| 	pagination.SinglePageBase | ||||
| } | ||||
|  | ||||
| // IsEmpty determines whether or not a page of default rules contains any results. | ||||
| func (page DefaultRulePage) IsEmpty() (bool, error) { | ||||
| 	users, err := ExtractDefaultRules(page) | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 	return len(users) == 0, nil | ||||
| } | ||||
|  | ||||
| // ExtractDefaultRules returns a slice of DefaultRules contained in a single | ||||
| // page of results. | ||||
| func ExtractDefaultRules(page pagination.Page) ([]DefaultRule, error) { | ||||
| 	casted := page.(DefaultRulePage).Body | ||||
| 	var response struct { | ||||
| 		Rules []DefaultRule `mapstructure:"security_group_default_rules"` | ||||
| 	} | ||||
|  | ||||
| 	err := mapstructure.WeakDecode(casted, &response) | ||||
|  | ||||
| 	return response.Rules, err | ||||
| } | ||||
|  | ||||
| type commonResult struct { | ||||
| 	gophercloud.Result | ||||
| } | ||||
|  | ||||
| // CreateResult represents the result of a create operation. | ||||
| type CreateResult struct { | ||||
| 	commonResult | ||||
| } | ||||
|  | ||||
| // GetResult represents the result of a get operation. | ||||
| type GetResult struct { | ||||
| 	commonResult | ||||
| } | ||||
|  | ||||
| // Extract will extract a DefaultRule struct from most responses. | ||||
| func (r commonResult) Extract() (*DefaultRule, error) { | ||||
| 	if r.Err != nil { | ||||
| 		return nil, r.Err | ||||
| 	} | ||||
|  | ||||
| 	var response struct { | ||||
| 		Rule DefaultRule `mapstructure:"security_group_default_rule"` | ||||
| 	} | ||||
|  | ||||
| 	err := mapstructure.WeakDecode(r.Body, &response) | ||||
|  | ||||
| 	return &response.Rule, err | ||||
| } | ||||
| @@ -1,13 +0,0 @@ | ||||
| package defsecrules | ||||
|  | ||||
| import "github.com/rackspace/gophercloud" | ||||
|  | ||||
| const rulepath = "os-security-group-default-rules" | ||||
|  | ||||
| func resourceURL(c *gophercloud.ServiceClient, id string) string { | ||||
| 	return c.ServiceURL(rulepath, id) | ||||
| } | ||||
|  | ||||
| func rootURL(c *gophercloud.ServiceClient) string { | ||||
| 	return c.ServiceURL(rulepath) | ||||
| } | ||||
							
								
								
									
										23
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/delegate.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/delegate.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,23 +0,0 @@ | ||||
| package extensions | ||||
|  | ||||
| import ( | ||||
| 	"github.com/rackspace/gophercloud" | ||||
| 	common "github.com/rackspace/gophercloud/openstack/common/extensions" | ||||
| 	"github.com/rackspace/gophercloud/pagination" | ||||
| ) | ||||
|  | ||||
| // ExtractExtensions interprets a Page as a slice of Extensions. | ||||
| func ExtractExtensions(page pagination.Page) ([]common.Extension, error) { | ||||
| 	return common.ExtractExtensions(page) | ||||
| } | ||||
|  | ||||
| // Get retrieves information for a specific extension using its alias. | ||||
| func Get(c *gophercloud.ServiceClient, alias string) common.GetResult { | ||||
| 	return common.Get(c, alias) | ||||
| } | ||||
|  | ||||
| // List returns a Pager which allows you to iterate over the full collection of extensions. | ||||
| // It does not accept query parameters. | ||||
| func List(c *gophercloud.ServiceClient) pagination.Pager { | ||||
| 	return common.List(c) | ||||
| } | ||||
							
								
								
									
										3
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,3 +0,0 @@ | ||||
| // Package extensions provides information and interaction with the | ||||
| // different extensions available for the OpenStack Compute service. | ||||
| package extensions | ||||
| @@ -1,3 +0,0 @@ | ||||
| // Package floatingip provides the ability to manage floating ips through | ||||
| // nova-network | ||||
| package floatingip | ||||
| @@ -1,193 +0,0 @@ | ||||
| // +build fixtures | ||||
|  | ||||
| package floatingip | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"testing" | ||||
|  | ||||
| 	th "github.com/rackspace/gophercloud/testhelper" | ||||
| 	"github.com/rackspace/gophercloud/testhelper/client" | ||||
| ) | ||||
|  | ||||
| // ListOutput is a sample response to a List call. | ||||
| const ListOutput = ` | ||||
| { | ||||
|     "floating_ips": [ | ||||
|         { | ||||
|             "fixed_ip": null, | ||||
|             "id": 1, | ||||
|             "instance_id": null, | ||||
|             "ip": "10.10.10.1", | ||||
|             "pool": "nova" | ||||
|         }, | ||||
|         { | ||||
|             "fixed_ip": "166.78.185.201", | ||||
|             "id": 2, | ||||
|             "instance_id": "4d8c3732-a248-40ed-bebc-539a6ffd25c0", | ||||
|             "ip": "10.10.10.2", | ||||
|             "pool": "nova" | ||||
|         } | ||||
|     ] | ||||
| } | ||||
| ` | ||||
|  | ||||
| // GetOutput is a sample response to a Get call. | ||||
| const GetOutput = ` | ||||
| { | ||||
|     "floating_ip": { | ||||
|         "fixed_ip": "166.78.185.201", | ||||
|         "id": 2, | ||||
|         "instance_id": "4d8c3732-a248-40ed-bebc-539a6ffd25c0", | ||||
|         "ip": "10.10.10.2", | ||||
|         "pool": "nova" | ||||
|     } | ||||
| } | ||||
| ` | ||||
|  | ||||
| // CreateOutput is a sample response to a Post call | ||||
| const CreateOutput = ` | ||||
| { | ||||
|     "floating_ip": { | ||||
|         "fixed_ip": null, | ||||
|         "id": 1, | ||||
|         "instance_id": null, | ||||
|         "ip": "10.10.10.1", | ||||
|         "pool": "nova" | ||||
|     } | ||||
| } | ||||
| ` | ||||
|  | ||||
| // FirstFloatingIP is the first result in ListOutput. | ||||
| var FirstFloatingIP = FloatingIP{ | ||||
| 	ID:   "1", | ||||
| 	IP:   "10.10.10.1", | ||||
| 	Pool: "nova", | ||||
| } | ||||
|  | ||||
| // SecondFloatingIP is the first result in ListOutput. | ||||
| var SecondFloatingIP = FloatingIP{ | ||||
| 	FixedIP:    "166.78.185.201", | ||||
| 	ID:         "2", | ||||
| 	InstanceID: "4d8c3732-a248-40ed-bebc-539a6ffd25c0", | ||||
| 	IP:         "10.10.10.2", | ||||
| 	Pool:       "nova", | ||||
| } | ||||
|  | ||||
| // ExpectedFloatingIPsSlice is the slice of results that should be parsed | ||||
| // from ListOutput, in the expected order. | ||||
| var ExpectedFloatingIPsSlice = []FloatingIP{FirstFloatingIP, SecondFloatingIP} | ||||
|  | ||||
| // CreatedFloatingIP is the parsed result from CreateOutput. | ||||
| var CreatedFloatingIP = FloatingIP{ | ||||
| 	ID:   "1", | ||||
| 	IP:   "10.10.10.1", | ||||
| 	Pool: "nova", | ||||
| } | ||||
|  | ||||
| // HandleListSuccessfully configures the test server to respond to a List request. | ||||
| func HandleListSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/os-floating-ips", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "GET") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		fmt.Fprintf(w, ListOutput) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // HandleGetSuccessfully configures the test server to respond to a Get request | ||||
| // for an existing floating ip | ||||
| func HandleGetSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/os-floating-ips/2", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "GET") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		fmt.Fprintf(w, GetOutput) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // HandleCreateSuccessfully configures the test server to respond to a Create request | ||||
| // for a new floating ip | ||||
| func HandleCreateSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/os-floating-ips", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "POST") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
| 		th.TestJSONRequest(t, r, ` | ||||
| { | ||||
| 	"pool": "nova" | ||||
| } | ||||
| `) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		fmt.Fprintf(w, CreateOutput) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // HandleDeleteSuccessfully configures the test server to respond to a Delete request for a | ||||
| // an existing floating ip | ||||
| func HandleDeleteSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/os-floating-ips/1", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "DELETE") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
|  | ||||
| 		w.WriteHeader(http.StatusAccepted) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // HandleAssociateSuccessfully configures the test server to respond to a Post request | ||||
| // to associate an allocated floating IP | ||||
| func HandleAssociateSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/action", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "POST") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
| 		th.TestJSONRequest(t, r, ` | ||||
| { | ||||
| 	"addFloatingIp": { | ||||
| 		"address": "10.10.10.2" | ||||
| 	} | ||||
| } | ||||
| `) | ||||
|  | ||||
| 		w.WriteHeader(http.StatusAccepted) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // HandleFixedAssociateSucessfully configures the test server to respond to a Post request | ||||
| // to associate an allocated floating IP with a specific fixed IP address | ||||
| func HandleAssociateFixedSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/action", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "POST") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
| 		th.TestJSONRequest(t, r, ` | ||||
| { | ||||
| 	"addFloatingIp": { | ||||
| 		"address": "10.10.10.2", | ||||
| 		"fixed_address": "166.78.185.201" | ||||
| 	} | ||||
| } | ||||
| `) | ||||
|  | ||||
| 		w.WriteHeader(http.StatusAccepted) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // HandleDisassociateSuccessfully configures the test server to respond to a Post request | ||||
| // to disassociate an allocated floating IP | ||||
| func HandleDisassociateSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/action", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "POST") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
| 		th.TestJSONRequest(t, r, ` | ||||
| { | ||||
| 	"removeFloatingIp": { | ||||
| 		"address": "10.10.10.2" | ||||
| 	} | ||||
| } | ||||
| `) | ||||
|  | ||||
| 		w.WriteHeader(http.StatusAccepted) | ||||
| 	}) | ||||
| } | ||||
| @@ -1,171 +0,0 @@ | ||||
| package floatingip | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
|  | ||||
| 	"github.com/rackspace/gophercloud" | ||||
| 	"github.com/rackspace/gophercloud/pagination" | ||||
| ) | ||||
|  | ||||
| // List returns a Pager that allows you to iterate over a collection of FloatingIPs. | ||||
| func List(client *gophercloud.ServiceClient) pagination.Pager { | ||||
| 	return pagination.NewPager(client, listURL(client), func(r pagination.PageResult) pagination.Page { | ||||
| 		return FloatingIPsPage{pagination.SinglePageBase(r)} | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // CreateOptsBuilder describes struct types that can be accepted by the Create call. Notable, the | ||||
| // CreateOpts struct in this package does. | ||||
| type CreateOptsBuilder interface { | ||||
| 	ToFloatingIPCreateMap() (map[string]interface{}, error) | ||||
| } | ||||
|  | ||||
| // CreateOpts specifies a Floating IP allocation request | ||||
| type CreateOpts struct { | ||||
| 	// Pool is the pool of floating IPs to allocate one from | ||||
| 	Pool string | ||||
| } | ||||
|  | ||||
| // AssociateOpts specifies the required information to associate or disassociate a floating IP to an instance | ||||
| type AssociateOpts struct { | ||||
| 	// ServerID is the UUID of the server | ||||
| 	ServerID string | ||||
|  | ||||
| 	// FixedIP is an optional fixed IP address of the server | ||||
| 	FixedIP string | ||||
|  | ||||
| 	// FloatingIP is the floating IP to associate with an instance | ||||
| 	FloatingIP string | ||||
| } | ||||
|  | ||||
| // ToFloatingIPCreateMap constructs a request body from CreateOpts. | ||||
| func (opts CreateOpts) ToFloatingIPCreateMap() (map[string]interface{}, error) { | ||||
| 	if opts.Pool == "" { | ||||
| 		return nil, errors.New("Missing field required for floating IP creation: Pool") | ||||
| 	} | ||||
|  | ||||
| 	return map[string]interface{}{"pool": opts.Pool}, nil | ||||
| } | ||||
|  | ||||
| // ToAssociateMap constructs a request body from AssociateOpts. | ||||
| func (opts AssociateOpts) ToAssociateMap() (map[string]interface{}, error) { | ||||
| 	if opts.ServerID == "" { | ||||
| 		return nil, errors.New("Required field missing for floating IP association: ServerID") | ||||
| 	} | ||||
|  | ||||
| 	if opts.FloatingIP == "" { | ||||
| 		return nil, errors.New("Required field missing for floating IP association: FloatingIP") | ||||
| 	} | ||||
|  | ||||
| 	associateInfo := map[string]interface{}{ | ||||
| 		"serverId":   opts.ServerID, | ||||
| 		"floatingIp": opts.FloatingIP, | ||||
| 		"fixedIp":    opts.FixedIP, | ||||
| 	} | ||||
|  | ||||
| 	return associateInfo, nil | ||||
|  | ||||
| } | ||||
|  | ||||
| // Create requests the creation of a new floating IP | ||||
| func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { | ||||
| 	var res CreateResult | ||||
|  | ||||
| 	reqBody, err := opts.ToFloatingIPCreateMap() | ||||
| 	if err != nil { | ||||
| 		res.Err = err | ||||
| 		return res | ||||
| 	} | ||||
|  | ||||
| 	_, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{ | ||||
| 		OkCodes: []int{200}, | ||||
| 	}) | ||||
| 	return res | ||||
| } | ||||
|  | ||||
| // Get returns data about a previously created FloatingIP. | ||||
| func Get(client *gophercloud.ServiceClient, id string) GetResult { | ||||
| 	var res GetResult | ||||
| 	_, res.Err = client.Get(getURL(client, id), &res.Body, nil) | ||||
| 	return res | ||||
| } | ||||
|  | ||||
| // Delete requests the deletion of a previous allocated FloatingIP. | ||||
| func Delete(client *gophercloud.ServiceClient, id string) DeleteResult { | ||||
| 	var res DeleteResult | ||||
| 	_, res.Err = client.Delete(deleteURL(client, id), nil) | ||||
| 	return res | ||||
| } | ||||
|  | ||||
| // association / disassociation | ||||
|  | ||||
| // Associate pairs an allocated floating IP with an instance | ||||
| // Deprecated. Use AssociateInstance. | ||||
| func Associate(client *gophercloud.ServiceClient, serverId, fip string) AssociateResult { | ||||
| 	var res AssociateResult | ||||
|  | ||||
| 	addFloatingIp := make(map[string]interface{}) | ||||
| 	addFloatingIp["address"] = fip | ||||
| 	reqBody := map[string]interface{}{"addFloatingIp": addFloatingIp} | ||||
|  | ||||
| 	_, res.Err = client.Post(associateURL(client, serverId), reqBody, nil, nil) | ||||
| 	return res | ||||
| } | ||||
|  | ||||
| // AssociateInstance pairs an allocated floating IP with an instance. | ||||
| func AssociateInstance(client *gophercloud.ServiceClient, opts AssociateOpts) AssociateResult { | ||||
| 	var res AssociateResult | ||||
|  | ||||
| 	associateInfo, err := opts.ToAssociateMap() | ||||
| 	if err != nil { | ||||
| 		res.Err = err | ||||
| 		return res | ||||
| 	} | ||||
|  | ||||
| 	addFloatingIp := make(map[string]interface{}) | ||||
| 	addFloatingIp["address"] = associateInfo["floatingIp"].(string) | ||||
|  | ||||
| 	// fixedIp is not required | ||||
| 	if associateInfo["fixedIp"] != "" { | ||||
| 		addFloatingIp["fixed_address"] = associateInfo["fixedIp"].(string) | ||||
| 	} | ||||
|  | ||||
| 	serverId := associateInfo["serverId"].(string) | ||||
|  | ||||
| 	reqBody := map[string]interface{}{"addFloatingIp": addFloatingIp} | ||||
| 	_, res.Err = client.Post(associateURL(client, serverId), reqBody, nil, nil) | ||||
| 	return res | ||||
| } | ||||
|  | ||||
| // Disassociate decouples an allocated floating IP from an instance | ||||
| // Deprecated. Use DisassociateInstance. | ||||
| func Disassociate(client *gophercloud.ServiceClient, serverId, fip string) DisassociateResult { | ||||
| 	var res DisassociateResult | ||||
|  | ||||
| 	removeFloatingIp := make(map[string]interface{}) | ||||
| 	removeFloatingIp["address"] = fip | ||||
| 	reqBody := map[string]interface{}{"removeFloatingIp": removeFloatingIp} | ||||
|  | ||||
| 	_, res.Err = client.Post(disassociateURL(client, serverId), reqBody, nil, nil) | ||||
| 	return res | ||||
| } | ||||
|  | ||||
| // DisassociateInstance decouples an allocated floating IP from an instance | ||||
| func DisassociateInstance(client *gophercloud.ServiceClient, opts AssociateOpts) DisassociateResult { | ||||
| 	var res DisassociateResult | ||||
|  | ||||
| 	associateInfo, err := opts.ToAssociateMap() | ||||
| 	if err != nil { | ||||
| 		res.Err = err | ||||
| 		return res | ||||
| 	} | ||||
|  | ||||
| 	removeFloatingIp := make(map[string]interface{}) | ||||
| 	removeFloatingIp["address"] = associateInfo["floatingIp"].(string) | ||||
| 	reqBody := map[string]interface{}{"removeFloatingIp": removeFloatingIp} | ||||
|  | ||||
| 	serverId := associateInfo["serverId"].(string) | ||||
|  | ||||
| 	_, res.Err = client.Post(disassociateURL(client, serverId), reqBody, nil, nil) | ||||
| 	return res | ||||
| } | ||||
| @@ -1,99 +0,0 @@ | ||||
| package floatingip | ||||
|  | ||||
| import ( | ||||
| 	"github.com/mitchellh/mapstructure" | ||||
| 	"github.com/rackspace/gophercloud" | ||||
| 	"github.com/rackspace/gophercloud/pagination" | ||||
| ) | ||||
|  | ||||
| // A FloatingIP is an IP that can be associated with an instance | ||||
| type FloatingIP struct { | ||||
| 	// ID is a unique ID of the Floating IP | ||||
| 	ID string `mapstructure:"id"` | ||||
|  | ||||
| 	// FixedIP is the IP of the instance related to the Floating IP | ||||
| 	FixedIP string `mapstructure:"fixed_ip,omitempty"` | ||||
|  | ||||
| 	// InstanceID is the ID of the instance that is using the Floating IP | ||||
| 	InstanceID string `mapstructure:"instance_id"` | ||||
|  | ||||
| 	// IP is the actual Floating IP | ||||
| 	IP string `mapstructure:"ip"` | ||||
|  | ||||
| 	// Pool is the pool of floating IPs that this floating IP belongs to | ||||
| 	Pool string `mapstructure:"pool"` | ||||
| } | ||||
|  | ||||
| // FloatingIPsPage stores a single, only page of FloatingIPs | ||||
| // results from a List call. | ||||
| type FloatingIPsPage struct { | ||||
| 	pagination.SinglePageBase | ||||
| } | ||||
|  | ||||
| // IsEmpty determines whether or not a FloatingIPsPage is empty. | ||||
| func (page FloatingIPsPage) IsEmpty() (bool, error) { | ||||
| 	va, err := ExtractFloatingIPs(page) | ||||
| 	return len(va) == 0, err | ||||
| } | ||||
|  | ||||
| // ExtractFloatingIPs interprets a page of results as a slice of | ||||
| // FloatingIPs. | ||||
| func ExtractFloatingIPs(page pagination.Page) ([]FloatingIP, error) { | ||||
| 	casted := page.(FloatingIPsPage).Body | ||||
| 	var response struct { | ||||
| 		FloatingIPs []FloatingIP `mapstructure:"floating_ips"` | ||||
| 	} | ||||
|  | ||||
| 	err := mapstructure.WeakDecode(casted, &response) | ||||
|  | ||||
| 	return response.FloatingIPs, err | ||||
| } | ||||
|  | ||||
| type FloatingIPResult struct { | ||||
| 	gophercloud.Result | ||||
| } | ||||
|  | ||||
| // Extract is a method that attempts to interpret any FloatingIP resource | ||||
| // response as a FloatingIP struct. | ||||
| func (r FloatingIPResult) Extract() (*FloatingIP, error) { | ||||
| 	if r.Err != nil { | ||||
| 		return nil, r.Err | ||||
| 	} | ||||
|  | ||||
| 	var res struct { | ||||
| 		FloatingIP *FloatingIP `json:"floating_ip" mapstructure:"floating_ip"` | ||||
| 	} | ||||
|  | ||||
| 	err := mapstructure.WeakDecode(r.Body, &res) | ||||
| 	return res.FloatingIP, err | ||||
| } | ||||
|  | ||||
| // CreateResult is the response from a Create operation. Call its Extract method to interpret it | ||||
| // as a FloatingIP. | ||||
| type CreateResult struct { | ||||
| 	FloatingIPResult | ||||
| } | ||||
|  | ||||
| // GetResult is the response from a Get operation. Call its Extract method to interpret it | ||||
| // as a FloatingIP. | ||||
| type GetResult struct { | ||||
| 	FloatingIPResult | ||||
| } | ||||
|  | ||||
| // DeleteResult is the response from a Delete operation. Call its Extract method to determine if | ||||
| // the call succeeded or failed. | ||||
| type DeleteResult struct { | ||||
| 	gophercloud.ErrResult | ||||
| } | ||||
|  | ||||
| // AssociateResult is the response from a Delete operation. Call its Extract method to determine if | ||||
| // the call succeeded or failed. | ||||
| type AssociateResult struct { | ||||
| 	gophercloud.ErrResult | ||||
| } | ||||
|  | ||||
| // DisassociateResult is the response from a Delete operation. Call its Extract method to determine if | ||||
| // the call succeeded or failed. | ||||
| type DisassociateResult struct { | ||||
| 	gophercloud.ErrResult | ||||
| } | ||||
| @@ -1,37 +0,0 @@ | ||||
| package floatingip | ||||
|  | ||||
| import "github.com/rackspace/gophercloud" | ||||
|  | ||||
| const resourcePath = "os-floating-ips" | ||||
|  | ||||
| func resourceURL(c *gophercloud.ServiceClient) string { | ||||
| 	return c.ServiceURL(resourcePath) | ||||
| } | ||||
|  | ||||
| func listURL(c *gophercloud.ServiceClient) string { | ||||
| 	return resourceURL(c) | ||||
| } | ||||
|  | ||||
| func createURL(c *gophercloud.ServiceClient) string { | ||||
| 	return resourceURL(c) | ||||
| } | ||||
|  | ||||
| func getURL(c *gophercloud.ServiceClient, id string) string { | ||||
| 	return c.ServiceURL(resourcePath, id) | ||||
| } | ||||
|  | ||||
| func deleteURL(c *gophercloud.ServiceClient, id string) string { | ||||
| 	return getURL(c, id) | ||||
| } | ||||
|  | ||||
| func serverURL(c *gophercloud.ServiceClient, serverId string) string { | ||||
| 	return c.ServiceURL("servers/" + serverId + "/action") | ||||
| } | ||||
|  | ||||
| func associateURL(c *gophercloud.ServiceClient, serverId string) string { | ||||
| 	return serverURL(c, serverId) | ||||
| } | ||||
|  | ||||
| func disassociateURL(c *gophercloud.ServiceClient, serverId string) string { | ||||
| 	return serverURL(c, serverId) | ||||
| } | ||||
| @@ -1,3 +0,0 @@ | ||||
| // Package keypairs provides information and interaction with the Keypairs | ||||
| // extension for the OpenStack Compute service. | ||||
| package keypairs | ||||
							
								
								
									
										171
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/fixtures.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										171
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/fixtures.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,171 +0,0 @@ | ||||
| // +build fixtures | ||||
|  | ||||
| package keypairs | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"testing" | ||||
|  | ||||
| 	th "github.com/rackspace/gophercloud/testhelper" | ||||
| 	"github.com/rackspace/gophercloud/testhelper/client" | ||||
| ) | ||||
|  | ||||
| // ListOutput is a sample response to a List call. | ||||
| const ListOutput = ` | ||||
| { | ||||
| 	"keypairs": [ | ||||
| 		{ | ||||
| 			"keypair": { | ||||
| 				"fingerprint": "15:b0:f8:b3:f9:48:63:71:cf:7b:5b:38:6d:44:2d:4a", | ||||
| 				"name": "firstkey", | ||||
| 				"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC+Eo/RZRngaGTkFs7I62ZjsIlO79KklKbMXi8F+KITD4bVQHHn+kV+4gRgkgCRbdoDqoGfpaDFs877DYX9n4z6FrAIZ4PES8TNKhatifpn9NdQYWA+IkU8CuvlEKGuFpKRi/k7JLos/gHi2hy7QUwgtRvcefvD/vgQZOVw/mGR9Q== Generated by Nova\n" | ||||
| 			} | ||||
| 		}, | ||||
| 		{ | ||||
| 			"keypair": { | ||||
| 				"fingerprint": "35:9d:d0:c3:4a:80:d3:d8:86:f1:ca:f7:df:c4:f9:d8", | ||||
| 				"name": "secondkey", | ||||
| 				"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC9mC3WZN9UGLxgPBpP7H5jZMc6pKwOoSgre8yun6REFktn/Kz7DUt9jaR1UJyRzHxITfCfAIgSxPdGqB/oF1suMyWgu5i0625vavLB5z5kC8Hq3qZJ9zJO1poE1kyD+htiTtPWJ88e12xuH2XB/CZN9OpEiF98hAagiOE0EnOS5Q== Generated by Nova\n" | ||||
| 			} | ||||
| 		} | ||||
| 	] | ||||
| } | ||||
| ` | ||||
|  | ||||
| // GetOutput is a sample response to a Get call. | ||||
| const GetOutput = ` | ||||
| { | ||||
| 	"keypair": { | ||||
| 		"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC+Eo/RZRngaGTkFs7I62ZjsIlO79KklKbMXi8F+KITD4bVQHHn+kV+4gRgkgCRbdoDqoGfpaDFs877DYX9n4z6FrAIZ4PES8TNKhatifpn9NdQYWA+IkU8CuvlEKGuFpKRi/k7JLos/gHi2hy7QUwgtRvcefvD/vgQZOVw/mGR9Q== Generated by Nova\n", | ||||
| 		"name": "firstkey", | ||||
| 		"fingerprint": "15:b0:f8:b3:f9:48:63:71:cf:7b:5b:38:6d:44:2d:4a" | ||||
| 	} | ||||
| } | ||||
| ` | ||||
|  | ||||
| // CreateOutput is a sample response to a Create call. | ||||
| const CreateOutput = ` | ||||
| { | ||||
| 	"keypair": { | ||||
| 		"fingerprint": "35:9d:d0:c3:4a:80:d3:d8:86:f1:ca:f7:df:c4:f9:d8", | ||||
| 		"name": "createdkey", | ||||
| 		"private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIICXAIBAAKBgQC9mC3WZN9UGLxgPBpP7H5jZMc6pKwOoSgre8yun6REFktn/Kz7\nDUt9jaR1UJyRzHxITfCfAIgSxPdGqB/oF1suMyWgu5i0625vavLB5z5kC8Hq3qZJ\n9zJO1poE1kyD+htiTtPWJ88e12xuH2XB/CZN9OpEiF98hAagiOE0EnOS5QIDAQAB\nAoGAE5XO1mDhORy9COvsg+kYPUhB1GsCYxh+v88wG7HeFDKBY6KUc/Kxo6yoGn5T\nTjRjekyi2KoDZHz4VlIzyZPwFS4I1bf3oCunVoAKzgLdmnTtvRNMC5jFOGc2vUgP\n9bSyRj3S1R4ClVk2g0IDeagko/jc8zzLEYuIK+fbkds79YECQQDt3vcevgegnkga\ntF4NsDmmBPRkcSHCqrANP/7vFcBQN3czxeYYWX3DK07alu6GhH1Y4sHbdm616uU0\nll7xbDzxAkEAzAtN2IyftNygV2EGiaGgqLyo/tD9+Vui2qCQplqe4jvWh/5Sparl\nOjmKo+uAW+hLrLVMnHzRWxbWU8hirH5FNQJATO+ZxCK4etXXAnQmG41NCAqANWB2\nB+2HJbH2NcQ2QHvAHUm741JGn/KI/aBlo7KEjFRDWUVUB5ji64BbUwCsMQJBAIku\nLGcjnBf/oLk+XSPZC2eGd2Ph5G5qYmH0Q2vkTx+wtTn3DV+eNsDfgMtWAJVJ5t61\ngU1QSXyhLPVlKpnnxuUCQC+xvvWjWtsLaFtAsZywJiqLxQzHts8XLGZptYJ5tLWV\nrtmYtBcJCN48RrgQHry/xWYeA4K/AFQpXfNPgprQ96Q=\n-----END RSA PRIVATE KEY-----\n", | ||||
| 		"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC9mC3WZN9UGLxgPBpP7H5jZMc6pKwOoSgre8yun6REFktn/Kz7DUt9jaR1UJyRzHxITfCfAIgSxPdGqB/oF1suMyWgu5i0625vavLB5z5kC8Hq3qZJ9zJO1poE1kyD+htiTtPWJ88e12xuH2XB/CZN9OpEiF98hAagiOE0EnOS5Q== Generated by Nova\n", | ||||
| 		"user_id": "fake" | ||||
| 	} | ||||
| } | ||||
| ` | ||||
|  | ||||
| // ImportOutput is a sample response to a Create call that provides its own public key. | ||||
| const ImportOutput = ` | ||||
| { | ||||
| 	"keypair": { | ||||
| 		"fingerprint": "1e:2c:9b:56:79:4b:45:77:f9:ca:7a:98:2c:b0:d5:3c", | ||||
| 		"name": "importedkey", | ||||
| 		"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDx8nkQv/zgGgB4rMYmIf+6A4l6Rr+o/6lHBQdW5aYd44bd8JttDCE/F/pNRr0lRE+PiqSPO8nDPHw0010JeMH9gYgnnFlyY3/OcJ02RhIPyyxYpv9FhY+2YiUkpwFOcLImyrxEsYXpD/0d3ac30bNH6Sw9JD9UZHYcpSxsIbECHw== Generated by Nova", | ||||
| 		"user_id": "fake" | ||||
| 	} | ||||
| } | ||||
| ` | ||||
|  | ||||
| // FirstKeyPair is the first result in ListOutput. | ||||
| var FirstKeyPair = KeyPair{ | ||||
| 	Name:        "firstkey", | ||||
| 	Fingerprint: "15:b0:f8:b3:f9:48:63:71:cf:7b:5b:38:6d:44:2d:4a", | ||||
| 	PublicKey:   "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC+Eo/RZRngaGTkFs7I62ZjsIlO79KklKbMXi8F+KITD4bVQHHn+kV+4gRgkgCRbdoDqoGfpaDFs877DYX9n4z6FrAIZ4PES8TNKhatifpn9NdQYWA+IkU8CuvlEKGuFpKRi/k7JLos/gHi2hy7QUwgtRvcefvD/vgQZOVw/mGR9Q== Generated by Nova\n", | ||||
| } | ||||
|  | ||||
| // SecondKeyPair is the second result in ListOutput. | ||||
| var SecondKeyPair = KeyPair{ | ||||
| 	Name:        "secondkey", | ||||
| 	Fingerprint: "35:9d:d0:c3:4a:80:d3:d8:86:f1:ca:f7:df:c4:f9:d8", | ||||
| 	PublicKey:   "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC9mC3WZN9UGLxgPBpP7H5jZMc6pKwOoSgre8yun6REFktn/Kz7DUt9jaR1UJyRzHxITfCfAIgSxPdGqB/oF1suMyWgu5i0625vavLB5z5kC8Hq3qZJ9zJO1poE1kyD+htiTtPWJ88e12xuH2XB/CZN9OpEiF98hAagiOE0EnOS5Q== Generated by Nova\n", | ||||
| } | ||||
|  | ||||
| // ExpectedKeyPairSlice is the slice of results that should be parsed from ListOutput, in the expected | ||||
| // order. | ||||
| var ExpectedKeyPairSlice = []KeyPair{FirstKeyPair, SecondKeyPair} | ||||
|  | ||||
| // CreatedKeyPair is the parsed result from CreatedOutput. | ||||
| var CreatedKeyPair = KeyPair{ | ||||
| 	Name:        "createdkey", | ||||
| 	Fingerprint: "35:9d:d0:c3:4a:80:d3:d8:86:f1:ca:f7:df:c4:f9:d8", | ||||
| 	PublicKey:   "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC9mC3WZN9UGLxgPBpP7H5jZMc6pKwOoSgre8yun6REFktn/Kz7DUt9jaR1UJyRzHxITfCfAIgSxPdGqB/oF1suMyWgu5i0625vavLB5z5kC8Hq3qZJ9zJO1poE1kyD+htiTtPWJ88e12xuH2XB/CZN9OpEiF98hAagiOE0EnOS5Q== Generated by Nova\n", | ||||
| 	PrivateKey:  "-----BEGIN RSA PRIVATE KEY-----\nMIICXAIBAAKBgQC9mC3WZN9UGLxgPBpP7H5jZMc6pKwOoSgre8yun6REFktn/Kz7\nDUt9jaR1UJyRzHxITfCfAIgSxPdGqB/oF1suMyWgu5i0625vavLB5z5kC8Hq3qZJ\n9zJO1poE1kyD+htiTtPWJ88e12xuH2XB/CZN9OpEiF98hAagiOE0EnOS5QIDAQAB\nAoGAE5XO1mDhORy9COvsg+kYPUhB1GsCYxh+v88wG7HeFDKBY6KUc/Kxo6yoGn5T\nTjRjekyi2KoDZHz4VlIzyZPwFS4I1bf3oCunVoAKzgLdmnTtvRNMC5jFOGc2vUgP\n9bSyRj3S1R4ClVk2g0IDeagko/jc8zzLEYuIK+fbkds79YECQQDt3vcevgegnkga\ntF4NsDmmBPRkcSHCqrANP/7vFcBQN3czxeYYWX3DK07alu6GhH1Y4sHbdm616uU0\nll7xbDzxAkEAzAtN2IyftNygV2EGiaGgqLyo/tD9+Vui2qCQplqe4jvWh/5Sparl\nOjmKo+uAW+hLrLVMnHzRWxbWU8hirH5FNQJATO+ZxCK4etXXAnQmG41NCAqANWB2\nB+2HJbH2NcQ2QHvAHUm741JGn/KI/aBlo7KEjFRDWUVUB5ji64BbUwCsMQJBAIku\nLGcjnBf/oLk+XSPZC2eGd2Ph5G5qYmH0Q2vkTx+wtTn3DV+eNsDfgMtWAJVJ5t61\ngU1QSXyhLPVlKpnnxuUCQC+xvvWjWtsLaFtAsZywJiqLxQzHts8XLGZptYJ5tLWV\nrtmYtBcJCN48RrgQHry/xWYeA4K/AFQpXfNPgprQ96Q=\n-----END RSA PRIVATE KEY-----\n", | ||||
| 	UserID:      "fake", | ||||
| } | ||||
|  | ||||
| // ImportedKeyPair is the parsed result from ImportOutput. | ||||
| var ImportedKeyPair = KeyPair{ | ||||
| 	Name:        "importedkey", | ||||
| 	Fingerprint: "1e:2c:9b:56:79:4b:45:77:f9:ca:7a:98:2c:b0:d5:3c", | ||||
| 	PublicKey:   "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDx8nkQv/zgGgB4rMYmIf+6A4l6Rr+o/6lHBQdW5aYd44bd8JttDCE/F/pNRr0lRE+PiqSPO8nDPHw0010JeMH9gYgnnFlyY3/OcJ02RhIPyyxYpv9FhY+2YiUkpwFOcLImyrxEsYXpD/0d3ac30bNH6Sw9JD9UZHYcpSxsIbECHw== Generated by Nova", | ||||
| 	UserID:      "fake", | ||||
| } | ||||
|  | ||||
| // HandleListSuccessfully configures the test server to respond to a List request. | ||||
| func HandleListSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/os-keypairs", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "GET") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		fmt.Fprintf(w, ListOutput) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // HandleGetSuccessfully configures the test server to respond to a Get request for "firstkey". | ||||
| func HandleGetSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/os-keypairs/firstkey", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "GET") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		fmt.Fprintf(w, GetOutput) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // HandleCreateSuccessfully configures the test server to respond to a Create request for a new | ||||
| // keypair called "createdkey". | ||||
| func HandleCreateSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/os-keypairs", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "POST") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
| 		th.TestJSONRequest(t, r, `{ "keypair": { "name": "createdkey" } }`) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		fmt.Fprintf(w, CreateOutput) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // HandleImportSuccessfully configures the test server to respond to an Import request for an | ||||
| // existing keypair called "importedkey". | ||||
| func HandleImportSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/os-keypairs", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "POST") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
| 		th.TestJSONRequest(t, r, ` | ||||
| 			{ | ||||
| 				"keypair": { | ||||
| 					"name": "importedkey", | ||||
| 					"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDx8nkQv/zgGgB4rMYmIf+6A4l6Rr+o/6lHBQdW5aYd44bd8JttDCE/F/pNRr0lRE+PiqSPO8nDPHw0010JeMH9gYgnnFlyY3/OcJ02RhIPyyxYpv9FhY+2YiUkpwFOcLImyrxEsYXpD/0d3ac30bNH6Sw9JD9UZHYcpSxsIbECHw== Generated by Nova" | ||||
| 				} | ||||
| 			} | ||||
| 		`) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		fmt.Fprintf(w, ImportOutput) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // HandleDeleteSuccessfully configures the test server to respond to a Delete request for a | ||||
| // keypair called "deletedkey". | ||||
| func HandleDeleteSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/os-keypairs/deletedkey", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "DELETE") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
|  | ||||
| 		w.WriteHeader(http.StatusAccepted) | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										102
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/requests.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										102
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/requests.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,102 +0,0 @@ | ||||
| package keypairs | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
|  | ||||
| 	"github.com/rackspace/gophercloud" | ||||
| 	"github.com/rackspace/gophercloud/openstack/compute/v2/servers" | ||||
| 	"github.com/rackspace/gophercloud/pagination" | ||||
| ) | ||||
|  | ||||
| // CreateOptsExt adds a KeyPair option to the base CreateOpts. | ||||
| type CreateOptsExt struct { | ||||
| 	servers.CreateOptsBuilder | ||||
| 	KeyName string `json:"key_name,omitempty"` | ||||
| } | ||||
|  | ||||
| // ToServerCreateMap adds the key_name and, optionally, key_data options to | ||||
| // the base server creation options. | ||||
| func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) { | ||||
| 	base, err := opts.CreateOptsBuilder.ToServerCreateMap() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if opts.KeyName == "" { | ||||
| 		return base, nil | ||||
| 	} | ||||
|  | ||||
| 	serverMap := base["server"].(map[string]interface{}) | ||||
| 	serverMap["key_name"] = opts.KeyName | ||||
|  | ||||
| 	return base, nil | ||||
| } | ||||
|  | ||||
| // List returns a Pager that allows you to iterate over a collection of KeyPairs. | ||||
| func List(client *gophercloud.ServiceClient) pagination.Pager { | ||||
| 	return pagination.NewPager(client, listURL(client), func(r pagination.PageResult) pagination.Page { | ||||
| 		return KeyPairPage{pagination.SinglePageBase(r)} | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // CreateOptsBuilder describes struct types that can be accepted by the Create call. Notable, the | ||||
| // CreateOpts struct in this package does. | ||||
| type CreateOptsBuilder interface { | ||||
| 	ToKeyPairCreateMap() (map[string]interface{}, error) | ||||
| } | ||||
|  | ||||
| // CreateOpts specifies keypair creation or import parameters. | ||||
| type CreateOpts struct { | ||||
| 	// Name [required] is a friendly name to refer to this KeyPair in other services. | ||||
| 	Name string | ||||
|  | ||||
| 	// PublicKey [optional] is a pregenerated OpenSSH-formatted public key. If provided, this key | ||||
| 	// will be imported and no new key will be created. | ||||
| 	PublicKey string | ||||
| } | ||||
|  | ||||
| // ToKeyPairCreateMap constructs a request body from CreateOpts. | ||||
| func (opts CreateOpts) ToKeyPairCreateMap() (map[string]interface{}, error) { | ||||
| 	if opts.Name == "" { | ||||
| 		return nil, errors.New("Missing field required for keypair creation: Name") | ||||
| 	} | ||||
|  | ||||
| 	keypair := make(map[string]interface{}) | ||||
| 	keypair["name"] = opts.Name | ||||
| 	if opts.PublicKey != "" { | ||||
| 		keypair["public_key"] = opts.PublicKey | ||||
| 	} | ||||
|  | ||||
| 	return map[string]interface{}{"keypair": keypair}, nil | ||||
| } | ||||
|  | ||||
| // Create requests the creation of a new keypair on the server, or to import a pre-existing | ||||
| // keypair. | ||||
| func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { | ||||
| 	var res CreateResult | ||||
|  | ||||
| 	reqBody, err := opts.ToKeyPairCreateMap() | ||||
| 	if err != nil { | ||||
| 		res.Err = err | ||||
| 		return res | ||||
| 	} | ||||
|  | ||||
| 	_, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{ | ||||
| 		OkCodes: []int{200}, | ||||
| 	}) | ||||
| 	return res | ||||
| } | ||||
|  | ||||
| // Get returns public data about a previously uploaded KeyPair. | ||||
| func Get(client *gophercloud.ServiceClient, name string) GetResult { | ||||
| 	var res GetResult | ||||
| 	_, res.Err = client.Get(getURL(client, name), &res.Body, nil) | ||||
| 	return res | ||||
| } | ||||
|  | ||||
| // Delete requests the deletion of a previous stored KeyPair from the server. | ||||
| func Delete(client *gophercloud.ServiceClient, name string) DeleteResult { | ||||
| 	var res DeleteResult | ||||
| 	_, res.Err = client.Delete(deleteURL(client, name), nil) | ||||
| 	return res | ||||
| } | ||||
| @@ -1,94 +0,0 @@ | ||||
| package keypairs | ||||
|  | ||||
| import ( | ||||
| 	"github.com/mitchellh/mapstructure" | ||||
| 	"github.com/rackspace/gophercloud" | ||||
| 	"github.com/rackspace/gophercloud/pagination" | ||||
| ) | ||||
|  | ||||
| // KeyPair is an SSH key known to the OpenStack cluster that is available to be injected into | ||||
| // servers. | ||||
| type KeyPair struct { | ||||
| 	// Name is used to refer to this keypair from other services within this region. | ||||
| 	Name string `mapstructure:"name"` | ||||
|  | ||||
| 	// Fingerprint is a short sequence of bytes that can be used to authenticate or validate a longer | ||||
| 	// public key. | ||||
| 	Fingerprint string `mapstructure:"fingerprint"` | ||||
|  | ||||
| 	// PublicKey is the public key from this pair, in OpenSSH format. "ssh-rsa AAAAB3Nz..." | ||||
| 	PublicKey string `mapstructure:"public_key"` | ||||
|  | ||||
| 	// PrivateKey is the private key from this pair, in PEM format. | ||||
| 	// "-----BEGIN RSA PRIVATE KEY-----\nMIICXA..." It is only present if this keypair was just | ||||
| 	// returned from a Create call | ||||
| 	PrivateKey string `mapstructure:"private_key"` | ||||
|  | ||||
| 	// UserID is the user who owns this keypair. | ||||
| 	UserID string `mapstructure:"user_id"` | ||||
| } | ||||
|  | ||||
| // KeyPairPage stores a single, only page of KeyPair results from a List call. | ||||
| type KeyPairPage struct { | ||||
| 	pagination.SinglePageBase | ||||
| } | ||||
|  | ||||
| // IsEmpty determines whether or not a KeyPairPage is empty. | ||||
| func (page KeyPairPage) IsEmpty() (bool, error) { | ||||
| 	ks, err := ExtractKeyPairs(page) | ||||
| 	return len(ks) == 0, err | ||||
| } | ||||
|  | ||||
| // ExtractKeyPairs interprets a page of results as a slice of KeyPairs. | ||||
| func ExtractKeyPairs(page pagination.Page) ([]KeyPair, error) { | ||||
| 	type pair struct { | ||||
| 		KeyPair KeyPair `mapstructure:"keypair"` | ||||
| 	} | ||||
|  | ||||
| 	var resp struct { | ||||
| 		KeyPairs []pair `mapstructure:"keypairs"` | ||||
| 	} | ||||
|  | ||||
| 	err := mapstructure.Decode(page.(KeyPairPage).Body, &resp) | ||||
| 	results := make([]KeyPair, len(resp.KeyPairs)) | ||||
| 	for i, pair := range resp.KeyPairs { | ||||
| 		results[i] = pair.KeyPair | ||||
| 	} | ||||
| 	return results, err | ||||
| } | ||||
|  | ||||
| type keyPairResult struct { | ||||
| 	gophercloud.Result | ||||
| } | ||||
|  | ||||
| // Extract is a method that attempts to interpret any KeyPair resource response as a KeyPair struct. | ||||
| func (r keyPairResult) Extract() (*KeyPair, error) { | ||||
| 	if r.Err != nil { | ||||
| 		return nil, r.Err | ||||
| 	} | ||||
|  | ||||
| 	var res struct { | ||||
| 		KeyPair *KeyPair `json:"keypair" mapstructure:"keypair"` | ||||
| 	} | ||||
|  | ||||
| 	err := mapstructure.Decode(r.Body, &res) | ||||
| 	return res.KeyPair, err | ||||
| } | ||||
|  | ||||
| // CreateResult is the response from a Create operation. Call its Extract method to interpret it | ||||
| // as a KeyPair. | ||||
| type CreateResult struct { | ||||
| 	keyPairResult | ||||
| } | ||||
|  | ||||
| // GetResult is the response from a Get operation. Call its Extract method to interpret it | ||||
| // as a KeyPair. | ||||
| type GetResult struct { | ||||
| 	keyPairResult | ||||
| } | ||||
|  | ||||
| // DeleteResult is the response from a Delete operation. Call its Extract method to determine if | ||||
| // the call succeeded or failed. | ||||
| type DeleteResult struct { | ||||
| 	gophercloud.ErrResult | ||||
| } | ||||
							
								
								
									
										25
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/urls.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/urls.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,25 +0,0 @@ | ||||
| package keypairs | ||||
|  | ||||
| import "github.com/rackspace/gophercloud" | ||||
|  | ||||
| const resourcePath = "os-keypairs" | ||||
|  | ||||
| func resourceURL(c *gophercloud.ServiceClient) string { | ||||
| 	return c.ServiceURL(resourcePath) | ||||
| } | ||||
|  | ||||
| func listURL(c *gophercloud.ServiceClient) string { | ||||
| 	return resourceURL(c) | ||||
| } | ||||
|  | ||||
| func createURL(c *gophercloud.ServiceClient) string { | ||||
| 	return resourceURL(c) | ||||
| } | ||||
|  | ||||
| func getURL(c *gophercloud.ServiceClient, name string) string { | ||||
| 	return c.ServiceURL(resourcePath, name) | ||||
| } | ||||
|  | ||||
| func deleteURL(c *gophercloud.ServiceClient, name string) string { | ||||
| 	return getURL(c, name) | ||||
| } | ||||
| @@ -1,2 +0,0 @@ | ||||
| // Package network provides the ability to manage nova-networks | ||||
| package networks | ||||
							
								
								
									
										209
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/fixtures.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										209
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/fixtures.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,209 +0,0 @@ | ||||
| // +build fixtures | ||||
|  | ||||
| package networks | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"testing" | ||||
| 	"time" | ||||
|  | ||||
| 	th "github.com/rackspace/gophercloud/testhelper" | ||||
| 	"github.com/rackspace/gophercloud/testhelper/client" | ||||
| ) | ||||
|  | ||||
| // ListOutput is a sample response to a List call. | ||||
| const ListOutput = ` | ||||
| { | ||||
|     "networks": [ | ||||
|         { | ||||
|             "bridge": "br100", | ||||
|             "bridge_interface": "eth0", | ||||
|             "broadcast": "10.0.0.7", | ||||
|             "cidr": "10.0.0.0/29", | ||||
|             "cidr_v6": null, | ||||
|             "created_at": "2011-08-15 06:19:19.387525", | ||||
|             "deleted": false, | ||||
|             "deleted_at": null, | ||||
|             "dhcp_start": "10.0.0.3", | ||||
|             "dns1": null, | ||||
|             "dns2": null, | ||||
|             "gateway": "10.0.0.1", | ||||
|             "gateway_v6": null, | ||||
|             "host": "nsokolov-desktop", | ||||
|             "id": "20c8acc0-f747-4d71-a389-46d078ebf047", | ||||
|             "injected": false, | ||||
|             "label": "mynet_0", | ||||
|             "multi_host": false, | ||||
|             "netmask": "255.255.255.248", | ||||
|             "netmask_v6": null, | ||||
|             "priority": null, | ||||
|             "project_id": "1234", | ||||
|             "rxtx_base": null, | ||||
|             "updated_at": "2011-08-16 09:26:13.048257", | ||||
|             "vlan": 100, | ||||
|             "vpn_private_address": "10.0.0.2", | ||||
|             "vpn_public_address": "127.0.0.1", | ||||
|             "vpn_public_port": 1000 | ||||
|         }, | ||||
|         { | ||||
|             "bridge": "br101", | ||||
|             "bridge_interface": "eth0", | ||||
|             "broadcast": "10.0.0.15", | ||||
|             "cidr": "10.0.0.10/29", | ||||
|             "cidr_v6": null, | ||||
|             "created_at": "2011-08-15 06:19:19.885495", | ||||
|             "deleted": false, | ||||
|             "deleted_at": null, | ||||
|             "dhcp_start": "10.0.0.11", | ||||
|             "dns1": null, | ||||
|             "dns2": null, | ||||
|             "gateway": "10.0.0.9", | ||||
|             "gateway_v6": null, | ||||
|             "host": null, | ||||
|             "id": "20c8acc0-f747-4d71-a389-46d078ebf000", | ||||
|             "injected": false, | ||||
|             "label": "mynet_1", | ||||
|             "multi_host": false, | ||||
|             "netmask": "255.255.255.248", | ||||
|             "netmask_v6": null, | ||||
|             "priority": null, | ||||
|             "project_id": null, | ||||
|             "rxtx_base": null, | ||||
|             "updated_at": null, | ||||
|             "vlan": 101, | ||||
|             "vpn_private_address": "10.0.0.10", | ||||
|             "vpn_public_address": null, | ||||
|             "vpn_public_port": 1001 | ||||
|         } | ||||
|     ] | ||||
| } | ||||
| ` | ||||
|  | ||||
| // GetOutput is a sample response to a Get call. | ||||
| const GetOutput = ` | ||||
| { | ||||
|     "network": { | ||||
| 			"bridge": "br101", | ||||
| 			"bridge_interface": "eth0", | ||||
| 			"broadcast": "10.0.0.15", | ||||
| 			"cidr": "10.0.0.10/29", | ||||
| 			"cidr_v6": null, | ||||
| 			"created_at": "2011-08-15 06:19:19.885495", | ||||
| 			"deleted": false, | ||||
| 			"deleted_at": null, | ||||
| 			"dhcp_start": "10.0.0.11", | ||||
| 			"dns1": null, | ||||
| 			"dns2": null, | ||||
| 			"gateway": "10.0.0.9", | ||||
| 			"gateway_v6": null, | ||||
| 			"host": null, | ||||
| 			"id": "20c8acc0-f747-4d71-a389-46d078ebf000", | ||||
| 			"injected": false, | ||||
| 			"label": "mynet_1", | ||||
| 			"multi_host": false, | ||||
| 			"netmask": "255.255.255.248", | ||||
| 			"netmask_v6": null, | ||||
| 			"priority": null, | ||||
| 			"project_id": null, | ||||
| 			"rxtx_base": null, | ||||
| 			"updated_at": null, | ||||
| 			"vlan": 101, | ||||
| 			"vpn_private_address": "10.0.0.10", | ||||
| 			"vpn_public_address": null, | ||||
| 			"vpn_public_port": 1001 | ||||
| 		} | ||||
| } | ||||
| ` | ||||
|  | ||||
| // FirstNetwork is the first result in ListOutput. | ||||
| var nilTime time.Time | ||||
| var FirstNetwork = Network{ | ||||
| 	Bridge:            "br100", | ||||
| 	BridgeInterface:   "eth0", | ||||
| 	Broadcast:         "10.0.0.7", | ||||
| 	CIDR:              "10.0.0.0/29", | ||||
| 	CIDRv6:            "", | ||||
| 	CreatedAt:         time.Date(2011, 8, 15, 6, 19, 19, 387525000, time.UTC), | ||||
| 	Deleted:           false, | ||||
| 	DeletedAt:         nilTime, | ||||
| 	DHCPStart:         "10.0.0.3", | ||||
| 	DNS1:              "", | ||||
| 	DNS2:              "", | ||||
| 	Gateway:           "10.0.0.1", | ||||
| 	Gatewayv6:         "", | ||||
| 	Host:              "nsokolov-desktop", | ||||
| 	ID:                "20c8acc0-f747-4d71-a389-46d078ebf047", | ||||
| 	Injected:          false, | ||||
| 	Label:             "mynet_0", | ||||
| 	MultiHost:         false, | ||||
| 	Netmask:           "255.255.255.248", | ||||
| 	Netmaskv6:         "", | ||||
| 	Priority:          0, | ||||
| 	ProjectID:         "1234", | ||||
| 	RXTXBase:          0, | ||||
| 	UpdatedAt:         time.Date(2011, 8, 16, 9, 26, 13, 48257000, time.UTC), | ||||
| 	VLAN:              100, | ||||
| 	VPNPrivateAddress: "10.0.0.2", | ||||
| 	VPNPublicAddress:  "127.0.0.1", | ||||
| 	VPNPublicPort:     1000, | ||||
| } | ||||
|  | ||||
| // SecondNetwork is the second result in ListOutput. | ||||
| var SecondNetwork = Network{ | ||||
| 	Bridge:            "br101", | ||||
| 	BridgeInterface:   "eth0", | ||||
| 	Broadcast:         "10.0.0.15", | ||||
| 	CIDR:              "10.0.0.10/29", | ||||
| 	CIDRv6:            "", | ||||
| 	CreatedAt:         time.Date(2011, 8, 15, 6, 19, 19, 885495000, time.UTC), | ||||
| 	Deleted:           false, | ||||
| 	DeletedAt:         nilTime, | ||||
| 	DHCPStart:         "10.0.0.11", | ||||
| 	DNS1:              "", | ||||
| 	DNS2:              "", | ||||
| 	Gateway:           "10.0.0.9", | ||||
| 	Gatewayv6:         "", | ||||
| 	Host:              "", | ||||
| 	ID:                "20c8acc0-f747-4d71-a389-46d078ebf000", | ||||
| 	Injected:          false, | ||||
| 	Label:             "mynet_1", | ||||
| 	MultiHost:         false, | ||||
| 	Netmask:           "255.255.255.248", | ||||
| 	Netmaskv6:         "", | ||||
| 	Priority:          0, | ||||
| 	ProjectID:         "", | ||||
| 	RXTXBase:          0, | ||||
| 	UpdatedAt:         nilTime, | ||||
| 	VLAN:              101, | ||||
| 	VPNPrivateAddress: "10.0.0.10", | ||||
| 	VPNPublicAddress:  "", | ||||
| 	VPNPublicPort:     1001, | ||||
| } | ||||
|  | ||||
| // ExpectedNetworkSlice is the slice of results that should be parsed | ||||
| // from ListOutput, in the expected order. | ||||
| var ExpectedNetworkSlice = []Network{FirstNetwork, SecondNetwork} | ||||
|  | ||||
| // HandleListSuccessfully configures the test server to respond to a List request. | ||||
| func HandleListSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/os-networks", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "GET") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		fmt.Fprintf(w, ListOutput) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // HandleGetSuccessfully configures the test server to respond to a Get request | ||||
| // for an existing network. | ||||
| func HandleGetSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/os-networks/20c8acc0-f747-4d71-a389-46d078ebf000", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "GET") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		fmt.Fprintf(w, GetOutput) | ||||
| 	}) | ||||
| } | ||||
| @@ -1,22 +0,0 @@ | ||||
| package networks | ||||
|  | ||||
| import ( | ||||
| 	"github.com/rackspace/gophercloud" | ||||
| 	"github.com/rackspace/gophercloud/pagination" | ||||
| ) | ||||
|  | ||||
| // List returns a Pager that allows you to iterate over a collection of Network. | ||||
| func List(client *gophercloud.ServiceClient) pagination.Pager { | ||||
| 	url := listURL(client) | ||||
| 	createPage := func(r pagination.PageResult) pagination.Page { | ||||
| 		return NetworkPage{pagination.SinglePageBase(r)} | ||||
| 	} | ||||
| 	return pagination.NewPager(client, url, createPage) | ||||
| } | ||||
|  | ||||
| // Get returns data about a previously created Network. | ||||
| func Get(client *gophercloud.ServiceClient, id string) GetResult { | ||||
| 	var res GetResult | ||||
| 	_, res.Err = client.Get(getURL(client, id), &res.Body, nil) | ||||
| 	return res | ||||
| } | ||||
							
								
								
									
										222
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/results.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										222
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/results.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,222 +0,0 @@ | ||||
| package networks | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/mitchellh/mapstructure" | ||||
| 	"github.com/rackspace/gophercloud" | ||||
| 	"github.com/rackspace/gophercloud/pagination" | ||||
| ) | ||||
|  | ||||
| // A Network represents a nova-network that an instance communicates on | ||||
| type Network struct { | ||||
| 	// The Bridge that VIFs on this network are connected to | ||||
| 	Bridge string `mapstructure:"bridge"` | ||||
|  | ||||
| 	// BridgeInterface is what interface is connected to the Bridge | ||||
| 	BridgeInterface string `mapstructure:"bridge_interface"` | ||||
|  | ||||
| 	// The Broadcast address of the network. | ||||
| 	Broadcast string `mapstructure:"broadcast"` | ||||
|  | ||||
| 	// CIDR is the IPv4 subnet. | ||||
| 	CIDR string `mapstructure:"cidr"` | ||||
|  | ||||
| 	// CIDRv6 is the IPv6 subnet. | ||||
| 	CIDRv6 string `mapstructure:"cidr_v6"` | ||||
|  | ||||
| 	// CreatedAt is when the network was created.. | ||||
| 	CreatedAt time.Time `mapstructure:"-"` | ||||
|  | ||||
| 	// Deleted shows if the network has been deleted. | ||||
| 	Deleted bool `mapstructure:"deleted"` | ||||
|  | ||||
| 	// DeletedAt is the time when the network was deleted. | ||||
| 	DeletedAt time.Time `mapstructure:"-"` | ||||
|  | ||||
| 	// DHCPStart is the start of the DHCP address range. | ||||
| 	DHCPStart string `mapstructure:"dhcp_start"` | ||||
|  | ||||
| 	// DNS1 is the first DNS server to use through DHCP. | ||||
| 	DNS1 string `mapstructure:"dns_1"` | ||||
|  | ||||
| 	// DNS2 is the first DNS server to use through DHCP. | ||||
| 	DNS2 string `mapstructure:"dns_2"` | ||||
|  | ||||
| 	// Gateway is the network gateway. | ||||
| 	Gateway string `mapstructure:"gateway"` | ||||
|  | ||||
| 	// Gatewayv6 is the IPv6 network gateway. | ||||
| 	Gatewayv6 string `mapstructure:"gateway_v6"` | ||||
|  | ||||
| 	// Host is the host that the network service is running on. | ||||
| 	Host string `mapstructure:"host"` | ||||
|  | ||||
| 	// ID is the UUID of the network. | ||||
| 	ID string `mapstructure:"id"` | ||||
|  | ||||
| 	// Injected determines if network information is injected into the host. | ||||
| 	Injected bool `mapstructure:"injected"` | ||||
|  | ||||
| 	// Label is the common name that the network has.. | ||||
| 	Label string `mapstructure:"label"` | ||||
|  | ||||
| 	// MultiHost is if multi-host networking is enablec.. | ||||
| 	MultiHost bool `mapstructure:"multi_host"` | ||||
|  | ||||
| 	// Netmask is the network netmask. | ||||
| 	Netmask string `mapstructure:"netmask"` | ||||
|  | ||||
| 	// Netmaskv6 is the IPv6 netmask. | ||||
| 	Netmaskv6 string `mapstructure:"netmask_v6"` | ||||
|  | ||||
| 	// Priority is the network interface priority. | ||||
| 	Priority int `mapstructure:"priority"` | ||||
|  | ||||
| 	// ProjectID is the project associated with this network. | ||||
| 	ProjectID string `mapstructure:"project_id"` | ||||
|  | ||||
| 	// RXTXBase configures bandwidth entitlement. | ||||
| 	RXTXBase int `mapstructure:"rxtx_base"` | ||||
|  | ||||
| 	// UpdatedAt is the time when the network was last updated. | ||||
| 	UpdatedAt time.Time `mapstructure:"-"` | ||||
|  | ||||
| 	// VLAN is the vlan this network runs on. | ||||
| 	VLAN int `mapstructure:"vlan"` | ||||
|  | ||||
| 	// VPNPrivateAddress is the private address of the CloudPipe VPN. | ||||
| 	VPNPrivateAddress string `mapstructure:"vpn_private_address"` | ||||
|  | ||||
| 	// VPNPublicAddress is the public address of the CloudPipe VPN. | ||||
| 	VPNPublicAddress string `mapstructure:"vpn_public_address"` | ||||
|  | ||||
| 	// VPNPublicPort is the port of the CloudPipe VPN. | ||||
| 	VPNPublicPort int `mapstructure:"vpn_public_port"` | ||||
| } | ||||
|  | ||||
| // NetworkPage stores a single, only page of Networks | ||||
| // results from a List call. | ||||
| type NetworkPage struct { | ||||
| 	pagination.SinglePageBase | ||||
| } | ||||
|  | ||||
| // IsEmpty determines whether or not a NetworkPage is empty. | ||||
| func (page NetworkPage) IsEmpty() (bool, error) { | ||||
| 	va, err := ExtractNetworks(page) | ||||
| 	return len(va) == 0, err | ||||
| } | ||||
|  | ||||
| // ExtractNetworks interprets a page of results as a slice of Networks | ||||
| func ExtractNetworks(page pagination.Page) ([]Network, error) { | ||||
| 	var res struct { | ||||
| 		Networks []Network `mapstructure:"networks"` | ||||
| 	} | ||||
|  | ||||
| 	err := mapstructure.Decode(page.(NetworkPage).Body, &res) | ||||
|  | ||||
| 	var rawNetworks []interface{} | ||||
| 	body := page.(NetworkPage).Body | ||||
| 	switch body.(type) { | ||||
| 	case map[string]interface{}: | ||||
| 		rawNetworks = body.(map[string]interface{})["networks"].([]interface{}) | ||||
| 	case map[string][]interface{}: | ||||
| 		rawNetworks = body.(map[string][]interface{})["networks"] | ||||
| 	default: | ||||
| 		return res.Networks, fmt.Errorf("Unknown type") | ||||
| 	} | ||||
|  | ||||
| 	for i := range rawNetworks { | ||||
| 		thisNetwork := rawNetworks[i].(map[string]interface{}) | ||||
| 		if t, ok := thisNetwork["created_at"].(string); ok && t != "" { | ||||
| 			createdAt, err := time.Parse("2006-01-02 15:04:05.000000", t) | ||||
| 			if err != nil { | ||||
| 				return res.Networks, err | ||||
| 			} | ||||
| 			res.Networks[i].CreatedAt = createdAt | ||||
| 		} | ||||
|  | ||||
| 		if t, ok := thisNetwork["updated_at"].(string); ok && t != "" { | ||||
| 			updatedAt, err := time.Parse("2006-01-02 15:04:05.000000", t) | ||||
| 			if err != nil { | ||||
| 				return res.Networks, err | ||||
| 			} | ||||
| 			res.Networks[i].UpdatedAt = updatedAt | ||||
| 		} | ||||
|  | ||||
| 		if t, ok := thisNetwork["deleted_at"].(string); ok && t != "" { | ||||
| 			deletedAt, err := time.Parse("2006-01-02 15:04:05.000000", t) | ||||
| 			if err != nil { | ||||
| 				return res.Networks, err | ||||
| 			} | ||||
| 			res.Networks[i].DeletedAt = deletedAt | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return res.Networks, err | ||||
| } | ||||
|  | ||||
| type NetworkResult struct { | ||||
| 	gophercloud.Result | ||||
| } | ||||
|  | ||||
| // Extract is a method that attempts to interpret any Network resource | ||||
| // response as a Network struct. | ||||
| func (r NetworkResult) Extract() (*Network, error) { | ||||
| 	if r.Err != nil { | ||||
| 		return nil, r.Err | ||||
| 	} | ||||
|  | ||||
| 	var res struct { | ||||
| 		Network *Network `json:"network" mapstructure:"network"` | ||||
| 	} | ||||
|  | ||||
| 	config := &mapstructure.DecoderConfig{ | ||||
| 		Result:           &res, | ||||
| 		WeaklyTypedInput: true, | ||||
| 	} | ||||
| 	decoder, err := mapstructure.NewDecoder(config) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if err := decoder.Decode(r.Body); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	b := r.Body.(map[string]interface{})["network"].(map[string]interface{}) | ||||
|  | ||||
| 	if t, ok := b["created_at"].(string); ok && t != "" { | ||||
| 		createdAt, err := time.Parse("2006-01-02 15:04:05.000000", t) | ||||
| 		if err != nil { | ||||
| 			return res.Network, err | ||||
| 		} | ||||
| 		res.Network.CreatedAt = createdAt | ||||
| 	} | ||||
|  | ||||
| 	if t, ok := b["updated_at"].(string); ok && t != "" { | ||||
| 		updatedAt, err := time.Parse("2006-01-02 15:04:05.000000", t) | ||||
| 		if err != nil { | ||||
| 			return res.Network, err | ||||
| 		} | ||||
| 		res.Network.UpdatedAt = updatedAt | ||||
| 	} | ||||
|  | ||||
| 	if t, ok := b["deleted_at"].(string); ok && t != "" { | ||||
| 		deletedAt, err := time.Parse("2006-01-02 15:04:05.000000", t) | ||||
| 		if err != nil { | ||||
| 			return res.Network, err | ||||
| 		} | ||||
| 		res.Network.DeletedAt = deletedAt | ||||
| 	} | ||||
|  | ||||
| 	return res.Network, err | ||||
|  | ||||
| } | ||||
|  | ||||
| // GetResult is the response from a Get operation. Call its Extract method to interpret it | ||||
| // as a Network. | ||||
| type GetResult struct { | ||||
| 	NetworkResult | ||||
| } | ||||
							
								
								
									
										17
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/urls.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										17
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/urls.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,17 +0,0 @@ | ||||
| package networks | ||||
|  | ||||
| import "github.com/rackspace/gophercloud" | ||||
|  | ||||
| const resourcePath = "os-networks" | ||||
|  | ||||
| func resourceURL(c *gophercloud.ServiceClient) string { | ||||
| 	return c.ServiceURL(resourcePath) | ||||
| } | ||||
|  | ||||
| func listURL(c *gophercloud.ServiceClient) string { | ||||
| 	return resourceURL(c) | ||||
| } | ||||
|  | ||||
| func getURL(c *gophercloud.ServiceClient, id string) string { | ||||
| 	return c.ServiceURL(resourcePath, id) | ||||
| } | ||||
| @@ -1,3 +0,0 @@ | ||||
| // Package quotasets provides information and interaction with QuotaSet | ||||
| // extension for the OpenStack Compute service. | ||||
| package quotasets | ||||
| @@ -1,59 +0,0 @@ | ||||
| // +build fixtures | ||||
|  | ||||
| package quotasets | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"testing" | ||||
|  | ||||
| 	th "github.com/rackspace/gophercloud/testhelper" | ||||
| 	"github.com/rackspace/gophercloud/testhelper/client" | ||||
| ) | ||||
|  | ||||
| // GetOutput is a sample response to a Get call. | ||||
| const GetOutput = ` | ||||
| { | ||||
|    "quota_set" : { | ||||
|       "instances" : 25, | ||||
|       "security_groups" : 10, | ||||
|       "security_group_rules" : 20, | ||||
|       "cores" : 200, | ||||
|       "injected_file_content_bytes" : 10240, | ||||
|       "injected_files" : 5, | ||||
|       "metadata_items" : 128, | ||||
|       "ram" : 200000, | ||||
|       "keypairs" : 10, | ||||
|       "injected_file_path_bytes" : 255 | ||||
|    } | ||||
| } | ||||
| ` | ||||
|  | ||||
| const FirstTenantID = "555544443333222211110000ffffeeee" | ||||
|  | ||||
| // FirstQuotaSet is the first result in ListOutput. | ||||
| var FirstQuotaSet = QuotaSet{ | ||||
| 	FixedIps:                 0, | ||||
| 	FloatingIps:              0, | ||||
| 	InjectedFileContentBytes: 10240, | ||||
| 	InjectedFilePathBytes:    255, | ||||
| 	InjectedFiles:            5, | ||||
| 	KeyPairs:                 10, | ||||
| 	MetadataItems:            128, | ||||
| 	Ram:                      200000, | ||||
| 	SecurityGroupRules:       20, | ||||
| 	SecurityGroups:           10, | ||||
| 	Cores:                    200, | ||||
| 	Instances:                25, | ||||
| } | ||||
|  | ||||
| // HandleGetSuccessfully configures the test server to respond to a Get request for sample tenant | ||||
| func HandleGetSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/os-quota-sets/"+FirstTenantID, func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "GET") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		fmt.Fprintf(w, GetOutput) | ||||
| 	}) | ||||
| } | ||||
| @@ -1,12 +0,0 @@ | ||||
| package quotasets | ||||
|  | ||||
| import ( | ||||
| 	"github.com/rackspace/gophercloud" | ||||
| ) | ||||
|  | ||||
| // Get returns public data about a previously created QuotaSet. | ||||
| func Get(client *gophercloud.ServiceClient, tenantID string) GetResult { | ||||
| 	var res GetResult | ||||
| 	_, res.Err = client.Get(getURL(client, tenantID), &res.Body, nil) | ||||
| 	return res | ||||
| } | ||||
| @@ -1,86 +0,0 @@ | ||||
| package quotasets | ||||
|  | ||||
| import ( | ||||
| 	"github.com/mitchellh/mapstructure" | ||||
| 	"github.com/rackspace/gophercloud" | ||||
| 	"github.com/rackspace/gophercloud/pagination" | ||||
| ) | ||||
|  | ||||
| // QuotaSet is a set of operational limits that allow for control of compute usage. | ||||
| type QuotaSet struct { | ||||
| 	//ID is tenant associated with this quota_set | ||||
| 	ID string `mapstructure:"id"` | ||||
| 	//FixedIps is number of fixed ips alloted this quota_set | ||||
| 	FixedIps int `mapstructure:"fixed_ips"` | ||||
| 	// FloatingIps is number of floating ips alloted this quota_set | ||||
| 	FloatingIps int `mapstructure:"floating_ips"` | ||||
| 	// InjectedFileContentBytes is content bytes allowed for each injected file | ||||
| 	InjectedFileContentBytes int `mapstructure:"injected_file_content_bytes"` | ||||
| 	// InjectedFilePathBytes is allowed bytes for each injected file path | ||||
| 	InjectedFilePathBytes int `mapstructure:"injected_file_path_bytes"` | ||||
| 	// InjectedFiles is injected files allowed for each project | ||||
| 	InjectedFiles int `mapstructure:"injected_files"` | ||||
| 	// KeyPairs is number of ssh keypairs | ||||
| 	KeyPairs int `mapstructure:"keypairs"` | ||||
| 	// MetadataItems is number of metadata items allowed for each instance | ||||
| 	MetadataItems int `mapstructure:"metadata_items"` | ||||
| 	// Ram is megabytes allowed for each instance | ||||
| 	Ram int `mapstructure:"ram"` | ||||
| 	// SecurityGroupRules is rules allowed for each security group | ||||
| 	SecurityGroupRules int `mapstructure:"security_group_rules"` | ||||
| 	// SecurityGroups security groups allowed for each project | ||||
| 	SecurityGroups int `mapstructure:"security_groups"` | ||||
| 	// Cores is number of instance cores allowed for each project | ||||
| 	Cores int `mapstructure:"cores"` | ||||
| 	// Instances is number of instances allowed for each project | ||||
| 	Instances int `mapstructure:"instances"` | ||||
| } | ||||
|  | ||||
| // QuotaSetPage stores a single, only page of QuotaSet results from a List call. | ||||
| type QuotaSetPage struct { | ||||
| 	pagination.SinglePageBase | ||||
| } | ||||
|  | ||||
| // IsEmpty determines whether or not a QuotaSetsetPage is empty. | ||||
| func (page QuotaSetPage) IsEmpty() (bool, error) { | ||||
| 	ks, err := ExtractQuotaSets(page) | ||||
| 	return len(ks) == 0, err | ||||
| } | ||||
|  | ||||
| // ExtractQuotaSets interprets a page of results as a slice of QuotaSets. | ||||
| func ExtractQuotaSets(page pagination.Page) ([]QuotaSet, error) { | ||||
| 	var resp struct { | ||||
| 		QuotaSets []QuotaSet `mapstructure:"quotas"` | ||||
| 	} | ||||
|  | ||||
| 	err := mapstructure.Decode(page.(QuotaSetPage).Body, &resp) | ||||
| 	results := make([]QuotaSet, len(resp.QuotaSets)) | ||||
| 	for i, q := range resp.QuotaSets { | ||||
| 		results[i] = q | ||||
| 	} | ||||
| 	return results, err | ||||
| } | ||||
|  | ||||
| type quotaResult struct { | ||||
| 	gophercloud.Result | ||||
| } | ||||
|  | ||||
| // Extract is a method that attempts to interpret any QuotaSet resource response as a QuotaSet struct. | ||||
| func (r quotaResult) Extract() (*QuotaSet, error) { | ||||
| 	if r.Err != nil { | ||||
| 		return nil, r.Err | ||||
| 	} | ||||
|  | ||||
| 	var res struct { | ||||
| 		QuotaSet *QuotaSet `json:"quota_set" mapstructure:"quota_set"` | ||||
| 	} | ||||
|  | ||||
| 	err := mapstructure.Decode(r.Body, &res) | ||||
| 	return res.QuotaSet, err | ||||
| } | ||||
|  | ||||
| // GetResult is the response from a Get operation. Call its Extract method to interpret it | ||||
| // as a QuotaSet. | ||||
| type GetResult struct { | ||||
| 	quotaResult | ||||
| } | ||||
| @@ -1,13 +0,0 @@ | ||||
| package quotasets | ||||
|  | ||||
| import "github.com/rackspace/gophercloud" | ||||
|  | ||||
| const resourcePath = "os-quota-sets" | ||||
|  | ||||
| func resourceURL(c *gophercloud.ServiceClient) string { | ||||
| 	return c.ServiceURL(resourcePath) | ||||
| } | ||||
|  | ||||
| func getURL(c *gophercloud.ServiceClient, tenantID string) string { | ||||
| 	return c.ServiceURL(resourcePath, tenantID) | ||||
| } | ||||
| @@ -1,3 +0,0 @@ | ||||
| // Package schedulerhints enables instances to provide the OpenStack scheduler | ||||
| // hints about where they should be placed in the cloud. | ||||
| package schedulerhints | ||||
| @@ -1,134 +0,0 @@ | ||||
| package schedulerhints | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"regexp" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/rackspace/gophercloud/openstack/compute/v2/servers" | ||||
| ) | ||||
|  | ||||
| // SchedulerHints represents a set of scheduling hints that are passed to the | ||||
| // OpenStack scheduler | ||||
| type SchedulerHints struct { | ||||
| 	// Group specifies a Server Group to place the instance in. | ||||
| 	Group string | ||||
|  | ||||
| 	// DifferentHost will place the instance on a compute node that does not | ||||
| 	// host the given instances. | ||||
| 	DifferentHost []string | ||||
|  | ||||
| 	// SameHost will place the instance on a compute node that hosts the given | ||||
| 	// instances. | ||||
| 	SameHost []string | ||||
|  | ||||
| 	// Query is a conditional statement that results in compute nodes able to | ||||
| 	// host the instance. | ||||
| 	Query []interface{} | ||||
|  | ||||
| 	// TargetCell specifies a cell name where the instance will be placed. | ||||
| 	TargetCell string | ||||
|  | ||||
| 	// BuildNearHostIP specifies a subnet of compute nodes to host the instance. | ||||
| 	BuildNearHostIP string | ||||
| } | ||||
|  | ||||
| // SchedulerHintsBuilder builds the scheduler hints into a serializable format. | ||||
| type SchedulerHintsBuilder interface { | ||||
| 	ToServerSchedulerHintsMap() (map[string]interface{}, error) | ||||
| } | ||||
|  | ||||
| // ToServerSchedulerHintsMap builds the scheduler hints into a serializable format. | ||||
| func (opts SchedulerHints) ToServerSchedulerHintsMap() (map[string]interface{}, error) { | ||||
| 	sh := make(map[string]interface{}) | ||||
|  | ||||
| 	uuidRegex, _ := regexp.Compile("^[a-z0-9]{8}-[a-z0-9]{4}-[1-5][a-z0-9]{3}-[a-z0-9]{4}-[a-z0-9]{12}$") | ||||
|  | ||||
| 	if opts.Group != "" { | ||||
| 		if !uuidRegex.MatchString(opts.Group) { | ||||
| 			return nil, fmt.Errorf("Group must be a UUID") | ||||
| 		} | ||||
| 		sh["group"] = opts.Group | ||||
| 	} | ||||
|  | ||||
| 	if len(opts.DifferentHost) > 0 { | ||||
| 		for _, diffHost := range opts.DifferentHost { | ||||
| 			if !uuidRegex.MatchString(diffHost) { | ||||
| 				return nil, fmt.Errorf("The hosts in DifferentHost must be in UUID format.") | ||||
| 			} | ||||
| 		} | ||||
| 		sh["different_host"] = opts.DifferentHost | ||||
| 	} | ||||
|  | ||||
| 	if len(opts.SameHost) > 0 { | ||||
| 		for _, sameHost := range opts.SameHost { | ||||
| 			if !uuidRegex.MatchString(sameHost) { | ||||
| 				return nil, fmt.Errorf("The hosts in SameHost must be in UUID format.") | ||||
| 			} | ||||
| 		} | ||||
| 		sh["same_host"] = opts.SameHost | ||||
| 	} | ||||
|  | ||||
| 	/* Query can be something simple like: | ||||
| 	     [">=", "$free_ram_mb", 1024] | ||||
|  | ||||
| 			Or more complex like: | ||||
| 				['and', | ||||
| 					['>=', '$free_ram_mb', 1024], | ||||
| 					['>=', '$free_disk_mb', 200 * 1024] | ||||
| 				] | ||||
|  | ||||
| 		Because of the possible complexity, just make sure the length is a minimum of 3. | ||||
| 	*/ | ||||
| 	if len(opts.Query) > 0 { | ||||
| 		if len(opts.Query) < 3 { | ||||
| 			return nil, fmt.Errorf("Query must be a conditional statement in the format of [op,variable,value]") | ||||
| 		} | ||||
| 		sh["query"] = opts.Query | ||||
| 	} | ||||
|  | ||||
| 	if opts.TargetCell != "" { | ||||
| 		sh["target_cell"] = opts.TargetCell | ||||
| 	} | ||||
|  | ||||
| 	if opts.BuildNearHostIP != "" { | ||||
| 		if _, _, err := net.ParseCIDR(opts.BuildNearHostIP); err != nil { | ||||
| 			return nil, fmt.Errorf("BuildNearHostIP must be a valid subnet in the form 192.168.1.1/24") | ||||
| 		} | ||||
| 		ipParts := strings.Split(opts.BuildNearHostIP, "/") | ||||
| 		sh["build_near_host_ip"] = ipParts[0] | ||||
| 		sh["cidr"] = "/" + ipParts[1] | ||||
| 	} | ||||
|  | ||||
| 	return sh, nil | ||||
| } | ||||
|  | ||||
| // CreateOptsExt adds a SchedulerHints option to the base CreateOpts. | ||||
| type CreateOptsExt struct { | ||||
| 	servers.CreateOptsBuilder | ||||
|  | ||||
| 	// SchedulerHints provides a set of hints to the scheduler. | ||||
| 	SchedulerHints SchedulerHintsBuilder | ||||
| } | ||||
|  | ||||
| // ToServerCreateMap adds the SchedulerHints option to the base server creation options. | ||||
| func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) { | ||||
| 	base, err := opts.CreateOptsBuilder.ToServerCreateMap() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	schedulerHints, err := opts.SchedulerHints.ToServerSchedulerHintsMap() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if len(schedulerHints) == 0 { | ||||
| 		return base, nil | ||||
| 	} | ||||
|  | ||||
| 	base["os:scheduler_hints"] = schedulerHints | ||||
|  | ||||
| 	return base, nil | ||||
| } | ||||
| @@ -1 +0,0 @@ | ||||
| package secgroups | ||||
| @@ -1,303 +0,0 @@ | ||||
| package secgroups | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"testing" | ||||
|  | ||||
| 	th "github.com/rackspace/gophercloud/testhelper" | ||||
| 	fake "github.com/rackspace/gophercloud/testhelper/client" | ||||
| ) | ||||
|  | ||||
| const rootPath = "/os-security-groups" | ||||
|  | ||||
| const listGroupsJSON = ` | ||||
| { | ||||
|   "security_groups": [ | ||||
|     { | ||||
|       "description": "default", | ||||
|       "id": "{groupID}", | ||||
|       "name": "default", | ||||
|       "rules": [], | ||||
|       "tenant_id": "openstack" | ||||
|     } | ||||
|   ] | ||||
| } | ||||
| ` | ||||
|  | ||||
| func mockListGroupsResponse(t *testing.T) { | ||||
| 	th.Mux.HandleFunc(rootPath, func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "GET") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		w.WriteHeader(http.StatusOK) | ||||
|  | ||||
| 		fmt.Fprintf(w, listGroupsJSON) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func mockListGroupsByServerResponse(t *testing.T, serverID string) { | ||||
| 	url := fmt.Sprintf("/servers/%s%s", serverID, rootPath) | ||||
| 	th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "GET") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		w.WriteHeader(http.StatusOK) | ||||
|  | ||||
| 		fmt.Fprintf(w, listGroupsJSON) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func mockCreateGroupResponse(t *testing.T) { | ||||
| 	th.Mux.HandleFunc(rootPath, func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "POST") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) | ||||
|  | ||||
| 		th.TestJSONRequest(t, r, ` | ||||
| { | ||||
|   "security_group": { | ||||
|     "name": "test", | ||||
|     "description": "something" | ||||
|   } | ||||
| } | ||||
| 	`) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		w.WriteHeader(http.StatusOK) | ||||
|  | ||||
| 		fmt.Fprintf(w, ` | ||||
| { | ||||
|   "security_group": { | ||||
|     "description": "something", | ||||
|     "id": "{groupID}", | ||||
|     "name": "test", | ||||
|     "rules": [], | ||||
|     "tenant_id": "openstack" | ||||
|   } | ||||
| } | ||||
| `) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func mockUpdateGroupResponse(t *testing.T, groupID string) { | ||||
| 	url := fmt.Sprintf("%s/%s", rootPath, groupID) | ||||
| 	th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "PUT") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) | ||||
|  | ||||
| 		th.TestJSONRequest(t, r, ` | ||||
| { | ||||
|   "security_group": { | ||||
|     "name": "new_name", | ||||
| 		"description": "new_desc" | ||||
|   } | ||||
| } | ||||
| 	`) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		w.WriteHeader(http.StatusOK) | ||||
|  | ||||
| 		fmt.Fprintf(w, ` | ||||
| { | ||||
|   "security_group": { | ||||
|     "description": "something", | ||||
|     "id": "{groupID}", | ||||
|     "name": "new_name", | ||||
|     "rules": [], | ||||
|     "tenant_id": "openstack" | ||||
|   } | ||||
| } | ||||
| `) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func mockGetGroupsResponse(t *testing.T, groupID string) { | ||||
| 	url := fmt.Sprintf("%s/%s", rootPath, groupID) | ||||
| 	th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "GET") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		w.WriteHeader(http.StatusOK) | ||||
|  | ||||
| 		fmt.Fprintf(w, ` | ||||
| { | ||||
|   "security_group": { | ||||
|     "description": "default", | ||||
|     "id": "{groupID}", | ||||
|     "name": "default", | ||||
|     "rules": [ | ||||
|       { | ||||
|         "from_port": 80, | ||||
|         "group": { | ||||
|           "tenant_id": "openstack", | ||||
|           "name": "default" | ||||
|         }, | ||||
|         "ip_protocol": "TCP", | ||||
|         "to_port": 85, | ||||
|         "parent_group_id": "{groupID}", | ||||
|         "ip_range": { | ||||
| 						"cidr": "0.0.0.0" | ||||
| 				}, | ||||
|         "id": "{ruleID}" | ||||
|       } | ||||
|     ], | ||||
|     "tenant_id": "openstack" | ||||
|   } | ||||
| } | ||||
| 			`) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func mockGetNumericIDGroupResponse(t *testing.T, groupID int) { | ||||
| 	url := fmt.Sprintf("%s/%d", rootPath, groupID) | ||||
| 	th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "GET") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		w.WriteHeader(http.StatusOK) | ||||
|  | ||||
| 		fmt.Fprintf(w, ` | ||||
| { | ||||
| 	"security_group": { | ||||
| 		"id": 12345 | ||||
| 	} | ||||
| } | ||||
| 			`) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func mockDeleteGroupResponse(t *testing.T, groupID string) { | ||||
| 	url := fmt.Sprintf("%s/%s", rootPath, groupID) | ||||
| 	th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "DELETE") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		w.WriteHeader(http.StatusAccepted) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func mockAddRuleResponse(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/os-security-group-rules", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "POST") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) | ||||
|  | ||||
| 		th.TestJSONRequest(t, r, ` | ||||
| { | ||||
|   "security_group_rule": { | ||||
|     "from_port": 22, | ||||
|     "ip_protocol": "TCP", | ||||
|     "to_port": 22, | ||||
|     "parent_group_id": "{groupID}", | ||||
|     "cidr": "0.0.0.0/0" | ||||
|   } | ||||
| }	`) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		w.WriteHeader(http.StatusOK) | ||||
|  | ||||
| 		fmt.Fprintf(w, ` | ||||
| { | ||||
|   "security_group_rule": { | ||||
|     "from_port": 22, | ||||
|     "group": {}, | ||||
|     "ip_protocol": "TCP", | ||||
|     "to_port": 22, | ||||
|     "parent_group_id": "{groupID}", | ||||
|     "ip_range": { | ||||
|       "cidr": "0.0.0.0/0" | ||||
|     }, | ||||
|     "id": "{ruleID}" | ||||
|   } | ||||
| }`) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func mockAddRuleResponseICMPZero(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/os-security-group-rules", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "POST") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) | ||||
|  | ||||
| 		th.TestJSONRequest(t, r, ` | ||||
| { | ||||
|   "security_group_rule": { | ||||
|     "from_port": 0, | ||||
|     "ip_protocol": "ICMP", | ||||
|     "to_port": 0, | ||||
|     "parent_group_id": "{groupID}", | ||||
|     "cidr": "0.0.0.0/0" | ||||
|   } | ||||
| }	`) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		w.WriteHeader(http.StatusOK) | ||||
|  | ||||
| 		fmt.Fprintf(w, ` | ||||
| { | ||||
|   "security_group_rule": { | ||||
|     "from_port": 0, | ||||
|     "group": {}, | ||||
|     "ip_protocol": "ICMP", | ||||
|     "to_port": 0, | ||||
|     "parent_group_id": "{groupID}", | ||||
|     "ip_range": { | ||||
|       "cidr": "0.0.0.0/0" | ||||
|     }, | ||||
|     "id": "{ruleID}" | ||||
|   } | ||||
| }`) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func mockDeleteRuleResponse(t *testing.T, ruleID string) { | ||||
| 	url := fmt.Sprintf("/os-security-group-rules/%s", ruleID) | ||||
| 	th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "DELETE") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		w.WriteHeader(http.StatusAccepted) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func mockAddServerToGroupResponse(t *testing.T, serverID string) { | ||||
| 	url := fmt.Sprintf("/servers/%s/action", serverID) | ||||
| 	th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "POST") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) | ||||
|  | ||||
| 		th.TestJSONRequest(t, r, ` | ||||
| { | ||||
|   "addSecurityGroup": { | ||||
|     "name": "test" | ||||
|   } | ||||
| } | ||||
| 	`) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		w.WriteHeader(http.StatusAccepted) | ||||
| 		fmt.Fprintf(w, `{}`) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func mockRemoveServerFromGroupResponse(t *testing.T, serverID string) { | ||||
| 	url := fmt.Sprintf("/servers/%s/action", serverID) | ||||
| 	th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "POST") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) | ||||
|  | ||||
| 		th.TestJSONRequest(t, r, ` | ||||
| { | ||||
|   "removeSecurityGroup": { | ||||
|     "name": "test" | ||||
|   } | ||||
| } | ||||
| 	`) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		w.WriteHeader(http.StatusAccepted) | ||||
| 		fmt.Fprintf(w, `{}`) | ||||
| 	}) | ||||
| } | ||||
| @@ -1,258 +0,0 @@ | ||||
| package secgroups | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/rackspace/gophercloud" | ||||
| 	"github.com/rackspace/gophercloud/pagination" | ||||
| ) | ||||
|  | ||||
| func commonList(client *gophercloud.ServiceClient, url string) pagination.Pager { | ||||
| 	createPage := func(r pagination.PageResult) pagination.Page { | ||||
| 		return SecurityGroupPage{pagination.SinglePageBase(r)} | ||||
| 	} | ||||
|  | ||||
| 	return pagination.NewPager(client, url, createPage) | ||||
| } | ||||
|  | ||||
| // List will return a collection of all the security groups for a particular | ||||
| // tenant. | ||||
| func List(client *gophercloud.ServiceClient) pagination.Pager { | ||||
| 	return commonList(client, rootURL(client)) | ||||
| } | ||||
|  | ||||
| // ListByServer will return a collection of all the security groups which are | ||||
| // associated with a particular server. | ||||
| func ListByServer(client *gophercloud.ServiceClient, serverID string) pagination.Pager { | ||||
| 	return commonList(client, listByServerURL(client, serverID)) | ||||
| } | ||||
|  | ||||
| // GroupOpts is the underlying struct responsible for creating or updating | ||||
| // security groups. It therefore represents the mutable attributes of a | ||||
| // security group. | ||||
| type GroupOpts struct { | ||||
| 	// Required - the name of your security group. | ||||
| 	Name string `json:"name"` | ||||
|  | ||||
| 	// Required - the description of your security group. | ||||
| 	Description string `json:"description"` | ||||
| } | ||||
|  | ||||
| // CreateOpts is the struct responsible for creating a security group. | ||||
| type CreateOpts GroupOpts | ||||
|  | ||||
| // CreateOptsBuilder builds the create options into a serializable format. | ||||
| type CreateOptsBuilder interface { | ||||
| 	ToSecGroupCreateMap() (map[string]interface{}, error) | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	errName = errors.New("Name is a required field") | ||||
| 	errDesc = errors.New("Description is a required field") | ||||
| ) | ||||
|  | ||||
| // ToSecGroupCreateMap builds the create options into a serializable format. | ||||
| func (opts CreateOpts) ToSecGroupCreateMap() (map[string]interface{}, error) { | ||||
| 	sg := make(map[string]interface{}) | ||||
|  | ||||
| 	if opts.Name == "" { | ||||
| 		return sg, errName | ||||
| 	} | ||||
| 	if opts.Description == "" { | ||||
| 		return sg, errDesc | ||||
| 	} | ||||
|  | ||||
| 	sg["name"] = opts.Name | ||||
| 	sg["description"] = opts.Description | ||||
|  | ||||
| 	return map[string]interface{}{"security_group": sg}, nil | ||||
| } | ||||
|  | ||||
| // Create will create a new security group. | ||||
| func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { | ||||
| 	var result CreateResult | ||||
|  | ||||
| 	reqBody, err := opts.ToSecGroupCreateMap() | ||||
| 	if err != nil { | ||||
| 		result.Err = err | ||||
| 		return result | ||||
| 	} | ||||
|  | ||||
| 	_, result.Err = client.Post(rootURL(client), reqBody, &result.Body, &gophercloud.RequestOpts{ | ||||
| 		OkCodes: []int{200}, | ||||
| 	}) | ||||
|  | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // UpdateOpts is the struct responsible for updating an existing security group. | ||||
| type UpdateOpts GroupOpts | ||||
|  | ||||
| // UpdateOptsBuilder builds the update options into a serializable format. | ||||
| type UpdateOptsBuilder interface { | ||||
| 	ToSecGroupUpdateMap() (map[string]interface{}, error) | ||||
| } | ||||
|  | ||||
| // ToSecGroupUpdateMap builds the update options into a serializable format. | ||||
| func (opts UpdateOpts) ToSecGroupUpdateMap() (map[string]interface{}, error) { | ||||
| 	sg := make(map[string]interface{}) | ||||
|  | ||||
| 	if opts.Name == "" { | ||||
| 		return sg, errName | ||||
| 	} | ||||
| 	if opts.Description == "" { | ||||
| 		return sg, errDesc | ||||
| 	} | ||||
|  | ||||
| 	sg["name"] = opts.Name | ||||
| 	sg["description"] = opts.Description | ||||
|  | ||||
| 	return map[string]interface{}{"security_group": sg}, nil | ||||
| } | ||||
|  | ||||
| // Update will modify the mutable properties of a security group, notably its | ||||
| // name and description. | ||||
| func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult { | ||||
| 	var result UpdateResult | ||||
|  | ||||
| 	reqBody, err := opts.ToSecGroupUpdateMap() | ||||
| 	if err != nil { | ||||
| 		result.Err = err | ||||
| 		return result | ||||
| 	} | ||||
|  | ||||
| 	_, result.Err = client.Put(resourceURL(client, id), reqBody, &result.Body, &gophercloud.RequestOpts{ | ||||
| 		OkCodes: []int{200}, | ||||
| 	}) | ||||
|  | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // Get will return details for a particular security group. | ||||
| func Get(client *gophercloud.ServiceClient, id string) GetResult { | ||||
| 	var result GetResult | ||||
| 	_, result.Err = client.Get(resourceURL(client, id), &result.Body, nil) | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // Delete will permanently delete a security group from the project. | ||||
| func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult { | ||||
| 	var result gophercloud.ErrResult | ||||
| 	_, result.Err = client.Delete(resourceURL(client, id), nil) | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // CreateRuleOpts represents the configuration for adding a new rule to an | ||||
| // existing security group. | ||||
| type CreateRuleOpts struct { | ||||
| 	// Required - the ID of the group that this rule will be added to. | ||||
| 	ParentGroupID string `json:"parent_group_id"` | ||||
|  | ||||
| 	// Required - the lower bound of the port range that will be opened. | ||||
| 	FromPort int `json:"from_port"` | ||||
|  | ||||
| 	// Required - the upper bound of the port range that will be opened. | ||||
| 	ToPort int `json:"to_port"` | ||||
|  | ||||
| 	// Required - the protocol type that will be allowed, e.g. TCP. | ||||
| 	IPProtocol string `json:"ip_protocol"` | ||||
|  | ||||
| 	// ONLY required if FromGroupID is blank. This represents the IP range that | ||||
| 	// will be the source of network traffic to your security group. Use | ||||
| 	// 0.0.0.0/0 to allow all IP addresses. | ||||
| 	CIDR string `json:"cidr,omitempty"` | ||||
|  | ||||
| 	// ONLY required if CIDR is blank. This value represents the ID of a group | ||||
| 	// that forwards traffic to the parent group. So, instead of accepting | ||||
| 	// network traffic from an entire IP range, you can instead refine the | ||||
| 	// inbound source by an existing security group. | ||||
| 	FromGroupID string `json:"group_id,omitempty"` | ||||
| } | ||||
|  | ||||
| // CreateRuleOptsBuilder builds the create rule options into a serializable format. | ||||
| type CreateRuleOptsBuilder interface { | ||||
| 	ToRuleCreateMap() (map[string]interface{}, error) | ||||
| } | ||||
|  | ||||
| // ToRuleCreateMap builds the create rule options into a serializable format. | ||||
| func (opts CreateRuleOpts) ToRuleCreateMap() (map[string]interface{}, error) { | ||||
| 	rule := make(map[string]interface{}) | ||||
|  | ||||
| 	if opts.ParentGroupID == "" { | ||||
| 		return rule, errors.New("A ParentGroupID must be set") | ||||
| 	} | ||||
| 	if opts.FromPort == 0 && strings.ToUpper(opts.IPProtocol) != "ICMP" { | ||||
| 		return rule, errors.New("A FromPort must be set") | ||||
| 	} | ||||
| 	if opts.ToPort == 0 && strings.ToUpper(opts.IPProtocol) != "ICMP" { | ||||
| 		return rule, errors.New("A ToPort must be set") | ||||
| 	} | ||||
| 	if opts.IPProtocol == "" { | ||||
| 		return rule, errors.New("A IPProtocol must be set") | ||||
| 	} | ||||
| 	if opts.CIDR == "" && opts.FromGroupID == "" { | ||||
| 		return rule, errors.New("A CIDR or FromGroupID must be set") | ||||
| 	} | ||||
|  | ||||
| 	rule["parent_group_id"] = opts.ParentGroupID | ||||
| 	rule["from_port"] = opts.FromPort | ||||
| 	rule["to_port"] = opts.ToPort | ||||
| 	rule["ip_protocol"] = opts.IPProtocol | ||||
|  | ||||
| 	if opts.CIDR != "" { | ||||
| 		rule["cidr"] = opts.CIDR | ||||
| 	} | ||||
| 	if opts.FromGroupID != "" { | ||||
| 		rule["group_id"] = opts.FromGroupID | ||||
| 	} | ||||
|  | ||||
| 	return map[string]interface{}{"security_group_rule": rule}, nil | ||||
| } | ||||
|  | ||||
| // CreateRule will add a new rule to an existing security group (whose ID is | ||||
| // specified in CreateRuleOpts). You have the option of controlling inbound | ||||
| // traffic from either an IP range (CIDR) or from another security group. | ||||
| func CreateRule(client *gophercloud.ServiceClient, opts CreateRuleOptsBuilder) CreateRuleResult { | ||||
| 	var result CreateRuleResult | ||||
|  | ||||
| 	reqBody, err := opts.ToRuleCreateMap() | ||||
| 	if err != nil { | ||||
| 		result.Err = err | ||||
| 		return result | ||||
| 	} | ||||
|  | ||||
| 	_, result.Err = client.Post(rootRuleURL(client), reqBody, &result.Body, &gophercloud.RequestOpts{ | ||||
| 		OkCodes: []int{200}, | ||||
| 	}) | ||||
|  | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // DeleteRule will permanently delete a rule from a security group. | ||||
| func DeleteRule(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult { | ||||
| 	var result gophercloud.ErrResult | ||||
| 	_, result.Err = client.Delete(resourceRuleURL(client, id), nil) | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| func actionMap(prefix, groupName string) map[string]map[string]string { | ||||
| 	return map[string]map[string]string{ | ||||
| 		prefix + "SecurityGroup": map[string]string{"name": groupName}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // AddServerToGroup will associate a server and a security group, enforcing the | ||||
| // rules of the group on the server. | ||||
| func AddServerToGroup(client *gophercloud.ServiceClient, serverID, groupName string) gophercloud.ErrResult { | ||||
| 	var result gophercloud.ErrResult | ||||
| 	_, result.Err = client.Post(serverActionURL(client, serverID), actionMap("add", groupName), &result.Body, nil) | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // RemoveServerFromGroup will disassociate a server from a security group. | ||||
| func RemoveServerFromGroup(client *gophercloud.ServiceClient, serverID, groupName string) gophercloud.ErrResult { | ||||
| 	var result gophercloud.ErrResult | ||||
| 	_, result.Err = client.Post(serverActionURL(client, serverID), actionMap("remove", groupName), &result.Body, nil) | ||||
| 	return result | ||||
| } | ||||
							
								
								
									
										147
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/results.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										147
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/results.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,147 +0,0 @@ | ||||
| package secgroups | ||||
|  | ||||
| import ( | ||||
| 	"github.com/mitchellh/mapstructure" | ||||
|  | ||||
| 	"github.com/rackspace/gophercloud" | ||||
| 	"github.com/rackspace/gophercloud/pagination" | ||||
| ) | ||||
|  | ||||
| // SecurityGroup represents a security group. | ||||
| type SecurityGroup struct { | ||||
| 	// The unique ID of the group. If Neutron is installed, this ID will be | ||||
| 	// represented as a string UUID; if Neutron is not installed, it will be a | ||||
| 	// numeric ID. For the sake of consistency, we always cast it to a string. | ||||
| 	ID string | ||||
|  | ||||
| 	// The human-readable name of the group, which needs to be unique. | ||||
| 	Name string | ||||
|  | ||||
| 	// The human-readable description of the group. | ||||
| 	Description string | ||||
|  | ||||
| 	// The rules which determine how this security group operates. | ||||
| 	Rules []Rule | ||||
|  | ||||
| 	// The ID of the tenant to which this security group belongs. | ||||
| 	TenantID string `mapstructure:"tenant_id"` | ||||
| } | ||||
|  | ||||
| // Rule represents a security group rule, a policy which determines how a | ||||
| // security group operates and what inbound traffic it allows in. | ||||
| type Rule struct { | ||||
| 	// The unique ID. If Neutron is installed, this ID will be | ||||
| 	// represented as a string UUID; if Neutron is not installed, it will be a | ||||
| 	// numeric ID. For the sake of consistency, we always cast it to a string. | ||||
| 	ID string | ||||
|  | ||||
| 	// The lower bound of the port range which this security group should open up | ||||
| 	FromPort int `mapstructure:"from_port"` | ||||
|  | ||||
| 	// The upper bound of the port range which this security group should open up | ||||
| 	ToPort int `mapstructure:"to_port"` | ||||
|  | ||||
| 	// The IP protocol (e.g. TCP) which the security group accepts | ||||
| 	IPProtocol string `mapstructure:"ip_protocol"` | ||||
|  | ||||
| 	// The CIDR IP range whose traffic can be received | ||||
| 	IPRange IPRange `mapstructure:"ip_range"` | ||||
|  | ||||
| 	// The security group ID to which this rule belongs | ||||
| 	ParentGroupID string `mapstructure:"parent_group_id"` | ||||
|  | ||||
| 	// Not documented. | ||||
| 	Group Group | ||||
| } | ||||
|  | ||||
| // IPRange represents the IP range whose traffic will be accepted by the | ||||
| // security group. | ||||
| type IPRange struct { | ||||
| 	CIDR string | ||||
| } | ||||
|  | ||||
| // Group represents a group. | ||||
| type Group struct { | ||||
| 	TenantID string `mapstructure:"tenant_id"` | ||||
| 	Name     string | ||||
| } | ||||
|  | ||||
| // SecurityGroupPage is a single page of a SecurityGroup collection. | ||||
| type SecurityGroupPage struct { | ||||
| 	pagination.SinglePageBase | ||||
| } | ||||
|  | ||||
| // IsEmpty determines whether or not a page of Security Groups contains any results. | ||||
| func (page SecurityGroupPage) IsEmpty() (bool, error) { | ||||
| 	users, err := ExtractSecurityGroups(page) | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 	return len(users) == 0, nil | ||||
| } | ||||
|  | ||||
| // ExtractSecurityGroups returns a slice of SecurityGroups contained in a single page of results. | ||||
| func ExtractSecurityGroups(page pagination.Page) ([]SecurityGroup, error) { | ||||
| 	casted := page.(SecurityGroupPage).Body | ||||
| 	var response struct { | ||||
| 		SecurityGroups []SecurityGroup `mapstructure:"security_groups"` | ||||
| 	} | ||||
|  | ||||
| 	err := mapstructure.WeakDecode(casted, &response) | ||||
|  | ||||
| 	return response.SecurityGroups, err | ||||
| } | ||||
|  | ||||
| type commonResult struct { | ||||
| 	gophercloud.Result | ||||
| } | ||||
|  | ||||
| // CreateResult represents the result of a create operation. | ||||
| type CreateResult struct { | ||||
| 	commonResult | ||||
| } | ||||
|  | ||||
| // GetResult represents the result of a get operation. | ||||
| type GetResult struct { | ||||
| 	commonResult | ||||
| } | ||||
|  | ||||
| // UpdateResult represents the result of an update operation. | ||||
| type UpdateResult struct { | ||||
| 	commonResult | ||||
| } | ||||
|  | ||||
| // Extract will extract a SecurityGroup struct from most responses. | ||||
| func (r commonResult) Extract() (*SecurityGroup, error) { | ||||
| 	if r.Err != nil { | ||||
| 		return nil, r.Err | ||||
| 	} | ||||
|  | ||||
| 	var response struct { | ||||
| 		SecurityGroup SecurityGroup `mapstructure:"security_group"` | ||||
| 	} | ||||
|  | ||||
| 	err := mapstructure.WeakDecode(r.Body, &response) | ||||
|  | ||||
| 	return &response.SecurityGroup, err | ||||
| } | ||||
|  | ||||
| // CreateRuleResult represents the result when adding rules to a security group. | ||||
| type CreateRuleResult struct { | ||||
| 	gophercloud.Result | ||||
| } | ||||
|  | ||||
| // Extract will extract a Rule struct from a CreateRuleResult. | ||||
| func (r CreateRuleResult) Extract() (*Rule, error) { | ||||
| 	if r.Err != nil { | ||||
| 		return nil, r.Err | ||||
| 	} | ||||
|  | ||||
| 	var response struct { | ||||
| 		Rule Rule `mapstructure:"security_group_rule"` | ||||
| 	} | ||||
|  | ||||
| 	err := mapstructure.WeakDecode(r.Body, &response) | ||||
|  | ||||
| 	return &response.Rule, err | ||||
| } | ||||
| @@ -1,32 +0,0 @@ | ||||
| package secgroups | ||||
|  | ||||
| import "github.com/rackspace/gophercloud" | ||||
|  | ||||
| const ( | ||||
| 	secgrouppath = "os-security-groups" | ||||
| 	rulepath     = "os-security-group-rules" | ||||
| ) | ||||
|  | ||||
| func resourceURL(c *gophercloud.ServiceClient, id string) string { | ||||
| 	return c.ServiceURL(secgrouppath, id) | ||||
| } | ||||
|  | ||||
| func rootURL(c *gophercloud.ServiceClient) string { | ||||
| 	return c.ServiceURL(secgrouppath) | ||||
| } | ||||
|  | ||||
| func listByServerURL(c *gophercloud.ServiceClient, serverID string) string { | ||||
| 	return c.ServiceURL("servers", serverID, secgrouppath) | ||||
| } | ||||
|  | ||||
| func rootRuleURL(c *gophercloud.ServiceClient) string { | ||||
| 	return c.ServiceURL(rulepath) | ||||
| } | ||||
|  | ||||
| func resourceRuleURL(c *gophercloud.ServiceClient, id string) string { | ||||
| 	return c.ServiceURL(rulepath, id) | ||||
| } | ||||
|  | ||||
| func serverActionURL(c *gophercloud.ServiceClient, id string) string { | ||||
| 	return c.ServiceURL("servers", id, "action") | ||||
| } | ||||
| @@ -1,2 +0,0 @@ | ||||
| // Package servergroups provides the ability to manage server groups | ||||
| package servergroups | ||||
| @@ -1,161 +0,0 @@ | ||||
| // +build fixtures | ||||
|  | ||||
| package servergroups | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"testing" | ||||
|  | ||||
| 	th "github.com/rackspace/gophercloud/testhelper" | ||||
| 	"github.com/rackspace/gophercloud/testhelper/client" | ||||
| ) | ||||
|  | ||||
| // ListOutput is a sample response to a List call. | ||||
| const ListOutput = ` | ||||
| { | ||||
|     "server_groups": [ | ||||
|         { | ||||
|             "id": "616fb98f-46ca-475e-917e-2563e5a8cd19", | ||||
|             "name": "test", | ||||
|             "policies": [ | ||||
|                 "anti-affinity" | ||||
|             ], | ||||
|             "members": [], | ||||
|             "metadata": {} | ||||
|         }, | ||||
|         { | ||||
|             "id": "4d8c3732-a248-40ed-bebc-539a6ffd25c0", | ||||
|             "name": "test2", | ||||
|             "policies": [ | ||||
|                 "affinity" | ||||
|             ], | ||||
|             "members": [], | ||||
|             "metadata": {} | ||||
|         } | ||||
|     ] | ||||
| } | ||||
| ` | ||||
|  | ||||
| // GetOutput is a sample response to a Get call. | ||||
| const GetOutput = ` | ||||
| { | ||||
|     "server_group": { | ||||
|         "id": "616fb98f-46ca-475e-917e-2563e5a8cd19", | ||||
|         "name": "test", | ||||
|         "policies": [ | ||||
|             "anti-affinity" | ||||
|         ], | ||||
|         "members": [], | ||||
|         "metadata": {} | ||||
|     } | ||||
| } | ||||
| ` | ||||
|  | ||||
| // CreateOutput is a sample response to a Post call | ||||
| const CreateOutput = ` | ||||
| { | ||||
|     "server_group": { | ||||
|         "id": "616fb98f-46ca-475e-917e-2563e5a8cd19", | ||||
|         "name": "test", | ||||
|         "policies": [ | ||||
|             "anti-affinity" | ||||
|         ], | ||||
|         "members": [], | ||||
|         "metadata": {} | ||||
|     } | ||||
| } | ||||
| ` | ||||
|  | ||||
| // FirstServerGroup is the first result in ListOutput. | ||||
| var FirstServerGroup = ServerGroup{ | ||||
| 	ID:   "616fb98f-46ca-475e-917e-2563e5a8cd19", | ||||
| 	Name: "test", | ||||
| 	Policies: []string{ | ||||
| 		"anti-affinity", | ||||
| 	}, | ||||
| 	Members:  []string{}, | ||||
| 	Metadata: map[string]interface{}{}, | ||||
| } | ||||
|  | ||||
| // SecondServerGroup is the second result in ListOutput. | ||||
| var SecondServerGroup = ServerGroup{ | ||||
| 	ID:   "4d8c3732-a248-40ed-bebc-539a6ffd25c0", | ||||
| 	Name: "test2", | ||||
| 	Policies: []string{ | ||||
| 		"affinity", | ||||
| 	}, | ||||
| 	Members:  []string{}, | ||||
| 	Metadata: map[string]interface{}{}, | ||||
| } | ||||
|  | ||||
| // ExpectedServerGroupSlice is the slice of results that should be parsed | ||||
| // from ListOutput, in the expected order. | ||||
| var ExpectedServerGroupSlice = []ServerGroup{FirstServerGroup, SecondServerGroup} | ||||
|  | ||||
| // CreatedServerGroup is the parsed result from CreateOutput. | ||||
| var CreatedServerGroup = ServerGroup{ | ||||
| 	ID:   "616fb98f-46ca-475e-917e-2563e5a8cd19", | ||||
| 	Name: "test", | ||||
| 	Policies: []string{ | ||||
| 		"anti-affinity", | ||||
| 	}, | ||||
| 	Members:  []string{}, | ||||
| 	Metadata: map[string]interface{}{}, | ||||
| } | ||||
|  | ||||
| // HandleListSuccessfully configures the test server to respond to a List request. | ||||
| func HandleListSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/os-server-groups", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "GET") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		fmt.Fprintf(w, ListOutput) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // HandleGetSuccessfully configures the test server to respond to a Get request | ||||
| // for an existing server group | ||||
| func HandleGetSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/os-server-groups/4d8c3732-a248-40ed-bebc-539a6ffd25c0", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "GET") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		fmt.Fprintf(w, GetOutput) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // HandleCreateSuccessfully configures the test server to respond to a Create request | ||||
| // for a new server group | ||||
| func HandleCreateSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/os-server-groups", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "POST") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
| 		th.TestJSONRequest(t, r, ` | ||||
| { | ||||
|     "server_group": { | ||||
|         "name": "test", | ||||
|         "policies": [ | ||||
|             "anti-affinity" | ||||
|         ] | ||||
|     } | ||||
| } | ||||
| `) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		fmt.Fprintf(w, CreateOutput) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // HandleDeleteSuccessfully configures the test server to respond to a Delete request for a | ||||
| // an existing server group | ||||
| func HandleDeleteSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/os-server-groups/616fb98f-46ca-475e-917e-2563e5a8cd19", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "DELETE") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
|  | ||||
| 		w.WriteHeader(http.StatusAccepted) | ||||
| 	}) | ||||
| } | ||||
| @@ -1,77 +0,0 @@ | ||||
| package servergroups | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
|  | ||||
| 	"github.com/rackspace/gophercloud" | ||||
| 	"github.com/rackspace/gophercloud/pagination" | ||||
| ) | ||||
|  | ||||
| // List returns a Pager that allows you to iterate over a collection of ServerGroups. | ||||
| func List(client *gophercloud.ServiceClient) pagination.Pager { | ||||
| 	return pagination.NewPager(client, listURL(client), func(r pagination.PageResult) pagination.Page { | ||||
| 		return ServerGroupsPage{pagination.SinglePageBase(r)} | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // CreateOptsBuilder describes struct types that can be accepted by the Create call. Notably, the | ||||
| // CreateOpts struct in this package does. | ||||
| type CreateOptsBuilder interface { | ||||
| 	ToServerGroupCreateMap() (map[string]interface{}, error) | ||||
| } | ||||
|  | ||||
| // CreateOpts specifies a Server Group allocation request | ||||
| type CreateOpts struct { | ||||
| 	// Name is the name of the server group | ||||
| 	Name string | ||||
|  | ||||
| 	// Policies are the server group policies | ||||
| 	Policies []string | ||||
| } | ||||
|  | ||||
| // ToServerGroupCreateMap constructs a request body from CreateOpts. | ||||
| func (opts CreateOpts) ToServerGroupCreateMap() (map[string]interface{}, error) { | ||||
| 	if opts.Name == "" { | ||||
| 		return nil, errors.New("Missing field required for server group creation: Name") | ||||
| 	} | ||||
|  | ||||
| 	if len(opts.Policies) < 1 { | ||||
| 		return nil, errors.New("Missing field required for server group creation: Policies") | ||||
| 	} | ||||
|  | ||||
| 	serverGroup := make(map[string]interface{}) | ||||
| 	serverGroup["name"] = opts.Name | ||||
| 	serverGroup["policies"] = opts.Policies | ||||
|  | ||||
| 	return map[string]interface{}{"server_group": serverGroup}, nil | ||||
| } | ||||
|  | ||||
| // Create requests the creation of a new Server Group | ||||
| func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { | ||||
| 	var res CreateResult | ||||
|  | ||||
| 	reqBody, err := opts.ToServerGroupCreateMap() | ||||
| 	if err != nil { | ||||
| 		res.Err = err | ||||
| 		return res | ||||
| 	} | ||||
|  | ||||
| 	_, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{ | ||||
| 		OkCodes: []int{200}, | ||||
| 	}) | ||||
| 	return res | ||||
| } | ||||
|  | ||||
| // Get returns data about a previously created ServerGroup. | ||||
| func Get(client *gophercloud.ServiceClient, id string) GetResult { | ||||
| 	var res GetResult | ||||
| 	_, res.Err = client.Get(getURL(client, id), &res.Body, nil) | ||||
| 	return res | ||||
| } | ||||
|  | ||||
| // Delete requests the deletion of a previously allocated ServerGroup. | ||||
| func Delete(client *gophercloud.ServiceClient, id string) DeleteResult { | ||||
| 	var res DeleteResult | ||||
| 	_, res.Err = client.Delete(deleteURL(client, id), nil) | ||||
| 	return res | ||||
| } | ||||
| @@ -1,87 +0,0 @@ | ||||
| package servergroups | ||||
|  | ||||
| import ( | ||||
| 	"github.com/mitchellh/mapstructure" | ||||
| 	"github.com/rackspace/gophercloud" | ||||
| 	"github.com/rackspace/gophercloud/pagination" | ||||
| ) | ||||
|  | ||||
| // A ServerGroup creates a policy for instance placement in the cloud | ||||
| type ServerGroup struct { | ||||
| 	// ID is the unique ID of the Server Group. | ||||
| 	ID string `mapstructure:"id"` | ||||
|  | ||||
| 	// Name is the common name of the server group. | ||||
| 	Name string `mapstructure:"name"` | ||||
|  | ||||
| 	// Polices are the group policies. | ||||
| 	Policies []string `mapstructure:"policies"` | ||||
|  | ||||
| 	// Members are the members of the server group. | ||||
| 	Members []string `mapstructure:"members"` | ||||
|  | ||||
| 	// Metadata includes a list of all user-specified key-value pairs attached to the Server Group. | ||||
| 	Metadata map[string]interface{} | ||||
| } | ||||
|  | ||||
| // ServerGroupsPage stores a single, only page of ServerGroups | ||||
| // results from a List call. | ||||
| type ServerGroupsPage struct { | ||||
| 	pagination.SinglePageBase | ||||
| } | ||||
|  | ||||
| // IsEmpty determines whether or not a ServerGroupsPage is empty. | ||||
| func (page ServerGroupsPage) IsEmpty() (bool, error) { | ||||
| 	va, err := ExtractServerGroups(page) | ||||
| 	return len(va) == 0, err | ||||
| } | ||||
|  | ||||
| // ExtractServerGroups interprets a page of results as a slice of | ||||
| // ServerGroups. | ||||
| func ExtractServerGroups(page pagination.Page) ([]ServerGroup, error) { | ||||
| 	casted := page.(ServerGroupsPage).Body | ||||
| 	var response struct { | ||||
| 		ServerGroups []ServerGroup `mapstructure:"server_groups"` | ||||
| 	} | ||||
|  | ||||
| 	err := mapstructure.WeakDecode(casted, &response) | ||||
|  | ||||
| 	return response.ServerGroups, err | ||||
| } | ||||
|  | ||||
| type ServerGroupResult struct { | ||||
| 	gophercloud.Result | ||||
| } | ||||
|  | ||||
| // Extract is a method that attempts to interpret any Server Group resource | ||||
| // response as a ServerGroup struct. | ||||
| func (r ServerGroupResult) Extract() (*ServerGroup, error) { | ||||
| 	if r.Err != nil { | ||||
| 		return nil, r.Err | ||||
| 	} | ||||
|  | ||||
| 	var res struct { | ||||
| 		ServerGroup *ServerGroup `json:"server_group" mapstructure:"server_group"` | ||||
| 	} | ||||
|  | ||||
| 	err := mapstructure.WeakDecode(r.Body, &res) | ||||
| 	return res.ServerGroup, err | ||||
| } | ||||
|  | ||||
| // CreateResult is the response from a Create operation. Call its Extract method to interpret it | ||||
| // as a ServerGroup. | ||||
| type CreateResult struct { | ||||
| 	ServerGroupResult | ||||
| } | ||||
|  | ||||
| // GetResult is the response from a Get operation. Call its Extract method to interpret it | ||||
| // as a ServerGroup. | ||||
| type GetResult struct { | ||||
| 	ServerGroupResult | ||||
| } | ||||
|  | ||||
| // DeleteResult is the response from a Delete operation. Call its Extract method to determine if | ||||
| // the call succeeded or failed. | ||||
| type DeleteResult struct { | ||||
| 	gophercloud.ErrResult | ||||
| } | ||||
| @@ -1,25 +0,0 @@ | ||||
| package servergroups | ||||
|  | ||||
| import "github.com/rackspace/gophercloud" | ||||
|  | ||||
| const resourcePath = "os-server-groups" | ||||
|  | ||||
| func resourceURL(c *gophercloud.ServiceClient) string { | ||||
| 	return c.ServiceURL(resourcePath) | ||||
| } | ||||
|  | ||||
| func listURL(c *gophercloud.ServiceClient) string { | ||||
| 	return resourceURL(c) | ||||
| } | ||||
|  | ||||
| func createURL(c *gophercloud.ServiceClient) string { | ||||
| 	return resourceURL(c) | ||||
| } | ||||
|  | ||||
| func getURL(c *gophercloud.ServiceClient, id string) string { | ||||
| 	return c.ServiceURL(resourcePath, id) | ||||
| } | ||||
|  | ||||
| func deleteURL(c *gophercloud.ServiceClient, id string) string { | ||||
| 	return getURL(c, id) | ||||
| } | ||||
| @@ -1,5 +0,0 @@ | ||||
| /* | ||||
| Package startstop provides functionality to start and stop servers that have | ||||
| been provisioned by the OpenStack Compute service. | ||||
| */ | ||||
| package startstop | ||||
| @@ -1,27 +0,0 @@ | ||||
| package startstop | ||||
|  | ||||
| import ( | ||||
| 	"net/http" | ||||
| 	"testing" | ||||
|  | ||||
| 	th "github.com/rackspace/gophercloud/testhelper" | ||||
| 	"github.com/rackspace/gophercloud/testhelper/client" | ||||
| ) | ||||
|  | ||||
| func mockStartServerResponse(t *testing.T, id string) { | ||||
| 	th.Mux.HandleFunc("/servers/"+id+"/action", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "POST") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
| 		th.TestJSONRequest(t, r, `{"os-start": null}`) | ||||
| 		w.WriteHeader(http.StatusAccepted) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func mockStopServerResponse(t *testing.T, id string) { | ||||
| 	th.Mux.HandleFunc("/servers/"+id+"/action", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "POST") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
| 		th.TestJSONRequest(t, r, `{"os-stop": null}`) | ||||
| 		w.WriteHeader(http.StatusAccepted) | ||||
| 	}) | ||||
| } | ||||
| @@ -1,23 +0,0 @@ | ||||
| package startstop | ||||
|  | ||||
| import "github.com/rackspace/gophercloud" | ||||
|  | ||||
| func actionURL(client *gophercloud.ServiceClient, id string) string { | ||||
| 	return client.ServiceURL("servers", id, "action") | ||||
| } | ||||
|  | ||||
| // Start is the operation responsible for starting a Compute server. | ||||
| func Start(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult { | ||||
| 	var res gophercloud.ErrResult | ||||
| 	reqBody := map[string]interface{}{"os-start": nil} | ||||
| 	_, res.Err = client.Post(actionURL(client, id), reqBody, nil, nil) | ||||
| 	return res | ||||
| } | ||||
|  | ||||
| // Stop is the operation responsible for stopping a Compute server. | ||||
| func Stop(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult { | ||||
| 	var res gophercloud.ErrResult | ||||
| 	reqBody := map[string]interface{}{"os-stop": nil} | ||||
| 	_, res.Err = client.Post(actionURL(client, id), reqBody, nil, nil) | ||||
| 	return res | ||||
| } | ||||
| @@ -1,2 +0,0 @@ | ||||
| // Package tenantnetworks provides the ability for tenants to see information about the networks they have access to | ||||
| package tenantnetworks | ||||
| @@ -1,84 +0,0 @@ | ||||
| // +build fixtures | ||||
|  | ||||
| package tenantnetworks | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"testing" | ||||
| 	"time" | ||||
|  | ||||
| 	th "github.com/rackspace/gophercloud/testhelper" | ||||
| 	"github.com/rackspace/gophercloud/testhelper/client" | ||||
| ) | ||||
|  | ||||
| // ListOutput is a sample response to a List call. | ||||
| const ListOutput = ` | ||||
| { | ||||
|     "networks": [ | ||||
|         { | ||||
|             "cidr": "10.0.0.0/29", | ||||
|             "id": "20c8acc0-f747-4d71-a389-46d078ebf047", | ||||
|             "label": "mynet_0" | ||||
|         }, | ||||
|         { | ||||
|             "cidr": "10.0.0.10/29", | ||||
|             "id": "20c8acc0-f747-4d71-a389-46d078ebf000", | ||||
|             "label": "mynet_1" | ||||
|         } | ||||
|     ] | ||||
| } | ||||
| ` | ||||
|  | ||||
| // GetOutput is a sample response to a Get call. | ||||
| const GetOutput = ` | ||||
| { | ||||
|     "network": { | ||||
| 			"cidr": "10.0.0.10/29", | ||||
| 			"id": "20c8acc0-f747-4d71-a389-46d078ebf000", | ||||
| 			"label": "mynet_1" | ||||
| 		} | ||||
| } | ||||
| ` | ||||
|  | ||||
| // FirstNetwork is the first result in ListOutput. | ||||
| var nilTime time.Time | ||||
| var FirstNetwork = Network{ | ||||
| 	CIDR: "10.0.0.0/29", | ||||
| 	ID:   "20c8acc0-f747-4d71-a389-46d078ebf047", | ||||
| 	Name: "mynet_0", | ||||
| } | ||||
|  | ||||
| // SecondNetwork is the second result in ListOutput. | ||||
| var SecondNetwork = Network{ | ||||
| 	CIDR: "10.0.0.10/29", | ||||
| 	ID:   "20c8acc0-f747-4d71-a389-46d078ebf000", | ||||
| 	Name: "mynet_1", | ||||
| } | ||||
|  | ||||
| // ExpectedNetworkSlice is the slice of results that should be parsed | ||||
| // from ListOutput, in the expected order. | ||||
| var ExpectedNetworkSlice = []Network{FirstNetwork, SecondNetwork} | ||||
|  | ||||
| // HandleListSuccessfully configures the test server to respond to a List request. | ||||
| func HandleListSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/os-tenant-networks", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "GET") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		fmt.Fprintf(w, ListOutput) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // HandleGetSuccessfully configures the test server to respond to a Get request | ||||
| // for an existing network. | ||||
| func HandleGetSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/os-tenant-networks/20c8acc0-f747-4d71-a389-46d078ebf000", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "GET") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		fmt.Fprintf(w, GetOutput) | ||||
| 	}) | ||||
| } | ||||
| @@ -1,22 +0,0 @@ | ||||
| package tenantnetworks | ||||
|  | ||||
| import ( | ||||
| 	"github.com/rackspace/gophercloud" | ||||
| 	"github.com/rackspace/gophercloud/pagination" | ||||
| ) | ||||
|  | ||||
| // List returns a Pager that allows you to iterate over a collection of Network. | ||||
| func List(client *gophercloud.ServiceClient) pagination.Pager { | ||||
| 	url := listURL(client) | ||||
| 	createPage := func(r pagination.PageResult) pagination.Page { | ||||
| 		return NetworkPage{pagination.SinglePageBase(r)} | ||||
| 	} | ||||
| 	return pagination.NewPager(client, url, createPage) | ||||
| } | ||||
|  | ||||
| // Get returns data about a previously created Network. | ||||
| func Get(client *gophercloud.ServiceClient, id string) GetResult { | ||||
| 	var res GetResult | ||||
| 	_, res.Err = client.Get(getURL(client, id), &res.Body, nil) | ||||
| 	return res | ||||
| } | ||||
| @@ -1,68 +0,0 @@ | ||||
| package tenantnetworks | ||||
|  | ||||
| import ( | ||||
| 	"github.com/mitchellh/mapstructure" | ||||
| 	"github.com/rackspace/gophercloud" | ||||
| 	"github.com/rackspace/gophercloud/pagination" | ||||
| ) | ||||
|  | ||||
| // A Network represents a nova-network that an instance communicates on | ||||
| type Network struct { | ||||
| 	// CIDR is the IPv4 subnet. | ||||
| 	CIDR string `mapstructure:"cidr"` | ||||
|  | ||||
| 	// ID is the UUID of the network. | ||||
| 	ID string `mapstructure:"id"` | ||||
|  | ||||
| 	// Name is the common name that the network has. | ||||
| 	Name string `mapstructure:"label"` | ||||
| } | ||||
|  | ||||
| // NetworkPage stores a single, only page of Networks | ||||
| // results from a List call. | ||||
| type NetworkPage struct { | ||||
| 	pagination.SinglePageBase | ||||
| } | ||||
|  | ||||
| // IsEmpty determines whether or not a NetworkPage is empty. | ||||
| func (page NetworkPage) IsEmpty() (bool, error) { | ||||
| 	va, err := ExtractNetworks(page) | ||||
| 	return len(va) == 0, err | ||||
| } | ||||
|  | ||||
| // ExtractNetworks interprets a page of results as a slice of Networks | ||||
| func ExtractNetworks(page pagination.Page) ([]Network, error) { | ||||
| 	networks := page.(NetworkPage).Body | ||||
| 	var res struct { | ||||
| 		Networks []Network `mapstructure:"networks"` | ||||
| 	} | ||||
|  | ||||
| 	err := mapstructure.WeakDecode(networks, &res) | ||||
|  | ||||
| 	return res.Networks, err | ||||
| } | ||||
|  | ||||
| type NetworkResult struct { | ||||
| 	gophercloud.Result | ||||
| } | ||||
|  | ||||
| // Extract is a method that attempts to interpret any Network resource | ||||
| // response as a Network struct. | ||||
| func (r NetworkResult) Extract() (*Network, error) { | ||||
| 	if r.Err != nil { | ||||
| 		return nil, r.Err | ||||
| 	} | ||||
|  | ||||
| 	var res struct { | ||||
| 		Network *Network `json:"network" mapstructure:"network"` | ||||
| 	} | ||||
|  | ||||
| 	err := mapstructure.Decode(r.Body, &res) | ||||
| 	return res.Network, err | ||||
| } | ||||
|  | ||||
| // GetResult is the response from a Get operation. Call its Extract method to interpret it | ||||
| // as a Network. | ||||
| type GetResult struct { | ||||
| 	NetworkResult | ||||
| } | ||||
| @@ -1,17 +0,0 @@ | ||||
| package tenantnetworks | ||||
|  | ||||
| import "github.com/rackspace/gophercloud" | ||||
|  | ||||
| const resourcePath = "os-tenant-networks" | ||||
|  | ||||
| func resourceURL(c *gophercloud.ServiceClient) string { | ||||
| 	return c.ServiceURL(resourcePath) | ||||
| } | ||||
|  | ||||
| func listURL(c *gophercloud.ServiceClient) string { | ||||
| 	return resourceURL(c) | ||||
| } | ||||
|  | ||||
| func getURL(c *gophercloud.ServiceClient, id string) string { | ||||
| 	return c.ServiceURL(resourcePath, id) | ||||
| } | ||||
| @@ -1,7 +0,0 @@ | ||||
| /* | ||||
| This is package created is to hold fixtures (which imports testing), | ||||
| so that importing volumeattach package does not inadvertently import testing into production code | ||||
| More information here: | ||||
| https://github.com/rackspace/gophercloud/issues/473 | ||||
| */ | ||||
| package testing | ||||
| @@ -1,110 +0,0 @@ | ||||
| // +build fixtures | ||||
|  | ||||
| package testing | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"testing" | ||||
|  | ||||
| 	th "github.com/rackspace/gophercloud/testhelper" | ||||
| 	"github.com/rackspace/gophercloud/testhelper/client" | ||||
| ) | ||||
|  | ||||
| // ListOutput is a sample response to a List call. | ||||
| const ListOutput = ` | ||||
| { | ||||
|   "volumeAttachments": [ | ||||
|     { | ||||
|       "device": "/dev/vdd", | ||||
|       "id": "a26887c6-c47b-4654-abb5-dfadf7d3f803", | ||||
|       "serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0", | ||||
|       "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f803" | ||||
|     }, | ||||
|     { | ||||
|       "device": "/dev/vdc", | ||||
|       "id": "a26887c6-c47b-4654-abb5-dfadf7d3f804", | ||||
|       "serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0", | ||||
|       "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804" | ||||
|     } | ||||
|   ] | ||||
| } | ||||
| ` | ||||
|  | ||||
| // GetOutput is a sample response to a Get call. | ||||
| const GetOutput = ` | ||||
| { | ||||
|   "volumeAttachment": { | ||||
|     "device": "/dev/vdc", | ||||
|     "id": "a26887c6-c47b-4654-abb5-dfadf7d3f804", | ||||
|     "serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0", | ||||
|     "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804" | ||||
|   } | ||||
| } | ||||
| ` | ||||
|  | ||||
| // CreateOutput is a sample response to a Create call. | ||||
| const CreateOutput = ` | ||||
| { | ||||
|   "volumeAttachment": { | ||||
|     "device": "/dev/vdc", | ||||
|     "id": "a26887c6-c47b-4654-abb5-dfadf7d3f804", | ||||
|     "serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0", | ||||
|     "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804" | ||||
|   } | ||||
| } | ||||
| ` | ||||
|  | ||||
| // HandleListSuccessfully configures the test server to respond to a List request. | ||||
| func HandleListSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/os-volume_attachments", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "GET") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		fmt.Fprintf(w, ListOutput) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // HandleGetSuccessfully configures the test server to respond to a Get request | ||||
| // for an existing attachment | ||||
| func HandleGetSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/os-volume_attachments/a26887c6-c47b-4654-abb5-dfadf7d3f804", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "GET") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		fmt.Fprintf(w, GetOutput) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // HandleCreateSuccessfully configures the test server to respond to a Create request | ||||
| // for a new attachment | ||||
| func HandleCreateSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/os-volume_attachments", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "POST") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
| 		th.TestJSONRequest(t, r, ` | ||||
| { | ||||
|   "volumeAttachment": { | ||||
|     "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804", | ||||
|     "device": "/dev/vdc" | ||||
|   } | ||||
| } | ||||
| `) | ||||
|  | ||||
| 		w.Header().Add("Content-Type", "application/json") | ||||
| 		fmt.Fprintf(w, CreateOutput) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // HandleDeleteSuccessfully configures the test server to respond to a Delete request for a | ||||
| // an existing attachment | ||||
| func HandleDeleteSuccessfully(t *testing.T) { | ||||
| 	th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/os-volume_attachments/a26887c6-c47b-4654-abb5-dfadf7d3f804", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		th.TestMethod(t, r, "DELETE") | ||||
| 		th.TestHeader(t, r, "X-Auth-Token", client.TokenID) | ||||
|  | ||||
| 		w.WriteHeader(http.StatusAccepted) | ||||
| 	}) | ||||
| } | ||||
		Reference in New Issue
	
	Block a user