Skip to content

Commit

Permalink
Merge pull request #5 from gianlucam76/pagination
Browse files Browse the repository at this point in the history
Add pagination
  • Loading branch information
gianlucam76 authored Apr 25, 2024
2 parents 4a72aff + 060913b commit 67ce68b
Show file tree
Hide file tree
Showing 8 changed files with 252 additions and 12 deletions.
6 changes: 4 additions & 2 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,14 @@ const (
)

// Add RBAC for the authorized diagnostics endpoint.
// +kubebuilder:rbac:groups=authentication.k8s.io,resources=tokenreviews,verbs=create
// +kubebuilder:rbac:groups=authorization.k8s.io,resources=subjectaccessreviews,verbs=create
//+kubebuilder:rbac:groups=authentication.k8s.io,resources=tokenreviews,verbs=create
//+kubebuilder:rbac:groups=authorization.k8s.io,resources=subjectaccessreviews,verbs=create

// Add RBAC to detect if ClusterAPI is installed
//+kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions,verbs=get;list;watch

//+kubebuilder:rbac:groups=lib.projectsveltos.io,resources=debuggingconfigurations,verbs=get;list;watch

func main() {
scheme, err := controller.InitScheme()
if err != nil {
Expand Down
8 changes: 8 additions & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ rules:
- get
- list
- watch
- apiGroups:
- lib.projectsveltos.io
resources:
- debuggingconfigurations
verbs:
- get
- list
- watch
- apiGroups:
- lib.projectsveltos.io
resources:
Expand Down
21 changes: 21 additions & 0 deletions internal/server/export_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
Copyright 2024. projectsveltos.io. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package server

var (
GetLimitedClusters = getLimitedClusters
)
64 changes: 55 additions & 9 deletions internal/server/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import (
"context"
"fmt"
"net/http"
"sort"
"strconv"
"syscall"

"github.com/gin-gonic/gin"
Expand All @@ -29,35 +31,50 @@ import (
logs "github.com/projectsveltos/libsveltos/lib/logsettings"
)

type ManagedCluster struct {
Namespace string `json:"namespace"`
Name string `json:"name"`
ClusterInfo `json:"clusterInfo"`
}
const (
maxItems = 6
)

var (
ginLogger logr.Logger

getManagedCAPIClusters = func(c *gin.Context) {
ginLogger.V(logs.LogDebug).Info("get managed ClusterAPI Clusters")

limit, skip := getLimitAndSkipFromQuery(c)
ginLogger.V(logs.LogDebug).Info(fmt.Sprintf("limit %d skip %d", limit, skip))

manager := GetManagerInstance()
clusters := manager.GetManagedCAPIClusters()
managedClusterData := getManagedClusterData(clusters)
sort.Sort(managedClusterData)

result, err := getLimitedClusters(managedClusterData, limit, skip)
if err != nil {
ginLogger.V(logs.LogInfo).Info(fmt.Sprintf("bad request %s: %v", c.Request.URL, err))
_ = c.AbortWithError(http.StatusBadRequest, err)
}
// Return JSON response
c.JSON(http.StatusOK, managedClusterData)
c.JSON(http.StatusOK, result)
}

getManagedSveltosClusters = func(c *gin.Context) {
ginLogger.V(logs.LogDebug).Info("get managed SveltosClusters")

limit, skip := getLimitAndSkipFromQuery(c)
ginLogger.V(logs.LogDebug).Info(fmt.Sprintf("limit %d skip %d", limit, skip))

manager := GetManagerInstance()
clusters := manager.GetManagedSveltosClusters()
managedClusterData := getManagedClusterData(clusters)
result, err := getLimitedClusters(managedClusterData, limit, skip)
if err != nil {
ginLogger.V(logs.LogInfo).Info(fmt.Sprintf("bad request %s: %v", c.Request.URL, err))
_ = c.AbortWithError(http.StatusBadRequest, err)
}

// Return JSON response
c.JSON(http.StatusOK, managedClusterData)
c.JSON(http.StatusOK, result)
}
)

Expand Down Expand Up @@ -92,8 +109,8 @@ func (m *instance) start(ctx context.Context, port string, logger logr.Logger) {
}
}

func getManagedClusterData(clusters map[corev1.ObjectReference]ClusterInfo) []ManagedCluster {
data := make([]ManagedCluster, len(clusters))
func getManagedClusterData(clusters map[corev1.ObjectReference]ClusterInfo) ManagedClusters {
data := make(ManagedClusters, len(clusters))
i := 0
for k := range clusters {
data[i] = ManagedCluster{
Expand All @@ -106,3 +123,32 @@ func getManagedClusterData(clusters map[corev1.ObjectReference]ClusterInfo) []Ma

return data
}

func getLimitAndSkipFromQuery(c *gin.Context) (limit, skip int) {
// Define default values for limit and skip
limit = maxItems
skip = 0

// Get the values from query parameters
queryLimit := c.Query("limit")
querySkip := c.Query("skip")

// Parse the query parameters to int (handle errors)
var err error
if queryLimit != "" {
limit, err = strconv.Atoi(queryLimit)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid limit parameter"})
return
}
}
if querySkip != "" {
skip, err = strconv.Atoi(querySkip)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid skip parameter"})
return
}
}

return
}
96 changes: 96 additions & 0 deletions internal/server/managed_cluster_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
Copyright 2024. projectsveltos.io. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package server_test

import (
"reflect"
"sort"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

"github.com/projectsveltos/ui-backend/internal/server"
)

var _ = Describe("ManageClusters", func() {
It("Clusters are sorted by Namespace/Name", func() {
managedClusters := make(server.ManagedClusters, 0)
for i := 0; i < 10; i++ {
cluster := server.ManagedCluster{
Namespace: randomString(),
Name: randomString(),
}

managedClusters = append(managedClusters, cluster)
}

sort.Sort(managedClusters)

var previousNamespace string
for i := range managedClusters {
if i == 0 {
previousNamespace = managedClusters[i].Namespace
} else {
Expect(previousNamespace < managedClusters[i].Namespace)
previousNamespace = managedClusters[i].Namespace
}
}
})

It("getLimitedClusters returns the right set of clusters", func() {
managedClusters := make(server.ManagedClusters, 0)
for i := 0; i < 10; i++ {
cluster := server.ManagedCluster{
Namespace: randomString(),
Name: randomString(),
}

managedClusters = append(managedClusters, cluster)
}

sort.Sort(managedClusters)

limit := 1
skip := 3
result, err := server.GetLimitedClusters(managedClusters, limit, skip)
Expect(err).To(BeNil())
for i := 0; i < limit; i++ {
Expect(reflect.DeepEqual(result[i], managedClusters[skip+i]))
}

limit = 3
skip = 5
result, err = server.GetLimitedClusters(managedClusters, limit, skip)
Expect(err).To(BeNil())
for i := 0; i < limit; i++ {
Expect(reflect.DeepEqual(result[i], managedClusters[skip+i]))
}

limit = 3
skip = 9
result, err = server.GetLimitedClusters(managedClusters, limit, skip)
Expect(err).To(BeNil())
// limit is 3 but skip starts from 9. Original number of clusters is 10. So expect only 1 cluster
Expect(len(result)).To(Equal(1))
Expect(reflect.DeepEqual(result[0], managedClusters[skip]))

limit = 3
skip = 11
_, err = server.GetLimitedClusters(managedClusters, limit, skip)
Expect(err).ToNot(BeNil())
})
})
59 changes: 59 additions & 0 deletions internal/server/managed_clusters.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
Copyright 2024. projectsveltos.io. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package server

import (
"errors"
)

type ManagedCluster struct {
Namespace string `json:"namespace"`
Name string `json:"name"`
ClusterInfo `json:"clusterInfo"`
}

type ManagedClusters []ManagedCluster

func (s ManagedClusters) Len() int { return len(s) }
func (s ManagedClusters) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s ManagedClusters) Less(i, j int) bool {
if s[i].Namespace == s[j].Namespace {
return s[i].Name < s[j].Name
}
return s[i].Namespace < s[j].Namespace
}

func getLimitedClusters(clusters ManagedClusters, limit, skip int) (ManagedClusters, error) {
if skip < 0 {
return nil, errors.New("skip cannot be negative")
}
if limit < 0 {
return nil, errors.New("limit cannot be negative")
}
if skip >= len(clusters) {
return nil, errors.New("skip cannot be greater than or equal to the length of the slice")
}

// Adjust limit based on slice length and skip
adjustedLimit := limit
if skip+limit > len(clusters) {
adjustedLimit = len(clusters) - skip
}

// Use slicing to extract the desired sub-slice
return clusters[skip : skip+adjustedLimit], nil
}
2 changes: 1 addition & 1 deletion internal/server/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ import (
"reflect"
"time"

"github.com/go-logr/logr"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

"github.com/go-logr/logr"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
Expand Down
8 changes: 8 additions & 0 deletions manifest/manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ rules:
- get
- list
- watch
- apiGroups:
- lib.projectsveltos.io
resources:
- debuggingconfigurations
verbs:
- get
- list
- watch
- apiGroups:
- lib.projectsveltos.io
resources:
Expand Down

0 comments on commit 67ce68b

Please sign in to comment.