mirror of https://github.com/k3s-io/k3s
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
parent
54dc9db17b
commit
cc71b0aebd
|
@ -2990,8 +2990,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/quobyte/api",
|
"ImportPath": "github.com/quobyte/api",
|
||||||
"Comment": "v0.1.1-4-g206ef832283c1a",
|
"Comment": "v0.1.2",
|
||||||
"Rev": "206ef832283c1a0144bbc762be2634d49987b5ff"
|
"Rev": "9cfd29338dd9fdaaf956b7082e5550aab5fe3841"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rancher/go-rancher/client",
|
"ImportPath": "github.com/rancher/go-rancher/client",
|
||||||
|
|
|
@ -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",
|
"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"
|
"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": {
|
"user": {
|
||||||
"description": "User to map volume access to Defaults to serivceaccount user",
|
"description": "User to map volume access to Defaults to serivceaccount user",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
|
|
@ -918,6 +918,11 @@ type QuobyteVolumeSource struct {
|
||||||
// Default is no group
|
// Default is no group
|
||||||
// +optional
|
// +optional
|
||||||
Group string
|
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.
|
// Represents a Glusterfs mount that lasts the lifetime of a pod.
|
||||||
|
|
|
@ -5989,6 +5989,7 @@ func autoConvert_v1_QuobyteVolumeSource_To_core_QuobyteVolumeSource(in *v1.Quoby
|
||||||
out.ReadOnly = in.ReadOnly
|
out.ReadOnly = in.ReadOnly
|
||||||
out.User = in.User
|
out.User = in.User
|
||||||
out.Group = in.Group
|
out.Group = in.Group
|
||||||
|
out.Tenant = in.Tenant
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6003,6 +6004,7 @@ func autoConvert_core_QuobyteVolumeSource_To_v1_QuobyteVolumeSource(in *core.Quo
|
||||||
out.ReadOnly = in.ReadOnly
|
out.ReadOnly = in.ReadOnly
|
||||||
out.User = in.User
|
out.User = in.User
|
||||||
out.Group = in.Group
|
out.Group = in.Group
|
||||||
|
out.Tenant = in.Tenant
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -873,6 +873,10 @@ func validateQuobyteVolumeSource(quobyte *core.QuobyteVolumeSource, fldPath *fie
|
||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
if len(quobyte.Registry) == 0 {
|
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"))
|
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 {
|
} else {
|
||||||
for _, hostPortPair := range strings.Split(quobyte.Registry, ",") {
|
for _, hostPortPair := range strings.Split(quobyte.Registry, ",") {
|
||||||
if _, _, err := net.SplitHostPort(hostPortPair); err != nil {
|
if _, _, err := net.SplitHostPort(hostPortPair); err != nil {
|
||||||
|
|
|
@ -3379,6 +3379,7 @@ func TestValidateVolumes(t *testing.T) {
|
||||||
ReadOnly: false,
|
ReadOnly: false,
|
||||||
User: "root",
|
User: "root",
|
||||||
Group: "root",
|
Group: "root",
|
||||||
|
Tenant: "ThisIsSomeTenantUUID",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -3390,6 +3391,7 @@ func TestValidateVolumes(t *testing.T) {
|
||||||
VolumeSource: core.VolumeSource{
|
VolumeSource: core.VolumeSource{
|
||||||
Quobyte: &core.QuobyteVolumeSource{
|
Quobyte: &core.QuobyteVolumeSource{
|
||||||
Volume: "/test",
|
Volume: "/test",
|
||||||
|
Tenant: "ThisIsSomeTenantUUID",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -3406,6 +3408,7 @@ func TestValidateVolumes(t *testing.T) {
|
||||||
Quobyte: &core.QuobyteVolumeSource{
|
Quobyte: &core.QuobyteVolumeSource{
|
||||||
Registry: "registry7861",
|
Registry: "registry7861",
|
||||||
Volume: "/test",
|
Volume: "/test",
|
||||||
|
Tenant: "ThisIsSomeTenantUUID",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -3422,6 +3425,7 @@ func TestValidateVolumes(t *testing.T) {
|
||||||
Quobyte: &core.QuobyteVolumeSource{
|
Quobyte: &core.QuobyteVolumeSource{
|
||||||
Registry: "registry:7861,reg2",
|
Registry: "registry:7861,reg2",
|
||||||
Volume: "/test",
|
Volume: "/test",
|
||||||
|
Tenant: "ThisIsSomeTenantUUID",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -3437,6 +3441,7 @@ func TestValidateVolumes(t *testing.T) {
|
||||||
VolumeSource: core.VolumeSource{
|
VolumeSource: core.VolumeSource{
|
||||||
Quobyte: &core.QuobyteVolumeSource{
|
Quobyte: &core.QuobyteVolumeSource{
|
||||||
Registry: "registry:7861",
|
Registry: "registry:7861",
|
||||||
|
Tenant: "ThisIsSomeTenantUUID",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -3445,6 +3450,40 @@ func TestValidateVolumes(t *testing.T) {
|
||||||
field: "quobyte.volume",
|
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
|
// AzureDisk
|
||||||
{
|
{
|
||||||
name: "valid AzureDisk",
|
name: "valid AzureDisk",
|
||||||
|
|
|
@ -326,6 +326,7 @@ func (plugin *quobytePlugin) newDeleterInternal(spec *volume.Spec) (volume.Delet
|
||||||
group: source.Group,
|
group: source.Group,
|
||||||
volume: source.Volume,
|
volume: source.Volume,
|
||||||
plugin: plugin,
|
plugin: plugin,
|
||||||
|
tenant: source.Tenant,
|
||||||
},
|
},
|
||||||
registry: source.Registry,
|
registry: source.Registry,
|
||||||
readOnly: readOnly,
|
readOnly: readOnly,
|
||||||
|
@ -424,6 +425,7 @@ func (provisioner *quobyteVolumeProvisioner) Provision(selectedNode *v1.Node, al
|
||||||
v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dGi", sizeGB)),
|
v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dGi", sizeGB)),
|
||||||
}
|
}
|
||||||
pv.Spec.MountOptions = provisioner.options.MountOptions
|
pv.Spec.MountOptions = provisioner.options.MountOptions
|
||||||
|
pv.Spec.PersistentVolumeSource.Quobyte.Tenant = provisioner.tenant
|
||||||
return pv, nil
|
return pv, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3421,6 +3421,11 @@ message QuobyteVolumeSource {
|
||||||
// Default is no group
|
// Default is no group
|
||||||
// +optional
|
// +optional
|
||||||
optional string group = 5;
|
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.
|
// Represents a Rados Block Device mount that lasts the lifetime of a pod.
|
||||||
|
|
|
@ -955,6 +955,11 @@ type QuobyteVolumeSource struct {
|
||||||
// Default is no group
|
// Default is no group
|
||||||
// +optional
|
// +optional
|
||||||
Group string `json:"group,omitempty" protobuf:"bytes,5,opt,name=group"`
|
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
|
// FlexPersistentVolumeSource represents a generic persistent volume resource that is
|
||||||
|
|
|
@ -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.",
|
"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",
|
"user": "User to map volume access to Defaults to serivceaccount user",
|
||||||
"group": "Group to map volume access to Default is no group",
|
"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 {
|
func (QuobyteVolumeSource) SwaggerDoc() map[string]string {
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
package quobyte
|
package quobyte
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
)
|
)
|
||||||
|
@ -15,6 +14,8 @@ const (
|
||||||
RetryOncePerTarget string = "ONCE_PER_TARGET"
|
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 {
|
type QuobyteClient struct {
|
||||||
client *http.Client
|
client *http.Client
|
||||||
url string
|
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
|
// 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) {
|
func (client QuobyteClient) CreateVolume(request *CreateVolumeRequest) (string, error) {
|
||||||
var response volumeUUID
|
var response volumeUUID
|
||||||
|
tenantUUID, err := client.GetTenantUUID(request.TenantID)
|
||||||
if request.TenantID != "" && !IsValidUUID(request.TenantID) {
|
if err != nil {
|
||||||
log.Printf("Tenant name resolution: Resolving %s to UUID\n", request.TenantID)
|
return "", err
|
||||||
tenantUUID, err := client.ResolveTenantNameToUUID(request.TenantID)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
request.TenantID = tenantUUID
|
|
||||||
}
|
}
|
||||||
|
request.TenantID = tenantUUID
|
||||||
|
|
||||||
if err := client.sendRequest("createVolume", request, &response); err != nil {
|
if err = client.sendRequest("createVolume", request, &response); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.VolumeUUID, nil
|
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
|
// ResolveVolumeNameToUUID resolves a volume name to a UUID
|
||||||
func (client *QuobyteClient) ResolveVolumeNameToUUID(volumeName, tenant string) (string, error) {
|
func (client *QuobyteClient) ResolveVolumeNameToUUID(volumeName, tenant string) (string, error) {
|
||||||
request := &resolveVolumeNameRequest{
|
request := &resolveVolumeNameRequest{
|
||||||
|
@ -77,6 +104,18 @@ func (client *QuobyteClient) ResolveVolumeNameToUUID(volumeName, tenant string)
|
||||||
return response.VolumeUUID, nil
|
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
|
// DeleteVolume deletes a Quobyte volume
|
||||||
func (client *QuobyteClient) DeleteVolume(UUID string) error {
|
func (client *QuobyteClient) DeleteVolume(UUID string) error {
|
||||||
return client.sendRequest(
|
return client.sendRequest(
|
||||||
|
@ -182,10 +221,9 @@ func (client *QuobyteClient) SetTenant(tenantName string) (string, error) {
|
||||||
return response.TenantID, nil
|
return response.TenantID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsValidUUID Validates given uuid
|
// IsValidUUID Validates the given uuid
|
||||||
func IsValidUUID(uuid string) bool {
|
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 UUIDValidator.MatchString(uuid)
|
||||||
return r.MatchString(uuid)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResolveTenantNameToUUID Returns UUID for given name, error if not found.
|
// ResolveTenantNameToUUID Returns UUID for given name, error if not found.
|
||||||
|
|
Loading…
Reference in New Issue