This is an automated email from the ASF dual-hosted git repository.
mani pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/yunikorn-core.git
The following commit(s) were added to refs/heads/master by this push:
new 375eb941 [YUNIKORN-2715] Handle special characters for params like
queue, username & groupname (#905)
375eb941 is described below
commit 375eb941273f9c5a85d412abe11fd702af0ed7d2
Author: Manikandan R <[email protected]>
AuthorDate: Thu Jul 4 13:21:39 2024 +0530
[YUNIKORN-2715] Handle special characters for params like queue, username &
groupname (#905)
Closes: #905
Signed-off-by: Manikandan R <[email protected]>
---
pkg/webservice/handlers.go | 44 ++++-
pkg/webservice/handlers_test.go | 422 ++++++++++++++++++++++------------------
2 files changed, 268 insertions(+), 198 deletions(-)
diff --git a/pkg/webservice/handlers.go b/pkg/webservice/handlers.go
index a66614dc..9bbb99bf 100644
--- a/pkg/webservice/handlers.go
+++ b/pkg/webservice/handlers.go
@@ -24,6 +24,7 @@ import (
"io"
"math"
"net/http"
+ "net/url"
"runtime"
"sort"
"strconv"
@@ -668,12 +669,17 @@ func getPartitionQueue(w http.ResponseWriter, r
*http.Request) {
return
}
queueName := vars.ByName("queue")
- queueErr := validateQueue(queueName)
+ unescapedQueueName, err := url.QueryUnescape(queueName)
+ if err != nil {
+ buildJSONErrorResponse(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+ queueErr := validateQueue(unescapedQueueName)
if queueErr != nil {
buildJSONErrorResponse(w, queueErr.Error(),
http.StatusBadRequest)
return
}
- queue := partitionContext.GetQueue(queueName)
+ queue := partitionContext.GetQueue(unescapedQueueName)
if queue == nil {
buildJSONErrorResponse(w, QueueDoesNotExists,
http.StatusNotFound)
return
@@ -737,7 +743,12 @@ func getQueueApplications(w http.ResponseWriter, r
*http.Request) {
}
partition := vars.ByName("partition")
queueName := vars.ByName("queue")
- queueErr := validateQueue(queueName)
+ unescapedQueueName, err := url.QueryUnescape(queueName)
+ if err != nil {
+ buildJSONErrorResponse(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+ queueErr := validateQueue(unescapedQueueName)
if queueErr != nil {
buildJSONErrorResponse(w, queueErr.Error(),
http.StatusBadRequest)
return
@@ -747,7 +758,7 @@ func getQueueApplications(w http.ResponseWriter, r
*http.Request) {
buildJSONErrorResponse(w, PartitionDoesNotExists,
http.StatusNotFound)
return
}
- queue := partitionContext.GetQueue(queueName)
+ queue := partitionContext.GetQueue(unescapedQueueName)
if queue == nil {
buildJSONErrorResponse(w, QueueDoesNotExists,
http.StatusNotFound)
return
@@ -820,6 +831,11 @@ func getApplication(w http.ResponseWriter, r
*http.Request) {
}
partition := vars.ByName("partition")
queueName := vars.ByName("queue")
+ unescapedQueueName, err := url.QueryUnescape(queueName)
+ if err != nil {
+ buildJSONErrorResponse(w, err.Error(), http.StatusBadRequest)
+ return
+ }
application := vars.ByName("application")
partitionContext :=
schedulerContext.GetPartitionWithoutClusterID(partition)
if partitionContext == nil {
@@ -827,15 +843,15 @@ func getApplication(w http.ResponseWriter, r
*http.Request) {
return
}
var app *objects.Application
- if len(queueName) == 0 {
+ if len(unescapedQueueName) == 0 {
app = partitionContext.GetApplication(application)
} else {
- queueErr := validateQueue(queueName)
+ queueErr := validateQueue(unescapedQueueName)
if queueErr != nil {
buildJSONErrorResponse(w, queueErr.Error(),
http.StatusBadRequest)
return
}
- queue := partitionContext.GetQueue(queueName)
+ queue := partitionContext.GetQueue(unescapedQueueName)
if queue == nil {
buildJSONErrorResponse(w, QueueDoesNotExists,
http.StatusNotFound)
return
@@ -1078,7 +1094,12 @@ func getUserResourceUsage(w http.ResponseWriter, r
*http.Request) {
buildJSONErrorResponse(w, UserNameMissing,
http.StatusBadRequest)
return
}
- userTracker := ugm.GetUserManager().GetUserTracker(user)
+ unescapedUser, err := url.QueryUnescape(user)
+ if err != nil {
+ buildJSONErrorResponse(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+ userTracker := ugm.GetUserManager().GetUserTracker(unescapedUser)
if userTracker == nil {
buildJSONErrorResponse(w, UserDoesNotExists,
http.StatusNotFound)
return
@@ -1114,7 +1135,12 @@ func getGroupResourceUsage(w http.ResponseWriter, r
*http.Request) {
buildJSONErrorResponse(w, GroupNameMissing,
http.StatusBadRequest)
return
}
- groupTracker := ugm.GetUserManager().GetGroupTracker(group)
+ unescapedGroupName, err := url.QueryUnescape(group)
+ if err != nil {
+ buildJSONErrorResponse(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+ groupTracker := ugm.GetUserManager().GetGroupTracker(unescapedGroupName)
if groupTracker == nil {
buildJSONErrorResponse(w, GroupDoesNotExists,
http.StatusNotFound)
return
diff --git a/pkg/webservice/handlers_test.go b/pkg/webservice/handlers_test.go
index a49df1a6..169cca86 100644
--- a/pkg/webservice/handlers_test.go
+++ b/pkg/webservice/handlers_test.go
@@ -25,6 +25,7 @@ import (
"fmt"
"net/http"
"net/http/httptest"
+ "net/url"
"reflect"
"strings"
"testing"
@@ -278,6 +279,7 @@ const rmID = "rm-123"
const policyGroup = "default-policy-group"
const queueName = "root.default"
const nodeID = "node-1"
+const invalidQueueName = "root.parent.test%Zt%23%3Art%3A%2F_ff-test"
var (
updatedExtraConf = map[string]string{
@@ -1106,74 +1108,17 @@ func TestGetPartitionQueuesHandler(t *testing.T) {
err = json.Unmarshal(resp.outputBytes, &partitionQueuesDao)
assert.NilError(t, err, unmarshalError)
// assert root fields
- assert.Equal(t, partitionQueuesDao.QueueName, configs.RootQueue)
- assert.Equal(t, partitionQueuesDao.Status, objects.Active.String())
- assert.Equal(t, partitionQueuesDao.Partition, configs.DefaultPartition)
- assert.Assert(t, partitionQueuesDao.PendingResource == nil)
- assert.Assert(t, partitionQueuesDao.MaxResource == nil)
- assert.Assert(t, partitionQueuesDao.GuaranteedResource == nil)
- assert.Assert(t, partitionQueuesDao.AllocatedResource == nil)
- assert.Assert(t, partitionQueuesDao.PreemptingResource == nil)
- assert.Assert(t, partitionQueuesDao.HeadRoom == nil)
- assert.Assert(t, !partitionQueuesDao.IsLeaf)
- assert.Assert(t, partitionQueuesDao.IsManaged)
- assert.Equal(t, partitionQueuesDao.Parent, "")
- assert.Assert(t, partitionQueuesDao.AbsUsedCapacity == nil)
- assert.Equal(t, partitionQueuesDao.MaxRunningApps, uint64(0))
- assert.Equal(t, partitionQueuesDao.RunningApps, uint64(0))
- assert.Equal(t, partitionQueuesDao.CurrentPriority, configs.MinPriority)
- assert.Assert(t, partitionQueuesDao.AllocatingAcceptedApps == nil)
- assert.Equal(t, len(partitionQueuesDao.Properties), 1)
- assert.Equal(t,
partitionQueuesDao.Properties[configs.ApplicationSortPolicy],
policies.FifoSortPolicy.String())
- assert.DeepEqual(t, partitionQueuesDao.TemplateInfo, &templateInfo)
+ assertPartitionQueueDaoInfo(t, &partitionQueuesDao, configs.RootQueue,
configs.DefaultPartition, nil, nil, false, true, "", &templateInfo)
// assert child root.a fields
assert.Equal(t, len(partitionQueuesDao.Children), 1)
child := &partitionQueuesDao.Children[0]
- assert.Equal(t, child.QueueName, "root.a")
- assert.Equal(t, child.Status, objects.Active.String())
- assert.Equal(t, child.Partition, "")
- assert.Assert(t, child.PendingResource == nil)
- assert.DeepEqual(t, child.MaxResource, maxResource.DAOMap())
- assert.DeepEqual(t, child.GuaranteedResource,
guaranteedResource.DAOMap())
- assert.Assert(t, child.AllocatedResource == nil)
- assert.Assert(t, child.PreemptingResource == nil)
- assert.DeepEqual(t, child.HeadRoom, maxResource.DAOMap())
- assert.Assert(t, !child.IsLeaf)
- assert.Assert(t, child.IsManaged)
- assert.Equal(t, child.Parent, configs.RootQueue)
- assert.Assert(t, child.AbsUsedCapacity == nil)
- assert.Equal(t, child.MaxRunningApps, uint64(0))
- assert.Equal(t, child.RunningApps, uint64(0))
- assert.Equal(t, child.CurrentPriority, configs.MinPriority)
- assert.Assert(t, child.AllocatingAcceptedApps == nil)
- assert.Equal(t, len(child.Properties), 1)
- assert.Equal(t, child.Properties[configs.ApplicationSortPolicy],
policies.FifoSortPolicy.String())
- assert.DeepEqual(t, child.TemplateInfo, &templateInfo)
+ assertPartitionQueueDaoInfo(t, child, "root.a", "",
maxResource.DAOMap(), guaranteedResource.DAOMap(), false, true, "root",
&templateInfo)
// assert child root.a.a1 fields
assert.Equal(t, len(partitionQueuesDao.Children[0].Children), 1)
child = &partitionQueuesDao.Children[0].Children[0]
- assert.Equal(t, child.QueueName, "root.a.a1")
- assert.Equal(t, child.Status, objects.Active.String())
- assert.Equal(t, child.Partition, "")
- assert.Assert(t, child.PendingResource == nil)
- assert.DeepEqual(t, child.MaxResource, maxResource.DAOMap())
- assert.DeepEqual(t, child.GuaranteedResource,
guaranteedResource.DAOMap())
- assert.Assert(t, child.AllocatedResource == nil)
- assert.Assert(t, child.PreemptingResource == nil)
- assert.DeepEqual(t, child.HeadRoom, maxResource.DAOMap())
- assert.Assert(t, child.IsLeaf)
- assert.Assert(t, child.IsManaged)
- assert.Equal(t, child.Parent, "root.a")
- assert.Assert(t, child.AbsUsedCapacity == nil)
- assert.Equal(t, child.MaxRunningApps, uint64(0))
- assert.Equal(t, child.RunningApps, uint64(0))
- assert.Equal(t, child.CurrentPriority, configs.MinPriority)
- assert.Assert(t, child.AllocatingAcceptedApps == nil)
- assert.Equal(t, len(child.Properties), 1)
- assert.Equal(t, child.Properties[configs.ApplicationSortPolicy],
policies.FifoSortPolicy.String())
- assert.Assert(t, child.TemplateInfo == nil)
+ assertPartitionQueueDaoInfo(t, child, "root.a.a1", "",
maxResource.DAOMap(), guaranteedResource.DAOMap(), true, true, "root.a", nil)
// test partition not exists
req, err = http.NewRequest("GET", "/ws/v1/partition/default/queues",
strings.NewReader(""))
@@ -1190,14 +1135,45 @@ func TestGetPartitionQueuesHandler(t *testing.T) {
resp = &MockResponseWriter{}
getPartitionQueues(resp, req)
assertParamsMissing(t, resp)
+}
+
+func assertPartitionQueueDaoInfo(t *testing.T, partitionQueueDAOInfo
*dao.PartitionQueueDAOInfo, queueName string, partition string, maxResource
map[string]int64, gResource map[string]int64, leaf bool, isManaged bool, parent
string, templateInfo *dao.TemplateInfo) {
+ assert.Equal(t, partitionQueueDAOInfo.QueueName, queueName)
+ assert.Equal(t, partitionQueueDAOInfo.Status, objects.Active.String())
+ assert.Equal(t, partitionQueueDAOInfo.Partition, partition)
+ assert.Assert(t, partitionQueueDAOInfo.PendingResource == nil)
+ assert.DeepEqual(t, partitionQueueDAOInfo.MaxResource, maxResource)
+ assert.DeepEqual(t, partitionQueueDAOInfo.GuaranteedResource, gResource)
+ assert.Assert(t, partitionQueueDAOInfo.AllocatedResource == nil)
+ assert.Assert(t, partitionQueueDAOInfo.PreemptingResource == nil)
+ assert.DeepEqual(t, partitionQueueDAOInfo.HeadRoom, maxResource)
+ assert.Equal(t, partitionQueueDAOInfo.IsLeaf, leaf)
+ assert.Equal(t, partitionQueueDAOInfo.IsManaged, isManaged)
+ assert.Equal(t, partitionQueueDAOInfo.Parent, parent)
+ assert.Assert(t, partitionQueueDAOInfo.AbsUsedCapacity == nil)
+ assert.Equal(t, partitionQueueDAOInfo.MaxRunningApps, uint64(0))
+ assert.Equal(t, partitionQueueDAOInfo.RunningApps, uint64(0))
+ assert.Equal(t, partitionQueueDAOInfo.CurrentPriority,
configs.MinPriority)
+ assert.Assert(t, partitionQueueDAOInfo.AllocatingAcceptedApps == nil)
+ assert.Equal(t, len(partitionQueueDAOInfo.Properties), 1)
+ assert.Equal(t,
partitionQueueDAOInfo.Properties[configs.ApplicationSortPolicy],
policies.FifoSortPolicy.String())
+ assert.DeepEqual(t, partitionQueueDAOInfo.TemplateInfo, templateInfo)
+}
+
+func TestGetPartitionQueueHandler(t *testing.T) {
+ partitionQueuesHandler := "/ws/v1/partition/default/queue/"
+ queueA := "root.a"
+ setup(t, configTwoLevelQueues, 2)
+
+ NewWebApp(schedulerContext, nil)
// test specific queue
var partitionQueueDao1 dao.PartitionQueueDAOInfo
- req, err = http.NewRequest("GET",
"/ws/v1/partition/default/queue/root.a", strings.NewReader(""))
+ req, err := http.NewRequest("GET", partitionQueuesHandler+queueA,
strings.NewReader(""))
assert.NilError(t, err, "HTTP request create failed")
req = req.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{httprouter.Param{Key: "partition",
Value: "default"}, httprouter.Param{Key: "queue", Value: "root.a"}}))
assert.NilError(t, err)
- resp = &MockResponseWriter{}
+ resp := &MockResponseWriter{}
getPartitionQueue(resp, req)
err = json.Unmarshal(resp.outputBytes, &partitionQueueDao1)
assert.NilError(t, err, unmarshalError)
@@ -1208,7 +1184,7 @@ func TestGetPartitionQueuesHandler(t *testing.T) {
// test hierarchy queue
var partitionQueueDao2 dao.PartitionQueueDAOInfo
- req, err = http.NewRequest("GET",
"/ws/v1/partition/default/queue/root.a?subtree", strings.NewReader(""))
+ req, err = http.NewRequest("GET",
partitionQueuesHandler+"root.a?subtree", strings.NewReader(""))
assert.NilError(t, err, "HTTP request create failed")
req = req.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{httprouter.Param{Key: "partition",
Value: "default"}, httprouter.Param{Key: "queue", Value: "root.a"}}))
assert.NilError(t, err)
@@ -1223,7 +1199,7 @@ func TestGetPartitionQueuesHandler(t *testing.T) {
assert.Equal(t, partitionQueueDao2.ChildNames[0], "root.a.a1")
// test partition not exists
- req, err = http.NewRequest("GET",
"/ws/v1/partition/default/queue/root.a", strings.NewReader(""))
+ req, err = http.NewRequest("GET", partitionQueuesHandler+queueA,
strings.NewReader(""))
assert.NilError(t, err, "HTTP request create failed")
req = req.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{httprouter.Param{Key: "partition",
Value: "notexists"}}))
assert.NilError(t, err)
@@ -1232,14 +1208,14 @@ func TestGetPartitionQueuesHandler(t *testing.T) {
assertPartitionNotExists(t, resp)
// test params name missing
- req, err = http.NewRequest("GET",
"/ws/v1/partition/default/queue/root.a", strings.NewReader(""))
+ req, err = http.NewRequest("GET", partitionQueuesHandler+queueA,
strings.NewReader(""))
assert.NilError(t, err)
resp = &MockResponseWriter{}
getPartitionQueue(resp, req)
assertParamsMissing(t, resp)
// test invalid queue name
- req, err = http.NewRequest("GET",
"/ws/v1/partition/default/queue/root.a", strings.NewReader(""))
+ req, err = http.NewRequest("GET", partitionQueuesHandler+queueA,
strings.NewReader(""))
assert.NilError(t, err, "HTTP request create failed")
req = req.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{httprouter.Param{Key: "partition",
Value: "default"}, httprouter.Param{Key: "queue", Value: "root.notexists!"}}))
assert.NilError(t, err)
@@ -1248,13 +1224,45 @@ func TestGetPartitionQueuesHandler(t *testing.T) {
assertQueueInvalid(t, resp, "root.notexists!", "notexists!")
// test queue is not exists
- req, err = http.NewRequest("GET",
"/ws/v1/partition/default/queue/root.a", strings.NewReader(""))
+ req, err = http.NewRequest("GET", partitionQueuesHandler+queueA,
strings.NewReader(""))
assert.NilError(t, err, "HTTP request create failed")
req = req.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{httprouter.Param{Key: "partition",
Value: "default"}, httprouter.Param{Key: "queue", Value: "notexists"}}))
assert.NilError(t, err)
resp = &MockResponseWriter{}
getPartitionQueue(resp, req)
assertQueueNotExists(t, resp)
+
+ // test queue name with special characters escaped properly
+ queueName := url.QueryEscape("root.parent.test@t#:rt:/_ff-test")
+ req, err = http.NewRequest("GET", partitionQueuesHandler+queueName,
strings.NewReader(""))
+ assert.NilError(t, err, "HTTP request create failed")
+ req = req.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{
+ httprouter.Param{Key: "partition", Value:
partitionNameWithoutClusterID},
+ httprouter.Param{Key: "queue", Value: queueName},
+ }))
+ resp = &MockResponseWriter{}
+ getPartitionQueue(resp, req)
+ assertQueueNotExists(t, resp)
+
+ // test queue name with special characters escaped not properly, catch
error at request level
+ _, err = http.NewRequest("GET",
partitionQueuesHandler+invalidQueueName, strings.NewReader(""))
+ assert.ErrorContains(t, err, "invalid URL escape")
+
+ // test queue name with special characters escaped not properly, catch
error while un escaping queue name
+ req, err = http.NewRequest("GET", partitionQueuesHandler+queueA,
strings.NewReader(""))
+ assert.NilError(t, err, "HTTP request create failed")
+ req = req.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{
+ httprouter.Param{Key: "partition", Value:
partitionNameWithoutClusterID},
+ httprouter.Param{Key: "queue", Value: invalidQueueName},
+ }))
+ resp = &MockResponseWriter{}
+ getPartitionQueue(resp, req)
+ var errInfo dao.YAPIError
+ err = json.Unmarshal(resp.outputBytes, &errInfo)
+ assert.NilError(t, err, unmarshalError)
+ assert.Equal(t, http.StatusBadRequest, resp.statusCode, statusCodeError)
+ assert.Equal(t, errInfo.Message, "invalid URL escape \"%Zt\"",
jsonMessageError)
+ assert.Equal(t, errInfo.StatusCode, http.StatusBadRequest)
}
func TestGetClusterInfo(t *testing.T) {
@@ -1408,10 +1416,13 @@ func addAppWithUserGroup(t *testing.T, id string, part
*scheduler.PartitionConte
}
func TestGetQueueApplicationsHandler(t *testing.T) {
+ handlerURL := "/ws/v1/partition/default/queue/"
+ handlerSuffix := "/applications"
+ defaultQueue := "root.default"
part := setup(t, configDefault, 1)
// add an application
- app := addApp(t, "app-1", part, "root.default", false)
+ app := addApp(t, "app-1", part, defaultQueue, false)
// add placeholder to test PlaceholderDAOInfo
tg := "tg-1"
@@ -1431,13 +1442,8 @@ func TestGetQueueApplicationsHandler(t *testing.T) {
NewWebApp(schedulerContext, nil)
var req *http.Request
- req, err = http.NewRequest("GET",
"/ws/v1/partition/default/queue/root.default/applications",
strings.NewReader(""))
- assert.NilError(t, err, "HTTP request create failed")
- req = req.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{
- httprouter.Param{Key: "partition", Value:
partitionNameWithoutClusterID},
- httprouter.Param{Key: "queue", Value: "root.default"},
- }))
- assert.NilError(t, err, "Get Queue Applications Handler request failed")
+ req, err = createRequest(t, handlerURL+defaultQueue+handlerSuffix,
map[string]string{"partition": partitionNameWithoutClusterID, "queue":
defaultQueue})
+ assert.NilError(t, err)
resp := &MockResponseWriter{}
var appsDao []*dao.ApplicationDAOInfo
getQueueApplications(resp, req)
@@ -1461,39 +1467,24 @@ func TestGetQueueApplicationsHandler(t *testing.T) {
// test nonexistent partition
var req1 *http.Request
- req1, err = http.NewRequest("GET",
"/ws/v1/partition/default/queue/root.default/applications",
strings.NewReader(""))
- assert.NilError(t, err, "HTTP request create failed")
- req1 = req1.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{
- httprouter.Param{Key: "partition", Value: "notexists"},
- httprouter.Param{Key: "queue", Value: "root.default"},
- }))
- assert.NilError(t, err, "Get Queue Applications Handler request failed")
+ req1, err = createRequest(t, handlerURL+defaultQueue+handlerSuffix,
map[string]string{"partition": "notexists", "queue": defaultQueue})
+ assert.NilError(t, err)
resp1 := &MockResponseWriter{}
getQueueApplications(resp1, req1)
assertPartitionNotExists(t, resp1)
// test nonexistent queue
var req2 *http.Request
- req2, err = http.NewRequest("GET",
"/ws/v1/partition/default/queue/root.default/applications",
strings.NewReader(""))
- assert.NilError(t, err, "HTTP request create failed")
- req2 = req2.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{
- httprouter.Param{Key: "partition", Value:
partitionNameWithoutClusterID},
- httprouter.Param{Key: "queue", Value: "notexists"},
- }))
- assert.NilError(t, err, "Get Queue Applications Handler request failed")
+ req2, err = createRequest(t, handlerURL+defaultQueue+handlerSuffix,
map[string]string{"partition": partitionNameWithoutClusterID, "queue":
"notexists"})
+ assert.NilError(t, err)
resp2 := &MockResponseWriter{}
getQueueApplications(resp2, req2)
assertQueueNotExists(t, resp2)
// test queue without applications
var req3 *http.Request
- req3, err = http.NewRequest("GET",
"/ws/v1/partition/default/queue/root.noapps/applications",
strings.NewReader(""))
- assert.NilError(t, err, "HTTP request create failed")
- req3 = req3.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{
- httprouter.Param{Key: "partition", Value:
partitionNameWithoutClusterID},
- httprouter.Param{Key: "queue", Value: "root.noapps"},
- }))
- assert.NilError(t, err, "Get Queue Applications Handler request failed")
+ req3, err = createRequest(t, handlerURL+"root.noapps"+handlerSuffix,
map[string]string{"partition": partitionNameWithoutClusterID, "queue":
"root.noapps"})
+ assert.NilError(t, err)
resp3 := &MockResponseWriter{}
var appsDao3 []*dao.ApplicationDAOInfo
getQueueApplications(resp3, req3)
@@ -1502,11 +1493,49 @@ func TestGetQueueApplicationsHandler(t *testing.T) {
assert.Equal(t, len(appsDao3), 0)
// test missing params name
- req, err = http.NewRequest("GET",
"/ws/v1/partition/default/queue/root.default/applications",
strings.NewReader(""))
- assert.NilError(t, err, "Get Queue Applications Handler request failed")
+ req, err = createRequest(t, handlerURL+queueName+handlerSuffix,
map[string]string{})
+ assert.NilError(t, err)
resp = &MockResponseWriter{}
getQueueApplications(resp, req)
assertParamsMissing(t, resp)
+
+ // test queue name with special characters escaped properly
+ queueName := url.QueryEscape("root.parent.test@t#:rt:/_ff-test")
+ req, err = createRequest(t, handlerURL+queueName+handlerSuffix,
map[string]string{"partition": partitionNameWithoutClusterID, "queue":
queueName})
+ assert.NilError(t, err)
+ resp = &MockResponseWriter{}
+ getQueueApplications(resp, req)
+ assertQueueNotExists(t, resp)
+
+ // test queue name with special characters escaped not properly, catch
error at request level
+ _, err = http.NewRequest("GET",
handlerURL+invalidQueueName+handlerSuffix, strings.NewReader(""))
+ assert.ErrorContains(t, err, "invalid URL escape")
+
+ // test queue name with special characters escaped not properly, catch
error while un escaping queue name
+ req, err = createRequest(t, handlerURL+defaultQueue+handlerSuffix,
map[string]string{"partition": partitionNameWithoutClusterID, "queue":
invalidQueueName})
+ assert.NilError(t, err)
+ resp = &MockResponseWriter{}
+ getQueueApplications(resp, req)
+ var errInfo dao.YAPIError
+ err = json.Unmarshal(resp.outputBytes, &errInfo)
+ assert.NilError(t, err, unmarshalError)
+ assert.Equal(t, http.StatusBadRequest, resp.statusCode, statusCodeError)
+ assert.Equal(t, errInfo.Message, "invalid URL escape \"%Zt\"",
jsonMessageError)
+ assert.Equal(t, errInfo.StatusCode, http.StatusBadRequest)
+}
+
+func createRequest(t *testing.T, url string, paramsMap map[string]string)
(*http.Request, error) {
+ var err error
+ var req *http.Request
+ req, err = http.NewRequest("GET", url, strings.NewReader(""))
+ assert.NilError(t, err, "Handler request create failed")
+ var params httprouter.Params
+ for k, v := range paramsMap {
+ param := httprouter.Param{Key: k, Value: v}
+ params = append(params, param)
+ }
+ req = req.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, params))
+ return req, err
}
func checkLegalGetAppsRequest(t *testing.T, url string, params
httprouter.Params, expected []*dao.ApplicationDAOInfo) {
@@ -1613,14 +1642,8 @@ func TestGetApplicationHandler(t *testing.T) {
NewWebApp(schedulerContext, nil)
var req *http.Request
- req, err = http.NewRequest("GET",
"/ws/v1/partition/default/queue/root.default/application/app-1",
strings.NewReader(""))
- assert.NilError(t, err, "HTTP request create failed")
- req = req.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{
- httprouter.Param{Key: "partition", Value:
partitionNameWithoutClusterID},
- httprouter.Param{Key: "queue", Value: "root.default"},
- httprouter.Param{Key: "application", Value: "app-1"},
- }))
- assert.NilError(t, err, "Get Application Handler request failed")
+ req, err = createRequest(t,
"/ws/v1/partition/default/queue/root.default/application/app-1",
map[string]string{"partition": partitionNameWithoutClusterID, "queue":
"root.default", "application": "app-1"})
+ assert.NilError(t, err)
resp := &MockResponseWriter{}
var appsDao *dao.ApplicationDAOInfo
getApplication(resp, req)
@@ -1635,55 +1658,32 @@ func TestGetApplicationHandler(t *testing.T) {
// test nonexistent partition
var req1 *http.Request
- req1, err = http.NewRequest("GET",
"/ws/v1/partition/default/queue/root.default/application/app-1",
strings.NewReader(""))
- assert.NilError(t, err, "HTTP request create failed")
- req1 = req1.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{
- httprouter.Param{Key: "partition", Value: "notexists"},
- httprouter.Param{Key: "queue", Value: "root.default"},
- httprouter.Param{Key: "application", Value: "app-1"},
- }))
- assert.NilError(t, err, "Get Application Handler request failed")
+ req1, err = createRequest(t,
"/ws/v1/partition/default/queue/root.default/application/app-1",
map[string]string{"partition": "notexists", "queue": "root.default",
"application": "app-1"})
+ assert.NilError(t, err)
resp1 := &MockResponseWriter{}
getApplication(resp1, req1)
assertPartitionNotExists(t, resp1)
// test nonexistent queue
var req2 *http.Request
- req2, err = http.NewRequest("GET",
"/ws/v1/partition/default/queue/root.default/application/app-1",
strings.NewReader(""))
- assert.NilError(t, err, "HTTP request create failed")
- req2 = req2.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{
- httprouter.Param{Key: "partition", Value:
partitionNameWithoutClusterID},
- httprouter.Param{Key: "queue", Value: "notexists"},
- httprouter.Param{Key: "application", Value: "app-1"},
- }))
- assert.NilError(t, err, "Get Application Handler request failed")
+ req2, err = createRequest(t,
"/ws/v1/partition/default/queue/root.default/application/app-1",
map[string]string{"partition": partitionNameWithoutClusterID, "queue":
"notexists", "application": "app-1"})
+ assert.NilError(t, err)
resp2 := &MockResponseWriter{}
getApplication(resp2, req2)
assertQueueNotExists(t, resp2)
// test nonexistent application
var req3 *http.Request
- req3, err = http.NewRequest("GET",
"/ws/v1/partition/default/queue/root.noapps/application/app-1",
strings.NewReader(""))
- assert.NilError(t, err, "HTTP request create failed")
- req3 = req3.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{
- httprouter.Param{Key: "partition", Value:
partitionNameWithoutClusterID},
- httprouter.Param{Key: "queue", Value: "root.noapps"},
- httprouter.Param{Key: "application", Value: "app-1"},
- }))
- assert.NilError(t, err, "Get Application Handler request failed")
+ req3, err = createRequest(t,
"/ws/v1/partition/default/queue/root.noapps/application/app-1",
map[string]string{"partition": partitionNameWithoutClusterID, "queue":
"root.noapps", "application": "app-1"})
+ assert.NilError(t, err)
resp3 := &MockResponseWriter{}
getApplication(resp3, req3)
assertApplicationNotExists(t, resp3)
// test without queue
var req4 *http.Request
- req4, err = http.NewRequest("GET",
"/ws/v1/partition/default/application/app-1", strings.NewReader(""))
- assert.NilError(t, err, "HTTP request create failed")
- req4 = req4.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{
- httprouter.Param{Key: "partition", Value:
partitionNameWithoutClusterID},
- httprouter.Param{Key: "application", Value: "app-1"},
- }))
- assert.NilError(t, err, "Get Application Handler request failed")
+ req4, err = createRequest(t,
"/ws/v1/partition/default/application/app-1", map[string]string{"partition":
partitionNameWithoutClusterID, "application": "app-1"})
+ assert.NilError(t, err)
resp4 := &MockResponseWriter{}
var appsDao4 *dao.ApplicationDAOInfo
getApplication(resp4, req4)
@@ -1692,24 +1692,42 @@ func TestGetApplicationHandler(t *testing.T) {
// test invalid queue name
var req5 *http.Request
- req5, err = http.NewRequest("GET",
"/ws/v1/partition/default/queue/root.default/application/app-1",
strings.NewReader(""))
- assert.NilError(t, err, "HTTP request create failed")
- req5 = req5.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{
- httprouter.Param{Key: "partition", Value:
partitionNameWithoutClusterID},
- httprouter.Param{Key: "queue", Value: "root.test.test123!"},
- httprouter.Param{Key: "application", Value: "app-1"},
- }))
- assert.NilError(t, err, "Get Application Handler request failed")
+ req5, err = createRequest(t,
"/ws/v1/partition/default/queue/root.default/application/app-1",
map[string]string{"partition": partitionNameWithoutClusterID, "queue":
"root.test.test123!", "application": "app-1"})
+ assert.NilError(t, err)
resp5 := &MockResponseWriter{}
getApplication(resp5, req5)
assertQueueInvalid(t, resp5, "root.test.test123!", "test123!")
// test missing params name
- req, err = http.NewRequest("GET",
"/ws/v1/partition/default/queue/root.default/application/app-1",
strings.NewReader(""))
- assert.NilError(t, err, "Get Application Handler request failed")
+ req, err = createRequest(t,
"/ws/v1/partition/default/queue/root.default/application/app-1",
map[string]string{})
+ assert.NilError(t, err)
resp = &MockResponseWriter{}
getApplication(resp, req)
assertParamsMissing(t, resp)
+
+ // test queue name with special characters escaped properly
+ queueName := url.QueryEscape("root.parent.test@t#:rt:/_ff-test")
+ req, err = createRequest(t,
"/ws/v1/partition/default/queue/root.default/application/app-1",
map[string]string{"partition": partitionNameWithoutClusterID, "queue":
queueName})
+ assert.NilError(t, err)
+ resp = &MockResponseWriter{}
+ getApplication(resp, req)
+ assertQueueNotExists(t, resp)
+
+ // test queue name with special characters escaped not properly, catch
error at request level
+ _, err = http.NewRequest("GET",
"/ws/v1/partition/default/queue/"+invalidQueueName+"/application/app-1",
strings.NewReader(""))
+ assert.ErrorContains(t, err, "invalid URL escape")
+
+ // test queue name with special characters escaped not properly, catch
error while un escaping queue name
+ req, err = createRequest(t,
"/ws/v1/partition/default/queue/root.default/application/app-1",
map[string]string{"partition": partitionNameWithoutClusterID, "queue":
invalidQueueName})
+ assert.NilError(t, err)
+ resp = &MockResponseWriter{}
+ getApplication(resp, req)
+ var errInfo dao.YAPIError
+ err = json.Unmarshal(resp.outputBytes, &errInfo)
+ assert.NilError(t, err, unmarshalError)
+ assert.Equal(t, http.StatusBadRequest, resp.statusCode, statusCodeError)
+ assert.Equal(t, errInfo.Message, "invalid URL escape \"%Zt\"",
jsonMessageError)
+ assert.Equal(t, errInfo.StatusCode, http.StatusBadRequest)
}
func assertParamsMissing(t *testing.T, resp *MockResponseWriter) {
@@ -1882,39 +1900,25 @@ func TestFullStateDumpPath(t *testing.T) {
verifyStateDumpJSON(t, &aggregated, 1)
}
-func TestSpecificUserAndGroupResourceUsage(t *testing.T) {
+func TestSpecificUserResourceUsage(t *testing.T) {
prepareUserAndGroupContext(t, groupsLimitsConfig)
// Test user name is missing
- req, err := http.NewRequest("GET",
"/ws/v1/partition/default/usage/user/", strings.NewReader(""))
- assert.NilError(t, err, "HTTP request create failed")
- req = req.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{
- httprouter.Param{Key: "group", Value: "testgroup"},
- }))
- assert.NilError(t, err, "Get User Resource Usage Handler request
failed")
+ req, err := createRequest(t, "/ws/v1/partition/default/usage/user/",
map[string]string{"group": "testgroup"})
+ assert.NilError(t, err)
resp := &MockResponseWriter{}
getUserResourceUsage(resp, req)
assertUserNameMissing(t, resp)
// Test group name is missing
- req, err = http.NewRequest("GET",
"/ws/v1/partition/default/usage/group/", strings.NewReader(""))
- assert.NilError(t, err, "HTTP request create failed")
- req = req.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{
- httprouter.Param{Key: "user", Value: "testuser"},
- httprouter.Param{Key: "group", Value: ""},
- }))
- assert.NilError(t, err, "Get Group Resource Usage Handler request
failed")
+ req, err = createRequest(t, "/ws/v1/partition/default/usage/group/",
map[string]string{"user": "testuser"})
+ assert.NilError(t, err)
resp = &MockResponseWriter{}
getGroupResourceUsage(resp, req)
assertGroupNameMissing(t, resp)
// Test existed user query
- req, err = http.NewRequest("GET",
"/ws/v1/partition/default/usage/user/", strings.NewReader(""))
- assert.NilError(t, err, "HTTP request create failed")
- req = req.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{
- httprouter.Param{Key: "user", Value: "testuser"},
- httprouter.Param{Key: "group", Value: "testgroup"},
- }))
- assert.NilError(t, err, "Get User Resource Usage Handler request
failed")
+ req, err = createRequest(t, "/ws/v1/partition/default/usage/user/",
map[string]string{"user": "testuser", "group": "testgroup"})
+ assert.NilError(t, err)
resp = &MockResponseWriter{}
getUserResourceUsage(resp, req)
assertUserExists(t, resp,
@@ -1936,25 +1940,44 @@ func TestSpecificUserAndGroupResourceUsage(t
*testing.T) {
})
// Test non-existing user query
- req, err = http.NewRequest("GET",
"/ws/v1/partition/default/usage/user/", strings.NewReader(""))
- assert.NilError(t, err, "HTTP request create failed")
- req = req.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{
- httprouter.Param{Key: "user", Value: "testNonExistingUser"},
- httprouter.Param{Key: "group", Value: "testgroup"},
- }))
- assert.NilError(t, err, "Get User Resource Usage Handler request
failed")
+ req, err = createRequest(t, "/ws/v1/partition/default/usage/user/",
map[string]string{"user": "testNonExistingUser", "group": "testgroup"})
+ assert.NilError(t, err)
resp = &MockResponseWriter{}
getUserResourceUsage(resp, req)
assertUserNotExists(t, resp)
- // Test existed group query
- req, err = http.NewRequest("GET",
"/ws/v1/partition/default/usage/group/", strings.NewReader(""))
- assert.NilError(t, err, "Get Group Resource Usage Handler request
failed")
- req = req.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{
- httprouter.Param{Key: "user", Value: "testuser"},
- httprouter.Param{Key: "group", Value: "testgroup"},
- }))
+ // Test username with special characters escaped properly
+ validUser := url.QueryEscape("test_a-b_c@#d@do:mai/n.com")
+ req, err = createRequest(t, "/ws/v1/partition/default/usage/user/",
map[string]string{"user": validUser, "group": "testgroup"})
+ assert.NilError(t, err)
resp = &MockResponseWriter{}
+ getUserResourceUsage(resp, req)
+ assertUserNotExists(t, resp)
+
+ // Test username with special characters not escaped properly, catch
error at request level
+ invalidUser := "test_a-b_c%Zt@#d@do:mai/n.com"
+ _, err = http.NewRequest("GET",
"/ws/v1/partition/default/usage/user/"+invalidUser, strings.NewReader(""))
+ assert.ErrorContains(t, err, "invalid URL escape")
+
+ // Test username with special characters not escaped properly, catch
error while un escaping username
+ req, err = createRequest(t, "/ws/v1/partition/default/usage/user/test",
map[string]string{"user": invalidUser, "group": "testgroup"})
+ assert.NilError(t, err)
+ resp = &MockResponseWriter{}
+ getUserResourceUsage(resp, req)
+ var errInfo dao.YAPIError
+ err = json.Unmarshal(resp.outputBytes, &errInfo)
+ assert.NilError(t, err, unmarshalError)
+ assert.Equal(t, http.StatusBadRequest, resp.statusCode, statusCodeError)
+ assert.Equal(t, errInfo.Message, "invalid URL escape \"%Zt\"",
jsonMessageError)
+ assert.Equal(t, errInfo.StatusCode, http.StatusBadRequest)
+}
+
+func TestSpecificGroupResourceUsage(t *testing.T) {
+ prepareUserAndGroupContext(t, groupsLimitsConfig)
+ // Test existed group query
+ req, err := createRequest(t, "/ws/v1/partition/default/usage/group",
map[string]string{"user": "testuser", "group": "testgroup"})
+ assert.NilError(t, err)
+ resp := &MockResponseWriter{}
getGroupResourceUsage(resp, req)
assertGroupExists(t, resp,
&dao.GroupResourceUsageDAOInfo{
@@ -1976,22 +1999,43 @@ func TestSpecificUserAndGroupResourceUsage(t
*testing.T) {
})
// Test non-existing group query
- req, err = http.NewRequest("GET",
"/ws/v1/partition/default/usage/group/", strings.NewReader(""))
- assert.NilError(t, err, "Get Group Resource Usage Handler request
failed")
- req = req.WithContext(context.WithValue(req.Context(),
httprouter.ParamsKey, httprouter.Params{
- httprouter.Param{Key: "user", Value: "testuser"},
- httprouter.Param{Key: "group", Value: "testNonExistingGroup"},
- }))
+ req, err = createRequest(t, "/ws/v1/partition/default/usage/group",
map[string]string{"user": "testuser", "group": "testNonExistingGroup"})
+ assert.NilError(t, err)
resp = &MockResponseWriter{}
getGroupResourceUsage(resp, req)
assertGroupNotExists(t, resp)
// Test params name missing
req, err = http.NewRequest("GET",
"/ws/v1/partition/default/usage/group/", strings.NewReader(""))
- assert.NilError(t, err, "Get Group Resource Usage Handler request
failed")
+ assert.NilError(t, err)
resp = &MockResponseWriter{}
getGroupResourceUsage(resp, req)
assertParamsMissing(t, resp)
+
+ // Test group name with special characters escaped properly
+ validGroup := url.QueryEscape("test_a-b_c@#d@do:mai/n.com")
+ req, err = createRequest(t, "/ws/v1/partition/default/usage/group",
map[string]string{"user": "testuser", "group": validGroup})
+ assert.NilError(t, err)
+ resp = &MockResponseWriter{}
+ getGroupResourceUsage(resp, req)
+ assertGroupNotExists(t, resp)
+
+ // Test group name with special characters not escaped properly, catch
error at request level
+ invalidGroup := "test_a-b_c%Zt@#d@do:mai/n.com"
+ _, err = http.NewRequest("GET",
"/ws/v1/partition/default/usage/group/"+invalidGroup, strings.NewReader(""))
+ assert.ErrorContains(t, err, "invalid URL escape")
+
+ // Test group name with special characters not escaped properly, catch
error while un escaping group name
+ req, err = createRequest(t,
"/ws/v1/partition/default/usage/group/test", map[string]string{"user":
"testuser", "group": invalidGroup})
+ assert.NilError(t, err)
+ resp = &MockResponseWriter{}
+ getGroupResourceUsage(resp, req)
+ var errInfo dao.YAPIError
+ err = json.Unmarshal(resp.outputBytes, &errInfo)
+ assert.NilError(t, err, unmarshalError)
+ assert.Equal(t, http.StatusBadRequest, resp.statusCode, statusCodeError)
+ assert.Equal(t, errInfo.Message, "invalid URL escape \"%Zt\"",
jsonMessageError)
+ assert.Equal(t, errInfo.StatusCode, http.StatusBadRequest)
}
func TestUsersAndGroupsResourceUsage(t *testing.T) {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]