@@ -1542,6 +1542,148 @@ func WriteYamlToFile(obj interface{}, filePath string) error {
1542
1542
return nil
1543
1543
}
1544
1544
1545
+ var _ = framework .SerialDescribe ("Karmadactl register testing" , ginkgo .Ordered , ginkgo.Labels {NeedCreateCluster }, func () {
1546
+ var (
1547
+ newClusterName , clusterContext string
1548
+ homeDir , kubeConfigPath , controlPlane string
1549
+ karmadaAPIEndpoint , karmadaAPIEndpointExpected string
1550
+ token , discoveryTokenCACertHash string
1551
+ )
1552
+
1553
+ ginkgo .BeforeAll (func () {
1554
+ ginkgo .By ("Initialize dependencies" , func () {
1555
+ // Initialize member cluster variables.
1556
+ newClusterName = "member-e2e-" + rand .String (RandomStrLength )
1557
+ homeDir = os .Getenv ("HOME" )
1558
+ kubeConfigPath = fmt .Sprintf ("%s/.kube/%s.config" , homeDir , newClusterName )
1559
+ controlPlane = fmt .Sprintf ("%s-control-plane" , newClusterName )
1560
+ clusterContext = fmt .Sprintf ("kind-%s" , newClusterName )
1561
+ })
1562
+
1563
+ ginkgo .By (fmt .Sprintf ("Creating cluster: %s" , newClusterName ), func () {
1564
+ err := createCluster (newClusterName , kubeConfigPath , controlPlane , clusterContext )
1565
+ gomega .Expect (err ).ShouldNot (gomega .HaveOccurred ())
1566
+ })
1567
+
1568
+ ginkgo .By ("Extract Karmada API server endpoint" , func () {
1569
+ var err error
1570
+ karmadaAPIEndpointExpected , err = extractAPIServerEndpoint (kubeconfig , "karmada-apiserver" )
1571
+ gomega .Expect (err ).ShouldNot (gomega .HaveOccurred ())
1572
+ })
1573
+
1574
+ ginkgo .By ("Generate token and discovery token CA cert hash" , func () {
1575
+ cmd := framework .NewKarmadactlCommand (
1576
+ kubeconfig , karmadaContext , karmadactlPath , "" , karmadactlTimeout ,
1577
+ "token" , "create" , "--print-register-command=" + "true" ,
1578
+ )
1579
+ output , err := cmd .ExecOrDie ()
1580
+ gomega .Expect (err ).ShouldNot (gomega .HaveOccurred ())
1581
+
1582
+ // Extract the endpoint for Karmada APIServer.
1583
+ endpointRegex := regexp .MustCompile (`(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):(\d{1,5})` )
1584
+ karmadaAPIEndpoint = endpointRegex .FindString (output )
1585
+ gomega .Expect (karmadaAPIEndpoint ).Should (gomega .Equal (karmadaAPIEndpointExpected ))
1586
+
1587
+ // Extract token.
1588
+ tokenRegex := regexp .MustCompile (`--token\s+(\S+)` )
1589
+ tokenMatches := tokenRegex .FindStringSubmatch (output )
1590
+ gomega .Expect (len (tokenMatches )).Should (gomega .BeNumerically (">" , 1 ))
1591
+ token = tokenMatches [1 ]
1592
+
1593
+ // Extract discovery token CA cert hash.
1594
+ hashRegex := regexp .MustCompile (`--discovery-token-ca-cert-hash\s+(\S+)` )
1595
+ hashMatches := hashRegex .FindStringSubmatch (output )
1596
+ gomega .Expect (len (hashMatches )).Should (gomega .BeNumerically (">" , 1 ))
1597
+ discoveryTokenCACertHash = hashMatches [1 ]
1598
+ })
1599
+ })
1600
+
1601
+ ginkgo .AfterEach (func () {
1602
+ ginkgo .By (fmt .Sprintf ("Unregistering cluster: %s" , newClusterName ), func () {
1603
+ cmd := framework .NewKarmadactlCommand (
1604
+ kubeconfig , karmadaContext , karmadactlPath , "" , 5 * options .DefaultKarmadactlCommandDuration ,
1605
+ "unregister" , "--cluster-kubeconfig" , kubeConfigPath , newClusterName ,
1606
+ )
1607
+ _ , err := cmd .ExecOrDie ()
1608
+ gomega .Expect (err ).ShouldNot (gomega .HaveOccurred ())
1609
+ })
1610
+ })
1611
+
1612
+ ginkgo .AfterAll (func () {
1613
+ ginkgo .By (fmt .Sprintf ("Deleting clusters: %s" , newClusterName ), func () {
1614
+ err := deleteCluster (newClusterName , kubeConfigPath )
1615
+ gomega .Expect (err ).ShouldNot (gomega .HaveOccurred ())
1616
+ _ = os .Remove (kubeConfigPath )
1617
+ })
1618
+ })
1619
+
1620
+ ginkgo .It ("should register a cluster without CA verification" , func () {
1621
+ ginkgo .By ("Register the new cluster in Karmada without CA verification" , func () {
1622
+ cmd := framework .NewKarmadactlCommand (
1623
+ "" , karmadaContext , karmadactlPath , "" , karmadactlTimeout * 5 , "register" , karmadaAPIEndpoint , "--token" , token ,
1624
+ "--discovery-token-unsafe-skip-ca-verification=" + "true" , "--kubeconfig=" + kubeConfigPath ,
1625
+ "--cluster-name" , newClusterName , "--karmada-agent-image" , "docker.io/karmada/karmada-agent:latest" ,
1626
+ )
1627
+ output , err := cmd .ExecOrDie ()
1628
+ gomega .Expect (err ).ShouldNot (gomega .HaveOccurred ())
1629
+ gomega .Expect (output ).Should (gomega .ContainSubstring (fmt .Sprintf ("cluster(%s) is joined successfully" , newClusterName )))
1630
+ })
1631
+
1632
+ ginkgo .By ("Wait for the new cluster to be ready" , func () {
1633
+ framework .WaitClusterFitWith (controlPlaneClient , newClusterName , func (cluster * clusterv1alpha1.Cluster ) bool {
1634
+ return meta .IsStatusConditionPresentAndEqual (cluster .Status .Conditions , clusterv1alpha1 .ClusterConditionReady , metav1 .ConditionTrue )
1635
+ })
1636
+ })
1637
+ })
1638
+
1639
+ ginkgo .It ("should register a cluster with CA verification" , func () {
1640
+ ginkgo .By ("Register the new cluster in Karmada with CA verification" , func () {
1641
+ cmd := framework .NewKarmadactlCommand (
1642
+ "" , karmadaContext , karmadactlPath , "" , karmadactlTimeout * 5 , "register" , karmadaAPIEndpoint ,
1643
+ "--token" , token , "--discovery-token-ca-cert-hash" , discoveryTokenCACertHash ,
1644
+ "--kubeconfig=" + kubeConfigPath , "--cluster-name" , newClusterName ,
1645
+ "--karmada-agent-image" , "docker.io/karmada/karmada-agent:latest" ,
1646
+ )
1647
+ output , err := cmd .ExecOrDie ()
1648
+ gomega .Expect (err ).ShouldNot (gomega .HaveOccurred ())
1649
+ gomega .Expect (output ).Should (gomega .ContainSubstring (fmt .Sprintf ("cluster(%s) is joined successfully" , newClusterName )))
1650
+ })
1651
+
1652
+ ginkgo .By ("Wait for the new cluster to be ready" , func () {
1653
+ framework .WaitClusterFitWith (controlPlaneClient , newClusterName , func (cluster * clusterv1alpha1.Cluster ) bool {
1654
+ return meta .IsStatusConditionPresentAndEqual (cluster .Status .Conditions , clusterv1alpha1 .ClusterConditionReady , metav1 .ConditionTrue )
1655
+ })
1656
+ })
1657
+ })
1658
+ })
1659
+
1660
+ // extractAPIServerEndpoint extracts the given clusterName API endpoint from a kubeconfig file.
1661
+ //
1662
+ // Parameters:
1663
+ // - kubeConfigPath: The file path to the kubeconfig file.
1664
+ //
1665
+ // Returns:
1666
+ // - string: The extracted API server endpoint without the "https://" prefix.
1667
+ // - error: An error if:
1668
+ // - the kubeconfig file cannot be read
1669
+ // - the YAML format is invalid
1670
+ // - the given clusterName is not found
1671
+ func extractAPIServerEndpoint (kubeConfigPath string , clusterName string ) (string , error ) {
1672
+ config , err := clientcmd .LoadFromFile (kubeConfigPath )
1673
+ if err != nil {
1674
+ return "" , err
1675
+ }
1676
+
1677
+ for name , cluster := range config .Clusters {
1678
+ if name == clusterName {
1679
+ endpointWithoutPrefix := strings .TrimPrefix (cluster .Server , "https://" )
1680
+ return endpointWithoutPrefix , nil
1681
+ }
1682
+ }
1683
+
1684
+ return "" , fmt .Errorf ("%s endpoint not found in kubeconfig" , clusterName )
1685
+ }
1686
+
1545
1687
// extractPropagationPolicyName extracts the propagation policy name from the input string.
1546
1688
//
1547
1689
// Parameters:
0 commit comments