Skip to content

Commit

Permalink
feat: add api for clusterpropagationpolicy resource (#138)
Browse files Browse the repository at this point in the history
* feat: add api for clusterpropagationpolicy resource

Signed-off-by: warjiang <1096409085@qq.com>

* fix: add resource kind for clusterpp

Signed-off-by: warjiang <1096409085@qq.com>

---------

Signed-off-by: warjiang <1096409085@qq.com>
  • Loading branch information
warjiang authored Oct 16, 2024
1 parent 1bbf77e commit e48b695
Show file tree
Hide file tree
Showing 6 changed files with 306 additions and 0 deletions.
1 change: 1 addition & 0 deletions cmd/api/app/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
// Importing route packages forces route registration
_ "github.com/karmada-io/dashboard/cmd/api/app/routes/auth"
_ "github.com/karmada-io/dashboard/cmd/api/app/routes/cluster"
_ "github.com/karmada-io/dashboard/cmd/api/app/routes/clusterpropagationpolicy"
_ "github.com/karmada-io/dashboard/cmd/api/app/routes/config"
_ "github.com/karmada-io/dashboard/cmd/api/app/routes/configmap"
_ "github.com/karmada-io/dashboard/cmd/api/app/routes/cronjob"
Expand Down
161 changes: 161 additions & 0 deletions cmd/api/app/routes/clusterpropagationpolicy/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package propagationpolicy

import (
"context"
"github.com/gin-gonic/gin"
"github.com/karmada-io/dashboard/cmd/api/app/router"
v1 "github.com/karmada-io/dashboard/cmd/api/app/types/api/v1"
"github.com/karmada-io/dashboard/cmd/api/app/types/common"
"github.com/karmada-io/dashboard/pkg/client"
"github.com/karmada-io/dashboard/pkg/common/errors"
"github.com/karmada-io/dashboard/pkg/resource/clusterpropagationpolicy"
"github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/util/retry"
"k8s.io/klog/v2"
"sigs.k8s.io/yaml"
)

func handleGetClusterPropagationPolicyList(c *gin.Context) {
karmadaClient := client.InClusterKarmadaClient()
dataSelect := common.ParseDataSelectPathParameter(c)
clusterPropagationList, err := clusterpropagationpolicy.GetClusterPropagationPolicyList(karmadaClient, dataSelect)
if err != nil {
klog.ErrorS(err, "Failed to GetClusterPropagationPolicyList")
common.Fail(c, err)
return
}
common.Success(c, clusterPropagationList)
}

func handleGetClusterPropagationPolicyDetail(c *gin.Context) {
karmadaClient := client.InClusterKarmadaClient()
name := c.Param("clusterPropagationPolicyName")
result, err := clusterpropagationpolicy.GetClusterPropagationPolicyDetail(karmadaClient, name)
if err != nil {
klog.ErrorS(err, "GetClusterPropagationPolicyDetail failed")
common.Fail(c, err)
return
}
common.Success(c, result)
}

func handlePostClusterPropagationPolicy(c *gin.Context) {
ctx := context.Context(c)
propagationpolicyRequest := new(v1.PostPropagationPolicyRequest)
if err := c.ShouldBind(&propagationpolicyRequest); err != nil {
common.Fail(c, err)
return
}

var err error
karmadaClient := client.InClusterKarmadaClient()
if propagationpolicyRequest.IsClusterScope {
clusterPropagationPolicy := v1alpha1.ClusterPropagationPolicy{}
if err = yaml.Unmarshal([]byte(propagationpolicyRequest.PropagationData), &clusterPropagationPolicy); err != nil {
klog.ErrorS(err, "Failed to unmarshal ClusterPropagationPolicy")
common.Fail(c, err)
return
}
_, err = karmadaClient.PolicyV1alpha1().ClusterPropagationPolicies().Create(ctx, &clusterPropagationPolicy, metav1.CreateOptions{})
} else {
propagationPolicy := v1alpha1.PropagationPolicy{}
if err = yaml.Unmarshal([]byte(propagationpolicyRequest.PropagationData), &propagationPolicy); err != nil {
klog.ErrorS(err, "Failed to unmarshal PropagationPolicy")
common.Fail(c, err)
return
}
_, err = karmadaClient.PolicyV1alpha1().PropagationPolicies(propagationpolicyRequest.Namespace).Create(ctx, &propagationPolicy, metav1.CreateOptions{})
}
if err != nil {
klog.ErrorS(err, "Failed to create PropagationPolicy")
common.Fail(c, err)
return
}
common.Success(c, "ok")
}

func handlePutClusterPropagationPolicy(c *gin.Context) {
ctx := context.Context(c)
propagationpolicyRequest := new(v1.PutPropagationPolicyRequest)
if err := c.ShouldBind(&propagationpolicyRequest); err != nil {
common.Fail(c, err)
return
}
var err error
karmadaClient := client.InClusterKarmadaClient()
// todo check pp exist
if propagationpolicyRequest.IsClusterScope {
clusterPropagationPolicy := v1alpha1.ClusterPropagationPolicy{}
if err = yaml.Unmarshal([]byte(propagationpolicyRequest.PropagationData), &clusterPropagationPolicy); err != nil {
klog.ErrorS(err, "Failed to unmarshal ClusterPropagationPolicy")
common.Fail(c, err)
return
}
_, err = karmadaClient.PolicyV1alpha1().ClusterPropagationPolicies().Update(ctx, &clusterPropagationPolicy, metav1.UpdateOptions{})
} else {
propagationPolicy := v1alpha1.PropagationPolicy{}
if err = yaml.Unmarshal([]byte(propagationpolicyRequest.PropagationData), &propagationPolicy); err != nil {
klog.ErrorS(err, "Failed to unmarshal PropagationPolicy")
common.Fail(c, err)
return
}
var oldPropagationPolicy *v1alpha1.PropagationPolicy
oldPropagationPolicy, err = karmadaClient.PolicyV1alpha1().PropagationPolicies(propagationpolicyRequest.Namespace).Get(ctx, propagationpolicyRequest.Name, metav1.GetOptions{})
if err == nil {
// only spec can be updated
propagationPolicy.TypeMeta = oldPropagationPolicy.TypeMeta
propagationPolicy.ObjectMeta = oldPropagationPolicy.ObjectMeta
_, err = karmadaClient.PolicyV1alpha1().PropagationPolicies(propagationpolicyRequest.Namespace).Update(ctx, &propagationPolicy, metav1.UpdateOptions{})
}
}
if err != nil {
klog.ErrorS(err, "Failed to update PropagationPolicy")
common.Fail(c, err)
return
}
common.Success(c, "ok")
}
func handleDeleteClusterPropagationPolicy(c *gin.Context) {
ctx := context.Context(c)
propagationpolicyRequest := new(v1.DeletePropagationPolicyRequest)
if err := c.ShouldBind(&propagationpolicyRequest); err != nil {
common.Fail(c, err)
return
}
var err error
karmadaClient := client.InClusterKarmadaClient()
if propagationpolicyRequest.IsClusterScope {
err = karmadaClient.PolicyV1alpha1().ClusterPropagationPolicies().Delete(ctx, propagationpolicyRequest.Name, metav1.DeleteOptions{})
if err != nil {
klog.ErrorS(err, "Failed to delete PropagationPolicy")
common.Fail(c, err)
return
}
} else {
err = karmadaClient.PolicyV1alpha1().PropagationPolicies(propagationpolicyRequest.Namespace).Delete(ctx, propagationpolicyRequest.Name, metav1.DeleteOptions{})
if err != nil {
klog.ErrorS(err, "Failed to delete PropagationPolicy")
common.Fail(c, err)
return
}
err = retry.OnError(
retry.DefaultRetry,
func(err error) bool {
return errors.IsNotFound(err)
},
func() error {
_, getErr := karmadaClient.PolicyV1alpha1().PropagationPolicies(propagationpolicyRequest.Namespace).Get(ctx, propagationpolicyRequest.Name, metav1.GetOptions{})
return getErr
})
}

common.Success(c, "ok")
}

func init() {
r := router.V1()
r.GET("/clusterpropagationpolicy", handleGetClusterPropagationPolicyList)
r.GET("/clusterpropagationpolicy/:clusterPropagationPolicyName", handleGetClusterPropagationPolicyDetail)
r.POST("/clusterpropagationpolicy", handlePostClusterPropagationPolicy)
}
1 change: 1 addition & 0 deletions pkg/common/types/resourcekind.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ type ResourceKind string
const (
ResourceKindCluster = "cluster"
ResourceKindPropagationPolicy = "propagationpolicy"
ResourceKindClusterPropagationPolicy = "clusterpropagationpolicy"
ResourceKindConfigMap = "configmap"
ResourceKindDaemonSet = "daemonset"
ResourceKindDeployment = "deployment"
Expand Down
36 changes: 36 additions & 0 deletions pkg/resource/clusterpropagationpolicy/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package clusterpropagationpolicy

import (
"github.com/karmada-io/dashboard/pkg/dataselect"
"github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
)

type ClusterPropagationPolicyCell v1alpha1.ClusterPropagationPolicy

func (self ClusterPropagationPolicyCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
switch name {
case dataselect.NameProperty:
return dataselect.StdComparableString(self.ObjectMeta.Name)
case dataselect.CreationTimestampProperty:
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
default:
// if name is not supported then just return a constant dummy value, sort will have no effect.
return nil
}
}

func toCells(std []v1alpha1.ClusterPropagationPolicy) []dataselect.DataCell {
cells := make([]dataselect.DataCell, len(std))
for i := range std {
cells[i] = ClusterPropagationPolicyCell(std[i])
}
return cells
}

func fromCells(cells []dataselect.DataCell) []v1alpha1.ClusterPropagationPolicy {
std := make([]v1alpha1.ClusterPropagationPolicy, len(cells))
for i := range std {
std[i] = v1alpha1.ClusterPropagationPolicy(cells[i].(ClusterPropagationPolicyCell))
}
return std
}
40 changes: 40 additions & 0 deletions pkg/resource/clusterpropagationpolicy/detail.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package clusterpropagationpolicy

import (
"context"
"github.com/karmada-io/dashboard/pkg/common/errors"
"github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

type ClusterPropagationPolicyDetail struct {
// Extends list item structure.
ClusterPropagationPolicy `json:",inline"`

// List of non-critical errors, that occurred during resource retrieval.
Errors []error `json:"errors"`
}

// GetClusterPropagationPolicyDetail gets clusterPropagationPolicy details.
func GetClusterPropagationPolicyDetail(client karmadaclientset.Interface, name string) (*ClusterPropagationPolicyDetail, error) {
propagationpolicyData, err := client.PolicyV1alpha1().ClusterPropagationPolicies().Get(context.TODO(), name, metaV1.GetOptions{})
if err != nil {
return nil, err
}

nonCriticalErrors, criticalError := errors.ExtractErrors(err)
if criticalError != nil {
return nil, criticalError
}

propagationpolicy := toPropagationPolicyDetail(propagationpolicyData, nonCriticalErrors)
return &propagationpolicy, nil
}

func toPropagationPolicyDetail(clusterPropagationpolicy *v1alpha1.ClusterPropagationPolicy, nonCriticalErrors []error) ClusterPropagationPolicyDetail {
return ClusterPropagationPolicyDetail{
ClusterPropagationPolicy: toClusterPropagationPolicy(clusterPropagationpolicy),
Errors: nonCriticalErrors,
}
}
67 changes: 67 additions & 0 deletions pkg/resource/clusterpropagationpolicy/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package clusterpropagationpolicy

import (
"context"
"github.com/karmada-io/dashboard/pkg/common/errors"
"github.com/karmada-io/dashboard/pkg/common/helpers"
"github.com/karmada-io/dashboard/pkg/common/types"
"github.com/karmada-io/dashboard/pkg/dataselect"
"github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
)

// ClusterPropagationPolicyList contains a list of propagation in the karmada control-plane.
type ClusterPropagationPolicyList struct {
ListMeta types.ListMeta `json:"listMeta"`

// Unordered list of PropagationPolicies.
ClusterPropagationPolicies []ClusterPropagationPolicy `json:"clusterPropagationPolicies"`

// List of non-critical errors, that occurred during resource retrieval.
Errors []error `json:"errors"`
}

type ClusterPropagationPolicy struct {
ObjectMeta types.ObjectMeta `json:"objectMeta"`
TypeMeta types.TypeMeta `json:"typeMeta"`
SchedulerName string `json:"schedulerName"`
ClusterAffinity *v1alpha1.ClusterAffinity `json:"clusterAffinity"`
ResourceSelectors []v1alpha1.ResourceSelector `json:"resourceSelectors"`
}

// GetClusterPropagationPolicyList returns a list of all propagations in the karmada control-plance.
func GetClusterPropagationPolicyList(client karmadaclientset.Interface, dsQuery *dataselect.DataSelectQuery) (*ClusterPropagationPolicyList, error) {
clusterPropagationPolicies, err := client.PolicyV1alpha1().ClusterPropagationPolicies().List(context.TODO(), helpers.ListEverything)
nonCriticalErrors, criticalError := errors.ExtractErrors(err)
if criticalError != nil {
return nil, criticalError
}

return toClusterPropagationPolicyList(clusterPropagationPolicies.Items, nonCriticalErrors, dsQuery), nil
}

func toClusterPropagationPolicyList(clusterPropagationPolicies []v1alpha1.ClusterPropagationPolicy, nonCriticalErrors []error, dsQuery *dataselect.DataSelectQuery) *ClusterPropagationPolicyList {
propagationpolicyList := &ClusterPropagationPolicyList{
ClusterPropagationPolicies: make([]ClusterPropagationPolicy, 0),
ListMeta: types.ListMeta{TotalItems: len(clusterPropagationPolicies)},
}
clusterPropagationPolicyCells, filteredTotal := dataselect.GenericDataSelectWithFilter(toCells(clusterPropagationPolicies), dsQuery)
clusterPropagationPolicies = fromCells(clusterPropagationPolicyCells)
propagationpolicyList.ListMeta = types.ListMeta{TotalItems: filteredTotal}
propagationpolicyList.Errors = nonCriticalErrors

for _, clusterPropagationPolicy := range clusterPropagationPolicies {
clusterPP := toClusterPropagationPolicy(&clusterPropagationPolicy)
propagationpolicyList.ClusterPropagationPolicies = append(propagationpolicyList.ClusterPropagationPolicies, clusterPP)
}
return propagationpolicyList
}

func toClusterPropagationPolicy(propagationpolicy *v1alpha1.ClusterPropagationPolicy) ClusterPropagationPolicy {
return ClusterPropagationPolicy{
ObjectMeta: types.NewObjectMeta(propagationpolicy.ObjectMeta),
TypeMeta: types.NewTypeMeta(types.ResourceKindClusterPropagationPolicy),
SchedulerName: propagationpolicy.Spec.SchedulerName,
ClusterAffinity: propagationpolicy.Spec.Placement.ClusterAffinity,
}
}

0 comments on commit e48b695

Please sign in to comment.