Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 08898e5

Browse files
authored
Keystone V3: Support EC2 credentials CRD (gophercloud#1916)
* Keystone V3: Support EC2 credentials CRD * add doc.go
1 parent e2dceb1 commit 08898e5

File tree

7 files changed

+511
-0
lines changed

7 files changed

+511
-0
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// +build acceptance
2+
3+
package v3
4+
5+
import (
6+
"testing"
7+
8+
"github.com/gophercloud/gophercloud/acceptance/clients"
9+
"github.com/gophercloud/gophercloud/acceptance/tools"
10+
"github.com/gophercloud/gophercloud/openstack"
11+
"github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/ec2credentials"
12+
"github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
13+
th "github.com/gophercloud/gophercloud/testhelper"
14+
)
15+
16+
func TestEC2CredentialsCRD(t *testing.T) {
17+
client, err := clients.NewIdentityV3Client()
18+
th.AssertNoErr(t, err)
19+
20+
ao, err := openstack.AuthOptionsFromEnv()
21+
th.AssertNoErr(t, err)
22+
23+
authOptions := tokens.AuthOptions{
24+
Username: ao.Username,
25+
Password: ao.Password,
26+
DomainName: ao.DomainName,
27+
DomainID: ao.DomainID,
28+
// We need a scope to get the token roles list
29+
Scope: tokens.Scope{
30+
ProjectID: ao.TenantID,
31+
ProjectName: ao.TenantName,
32+
DomainID: ao.DomainID,
33+
DomainName: ao.DomainName,
34+
},
35+
}
36+
37+
res := tokens.Create(client, &authOptions)
38+
th.AssertNoErr(t, res.Err)
39+
token, err := res.Extract()
40+
th.AssertNoErr(t, err)
41+
tools.PrintResource(t, token)
42+
43+
user, err := res.ExtractUser()
44+
th.AssertNoErr(t, err)
45+
tools.PrintResource(t, user)
46+
47+
project, err := res.ExtractProject()
48+
th.AssertNoErr(t, err)
49+
tools.PrintResource(t, project)
50+
51+
createOpts := ec2credentials.CreateOpts{
52+
TenantID: project.ID,
53+
}
54+
55+
ec2credential, err := ec2credentials.Create(client, user.ID, createOpts).Extract()
56+
th.AssertNoErr(t, err)
57+
defer ec2credentials.Delete(client, user.ID, ec2credential.Access)
58+
tools.PrintResource(t, ec2credential)
59+
60+
access := ec2credential.Access
61+
secret := ec2credential.Secret
62+
if access == "" {
63+
t.Fatalf("EC2 credential access was not generated")
64+
}
65+
66+
if secret == "" {
67+
t.Fatalf("EC2 credential secret was not generated")
68+
}
69+
70+
th.AssertEquals(t, ec2credential.UserID, user.ID)
71+
th.AssertEquals(t, ec2credential.TenantID, project.ID)
72+
73+
// Get an ec2 credential
74+
getEC2Credential, err := ec2credentials.Get(client, user.ID, ec2credential.Access).Extract()
75+
th.AssertNoErr(t, err)
76+
tools.PrintResource(t, getEC2Credential)
77+
78+
th.AssertEquals(t, getEC2Credential.UserID, user.ID)
79+
th.AssertEquals(t, getEC2Credential.TenantID, project.ID)
80+
th.AssertEquals(t, getEC2Credential.Access, access)
81+
th.AssertEquals(t, getEC2Credential.Secret, secret)
82+
83+
allPages, err := ec2credentials.List(client, user.ID).AllPages()
84+
th.AssertNoErr(t, err)
85+
credentials, err := ec2credentials.ExtractCredentials(allPages)
86+
th.AssertNoErr(t, err)
87+
88+
if v := len(credentials); v != 1 {
89+
t.Fatalf("expected to list one credential, got %d", v)
90+
}
91+
92+
th.AssertEquals(t, credentials[0].UserID, user.ID)
93+
th.AssertEquals(t, credentials[0].TenantID, project.ID)
94+
th.AssertEquals(t, credentials[0].Access, access)
95+
th.AssertEquals(t, credentials[0].Secret, secret)
96+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
Package ec2credentials provides information and interaction with the EC2
3+
credentials API resource for the OpenStack Identity service.
4+
5+
For more information, see:
6+
https://docs.openstack.org/api-ref/identity/v2-ext/
7+
8+
Example to Create an EC2 credential
9+
10+
createOpts := ec2credentials.CreateOpts{
11+
// project ID of the EC2 credential scope
12+
TenantID: projectID,
13+
}
14+
15+
credential, err := ec2credentials.Create(identityClient, userID, createOpts).Extract()
16+
if err != nil {
17+
panic(err)
18+
}
19+
20+
*/
21+
package ec2credentials
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package ec2credentials
2+
3+
import (
4+
"github.com/gophercloud/gophercloud"
5+
"github.com/gophercloud/gophercloud/pagination"
6+
)
7+
8+
// List enumerates the Credentials to which the current token has access.
9+
func List(client *gophercloud.ServiceClient, userID string) pagination.Pager {
10+
url := listURL(client, userID)
11+
return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
12+
return CredentialPage{pagination.LinkedPageBase{PageResult: r}}
13+
})
14+
}
15+
16+
// Get retrieves details on a single EC2 credential by ID.
17+
func Get(client *gophercloud.ServiceClient, userID string, id string) (r GetResult) {
18+
_, r.Err = client.Get(getURL(client, userID, id), &r.Body, nil)
19+
return
20+
}
21+
22+
// CreateOpts provides options used to create an EC2 credential.
23+
type CreateOpts struct {
24+
// TenantID is the project ID scope of the EC2 credential.
25+
TenantID string `json:"tenant_id" required:"true"`
26+
}
27+
28+
// ToCredentialCreateMap formats a CreateOpts into a create request.
29+
func (opts CreateOpts) ToCredentialCreateMap() (map[string]interface{}, error) {
30+
return gophercloud.BuildRequestBody(opts, "")
31+
}
32+
33+
// Create creates a new EC2 Credential.
34+
func Create(client *gophercloud.ServiceClient, userID string, opts CreateOpts) (r CreateResult) {
35+
b, err := opts.ToCredentialCreateMap()
36+
if err != nil {
37+
r.Err = err
38+
return
39+
}
40+
_, r.Err = client.Post(createURL(client, userID), &b, &r.Body, &gophercloud.RequestOpts{
41+
OkCodes: []int{201},
42+
})
43+
return
44+
}
45+
46+
// Delete deletes an EC2 credential.
47+
func Delete(client *gophercloud.ServiceClient, userID string, id string) (r DeleteResult) {
48+
_, r.Err = client.Delete(deleteURL(client, userID, id), nil)
49+
return
50+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package ec2credentials
2+
3+
import (
4+
"github.com/gophercloud/gophercloud"
5+
"github.com/gophercloud/gophercloud/pagination"
6+
)
7+
8+
// Credential represents the application credential object
9+
type Credential struct {
10+
// UserID contains a User ID of the EC2 credential owner.
11+
UserID string `json:"user_id"`
12+
// TenantID contains an EC2 credential project scope.
13+
TenantID string `json:"tenant_id"`
14+
// Access contains an EC2 credential access UUID.
15+
Access string `json:"access"`
16+
// Secret contains an EC2 credential secret UUID.
17+
Secret string `json:"secret"`
18+
// TrustID contains an EC2 credential trust ID scope.
19+
TrustID string `json:"trust_id"`
20+
// Links contains referencing links to the application credential.
21+
Links map[string]interface{} `json:"links"`
22+
}
23+
24+
type credentialResult struct {
25+
gophercloud.Result
26+
}
27+
28+
// GetResult is the response from a Get operation. Call its Extract method
29+
// to interpret it as an Credential.
30+
type GetResult struct {
31+
credentialResult
32+
}
33+
34+
// CreateResult is the response from a Create operation. Call its Extract method
35+
// to interpret it as an Credential.
36+
type CreateResult struct {
37+
credentialResult
38+
}
39+
40+
// DeleteResult is the response from a Delete operation. Call its ExtractErr to
41+
// determine if the request succeeded or failed.
42+
type DeleteResult struct {
43+
gophercloud.ErrResult
44+
}
45+
46+
// an CredentialPage is a single page of an Credential results.
47+
type CredentialPage struct {
48+
pagination.LinkedPageBase
49+
}
50+
51+
// IsEmpty determines whether or not a an CredentialPage contains any results.
52+
func (r CredentialPage) IsEmpty() (bool, error) {
53+
ec2Credentials, err := ExtractCredentials(r)
54+
return len(ec2Credentials) == 0, err
55+
}
56+
57+
// NextPageURL extracts the "next" link from the links section of the result.
58+
func (r CredentialPage) NextPageURL() (string, error) {
59+
var s struct {
60+
Links struct {
61+
Next string `json:"next"`
62+
Previous string `json:"previous"`
63+
} `json:"links"`
64+
}
65+
err := r.ExtractInto(&s)
66+
if err != nil {
67+
return "", err
68+
}
69+
return s.Links.Next, err
70+
}
71+
72+
// Extractan Credentials returns a slice of Credentials contained in a single page of results.
73+
func ExtractCredentials(r pagination.Page) ([]Credential, error) {
74+
var s struct {
75+
Credentials []Credential `json:"credentials"`
76+
}
77+
err := (r.(CredentialPage)).ExtractInto(&s)
78+
return s.Credentials, err
79+
}
80+
81+
// Extract interprets any Credential results as a Credential.
82+
func (r credentialResult) Extract() (*Credential, error) {
83+
var s struct {
84+
Credential *Credential `json:"credential"`
85+
}
86+
err := r.ExtractInto(&s)
87+
return s.Credential, err
88+
}

0 commit comments

Comments
 (0)