Adding Tenant to QuobyteVolumeSource

Adds the tenant id to the QuobyteVolumeSource type and
updates the quobyte api client to support looking up
volume ids.
pull/564/head
Silvan Kaiser 2018-07-25 10:22:02 +02:00
parent 54dc9db17b
commit cc71b0aebd
12 changed files with 962 additions and 820 deletions

4
Godeps/Godeps.json generated
View File

@ -2990,8 +2990,8 @@
},
{
"ImportPath": "github.com/quobyte/api",
"Comment": "v0.1.1-4-g206ef832283c1a",
"Rev": "206ef832283c1a0144bbc762be2634d49987b5ff"
"Comment": "v0.1.2",
"Rev": "9cfd29338dd9fdaaf956b7082e5550aab5fe3841"
},
{
"ImportPath": "github.com/rancher/go-rancher/client",

View File

@ -88245,6 +88245,10 @@
"description": "Registry represents a single or multiple Quobyte Registry services specified as a string as host:port pair (multiple entries are separated with commas) which acts as the central registry for volumes",
"type": "string"
},
"tenant": {
"description": "Tenant owning the given Quobyte volume in the Backend Used with dynamically provisioned Quobyte volumes, value is set by the plugin",
"type": "string"
},
"user": {
"description": "User to map volume access to Defaults to serivceaccount user",
"type": "string"

View File

@ -918,6 +918,11 @@ type QuobyteVolumeSource struct {
// Default is no group
// +optional
Group string
// Tenant owning the given Quobyte volume in the Backend
// Used with dynamically provisioned Quobyte volumes, value is set by the plugin
// +optional
Tenant string
}
// Represents a Glusterfs mount that lasts the lifetime of a pod.

View File

@ -5989,6 +5989,7 @@ func autoConvert_v1_QuobyteVolumeSource_To_core_QuobyteVolumeSource(in *v1.Quoby
out.ReadOnly = in.ReadOnly
out.User = in.User
out.Group = in.Group
out.Tenant = in.Tenant
return nil
}
@ -6003,6 +6004,7 @@ func autoConvert_core_QuobyteVolumeSource_To_v1_QuobyteVolumeSource(in *core.Quo
out.ReadOnly = in.ReadOnly
out.User = in.User
out.Group = in.Group
out.Tenant = in.Tenant
return nil
}

View File

@ -873,6 +873,10 @@ func validateQuobyteVolumeSource(quobyte *core.QuobyteVolumeSource, fldPath *fie
allErrs := field.ErrorList{}
if len(quobyte.Registry) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("registry"), "must be a host:port pair or multiple pairs separated by commas"))
} else if len(quobyte.Tenant) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("tenant"), "must be a UUID provided by the configuration and may not be omitted "))
} else if len(quobyte.Tenant) >= 65 {
allErrs = append(allErrs, field.Required(fldPath.Child("tenant"), "must be a UUID and may not exceed a length of 64 characters"))
} else {
for _, hostPortPair := range strings.Split(quobyte.Registry, ",") {
if _, _, err := net.SplitHostPort(hostPortPair); err != nil {

View File

@ -3379,6 +3379,7 @@ func TestValidateVolumes(t *testing.T) {
ReadOnly: false,
User: "root",
Group: "root",
Tenant: "ThisIsSomeTenantUUID",
},
},
},
@ -3390,6 +3391,7 @@ func TestValidateVolumes(t *testing.T) {
VolumeSource: core.VolumeSource{
Quobyte: &core.QuobyteVolumeSource{
Volume: "/test",
Tenant: "ThisIsSomeTenantUUID",
},
},
},
@ -3406,6 +3408,7 @@ func TestValidateVolumes(t *testing.T) {
Quobyte: &core.QuobyteVolumeSource{
Registry: "registry7861",
Volume: "/test",
Tenant: "ThisIsSomeTenantUUID",
},
},
},
@ -3422,6 +3425,7 @@ func TestValidateVolumes(t *testing.T) {
Quobyte: &core.QuobyteVolumeSource{
Registry: "registry:7861,reg2",
Volume: "/test",
Tenant: "ThisIsSomeTenantUUID",
},
},
},
@ -3437,6 +3441,7 @@ func TestValidateVolumes(t *testing.T) {
VolumeSource: core.VolumeSource{
Quobyte: &core.QuobyteVolumeSource{
Registry: "registry:7861",
Tenant: "ThisIsSomeTenantUUID",
},
},
},
@ -3445,6 +3450,40 @@ func TestValidateVolumes(t *testing.T) {
field: "quobyte.volume",
}},
},
{
name: "empty tenant quobyte",
vol: core.Volume{
Name: "quobyte",
VolumeSource: core.VolumeSource{
Quobyte: &core.QuobyteVolumeSource{
Registry: "registry:7861,reg2",
Volume: "/test",
Tenant: "",
},
},
},
errs: []verr{{
etype: field.ErrorTypeRequired,
field: "quobyte.tenant",
}},
},
{
name: "too long tenant quobyte",
vol: core.Volume{
Name: "quobyte",
VolumeSource: core.VolumeSource{
Quobyte: &core.QuobyteVolumeSource{
Registry: "registry:7861,reg2",
Volume: "/test",
Tenant: "this is too long to be a valid uuid so this test has to fail on the maximum length validation of the tenant.",
},
},
},
errs: []verr{{
etype: field.ErrorTypeRequired,
field: "quobyte.tenant",
}},
},
// AzureDisk
{
name: "valid AzureDisk",

View File

@ -326,6 +326,7 @@ func (plugin *quobytePlugin) newDeleterInternal(spec *volume.Spec) (volume.Delet
group: source.Group,
volume: source.Volume,
plugin: plugin,
tenant: source.Tenant,
},
registry: source.Registry,
readOnly: readOnly,
@ -424,6 +425,7 @@ func (provisioner *quobyteVolumeProvisioner) Provision(selectedNode *v1.Node, al
v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dGi", sizeGB)),
}
pv.Spec.MountOptions = provisioner.options.MountOptions
pv.Spec.PersistentVolumeSource.Quobyte.Tenant = provisioner.tenant
return pv, nil
}

File diff suppressed because it is too large Load Diff

View File

@ -3421,6 +3421,11 @@ message QuobyteVolumeSource {
// Default is no group
// +optional
optional string group = 5;
// Tenant owning the given Quobyte volume in the Backend
// Used with dynamically provisioned Quobyte volumes, value is set by the plugin
// +optional
optional string tenant = 6;
}
// Represents a Rados Block Device mount that lasts the lifetime of a pod.

View File

@ -955,6 +955,11 @@ type QuobyteVolumeSource struct {
// Default is no group
// +optional
Group string `json:"group,omitempty" protobuf:"bytes,5,opt,name=group"`
// Tenant owning the given Quobyte volume in the Backend
// Used with dynamically provisioned Quobyte volumes, value is set by the plugin
// +optional
Tenant string `json:"tenant,omitempty" protobuf:"bytes,6,opt,name=tenant"`
}
// FlexPersistentVolumeSource represents a generic persistent volume resource that is

View File

@ -1678,6 +1678,7 @@ var map_QuobyteVolumeSource = map[string]string{
"readOnly": "ReadOnly here will force the Quobyte volume to be mounted with read-only permissions. Defaults to false.",
"user": "User to map volume access to Defaults to serivceaccount user",
"group": "Group to map volume access to Default is no group",
"tenant": "Tenant owning the given Quobyte volume in the Backend Used with dynamically provisioned Quobyte volumes, value is set by the plugin",
}
func (QuobyteVolumeSource) SwaggerDoc() map[string]string {

View File

@ -2,7 +2,6 @@
package quobyte
import (
"log"
"net/http"
"regexp"
)
@ -15,6 +14,8 @@ const (
RetryOncePerTarget string = "ONCE_PER_TARGET"
)
var UUIDValidator = regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$")
type QuobyteClient struct {
client *http.Client
url string
@ -45,24 +46,50 @@ func NewQuobyteClient(url string, username string, password string) *QuobyteClie
// CreateVolume creates a new Quobyte volume. Its root directory will be owned by given user and group
func (client QuobyteClient) CreateVolume(request *CreateVolumeRequest) (string, error) {
var response volumeUUID
if request.TenantID != "" && !IsValidUUID(request.TenantID) {
log.Printf("Tenant name resolution: Resolving %s to UUID\n", request.TenantID)
tenantUUID, err := client.ResolveTenantNameToUUID(request.TenantID)
if err != nil {
return "", err
}
request.TenantID = tenantUUID
tenantUUID, err := client.GetTenantUUID(request.TenantID)
if err != nil {
return "", err
}
request.TenantID = tenantUUID
if err := client.sendRequest("createVolume", request, &response); err != nil {
if err = client.sendRequest("createVolume", request, &response); err != nil {
return "", err
}
return response.VolumeUUID, nil
}
// GetVolumeUUID resolves the volumeUUID for the given volume and tenant name.
// This method should be used when it is not clear if the given string is volume UUID or Name.
func (client QuobyteClient) GetVolumeUUID(volume, tenant string) (string, error) {
if len(volume) != 0 && !IsValidUUID(volume) {
tenantUUID, err := client.GetTenantUUID(tenant)
if err != nil {
return "", err
}
volUUID, err := client.ResolveVolumeNameToUUID(volume, tenantUUID)
if err != nil {
return "", err
}
return volUUID, nil
}
return volume, nil
}
// GetTenantUUID resolves the tenatnUUID for the given name
// This method should be used when it is not clear if the given string is Tenant UUID or Name.
func (client QuobyteClient) GetTenantUUID(tenant string) (string, error) {
if len(tenant) != 0 && !IsValidUUID(tenant) {
tenantUUID, err := client.ResolveTenantNameToUUID(tenant)
if err != nil {
return "", err
}
return tenantUUID, nil
}
return tenant, nil
}
// ResolveVolumeNameToUUID resolves a volume name to a UUID
func (client *QuobyteClient) ResolveVolumeNameToUUID(volumeName, tenant string) (string, error) {
request := &resolveVolumeNameRequest{
@ -77,6 +104,18 @@ func (client *QuobyteClient) ResolveVolumeNameToUUID(volumeName, tenant string)
return response.VolumeUUID, nil
}
// DeleteVolumeByResolvingNamesToUUID deletes the volume by resolving the volume name and tenant name to
// respective UUID if required.
// This method should be used if the given volume, tenant information is name or UUID.
func (client *QuobyteClient) DeleteVolumeByResolvingNamesToUUID(volume, tenant string) error {
volumeUUID, err := client.GetVolumeUUID(volume, tenant)
if err != nil {
return err
}
return client.DeleteVolume(volumeUUID)
}
// DeleteVolume deletes a Quobyte volume
func (client *QuobyteClient) DeleteVolume(UUID string) error {
return client.sendRequest(
@ -182,10 +221,9 @@ func (client *QuobyteClient) SetTenant(tenantName string) (string, error) {
return response.TenantID, nil
}
// IsValidUUID Validates given uuid
// IsValidUUID Validates the given uuid
func IsValidUUID(uuid string) bool {
r := regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$")
return r.MatchString(uuid)
return UUIDValidator.MatchString(uuid)
}
// ResolveTenantNameToUUID Returns UUID for given name, error if not found.