diff --git a/apis/config/v1alpha1/clusterconfig_types.go b/apis/config/v1alpha1/clusterconfig_types.go index c7e6b794e8..99d06aa6c6 100644 --- a/apis/config/v1alpha1/clusterconfig_types.go +++ b/apis/config/v1alpha1/clusterconfig_types.go @@ -115,7 +115,6 @@ type LabelPolicy struct { // APIServerConfig defines the configuration of the cluster APIServer. type APIServerConfig struct { Address string `json:"address,omitempty"` - Port string `json:"port,omitempty"` TrustedCA bool `json:"trustedCA,omitempty"` } diff --git a/deployments/liqo/README.md b/deployments/liqo/README.md index be9fc2c70c..88bed90990 100644 --- a/deployments/liqo/README.md +++ b/deployments/liqo/README.md @@ -3,7 +3,6 @@ | Key | Type | Default | Description | |-----|------|---------|-------------| | apiServer.address | string | `""` | The address that must be used to contact your API server, it needs to be reachable from the clusters that you will peer with (defaults to your master IP) | -| apiServer.port | string | `"6443"` | The port that must be used to contact your API server | | apiServer.trustedCA | bool | `false` | Indicates that the API Server is exposing a certificate issued by a trusted Certification Authority | | auth.config.allowEmptyToken | bool | `false` | Set to true to disable the authentication of discovered clusters. NB: use it only for testing installations | | auth.imageName | string | `"liqo/auth-service"` | auth image repository | diff --git a/deployments/liqo/crds/config.liqo.io_clusterconfigs.yaml b/deployments/liqo/crds/config.liqo.io_clusterconfigs.yaml index 8c57bea8e8..eb7460c491 100644 --- a/deployments/liqo/crds/config.liqo.io_clusterconfigs.yaml +++ b/deployments/liqo/crds/config.liqo.io_clusterconfigs.yaml @@ -42,8 +42,6 @@ spec: properties: address: type: string - port: - type: string trustedCA: type: boolean type: object diff --git a/deployments/liqo/values.yaml b/deployments/liqo/values.yaml index 5f2cf0ef11..1079e4e408 100644 --- a/deployments/liqo/values.yaml +++ b/deployments/liqo/values.yaml @@ -9,8 +9,6 @@ pullPolicy: "IfNotPresent" apiServer: # -- The address that must be used to contact your API server, it needs to be reachable from the clusters that you will peer with (defaults to your master IP) address: "" - # -- The port that must be used to contact your API server - port: "6443" # -- Indicates that the API Server is exposing a certificate issued by a trusted Certification Authority trustedCA: false diff --git a/install.sh b/install.sh index 385ccb3cda..8a60207be9 100755 --- a/install.sh +++ b/install.sh @@ -461,7 +461,6 @@ function install_liqo() { --set auth.ingress.host="${LIQO_AUTHSERVER_ADDR:-}" \ --set auth.ingress.class="${LIQO_INGRESS_CLASS:-}" \ --set apiServer.address="${LIQO_APISERVER_ADDR:-}" \ - --set apiServer.port="${LIQO_APISERVER_PORT:-}" \ --set auth.ingress.host="${LIQO_AUTHSERVER_ADDR:-}" \ --set auth.portOverride="${LIQO_AUTHSERVER_PORT:-}" >/dev/null || fatal "[INSTALL]" "Something went wrong while installing Liqo" diff --git a/internal/auth-service/auth_test.go b/internal/auth-service/auth_test.go index 8a0e689c9f..0538dc1e73 100644 --- a/internal/auth-service/auth_test.go +++ b/internal/auth-service/auth_test.go @@ -11,7 +11,6 @@ import ( "encoding/pem" "os" "path/filepath" - "strings" "testing" "time" @@ -53,16 +52,6 @@ func (man *tokenManagerMock) createToken() error { return nil } -// getHost get the address given the address:port string -func getHost(address string) string { - return strings.Split(address, ":")[0] -} - -// getPort get the port given the address:port string -func getPort(address string) string { - return strings.Split(address, ":")[1] -} - // getCSR get a CertificateSigningRequest for testing purposes func getCSR(localClusterID string) (csrBytes []byte, err error) { key, err := rsa.GenerateKey(rand.Reader, 2048) @@ -159,8 +148,7 @@ var _ = Describe("Auth", func() { useTLS: false, credentialsValidator: &tokenValidator{}, apiServerConfig: &v1alpha1.APIServerConfig{ - Address: getHost(cluster.GetCfg().Host), - Port: getPort(cluster.GetCfg().Host), + Address: cluster.GetCfg().Host, TrustedCA: false, }, } diff --git a/internal/discovery/foreign-cluster-operator/foreign-cluster-operator_test.go b/internal/discovery/foreign-cluster-operator/foreign-cluster-operator_test.go index 3a3ec61f07..6cfa31ae63 100644 --- a/internal/discovery/foreign-cluster-operator/foreign-cluster-operator_test.go +++ b/internal/discovery/foreign-cluster-operator/foreign-cluster-operator_test.go @@ -49,7 +49,6 @@ func (c *configMock) GetConfig() *v1alpha1.DiscoveryConfig { func (c *configMock) GetAPIServerConfig() *v1alpha1.APIServerConfig { return &v1alpha1.APIServerConfig{ Address: os.Getenv("APISERVER"), - Port: os.Getenv("APISERVER_PORT"), TrustedCA: false, } } diff --git a/pkg/identityManager/identityManager_test.go b/pkg/identityManager/identityManager_test.go index 4306446be0..75817b54dd 100644 --- a/pkg/identityManager/identityManager_test.go +++ b/pkg/identityManager/identityManager_test.go @@ -36,14 +36,12 @@ import ( type mockApiServerConfigProvider struct { address string - port string trustedCA bool } -func newMockApiServerConfigProvider(address, port string, trustedCA bool) utils.ApiServerConfigProvider { +func newMockAPIServerConfigProvider(address string, trustedCA bool) utils.ApiServerConfigProvider { return &mockApiServerConfigProvider{ address: address, - port: port, trustedCA: trustedCA, } } @@ -51,7 +49,6 @@ func newMockApiServerConfigProvider(address, port string, trustedCA bool) utils. func (mock *mockApiServerConfigProvider) GetAPIServerConfig() *configv1alpha1.APIServerConfig { return &configv1alpha1.APIServerConfig{ Address: mock.address, - Port: mock.port, TrustedCA: mock.trustedCA, } } @@ -220,7 +217,7 @@ var _ = Describe("IdentityManager", func() { Context("Storage", func() { It("StoreCertificate", func() { - apiServerConfig := newMockApiServerConfigProvider("127.0.0.1", "6443", false) + apiServerConfig := newMockAPIServerConfigProvider("127.0.0.1", false) signingIdentityResponse := responsetypes.SigningRequestResponse{ ResponseType: responsetypes.SigningRequestResponseCertificate, @@ -241,8 +238,7 @@ var _ = Describe("IdentityManager", func() { Expect(cnf).NotTo(BeNil()) Expect(cnf.Host).To(Equal( fmt.Sprintf( - "https://%v:%v", apiServerConfig.GetAPIServerConfig().Address, - apiServerConfig.GetAPIServerConfig().Port))) + "https://%v", apiServerConfig.GetAPIServerConfig().Address))) // retrieve the remote tenant namespace remoteNamespace, err := identityMan.GetRemoteTenantNamespace(remoteClusterID, "") @@ -251,7 +247,7 @@ var _ = Describe("IdentityManager", func() { }) It("StoreCertificate IAM", func() { - apiServerConfig := newMockApiServerConfigProvider("127.0.0.1", "6443", false) + apiServerConfig := newMockAPIServerConfigProvider("127.0.0.1", false) signingIAMResponse := responsetypes.SigningRequestResponse{ ResponseType: responsetypes.SigningRequestResponseIAM, diff --git a/pkg/kubeconfig/create.go b/pkg/kubeconfig/create.go index 1f8f42997a..5ab8c5dbf8 100644 --- a/pkg/kubeconfig/create.go +++ b/pkg/kubeconfig/create.go @@ -2,8 +2,8 @@ package kubeconfig import ( "context" - "errors" "fmt" + "strings" corev1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -13,7 +13,6 @@ import ( "k8s.io/klog" kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" - "github.com/liqotech/liqo/pkg/discovery" "github.com/liqotech/liqo/pkg/utils" ) @@ -56,33 +55,17 @@ func CreateKubeConfigFromServiceAccount(apiServerConfigProvider utils.ApiServerC // 1. from the ClusterConfig // 2. defaults to 6443. func GetApiServerURL(apiServerConfigProvider utils.ApiServerConfigProvider, clientset kubernetes.Interface) (string, error) { - address := apiServerConfigProvider.GetAPIServerConfig().Address - if address == "" { - nodes, err := clientset.CoreV1().Nodes().List(context.TODO(), v1.ListOptions{ - LabelSelector: "node-role.kubernetes.io/master", - }) - if err != nil { - klog.Error(err) - return "", err - } - if len(nodes.Items) == 0 { - err = errors.New("no APISERVER env variable found and no master node found, one of the two values must be present") - klog.Error(err) - return "", err - } - address, err = discovery.GetAddressFromNodeList(nodes.Items) - if err != nil { - klog.Error(err) - return "", err - } - } + config := apiServerConfigProvider.GetAPIServerConfig() - port := apiServerConfigProvider.GetAPIServerConfig().Port - if port == "" { - port = "6443" + address := config.Address + if address != "" { + if !strings.HasPrefix(address, "https://") { + address = fmt.Sprintf("https://%v", address) + } + return address, nil } - return fmt.Sprintf("https://%v:%v", address, port), nil + return utils.GetAPIServerAddressFromMasterNode(context.TODO(), clientset) } // this function creates a kube-config file for a specified ServiceAccount. diff --git a/pkg/utils/address.go b/pkg/utils/address.go new file mode 100644 index 0000000000..45f25d2eac --- /dev/null +++ b/pkg/utils/address.go @@ -0,0 +1,59 @@ +package utils + +import ( + "context" + "fmt" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/klog/v2" + + "github.com/liqotech/liqo/pkg/discovery" +) + +// GetAPIServerAddressFromMasterNode returns the API Server address using the IP of the +// master node of this cluster. The port is always defaulted to 6443. +func GetAPIServerAddressFromMasterNode(ctx context.Context, + clientset kubernetes.Interface) (address string, err error) { + nodes, err := getMasterNodes(ctx, clientset) + if err != nil { + klog.Error(err) + return "", err + } + host, err := discovery.GetAddressFromNodeList(nodes.Items) + if err != nil { + klog.Error(err) + return "", err + } + return fmt.Sprintf("https://%v:6443", host), nil +} + +func getMasterNodes(ctx context.Context, clientset kubernetes.Interface) (*v1.NodeList, error) { + labelSelectors := []string{ + "node-role.kubernetes.io/control-plane", + "node-role.kubernetes.io/master", + } + + nodes := &v1.NodeList{} + var err error + for _, selector := range labelSelectors { + nodes, err = clientset.CoreV1().Nodes().List(ctx, metav1.ListOptions{ + LabelSelector: selector, + }) + if err != nil { + klog.Error(err) + return nodes, err + } + if len(nodes.Items) != 0 { + break + } + } + + if len(nodes.Items) == 0 { + err = fmt.Errorf("no ApiServer.Address variable provided and no master node found, one of the two values must be present") + klog.Error(err) + return nodes, err + } + return nodes, nil +} diff --git a/pkg/utils/address_test.go b/pkg/utils/address_test.go new file mode 100644 index 0000000000..1037d304b9 --- /dev/null +++ b/pkg/utils/address_test.go @@ -0,0 +1,120 @@ +package utils + +import ( + "context" + "os" + "path/filepath" + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/extensions/table" + . "github.com/onsi/gomega" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + + "github.com/liqotech/liqo/pkg/utils/testutil" +) + +func TestAddress(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Address Suite") +} + +var _ = Describe("Address", func() { + + var ( + cluster testutil.Cluster + ctx context.Context + cancel context.CancelFunc + ) + + BeforeSuite(func() { + ctx, cancel = context.WithCancel(context.Background()) + + var err error + cluster, _, err = testutil.NewTestCluster([]string{filepath.Join("..", "..", "..", "deployments", "liqo", "crds")}) + if err != nil { + By(err.Error()) + os.Exit(1) + } + }) + + AfterSuite(func() { + cancel() + + err := cluster.GetEnv().Stop() + if err != nil { + By(err.Error()) + os.Exit(1) + } + }) + + type addressTestcase struct { + node *v1.Node + expectedAddress string + } + + DescribeTable("Address table", + + func(c addressTestcase) { + client := kubernetes.NewForConfigOrDie(cluster.GetCfg()) + + node, err := client.CoreV1().Nodes().Create(ctx, c.node, metav1.CreateOptions{}) + Expect(err).To(Succeed()) + node.Status = *c.node.Status.DeepCopy() + node, err = client.CoreV1().Nodes().Update(ctx, node, metav1.UpdateOptions{}) + Expect(err).To(Succeed()) + + address, err := GetAPIServerAddressFromMasterNode(ctx, client) + Expect(err).To(Succeed()) + + Expect(address).To(Equal(c.expectedAddress)) + + Expect(client.CoreV1().Nodes().Delete(ctx, node.Name, metav1.DeleteOptions{})).To(Succeed()) + }, + + Entry("master node", addressTestcase{ + node: &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "master-1", + Labels: map[string]string{ + "node-role.kubernetes.io/master": "", + }, + }, + Spec: v1.NodeSpec{}, + Status: v1.NodeStatus{ + Addresses: []v1.NodeAddress{ + { + Type: v1.NodeExternalIP, + Address: "1.2.3.4", + }, + }, + }, + }, + expectedAddress: "https://1.2.3.4:6443", + }), + + Entry("control plane node", addressTestcase{ + node: &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "master-1", + Labels: map[string]string{ + "node-role.kubernetes.io/control-plane": "", + }, + }, + Spec: v1.NodeSpec{}, + Status: v1.NodeStatus{ + Addresses: []v1.NodeAddress{ + { + Type: v1.NodeExternalIP, + Address: "1.2.3.4", + }, + }, + }, + }, + expectedAddress: "https://1.2.3.4:6443", + }), + ) + +})