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

[WIP] add full CRUD operations to openstack/identity/v2/tenants #562

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions openstack/identity/v2/tenants/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,120 @@ func List(client *gophercloud.ServiceClient, opts *ListOpts) pagination.Pager {

return pagination.NewPager(client, url, createPage)
}

// EnabledState represents whether the tenant is enabled or not.
type EnabledState *bool

// Useful variables to use when creating or updating tenants.
var (
iTrue = true
iFalse = false

Enabled EnabledState = &iTrue
Disabled EnabledState = &iFalse
)

// CommonOpts are the parameters that are shared between CreateOpts and
// UpdateOpts
type CommonOpts struct {
// A name is required. When provided, the value must be
// unique or a 409 conflict error will be returned.
Name string

// Indicates whether this user is enabled or not.
Enabled EnabledState

// The description of this tenant.
Description string
}

// CreateOpts represents the options needed when creating new tenants.
type CreateOpts CommonOpts

// CreateOptsBuilder describes struct types that can be accepted by the Create call.
type CreateOptsBuilder interface {
ToTenantCreateMap() (map[string]interface{}, error)
}

// ToTenantCreateMap assembles a request body based on the contents of a CreateOpts.
func (opts CreateOpts) ToTenantCreateMap() (map[string]interface{}, error) {
m := make(map[string]interface{})

if opts.Name != "" {
m["name"] = opts.Name
}
if opts.Description != "" {
m["description"] = opts.Description
}
if opts.Enabled != nil {
m["enabled"] = &opts.Enabled
}

return map[string]interface{}{"tenant": m}, nil
}

// Create is the operation responsible for creating new tenants.
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
var res CreateResult

reqBody, err := opts.ToTenantCreateMap()
if err != nil {
res.Err = err
return res
}

_, res.Err = client.Post(rootURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 201},
})

return res
}

// Get requests details on a single tenant, either by ID.
func Get(client *gophercloud.ServiceClient, id string) GetResult {
var result GetResult
_, result.Err = client.Get(ResourceURL(client, id), &result.Body, nil)
return result
}

// UpdateOptsBuilder allows extensions to add additional attributes to the Update request.
type UpdateOptsBuilder interface {
ToTenantUpdateMap() map[string]interface{}
}

// UpdateOpts specifies the base attributes that may be updated on an existing tenant.
type UpdateOpts CommonOpts

// ToUserUpdateMap formats an UpdateOpts structure into a request body.
func (opts UpdateOpts) ToTenantUpdateMap() map[string]interface{} {
m := make(map[string]interface{})

if opts.Name != "" {
m["name"] = opts.Name
}
if opts.Description != "" {
m["description"] = opts.Description
}
if opts.Enabled != nil {
m["enabled"] = &opts.Enabled
}

return map[string]interface{}{"tenant": m}
}

// Update is the operation responsible for updating exist users by their UUID.
func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
var result UpdateResult
reqBody := opts.ToTenantUpdateMap()
_, result.Err = client.Put(ResourceURL(client, id), reqBody, &result.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
return result
}

// Delete is the operation responsible for permanently deleting an API user.
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
var result DeleteResult
_, result.Err = client.Delete(ResourceURL(client, id), nil)
return result
}
39 changes: 39 additions & 0 deletions openstack/identity/v2/tenants/results.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,42 @@ func ExtractTenants(page pagination.Page) ([]Tenant, error) {
err := mapstructure.Decode(casted, &response)
return response.Tenants, err
}

type commonResult struct {
gophercloud.Result
}

// Extract interprets any commonResult as a Tenant, if possible.
func (r commonResult) Extract() (*Tenant, error) {
if r.Err != nil {
return nil, r.Err
}

var response struct {
Tenant Tenant `mapstructure:"tenant"`
}

err := mapstructure.Decode(r.Body, &response)

return &response.Tenant, err
}

// 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
}

// DeleteResult represents the result of a Delete operation
type DeleteResult struct {
commonResult
}
8 changes: 8 additions & 0 deletions openstack/identity/v2/tenants/urls.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ package tenants

import "github.com/rackspace/gophercloud"

func ResourceURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL("tenants", id)
}

func rootURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL("tenants")
}

func listURL(client *gophercloud.ServiceClient) string {
return client.ServiceURL("tenants")
}