github.com/oam-dev/kubevela@v1.9.11/pkg/multicluster/cluster_metrics_management_test.go (about)

     1  /*
     2  Copyright 2022 The KubeVela Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package multicluster
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"strconv"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/stretchr/testify/assert"
    27  	corev1 "k8s.io/api/core/v1"
    28  	"k8s.io/apimachinery/pkg/api/resource"
    29  	metricsV1beta1api "k8s.io/metrics/pkg/apis/metrics/v1beta1"
    30  	clusterv1 "open-cluster-management.io/api/cluster/v1"
    31  	"sigs.k8s.io/controller-runtime/pkg/client"
    32  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    33  
    34  	clustercommon "github.com/oam-dev/cluster-gateway/pkg/common"
    35  
    36  	"github.com/oam-dev/kubevela/pkg/utils/common"
    37  )
    38  
    39  const (
    40  	NormalClusterName       = "normal-cluster"
    41  	DisconnectedClusterName = "disconnected-cluster"
    42  
    43  	NodeName1 = "node-1"
    44  	NodeName2 = "node-2"
    45  )
    46  
    47  func TestRefresh(t *testing.T) {
    48  	ClusterGatewaySecretNamespace = "default"
    49  	fakeClient := NewFakeClient(fake.NewClientBuilder().
    50  		WithScheme(common.Scheme).
    51  		WithRuntimeObjects(FakeManagedCluster("managed-cluster")).
    52  		WithObjects(FakeSecret(NormalClusterName), FakeSecret(DisconnectedClusterName)).
    53  		Build())
    54  
    55  	normalCluster := fake.NewClientBuilder().
    56  		WithScheme(common.Scheme).
    57  		WithObjects(FakeNode(NodeName1, "8", strconv.FormatInt(16*1024*1024*1024, 10)),
    58  			FakeNode(NodeName2, "7", strconv.FormatInt(32*1024*1024*1024, 10)),
    59  			FakeNodeMetrics(NodeName1, "4", strconv.FormatInt(8*1024*1024*1024, 10)),
    60  			FakeNodeMetrics(NodeName2, "1", strconv.FormatInt(3*1024*1024*1024, 10))).
    61  		Build()
    62  
    63  	disconnectedCluster := &disconnectedClient{}
    64  
    65  	fakeClient.AddCluster(NormalClusterName, normalCluster)
    66  	fakeClient.AddCluster(DisconnectedClusterName, disconnectedCluster)
    67  
    68  	mgr, err := NewClusterMetricsMgr(context.Background(), fakeClient, 15*time.Second)
    69  	assert.NoError(t, err)
    70  
    71  	_, err = mgr.Refresh()
    72  	assert.NoError(t, err)
    73  
    74  	clusters, err := ListVirtualClusters(context.Background(), fakeClient)
    75  	assert.NoError(t, err)
    76  
    77  	for _, cluster := range clusters {
    78  		assertClusterMetrics(t, &cluster)
    79  	}
    80  
    81  	disCluster, err := GetVirtualCluster(context.Background(), fakeClient, DisconnectedClusterName)
    82  	assert.NoError(t, err)
    83  	assertClusterMetrics(t, disCluster)
    84  
    85  	norCluster, err := GetVirtualCluster(context.Background(), fakeClient, NormalClusterName)
    86  	assert.NoError(t, err)
    87  	assertClusterMetrics(t, norCluster)
    88  
    89  	exportMetrics(disCluster.Metrics, disCluster.Name)
    90  	exportMetrics(norCluster.Metrics, norCluster.Name)
    91  }
    92  
    93  func assertClusterMetrics(t *testing.T, cluster *VirtualCluster) {
    94  	metrics := cluster.Metrics
    95  	switch cluster.Name {
    96  	case DisconnectedClusterName:
    97  		assert.Equal(t, metrics.IsConnected, false)
    98  		assert.True(t, metrics.ClusterInfo == nil)
    99  		assert.True(t, metrics.ClusterUsageMetrics == nil)
   100  	case NormalClusterName:
   101  		assert.Equal(t, metrics.IsConnected, true)
   102  
   103  		assert.True(t, resource.MustParse("15").Equal(metrics.ClusterInfo.CPUCapacity))
   104  		assert.True(t, resource.MustParse(strconv.FormatInt(48*1024*1024*1024, 10)).Equal(metrics.ClusterInfo.MemoryCapacity))
   105  		assert.True(t, resource.MustParse("15").Equal(metrics.ClusterInfo.CPUAllocatable))
   106  		assert.True(t, resource.MustParse(strconv.FormatInt(48*1024*1024*1024, 10)).Equal(metrics.ClusterInfo.MemoryAllocatable))
   107  
   108  		assert.True(t, resource.MustParse("5").Equal(metrics.ClusterUsageMetrics.CPUUsage))
   109  		assert.True(t, resource.MustParse(strconv.FormatInt(11*1024*1024*1024, 10)).Equal(metrics.ClusterUsageMetrics.MemoryUsage))
   110  	}
   111  }
   112  
   113  func FakeNodeMetrics(name string, cpu string, memory string) *metricsV1beta1api.NodeMetrics {
   114  	nodeMetrics := &metricsV1beta1api.NodeMetrics{}
   115  	nodeMetrics.Name = name
   116  	nodeMetrics.Usage = corev1.ResourceList{
   117  		corev1.ResourceCPU:    resource.MustParse(cpu),
   118  		corev1.ResourceMemory: resource.MustParse(memory),
   119  	}
   120  	return nodeMetrics
   121  }
   122  
   123  func FakeNode(name string, cpu string, memory string) *corev1.Node {
   124  	node := &corev1.Node{}
   125  	node.Name = name
   126  	node.Status = corev1.NodeStatus{
   127  		Allocatable: map[corev1.ResourceName]resource.Quantity{
   128  			corev1.ResourceCPU:    resource.MustParse(cpu),
   129  			corev1.ResourceMemory: resource.MustParse(memory),
   130  		},
   131  		Capacity: map[corev1.ResourceName]resource.Quantity{
   132  			corev1.ResourceCPU:    resource.MustParse(cpu),
   133  			corev1.ResourceMemory: resource.MustParse(memory),
   134  		},
   135  	}
   136  	return node
   137  }
   138  
   139  func FakeSecret(name string) *corev1.Secret {
   140  	secret := &corev1.Secret{}
   141  	secret.Name = name
   142  	secret.Namespace = ClusterGatewaySecretNamespace
   143  	secret.Labels = map[string]string{
   144  		clustercommon.LabelKeyClusterCredentialType: "ServiceAccountToken",
   145  	}
   146  	return secret
   147  }
   148  
   149  func FakeManagedCluster(name string) *clusterv1.ManagedCluster {
   150  	managedCluster := &clusterv1.ManagedCluster{}
   151  	managedCluster.Name = name
   152  	return managedCluster
   153  }
   154  
   155  type disconnectedClient struct {
   156  	client.Client
   157  }
   158  
   159  func (cli *disconnectedClient) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error {
   160  	return errors.New("no such host")
   161  }