Skip to content
This repository was archived by the owner on Aug 1, 2023. It is now read-only.

Commit 2e84b74

Browse files
author
Kirill Shirinkin
committed
Resolve conflicts
2 parents 3b07ffd + 6769c3b commit 2e84b74

File tree

21 files changed

+441
-56
lines changed

21 files changed

+441
-56
lines changed

acceptance/openstack/compute/v2/bootfromvolume_test.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,64 @@ func TestBootFromVolume(t *testing.T) {
5353
defer servers.Delete(client, server.ID)
5454
t.Logf("Deleting server [%s]...", name)
5555
}
56+
57+
func TestMultiEphemeral(t *testing.T) {
58+
client, err := newClient()
59+
th.AssertNoErr(t, err)
60+
61+
if testing.Short() {
62+
t.Skip("Skipping test that requires server creation in short mode.")
63+
}
64+
65+
choices, err := ComputeChoicesFromEnv()
66+
if err != nil {
67+
t.Fatal(err)
68+
}
69+
70+
name := tools.RandomString("Gophercloud-", 8)
71+
t.Logf("Creating server [%s].", name)
72+
73+
bd := []bootfromvolume.BlockDevice{
74+
bootfromvolume.BlockDevice{
75+
BootIndex: 0,
76+
UUID: choices.ImageID,
77+
SourceType: bootfromvolume.Image,
78+
DestinationType: "local",
79+
DeleteOnTermination: true,
80+
},
81+
bootfromvolume.BlockDevice{
82+
BootIndex: -1,
83+
SourceType: bootfromvolume.Blank,
84+
DestinationType: "local",
85+
DeleteOnTermination: true,
86+
GuestFormat: "ext4",
87+
VolumeSize: 1,
88+
},
89+
bootfromvolume.BlockDevice{
90+
BootIndex: -1,
91+
SourceType: bootfromvolume.Blank,
92+
DestinationType: "local",
93+
DeleteOnTermination: true,
94+
GuestFormat: "ext4",
95+
VolumeSize: 1,
96+
},
97+
}
98+
99+
serverCreateOpts := servers.CreateOpts{
100+
Name: name,
101+
FlavorRef: choices.FlavorID,
102+
ImageRef: choices.ImageID,
103+
}
104+
server, err := bootfromvolume.Create(client, bootfromvolume.CreateOptsExt{
105+
serverCreateOpts,
106+
bd,
107+
}).Extract()
108+
th.AssertNoErr(t, err)
109+
if err = waitForStatus(client, server, "ACTIVE"); err != nil {
110+
t.Fatal(err)
111+
}
112+
113+
t.Logf("Created server: %+v\n", server)
114+
defer servers.Delete(client, server.ID)
115+
t.Logf("Deleting server [%s]...", name)
116+
}

acceptance/openstack/networking/v2/port_test.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,20 @@ func TestPortCRUD(t *testing.T) {
4545
th.AssertEquals(t, p.ID, portID)
4646

4747
// Update port
48-
p, err = ports.Update(Client, portID, ports.UpdateOpts{Name: "new_port_name"}).Extract()
48+
updateOpts := ports.UpdateOpts{
49+
Name: "new_port_name",
50+
AllowedAddressPairs: []ports.AddressPair{
51+
ports.AddressPair{IPAddress: "192.168.199.201"},
52+
},
53+
}
54+
p, err = ports.Update(Client, portID, updateOpts).Extract()
55+
4956
th.AssertNoErr(t, err)
5057
th.AssertEquals(t, p.Name, "new_port_name")
5158

59+
updatedPort, err := ports.Get(Client, portID).Extract()
60+
th.AssertEquals(t, updatedPort.AllowedAddressPairs[0].IPAddress, "192.168.199.201")
61+
5262
// Delete port
5363
res := ports.Delete(Client, portID)
5464
th.AssertNoErr(t, res.Err)
@@ -82,8 +92,8 @@ func listPorts(t *testing.T) {
8292
th.AssertNoErr(t, err)
8393

8494
for _, p := range portList {
85-
t.Logf("Port: ID [%s] Name [%s] Status [%s] MAC addr [%s] Fixed IPs [%#v] Security groups [%#v]",
86-
p.ID, p.Name, p.Status, p.MACAddress, p.FixedIPs, p.SecurityGroups)
95+
t.Logf("Port: ID [%s] Name [%s] Status [%s] MAC addr [%s] Fixed IPs [%#v] Security groups [%#v] Allowed Address Pairs [%#v]",
96+
p.ID, p.Name, p.Status, p.MACAddress, p.FixedIPs, p.SecurityGroups, p.AllowedAddressPairs)
8797
}
8898

8999
return true, nil
@@ -108,6 +118,9 @@ func createSubnet(networkID string) (string, error) {
108118
IPVersion: subnets.IPv4,
109119
Name: "my_subnet",
110120
EnableDHCP: subnets.Down,
121+
AllocationPools: []subnets.AllocationPool{
122+
subnets.AllocationPool{Start: "192.168.199.2", End: "192.168.199.200"},
123+
},
111124
}).Extract()
112125
return s.ID, err
113126
}

openstack/client.go

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package openstack
33
import (
44
"fmt"
55
"net/url"
6+
"strings"
67

78
"github.com/rackspace/gophercloud"
89
tokens2 "github.com/rackspace/gophercloud/openstack/identity/v2/tokens"
@@ -64,8 +65,8 @@ func AuthenticatedClient(options gophercloud.AuthOptions) (*gophercloud.Provider
6465
// Authenticate or re-authenticate against the most recent identity service supported at the provided endpoint.
6566
func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error {
6667
versions := []*utils.Version{
67-
&utils.Version{ID: v20, Priority: 20, Suffix: "/v2.0/"},
68-
&utils.Version{ID: v30, Priority: 30, Suffix: "/v3/"},
68+
{ID: v20, Priority: 20, Suffix: "/v2.0/"},
69+
{ID: v30, Priority: 30, Suffix: "/v3/"},
6970
}
7071

7172
chosen, endpoint, err := utils.ChooseVersion(client, versions)
@@ -110,7 +111,7 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc
110111
if options.AllowReauth {
111112
client.ReauthFunc = func() error {
112113
client.TokenID = ""
113-
return AuthenticateV2(client, options)
114+
return v2auth(client, endpoint, options)
114115
}
115116
}
116117
client.TokenID = token.ID
@@ -168,7 +169,7 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, options gopherc
168169
if options.AllowReauth {
169170
client.ReauthFunc = func() error {
170171
client.TokenID = ""
171-
return AuthenticateV3(client, options)
172+
return v3auth(client, endpoint, options)
172173
}
173174
}
174175
client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
@@ -198,6 +199,40 @@ func NewIdentityV3(client *gophercloud.ProviderClient) *gophercloud.ServiceClien
198199
}
199200
}
200201

202+
func NewIdentityAdminV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
203+
eo.ApplyDefaults("identity")
204+
eo.Availability = gophercloud.AvailabilityAdmin
205+
206+
url, err := client.EndpointLocator(eo)
207+
if err != nil {
208+
return nil, err
209+
}
210+
211+
// Force using v2 API
212+
if strings.Contains(url, "/v3") {
213+
url = strings.Replace(url, "/v3", "/v2.0", -1)
214+
}
215+
216+
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
217+
}
218+
219+
func NewIdentityAdminV3(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
220+
eo.ApplyDefaults("identity")
221+
eo.Availability = gophercloud.AvailabilityAdmin
222+
223+
url, err := client.EndpointLocator(eo)
224+
if err != nil {
225+
return nil, err
226+
}
227+
228+
// Force using v3 API
229+
if strings.Contains(url, "/v2.0") {
230+
url = strings.Replace(url, "/v2.0", "/v3", -1)
231+
}
232+
233+
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
234+
}
235+
201236
// NewObjectStorageV1 creates a ServiceClient that may be used with the v1 object storage package.
202237
func NewObjectStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
203238
eo.ApplyDefaults("object-store")

openstack/compute/v2/extensions/bootfromvolume/requests.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const (
1515
Volume SourceType = "volume"
1616
Snapshot SourceType = "snapshot"
1717
Image SourceType = "image"
18+
Blank SourceType = "blank"
1819
)
1920

2021
// BlockDevice is a structure with options for booting a server instance
@@ -32,6 +33,9 @@ type BlockDevice struct {
3233
// and "local".
3334
DestinationType string `json:"destination_type"`
3435

36+
// GuestFormat [optional] specifies the format of the block device.
37+
GuestFormat string `json:"guest_format"`
38+
3539
// SourceType [required] must be one of: "volume", "snapshot", "image".
3640
SourceType SourceType `json:"source_type"`
3741

@@ -82,6 +86,9 @@ func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) {
8286
if bd.DestinationType != "" {
8387
blockDevice[i]["destination_type"] = bd.DestinationType
8488
}
89+
if bd.GuestFormat != "" {
90+
blockDevice[i]["guest_format"] = bd.GuestFormat
91+
}
8592

8693
}
8794
serverMap["block_device_mapping_v2"] = blockDevice

openstack/compute/v2/extensions/bootfromvolume/requests_test.go

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ func TestCreateOpts(t *testing.T) {
3232
"name": "createdserver",
3333
"imageRef": "asdfasdfasdf",
3434
"flavorRef": "performance1-1",
35-
"flavorName": "",
36-
"imageName": "",
35+
"flavorName": "",
36+
"imageName": "",
3737
"block_device_mapping_v2":[
3838
{
3939
"uuid":"123456",
@@ -51,3 +51,81 @@ func TestCreateOpts(t *testing.T) {
5151
th.AssertNoErr(t, err)
5252
th.CheckJSONEquals(t, expected, actual)
5353
}
54+
55+
func TestCreateMultiEphemeralOpts(t *testing.T) {
56+
base := servers.CreateOpts{
57+
Name: "createdserver",
58+
ImageRef: "asdfasdfasdf",
59+
FlavorRef: "performance1-1",
60+
}
61+
62+
ext := CreateOptsExt{
63+
CreateOptsBuilder: base,
64+
BlockDevice: []BlockDevice{
65+
BlockDevice{
66+
BootIndex: 0,
67+
DeleteOnTermination: true,
68+
DestinationType: "local",
69+
SourceType: Image,
70+
UUID: "123456",
71+
},
72+
BlockDevice{
73+
BootIndex: -1,
74+
DeleteOnTermination: true,
75+
DestinationType: "local",
76+
GuestFormat: "ext4",
77+
SourceType: Blank,
78+
VolumeSize: 1,
79+
},
80+
BlockDevice{
81+
BootIndex: -1,
82+
DeleteOnTermination: true,
83+
DestinationType: "local",
84+
GuestFormat: "ext4",
85+
SourceType: Blank,
86+
VolumeSize: 1,
87+
},
88+
},
89+
}
90+
91+
expected := `
92+
{
93+
"server": {
94+
"name": "createdserver",
95+
"imageRef": "asdfasdfasdf",
96+
"flavorRef": "performance1-1",
97+
"flavorName": "",
98+
"imageName": "",
99+
"block_device_mapping_v2":[
100+
{
101+
"boot_index": "0",
102+
"delete_on_termination": "true",
103+
"destination_type":"local",
104+
"source_type":"image",
105+
"uuid":"123456",
106+
"volume_size": "0"
107+
},
108+
{
109+
"boot_index": "-1",
110+
"delete_on_termination": "true",
111+
"destination_type":"local",
112+
"guest_format":"ext4",
113+
"source_type":"blank",
114+
"volume_size": "1"
115+
},
116+
{
117+
"boot_index": "-1",
118+
"delete_on_termination": "true",
119+
"destination_type":"local",
120+
"guest_format":"ext4",
121+
"source_type":"blank",
122+
"volume_size": "1"
123+
}
124+
]
125+
}
126+
}
127+
`
128+
actual, err := ext.ToServerCreateMap()
129+
th.AssertNoErr(t, err)
130+
th.CheckJSONEquals(t, expected, actual)
131+
}

openstack/compute/v2/servers/fixtures.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,18 @@ func HandleServerDeletionSuccessfully(t *testing.T) {
399399
})
400400
}
401401

402+
// HandleAdminPasswordChangeSuccessfully sets up the test server to respond to a server password
403+
// change request.
404+
func HandleServerForceDeletionSuccessfully(t *testing.T) {
405+
th.Mux.HandleFunc("/servers/asdfasdfasdf/action", func(w http.ResponseWriter, r *http.Request) {
406+
th.TestMethod(t, r, "POST")
407+
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
408+
th.TestJSONRequest(t, r, `{ "forceDelete": "" }`)
409+
410+
w.WriteHeader(http.StatusAccepted)
411+
})
412+
}
413+
402414
// HandleServerGetSuccessfully sets up the test server to respond to a server Get request.
403415
func HandleServerGetSuccessfully(t *testing.T) {
404416
th.Mux.HandleFunc("/servers/1234asdf", func(w http.ResponseWriter, r *http.Request) {

openstack/compute/v2/servers/requests.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,17 @@ func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
303303
return res
304304
}
305305

306+
func ForceDelete(client *gophercloud.ServiceClient, id string) ActionResult {
307+
var req struct {
308+
ForceDelete string `json:"forceDelete"`
309+
}
310+
311+
var res ActionResult
312+
_, res.Err = client.Post(actionURL(client, id), req, nil, nil)
313+
return res
314+
315+
}
316+
306317
// Get requests details on a single server, by ID.
307318
func Get(client *gophercloud.ServiceClient, id string) GetResult {
308319
var result GetResult

openstack/compute/v2/servers/requests_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,15 @@ func TestDeleteServer(t *testing.T) {
7878
th.AssertNoErr(t, res.Err)
7979
}
8080

81+
func TestForceDeleteServer(t *testing.T) {
82+
th.SetupHTTP()
83+
defer th.TeardownHTTP()
84+
HandleServerForceDeletionSuccessfully(t)
85+
86+
res := ForceDelete(client.ServiceClient(), "asdfasdfasdf")
87+
th.AssertNoErr(t, res.Err)
88+
}
89+
8190
func TestGetServer(t *testing.T) {
8291
th.SetupHTTP()
8392
defer th.TeardownHTTP()

openstack/db/v1/configurations/results.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package configurations
22

33
import (
4+
"fmt"
5+
"reflect"
46
"time"
57

68
"github.com/mitchellh/mapstructure"
@@ -43,12 +45,18 @@ func ExtractConfigs(page pagination.Page) ([]Config, error) {
4345
Configs []Config `mapstructure:"configurations" json:"configurations"`
4446
}
4547

46-
err := mapstructure.Decode(casted, &resp)
48+
if err := mapstructure.Decode(casted, &resp); err != nil {
49+
return nil, err
50+
}
4751

4852
var vals []interface{}
49-
switch (casted).(type) {
50-
case interface{}:
53+
switch casted.(type) {
54+
case map[string]interface{}:
5155
vals = casted.(map[string]interface{})["configurations"].([]interface{})
56+
case map[string][]interface{}:
57+
vals = casted.(map[string][]interface{})["configurations"]
58+
default:
59+
return resp.Configs, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
5260
}
5361

5462
for i, v := range vals {
@@ -71,7 +79,7 @@ func ExtractConfigs(page pagination.Page) ([]Config, error) {
7179
}
7280
}
7381

74-
return resp.Configs, err
82+
return resp.Configs, nil
7583
}
7684

7785
type commonResult struct {

0 commit comments

Comments
 (0)