diff --git a/cmd/api/app/api.go b/cmd/api/app/api.go index 3688f356..76af08c0 100644 --- a/cmd/api/app/api.go +++ b/cmd/api/app/api.go @@ -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/clusteroverridepolicy" _ "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" @@ -27,6 +28,7 @@ import ( _ "github.com/karmada-io/dashboard/cmd/api/app/routes/job" _ "github.com/karmada-io/dashboard/cmd/api/app/routes/member/node" _ "github.com/karmada-io/dashboard/cmd/api/app/routes/namespace" + _ "github.com/karmada-io/dashboard/cmd/api/app/routes/overridepolicy" _ "github.com/karmada-io/dashboard/cmd/api/app/routes/overview" _ "github.com/karmada-io/dashboard/cmd/api/app/routes/propagationpolicy" _ "github.com/karmada-io/dashboard/cmd/api/app/routes/secret" diff --git a/cmd/api/app/routes/clusteroverridepolicy/handler.go b/cmd/api/app/routes/clusteroverridepolicy/handler.go new file mode 100644 index 00000000..5bf7ed29 --- /dev/null +++ b/cmd/api/app/routes/clusteroverridepolicy/handler.go @@ -0,0 +1,162 @@ +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/clusteroverridepolicy" + "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 handleGetClusterOverridePolicyList(c *gin.Context) { + karmadaClient := client.InClusterKarmadaClient() + dataSelect := common.ParseDataSelectPathParameter(c) + clusterOverrideList, err := clusteroverridepolicy.GetClusterOverridePolicyList(karmadaClient, dataSelect) + if err != nil { + klog.ErrorS(err, "Failed to GetClusterOverridePolicyList") + common.Fail(c, err) + return + } + common.Success(c, clusterOverrideList) +} + +func handleGetClusterOverridePolicyDetail(c *gin.Context) { + karmadaClient := client.InClusterKarmadaClient() + name := c.Param("clusterOverridePolicyName") + result, err := clusteroverridepolicy.GetClusterOverridePolicyDetail(karmadaClient, name) + if err != nil { + klog.ErrorS(err, "GetClusterOverridePolicyDetail failed") + common.Fail(c, err) + return + } + common.Success(c, result) +} + +func handlePostClusterOverridePolicy(c *gin.Context) { + ctx := context.Context(c) + overridepolicyRequest := new(v1.PostOverridePolicyRequest) + if err := c.ShouldBind(&overridepolicyRequest); err != nil { + common.Fail(c, err) + return + } + + var err error + karmadaClient := client.InClusterKarmadaClient() + if overridepolicyRequest.IsClusterScope { + clusterOverridePolicy := v1alpha1.ClusterOverridePolicy{} + if err = yaml.Unmarshal([]byte(overridepolicyRequest.OverrideData), &clusterOverridePolicy); err != nil { + klog.ErrorS(err, "Failed to unmarshal ClusterOverridePolicy") + common.Fail(c, err) + return + } + _, err = karmadaClient.PolicyV1alpha1().ClusterOverridePolicies().Create(ctx, &clusterOverridePolicy, metav1.CreateOptions{}) + } else { + overridePolicy := v1alpha1.OverridePolicy{} + if err = yaml.Unmarshal([]byte(overridepolicyRequest.OverrideData), &overridePolicy); err != nil { + klog.ErrorS(err, "Failed to unmarshal OverridePolicy") + common.Fail(c, err) + return + } + _, err = karmadaClient.PolicyV1alpha1().OverridePolicies(overridepolicyRequest.Namespace).Create(ctx, &overridePolicy, metav1.CreateOptions{}) + } + if err != nil { + klog.ErrorS(err, "Failed to create OverridePolicy") + common.Fail(c, err) + return + } + common.Success(c, "ok") +} + +func handlePutClusterOverridePolicy(c *gin.Context) { + ctx := context.Context(c) + overridepolicyRequest := new(v1.PutOverridePolicyRequest) + if err := c.ShouldBind(&overridepolicyRequest); err != nil { + common.Fail(c, err) + return + } + var err error + karmadaClient := client.InClusterKarmadaClient() + // todo check pp exist + if overridepolicyRequest.IsClusterScope { + clusterOverridePolicy := v1alpha1.ClusterOverridePolicy{} + if err = yaml.Unmarshal([]byte(overridepolicyRequest.OverrideData), &clusterOverridePolicy); err != nil { + klog.ErrorS(err, "Failed to unmarshal ClusterOverridePolicy") + common.Fail(c, err) + return + } + _, err = karmadaClient.PolicyV1alpha1().ClusterOverridePolicies().Update(ctx, &clusterOverridePolicy, metav1.UpdateOptions{}) + } else { + overridePolicy := v1alpha1.OverridePolicy{} + if err = yaml.Unmarshal([]byte(overridepolicyRequest.OverrideData), &overridePolicy); err != nil { + klog.ErrorS(err, "Failed to unmarshal OverridePolicy") + common.Fail(c, err) + return + } + var oldPropagationPolicy *v1alpha1.OverridePolicy + oldPropagationPolicy, err = karmadaClient.PolicyV1alpha1().OverridePolicies(overridepolicyRequest.Namespace).Get(ctx, overridepolicyRequest.Name, metav1.GetOptions{}) + if err == nil { + // only spec can be updated + overridePolicy.TypeMeta = oldPropagationPolicy.TypeMeta + overridePolicy.ObjectMeta = oldPropagationPolicy.ObjectMeta + _, err = karmadaClient.PolicyV1alpha1().OverridePolicies(overridepolicyRequest.Namespace).Update(ctx, &overridePolicy, metav1.UpdateOptions{}) + } + } + if err != nil { + klog.ErrorS(err, "Failed to update OverridePolicy") + common.Fail(c, err) + return + } + common.Success(c, "ok") +} + +func handleDeleteClusterOverridePolicy(c *gin.Context) { + ctx := context.Context(c) + overridepolicyRequest := new(v1.DeleteOverridePolicyRequest) + if err := c.ShouldBind(&overridepolicyRequest); err != nil { + common.Fail(c, err) + return + } + var err error + karmadaClient := client.InClusterKarmadaClient() + if overridepolicyRequest.IsClusterScope { + err = karmadaClient.PolicyV1alpha1().ClusterOverridePolicies().Delete(ctx, overridepolicyRequest.Name, metav1.DeleteOptions{}) + if err != nil { + klog.ErrorS(err, "Failed to delete ClusterOverridePolicy") + common.Fail(c, err) + return + } + } else { + err = karmadaClient.PolicyV1alpha1().OverridePolicies(overridepolicyRequest.Namespace).Delete(ctx, overridepolicyRequest.Name, metav1.DeleteOptions{}) + if err != nil { + klog.ErrorS(err, "Failed to delete OverridePolicy") + common.Fail(c, err) + return + } + err = retry.OnError( + retry.DefaultRetry, + func(err error) bool { + return errors.IsNotFound(err) + }, + func() error { + _, getErr := karmadaClient.PolicyV1alpha1().OverridePolicies(overridepolicyRequest.Namespace).Get(ctx, overridepolicyRequest.Name, metav1.GetOptions{}) + return getErr + }) + } + + common.Success(c, "ok") +} + +func init() { + r := router.V1() + r.GET("/clusteroverridepolicy", handleGetClusterOverridePolicyList) + r.GET("/clusteroverridepolicy/:clusterOverridePolicyName", handleGetClusterOverridePolicyDetail) + r.POST("/clusteroverridepolicy", handlePostClusterOverridePolicy) +} diff --git a/cmd/api/app/routes/overridepolicy/handler.go b/cmd/api/app/routes/overridepolicy/handler.go new file mode 100644 index 00000000..52375519 --- /dev/null +++ b/cmd/api/app/routes/overridepolicy/handler.go @@ -0,0 +1,168 @@ +package overridepolicy + +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/overridepolicy" + "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 handleGetOverridePolicyList(c *gin.Context) { + karmadaClient := client.InClusterKarmadaClient() + dataSelect := common.ParseDataSelectPathParameter(c) + namespace := common.ParseNamespacePathParameter(c) + k8sClient := client.InClusterClientForKarmadaApiServer() + overrideList, err := overridepolicy.GetOverridePolicyList(karmadaClient, k8sClient, namespace, dataSelect) + if err != nil { + klog.ErrorS(err, "Failed to GetOverridePolicyList") + common.Fail(c, err) + return + } + common.Success(c, overrideList) +} +func handleGetOverridePolicyDetail(c *gin.Context) { + karmadaClient := client.InClusterKarmadaClient() + namespace := c.Param("namespace") + name := c.Param("overridePolicyName") + result, err := overridepolicy.GetOverridePolicyDetail(karmadaClient, namespace, name) + if err != nil { + klog.ErrorS(err, "GetOverridePolicyDetail failed") + common.Fail(c, err) + return + } + common.Success(c, result) +} +func handlePostOverridePolicy(c *gin.Context) { + // todo precheck existence of namespace, now we tested it under scope of default, it's ok till now. + ctx := context.Context(c) + overridepolicyRequest := new(v1.PostOverridePolicyRequest) + if err := c.ShouldBind(&overridepolicyRequest); err != nil { + common.Fail(c, err) + return + } + if overridepolicyRequest.Namespace == "" { + overridepolicyRequest.Namespace = "default" + } + + var err error + karmadaClient := client.InClusterKarmadaClient() + if overridepolicyRequest.IsClusterScope { + clusteroverridePolicy := v1alpha1.ClusterOverridePolicy{} + if err = yaml.Unmarshal([]byte(overridepolicyRequest.OverrideData), &clusteroverridePolicy); err != nil { + klog.ErrorS(err, "Failed to unmarshal ClusterOverridePolicy") + common.Fail(c, err) + return + } + _, err = karmadaClient.PolicyV1alpha1().ClusterOverridePolicies().Create(ctx, &clusteroverridePolicy, metav1.CreateOptions{}) + } else { + overridePolicy := v1alpha1.OverridePolicy{} + if err = yaml.Unmarshal([]byte(overridepolicyRequest.OverrideData), &overridePolicy); err != nil { + klog.ErrorS(err, "Failed to unmarshal OverridePolicy") + common.Fail(c, err) + return + } + _, err = karmadaClient.PolicyV1alpha1().OverridePolicies(overridepolicyRequest.Namespace).Create(ctx, &overridePolicy, metav1.CreateOptions{}) + } + if err != nil { + klog.ErrorS(err, "Failed to create OverridePolicies") + common.Fail(c, err) + return + } + common.Success(c, "ok") +} +func handlePutOverridePolicy(c *gin.Context) { + ctx := context.Context(c) + overridepolicyRequest := new(v1.PutOverridePolicyRequest) + if err := c.ShouldBind(&overridepolicyRequest); err != nil { + common.Fail(c, err) + return + } + var err error + karmadaClient := client.InClusterKarmadaClient() + // todo check pp exist + if overridepolicyRequest.IsClusterScope { + clusteroverridePolicy := v1alpha1.ClusterOverridePolicy{} + if err = yaml.Unmarshal([]byte(overridepolicyRequest.OverrideData), &clusteroverridePolicy); err != nil { + klog.ErrorS(err, "Failed to unmarshal ClusterOverridePolicy") + common.Fail(c, err) + return + } + _, err = karmadaClient.PolicyV1alpha1().ClusterOverridePolicies().Update(ctx, &clusteroverridePolicy, metav1.UpdateOptions{}) + } else { + overridePolicy := v1alpha1.OverridePolicy{} + if err = yaml.Unmarshal([]byte(overridepolicyRequest.OverrideData), &overridePolicy); err != nil { + klog.ErrorS(err, "Failed to unmarshal OverridePolicy") + common.Fail(c, err) + return + } + var oldOverridePolicy *v1alpha1.OverridePolicy + oldOverridePolicy, err = karmadaClient.PolicyV1alpha1().OverridePolicies(overridepolicyRequest.Namespace).Get(ctx, overridepolicyRequest.Name, metav1.GetOptions{}) + if err == nil { + // only spec can be updated + overridePolicy.TypeMeta = oldOverridePolicy.TypeMeta + overridePolicy.ObjectMeta = oldOverridePolicy.ObjectMeta + _, err = karmadaClient.PolicyV1alpha1().OverridePolicies(overridepolicyRequest.Namespace).Update(ctx, &overridePolicy, metav1.UpdateOptions{}) + } + } + if err != nil { + klog.ErrorS(err, "Failed to update OverridePolicy") + common.Fail(c, err) + return + } + common.Success(c, "ok") +} +func handleDeleteOverridePolicy(c *gin.Context) { + ctx := context.Context(c) + overridepolicyRequest := new(v1.DeleteOverridePolicyRequest) + if err := c.ShouldBind(&overridepolicyRequest); err != nil { + common.Fail(c, err) + return + } + var err error + karmadaClient := client.InClusterKarmadaClient() + if overridepolicyRequest.IsClusterScope { + err = karmadaClient.PolicyV1alpha1().ClusterOverridePolicies().Delete(ctx, overridepolicyRequest.Name, metav1.DeleteOptions{}) + if err != nil { + klog.ErrorS(err, "Failed to delete ClusterOverridePolicy") + common.Fail(c, err) + return + } + } else { + err = karmadaClient.PolicyV1alpha1().OverridePolicies(overridepolicyRequest.Namespace).Delete(ctx, overridepolicyRequest.Name, metav1.DeleteOptions{}) + if err != nil { + klog.ErrorS(err, "Failed to delete OverridePolicy") + common.Fail(c, err) + return + } + err = retry.OnError( + retry.DefaultRetry, + func(err error) bool { + return errors.IsNotFound(err) + }, + func() error { + _, getErr := karmadaClient.PolicyV1alpha1().OverridePolicies(overridepolicyRequest.Namespace).Get(ctx, overridepolicyRequest.Name, metav1.GetOptions{}) + return getErr + }) + } + + common.Success(c, "ok") +} + +func init() { + r := router.V1() + r.GET("/overridepolicy", handleGetOverridePolicyList) + r.GET("/overridepolicy/:namespace", handleGetOverridePolicyList) + r.GET("/overridepolicy/namespace/:namespace/:overridePolicyName", handleGetOverridePolicyDetail) + r.POST("/overridepolicy", handlePostOverridePolicy) + r.PUT("/overridepolicy", handlePutOverridePolicy) + r.DELETE("/overridepolicy", handleDeleteOverridePolicy) +} diff --git a/cmd/api/app/types/api/v1/overridepolicy.go b/cmd/api/app/types/api/v1/overridepolicy.go new file mode 100644 index 00000000..fbbee2ce --- /dev/null +++ b/cmd/api/app/types/api/v1/overridepolicy.go @@ -0,0 +1,29 @@ +package v1 + +type PostOverridePolicyRequest struct { + OverrideData string `json:"overrideData" binding:"required"` + IsClusterScope bool `json:"isClusterScope"` + Namespace string `json:"namespace"` +} + +type PostOverridePolicyResponse struct { +} + +type PutOverridePolicyRequest struct { + OverrideData string `json:"overrideData" binding:"required"` + IsClusterScope bool `json:"isClusterScope"` + Namespace string `json:"namespace"` + Name string `json:"name" binding:"required"` +} + +type PutOverridePolicyResponse struct { +} + +type DeleteOverridePolicyRequest struct { + IsClusterScope bool `json:"isClusterScope"` + Namespace string `json:"namespace"` + Name string `json:"name" binding:"required"` +} + +type DeleteOverridePolicyResponse struct { +} diff --git a/pkg/common/types/resourcekind.go b/pkg/common/types/resourcekind.go index 615f617a..b41edf48 100644 --- a/pkg/common/types/resourcekind.go +++ b/pkg/common/types/resourcekind.go @@ -10,6 +10,8 @@ const ( ResourceKindCluster = "cluster" ResourceKindPropagationPolicy = "propagationpolicy" ResourceKindClusterPropagationPolicy = "clusterpropagationpolicy" + ResourceKindOverridePolicy = "overridepolicy" + ResourceKindClusterOverridePolicy = "clusteroverridepolicy" ResourceKindConfigMap = "configmap" ResourceKindDaemonSet = "daemonset" ResourceKindDeployment = "deployment" diff --git a/pkg/resource/clusteroverridepolicy/common.go b/pkg/resource/clusteroverridepolicy/common.go new file mode 100644 index 00000000..3790e736 --- /dev/null +++ b/pkg/resource/clusteroverridepolicy/common.go @@ -0,0 +1,36 @@ +package clusteroverridepolicy + +import ( + "github.com/karmada-io/dashboard/pkg/dataselect" + "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1" +) + +type ClusterOverridePolicyCell v1alpha1.ClusterOverridePolicy + +func (self ClusterOverridePolicyCell) 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.ClusterOverridePolicy) []dataselect.DataCell { + cells := make([]dataselect.DataCell, len(std)) + for i := range std { + cells[i] = ClusterOverridePolicyCell(std[i]) + } + return cells +} + +func fromCells(cells []dataselect.DataCell) []v1alpha1.ClusterOverridePolicy { + std := make([]v1alpha1.ClusterOverridePolicy, len(cells)) + for i := range std { + std[i] = v1alpha1.ClusterOverridePolicy(cells[i].(ClusterOverridePolicyCell)) + } + return std +} diff --git a/pkg/resource/clusteroverridepolicy/detail.go b/pkg/resource/clusteroverridepolicy/detail.go new file mode 100644 index 00000000..9c544825 --- /dev/null +++ b/pkg/resource/clusteroverridepolicy/detail.go @@ -0,0 +1,40 @@ +package clusteroverridepolicy + +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 ClusterOverridePolicyDetail struct { + // Extends list item structure. + ClusterOverridePolicy `json:",inline"` + + // List of non-critical errors, that occurred during resource retrieval. + Errors []error `json:"errors"` +} + +// GetClusterOverridePolicyDetail gets clusterPropagationPolicy details. +func GetClusterOverridePolicyDetail(client karmadaclientset.Interface, name string) (*ClusterOverridePolicyDetail, error) { + overridepolicyData, err := client.PolicyV1alpha1().ClusterOverridePolicies().Get(context.TODO(), name, metaV1.GetOptions{}) + if err != nil { + return nil, err + } + + nonCriticalErrors, criticalError := errors.ExtractErrors(err) + if criticalError != nil { + return nil, criticalError + } + + propagationpolicy := toOverridePolicyDetail(overridepolicyData, nonCriticalErrors) + return &propagationpolicy, nil +} + +func toOverridePolicyDetail(clusterOverridepolicy *v1alpha1.ClusterOverridePolicy, nonCriticalErrors []error) ClusterOverridePolicyDetail { + return ClusterOverridePolicyDetail{ + ClusterOverridePolicy: toClusterOverridePolicy(clusterOverridepolicy), + Errors: nonCriticalErrors, + } +} diff --git a/pkg/resource/clusteroverridepolicy/list.go b/pkg/resource/clusteroverridepolicy/list.go new file mode 100644 index 00000000..6be7efa0 --- /dev/null +++ b/pkg/resource/clusteroverridepolicy/list.go @@ -0,0 +1,67 @@ +package clusteroverridepolicy + +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" +) + +// ClusterOverridePolicyList contains a list of overriders in the karmada control-plane. +type ClusterOverridePolicyList struct { + ListMeta types.ListMeta `json:"listMeta"` + + // Unordered list of clusterOverridePolicies. + ClusterOverridePolicies []ClusterOverridePolicy `json:"clusterOverridePolicies"` + + // List of non-critical errors, that occurred during resource retrieval. + Errors []error `json:"errors"` +} + +type ClusterOverridePolicy struct { + ObjectMeta types.ObjectMeta `json:"objectMeta"` + TypeMeta types.TypeMeta `json:"typeMeta"` + // Override specificed data + ResourceSelectors []v1alpha1.ResourceSelector `json:"resourceSelectors"` + OverrideRules []v1alpha1.RuleWithCluster `json:"overrideRules"` +} + +// GetClusterOverridePolicyList returns a list of all overiders in the karmada control-plance. +func GetClusterOverridePolicyList(client karmadaclientset.Interface, dsQuery *dataselect.DataSelectQuery) (*ClusterOverridePolicyList, error) { + clusterOverridePolicies, err := client.PolicyV1alpha1().ClusterOverridePolicies().List(context.TODO(), helpers.ListEverything) + nonCriticalErrors, criticalError := errors.ExtractErrors(err) + if criticalError != nil { + return nil, criticalError + } + + return toClusterOverridePolicyList(clusterOverridePolicies.Items, nonCriticalErrors, dsQuery), nil +} + +func toClusterOverridePolicyList(clusterOverridePolicies []v1alpha1.ClusterOverridePolicy, nonCriticalErrors []error, dsQuery *dataselect.DataSelectQuery) *ClusterOverridePolicyList { + overridepolicyList := &ClusterOverridePolicyList{ + ClusterOverridePolicies: make([]ClusterOverridePolicy, 0), + ListMeta: types.ListMeta{TotalItems: len(clusterOverridePolicies)}, + } + clusterOverridePolicyCells, filteredTotal := dataselect.GenericDataSelectWithFilter(toCells(clusterOverridePolicies), dsQuery) + clusterOverridePolicies = fromCells(clusterOverridePolicyCells) + overridepolicyList.ListMeta = types.ListMeta{TotalItems: filteredTotal} + overridepolicyList.Errors = nonCriticalErrors + + for _, clusterOverridePolicy := range clusterOverridePolicies { + clusterOP := toClusterOverridePolicy(&clusterOverridePolicy) + overridepolicyList.ClusterOverridePolicies = append(overridepolicyList.ClusterOverridePolicies, clusterOP) + } + return overridepolicyList +} + +func toClusterOverridePolicy(overridepolicy *v1alpha1.ClusterOverridePolicy) ClusterOverridePolicy { + return ClusterOverridePolicy{ + ObjectMeta: types.NewObjectMeta(overridepolicy.ObjectMeta), + TypeMeta: types.NewTypeMeta(types.ResourceKindClusterOverridePolicy), + ResourceSelectors: overridepolicy.Spec.ResourceSelectors, + OverrideRules: overridepolicy.Spec.OverrideRules, + } +} diff --git a/pkg/resource/overridepolicy/common.go b/pkg/resource/overridepolicy/common.go new file mode 100644 index 00000000..ad9a0ab4 --- /dev/null +++ b/pkg/resource/overridepolicy/common.go @@ -0,0 +1,39 @@ +package overridepolicy + +import ( + "github.com/karmada-io/dashboard/pkg/dataselect" + "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1" +) + +type OverridePolicyCell v1alpha1.OverridePolicy + +func (self OverridePolicyCell) 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) + case dataselect.NamespaceProperty: + + return dataselect.StdComparableString(self.ObjectMeta.Namespace) + default: + // if name is not supported then just return a constant dummy value, sort will have no effect. + return nil + } +} + +func toCells(std []v1alpha1.OverridePolicy) []dataselect.DataCell { + cells := make([]dataselect.DataCell, len(std)) + for i := range std { + cells[i] = OverridePolicyCell(std[i]) + } + return cells +} + +func fromCells(cells []dataselect.DataCell) []v1alpha1.OverridePolicy { + std := make([]v1alpha1.OverridePolicy, len(cells)) + for i := range std { + std[i] = v1alpha1.OverridePolicy(cells[i].(OverridePolicyCell)) + } + return std +} diff --git a/pkg/resource/overridepolicy/detail.go b/pkg/resource/overridepolicy/detail.go new file mode 100644 index 00000000..208fc71b --- /dev/null +++ b/pkg/resource/overridepolicy/detail.go @@ -0,0 +1,42 @@ +package overridepolicy + +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" +) + +// OverridePolicyDetail is a presentation layer view of Karmada OverridePolicy resource. This means it is OverridePolicy plus +// additional augmented data we can get from other sources. +type OverridePolicyDetail struct { + // Extends list item structure. + OverridePolicy `json:",inline"` + + // List of non-critical errors, that occurred during resource retrieval. + Errors []error `json:"errors"` +} + +// GetOverridePolicyDetail gets Overridepolicy details. +func GetOverridePolicyDetail(client karmadaclientset.Interface, namespace, name string) (*OverridePolicyDetail, error) { + OverridepolicyData, err := client.PolicyV1alpha1().OverridePolicies(namespace).Get(context.TODO(), name, metaV1.GetOptions{}) + if err != nil { + return nil, err + } + + nonCriticalErrors, criticalError := errors.ExtractErrors(err) + if criticalError != nil { + return nil, criticalError + } + + Overridepolicy := toOverridePolicyDetail(OverridepolicyData, nonCriticalErrors) + return &Overridepolicy, nil +} + +func toOverridePolicyDetail(Overridepolicy *v1alpha1.OverridePolicy, nonCriticalErrors []error) OverridePolicyDetail { + return OverridePolicyDetail{ + OverridePolicy: toOverridePolicy(Overridepolicy), + Errors: nonCriticalErrors, + } +} diff --git a/pkg/resource/overridepolicy/list.go b/pkg/resource/overridepolicy/list.go new file mode 100644 index 00000000..86c8975b --- /dev/null +++ b/pkg/resource/overridepolicy/list.go @@ -0,0 +1,71 @@ +package overridepolicy + +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/dashboard/pkg/resource/common" + "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1" + karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned" + "k8s.io/client-go/kubernetes" + "log" +) + +// OverridePolicyList contains a list of propagation in the karmada control-plance. +type OverridePolicyList struct { + ListMeta types.ListMeta `json:"listMeta"` + + // Unordered list of OverridePolicys. + OverridePolicys []OverridePolicy `json:"overridepolicys"` + + // List of non-critical errors, that occurred during resource retrieval. + Errors []error `json:"errors"` +} + +type OverridePolicy struct { + ObjectMeta types.ObjectMeta `json:"objectMeta"` + TypeMeta types.TypeMeta `json:"typeMeta"` + // Override specificed data + ResourceSelectors []v1alpha1.ResourceSelector `json:"resourceSelectors"` + OverrideRules []v1alpha1.RuleWithCluster `json:"overrideRules"` +} + +// GetOverridePolicyList returns a list of all propagations in the karmada control-plance. +func GetOverridePolicyList(client karmadaclientset.Interface, k8sClient kubernetes.Interface, nsQuery *common.NamespaceQuery, dsQuery *dataselect.DataSelectQuery) (*OverridePolicyList, error) { + log.Println("Getting list of overridepolicy") + overridePolicies, err := client.PolicyV1alpha1().OverridePolicies(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything) + nonCriticalErrors, criticalError := errors.ExtractErrors(err) + if criticalError != nil { + return nil, criticalError + } + + return toOverridePolicyList(k8sClient, overridePolicies.Items, nonCriticalErrors, dsQuery), nil +} + +func toOverridePolicyList(k8sClient kubernetes.Interface, overridepolicies []v1alpha1.OverridePolicy, nonCriticalErrors []error, dsQuery *dataselect.DataSelectQuery) *OverridePolicyList { + overridepolicyList := &OverridePolicyList{ + OverridePolicys: make([]OverridePolicy, 0), + ListMeta: types.ListMeta{TotalItems: len(overridepolicies)}, + } + overridepolicyCells, filteredTotal := dataselect.GenericDataSelectWithFilter(toCells(overridepolicies), dsQuery) + overridepolicies = fromCells(overridepolicyCells) + overridepolicyList.ListMeta = types.ListMeta{TotalItems: filteredTotal} + overridepolicyList.Errors = nonCriticalErrors + + for _, overridepolicy := range overridepolicies { + op := toOverridePolicy(&overridepolicy) + overridepolicyList.OverridePolicys = append(overridepolicyList.OverridePolicys, op) + } + return overridepolicyList +} + +func toOverridePolicy(overridepolicy *v1alpha1.OverridePolicy) OverridePolicy { + return OverridePolicy{ + ObjectMeta: types.NewObjectMeta(overridepolicy.ObjectMeta), + TypeMeta: types.NewTypeMeta(types.ResourceKindOverridePolicy), + ResourceSelectors: overridepolicy.Spec.ResourceSelectors, + OverrideRules: overridepolicy.Spec.OverrideRules, + } +}