Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add api for clusterpropagationpolicy resource #138

Merged
merged 2 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,
}
}