Skip to content

Commit

Permalink
get member cluster node
Browse files Browse the repository at this point in the history
Signed-off-by: Heylosky <2547226479@qq.com>
  • Loading branch information
Heylosky committed Oct 30, 2024
1 parent e2c5898 commit 8be6169
Show file tree
Hide file tree
Showing 6 changed files with 223 additions and 8 deletions.
25 changes: 25 additions & 0 deletions cmd/api/app/routes/node/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package node

import (
"github.com/gin-gonic/gin"
"github.com/karmada-io/dashboard/cmd/api/app/router"
"github.com/karmada-io/dashboard/cmd/api/app/types/common"
"github.com/karmada-io/dashboard/pkg/client"
"github.com/karmada-io/dashboard/pkg/resource/node"
)

func handleGetClusterNode(c *gin.Context) {
karmadaClient := client.InClusterClientForKarmadactlApiServer(c.Param("clustername"))
dataSelect := common.ParseDataSelectPathParameter(c)
result, err := node.GetNodeList(karmadaClient, dataSelect)
if err != nil {
common.Fail(c, err)
return
}
common.Success(c, result)
}

func init() {
r := router.V1()
r.GET("/node/:clustername", handleGetClusterNode)
}
45 changes: 37 additions & 8 deletions pkg/client/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,26 @@ package client
import (
"errors"
"fmt"
"os"
"strings"

karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
kubeclient "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"k8s.io/klog/v2"
"os"
)

var (
kubernetesRestConfig *rest.Config
kubernetesApiConfig *clientcmdapi.Config
inClusterClient kubeclient.Interface
karmadaRestConfig *rest.Config
karmadaApiConfig *clientcmdapi.Config
inClusterKarmadaClient karmadaclientset.Interface
inClusterClientForKarmadaApiServer kubeclient.Interface
kubernetesRestConfig *rest.Config
kubernetesApiConfig *clientcmdapi.Config
inClusterClient kubeclient.Interface
karmadaRestConfig *rest.Config
karmadaApiConfig *clientcmdapi.Config
inClusterKarmadaClient karmadaclientset.Interface
inClusterClientForKarmadaApiServer kubeclient.Interface
inClusterClientForKarmadactlApiServer kubeclient.Interface
clusterHost string
)

type configBuilder struct {
Expand Down Expand Up @@ -185,6 +189,8 @@ func InitKarmadaConfig(options ...Option) {
os.Exit(1)
}
karmadaApiConfig = apiConfig

clusterHost = karmadaRestConfig.Host
}

func InClusterKarmadaClient() karmadaclientset.Interface {
Expand Down Expand Up @@ -233,6 +239,29 @@ func InClusterClientForKarmadaApiServer() kubeclient.Interface {
return inClusterClientForKarmadaApiServer
}

func InClusterClientForKarmadactlApiServer(clustername string) kubeclient.Interface {
if !isKarmadaInitialized() {
return nil
}
karmadaCtlRestConfig, _, err := GetKarmadaConfig()
if strings.Contains(karmadaCtlRestConfig.Host, clustername) {
return inClusterClientForKarmadactlApiServer
} else {
karmadaCtlRestConfig.Host = clusterHost + "/apis/cluster.karmada.io/v1alpha1/clusters/" + clustername + "/proxy"
}
if err != nil {
klog.ErrorS(err, "Could not get karmadactl restConfig")
return nil
}
c, err := kubeclient.NewForConfig(karmadaCtlRestConfig)
if err != nil {
klog.ErrorS(err, "Could not init kubernetes in-cluster client for karmadactl apiserver")
return nil
}
inClusterClientForKarmadactlApiServer = c
return inClusterClientForKarmadactlApiServer
}

func ConvertRestConfigToAPIConfig(restConfig *rest.Config) *clientcmdapi.Config {
// 将 rest.Config 转换为 clientcmdapi.Config
clientcmdConfig := clientcmdapi.NewConfig()
Expand Down
20 changes: 20 additions & 0 deletions pkg/resource/common/resourcechannels.go
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,26 @@ type NodeListChannel struct {
Error chan error
}

// GetNodeListChannel returns a pair of channels to a Node list and errors that both must be read
// numReads times.
func GetNodeListChannel(client client.Interface, numReads int) NodeListChannel {

channel := NodeListChannel{
List: make(chan *v1.NodeList, numReads),
Error: make(chan error, numReads),
}

go func() {
list, err := client.CoreV1().Nodes().List(context.TODO(), helpers.ListEverything)
for i := 0; i < numReads; i++ {
channel.List <- list
channel.Error <- err
}
}()

return channel
}

// NamespaceListChannel is a list and error channels to Namespaces.
type NamespaceListChannel struct {
List chan *v1.NamespaceList
Expand Down
38 changes: 38 additions & 0 deletions pkg/resource/node/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package node

import (
"github.com/karmada-io/dashboard/pkg/dataselect"
api "k8s.io/api/core/v1"
)

type NodeCell api.Node

func (self NodeCell) 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 []api.Node) []dataselect.DataCell {
cells := make([]dataselect.DataCell, len(std))
for i := range std {
cells[i] = NodeCell(std[i])
}
return cells
}

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

type NodeAllocatedResources struct {
// CPUCapacity is specified node CPU capacity in milicores.
CPUCapacity int64 `json:"cpuCapacity"`
CPUFraction float64 `json:"cpuFraction"`

// MemoryCapacity is specified node memory capacity in bytes.
MemoryCapacity int64 `json:"memoryCapacity"`
MemoryFraction float64 `json:"memoryFraction"`

// AllocatedPods in number of currently allocated pods on the node.
AllocatedPods int64 `json:"allocatedPods"`

// PodCapacity is maximum number of pods, that can be allocated on the node.
PodCapacity int64 `json:"podCapacity"`

// PodFraction is a fraction of pods, that can be allocated on given node.
PodFraction float64 `json:"podFraction"`
}
83 changes: 83 additions & 0 deletions pkg/resource/node/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package node

import (
"log"

"github.com/karmada-io/dashboard/pkg/common/errors"
"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/cluster/v1alpha1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)

type Node struct {
ObjectMeta types.ObjectMeta `json:"objectMeta"`
TypeMeta types.TypeMeta `json:"typeMeta"`
Ready metav1.ConditionStatus `json:"ready,omitempty"`
KubernetesVersion string `json:"kubernetesVersion,omitempty"`
NodeSummary *v1alpha1.NodeSummary `json:"nodeSummary,omitempty"`
AllocatedResources NodeAllocatedResources `json:"allocatedResources"`
}

// NodeList contains a list of node.
type NodeList struct {
ListMeta types.ListMeta `json:"listMeta"`

// Unordered list of Nodes
Items []Node `json:"items"`

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

// GetNodeList returns a list of all Nodes in all cluster.
func GetNodeList(client kubernetes.Interface, dsQuery *dataselect.DataSelectQuery) (*NodeList, error) {
log.Printf("Getting nodes")
channels := &common.ResourceChannels{
NodeList: common.GetNodeListChannel(client, 1),
}

return GetNodeListFromChannels(channels, dsQuery)
}

// GetNodeListFromChannels returns a list of all Nodes in the cluster reading required resource list once from the channels.
func GetNodeListFromChannels(channels *common.ResourceChannels, dsQuery *dataselect.DataSelectQuery) (*NodeList, error) {
nodes := <-channels.NodeList.List
err := <-channels.NodeList.Error
nonCriticalErrors, criticalError := errors.ExtractErrors(err)
if criticalError != nil {
return nil, criticalError
}

result := toNodeList(nodes.Items, nonCriticalErrors, dsQuery)

return result, nil
}

func toNode(meta metav1.ObjectMeta) Node {
return Node{
ObjectMeta: types.NewObjectMeta(meta),
TypeMeta: types.NewTypeMeta(types.ResourceKindNode),
}
}

func toNodeList(nodes []v1.Node, nonCriticalErrors []error, dsQuery *dataselect.DataSelectQuery) *NodeList {
result := &NodeList{
Items: make([]Node, 0),
ListMeta: types.ListMeta{TotalItems: len(nodes)},
Errors: nonCriticalErrors,
}

nodeCells, filteredTotal := dataselect.GenericDataSelectWithFilter(toCells(nodes), dsQuery)
nodes = fromCells(nodeCells)
result.ListMeta = types.ListMeta{TotalItems: filteredTotal}

for _, item := range nodes {
result.Items = append(result.Items, toNode(item.ObjectMeta))
}

return result
}

0 comments on commit 8be6169

Please sign in to comment.