Skip to content

Commit

Permalink
Liqoctl network connect: fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
fra98 committed Oct 27, 2023
1 parent ba2071e commit 920a5cc
Show file tree
Hide file tree
Showing 16 changed files with 249 additions and 130 deletions.
6 changes: 2 additions & 4 deletions cmd/liqoctl/cmd/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,6 @@ func newNetworkConnectCommand(ctx context.Context, options *network.Options) *co
fmt.Sprintf("Service type of the Gateway Server. Default: %s", gatewayserver.DefaultServiceType))
cmd.Flags().Int32Var(&options.ServerPort, "server-port", gatewayserver.DefaultPort,
fmt.Sprintf("Port of the Gateway Server. Default: %d", gatewayserver.DefaultPort))
cmd.Flags().IntVar(&options.ServerMTU, "server-mtu", gatewayserver.DefaultMTU,
fmt.Sprintf("MTU of the Gateway Server. Default: %d", gatewayserver.DefaultMTU))

// Client flags
cmd.Flags().StringVar(&options.ClientGatewayType, "client-type", gatewayclient.DefaultGatewayType,
Expand All @@ -128,10 +126,10 @@ func newNetworkConnectCommand(ctx context.Context, options *network.Options) *co
"Name of the Gateway Client template")
cmd.Flags().StringVar(&options.ClientTemplateNamespace, "client-template-namespace", gatewayclient.DefaultTemplateNamespace,
"Namespace of the Gateway Client template")
cmd.Flags().IntVar(&options.ClientMTU, "client-mtu", gatewayclient.DefaultMTU,
fmt.Sprintf("MTU of the Gateway Client. Default: %d", gatewayclient.DefaultMTU))

// Common flags
cmd.Flags().IntVar(&options.MTU, "mtu", gatewayserver.DefaultMTU,
fmt.Sprintf("MTU of the Gateway server and client. Default: %d", gatewayserver.DefaultMTU))
cmd.Flags().BoolVar(&options.DisableSharingKeys, "disable-sharing-keys", false, "Disable the sharing of public keys between the two clusters")
cmd.Flags().BoolVar(&options.Proxy, "proxy", gatewayserver.DefaultProxy, "Enable proxy for the Gateway Server")

Expand Down
98 changes: 67 additions & 31 deletions pkg/liqoctl/network/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"context"
"fmt"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"

Expand All @@ -31,27 +32,31 @@ import (
"github.com/liqotech/liqo/pkg/liqoctl/rest/gatewayserver"
"github.com/liqotech/liqo/pkg/liqoctl/rest/publickey"
"github.com/liqotech/liqo/pkg/liqoctl/wait"
liqogetters "github.com/liqotech/liqo/pkg/utils/getters"
liqolabels "github.com/liqotech/liqo/pkg/utils/labels"
tenantnamespace "github.com/liqotech/liqo/pkg/tenantNamespace"
liqoutils "github.com/liqotech/liqo/pkg/utils"
)

// Cluster contains the information about a cluster.
type Cluster struct {
local *factory.Factory
remote *factory.Factory
Waiter *wait.Waiter
local *factory.Factory
remote *factory.Factory
localNamespaceManager tenantnamespace.Manager
remoteNamespaceManager tenantnamespace.Manager
Waiter *wait.Waiter

clusterIdentity *discoveryv1alpha1.ClusterIdentity

NetworkConfiguration *networkingv1alpha1.Configuration
networkConfiguration *networkingv1alpha1.Configuration
}

// NewCluster returns a new Cluster struct.
func NewCluster(local, remote *factory.Factory) *Cluster {
return &Cluster{
local: local,
remote: remote,
Waiter: wait.NewWaiterFromFactory(local),
local: local,
remote: remote,
localNamespaceManager: tenantnamespace.NewManager(local.KubeClient),
remoteNamespaceManager: tenantnamespace.NewManager(remote.KubeClient),
Waiter: wait.NewWaiterFromFactory(local),
}
}

Expand All @@ -62,46 +67,73 @@ func (c *Cluster) Init(ctx context.Context) error {
return err
}

// Get network configuration.
s := c.local.Printer.StartSpinner("Retrieving network configuration")
conf, err := configuration.ForgeLocalConfiguration(ctx, c.local.CRClient, c.local.Namespace, c.local.LiqoNamespace)
// Set local and remote namespaces.
return c.SetNamespaces(ctx)
}

// SetClusterIdentity set cluster identities of both local and remote clusters retrieving it from the Liqo configmaps.
func (c *Cluster) SetClusterIdentity(ctx context.Context) error {
// Get cluster identity.
s := c.local.Printer.StartSpinner("Retrieving cluster identity")

clusterIdentity, err := liqoutils.GetClusterIdentityWithControllerClient(ctx, c.local.CRClient, c.local.LiqoNamespace)
if err != nil {
s.Fail(fmt.Sprintf("An error occurred while retrieving network configuration: %v", output.PrettyErr(err)))
s.Fail(fmt.Sprintf("An error occurred while retrieving cluster identity: %v", output.PrettyErr(err)))
return err
}
c.NetworkConfiguration = conf
s.Success("Network configuration correctly retrieved")
c.clusterIdentity = &clusterIdentity

s.Success("Cluster identity correctly retrieved")

return nil
}

// SetClusterIdentity set cluster identity retrieving it from the Liqo configmap.
func (c *Cluster) SetClusterIdentity(ctx context.Context) error {
// Get cluster identity.
s := c.local.Printer.StartSpinner("Retrieving cluster identity")
selector, err := metav1.LabelSelectorAsSelector(&liqolabels.ClusterIDConfigMapLabelSelector)
// SetNamespaces sets the local and remote namespaces to the liqo-tenants namespaces (creating them if necessary),
// unless the user has explicitly set custom namespaces with the `--namespace` and/or `--remote-namespace` flags.
// All the external network resources will be created in these namespaces in their respective clusters.
func (c *Cluster) SetNamespaces(ctx context.Context) error {
remoteClusterIdentity, err := liqoutils.GetClusterIdentityWithControllerClient(ctx, c.remote.CRClient, c.remote.LiqoNamespace)
if err != nil {
s.Fail(fmt.Sprintf("An error occurred while retrieving cluster identity: %v", output.PrettyErr(err)))
return err
}
cm, err := liqogetters.GetConfigMapByLabel(ctx, c.local.CRClient, c.local.LiqoNamespace, selector)
if c.local.Namespace == "" || c.local.Namespace == corev1.NamespaceDefault {
if _, err := c.localNamespaceManager.CreateNamespace(ctx, remoteClusterIdentity); err != nil {
return err
}
c.local.Namespace = tenantnamespace.GetNameForNamespace(remoteClusterIdentity)
}

localClusterIdentity, err := liqoutils.GetClusterIdentityWithControllerClient(ctx, c.local.CRClient, c.local.LiqoNamespace)
if err != nil {
s.Fail(fmt.Sprintf("An error occurred while retrieving cluster identity: %v", output.PrettyErr(err)))
return err
}
clusterIdentity, err := liqogetters.RetrieveClusterIDFromConfigMap(cm)
if c.remote.Namespace == "" || c.remote.Namespace == corev1.NamespaceDefault {
if _, err := c.remoteNamespaceManager.CreateNamespace(ctx, localClusterIdentity); err != nil {
return err
}
c.remote.Namespace = tenantnamespace.GetNameForNamespace(localClusterIdentity)
}

return nil
}

// SetLocalConfiguration forges and set a local Configuration to be applied on remote clusters.
func (c *Cluster) SetLocalConfiguration(ctx context.Context) error {
// Get network configuration.
s := c.local.Printer.StartSpinner("Retrieving network configuration")
conf, err := configuration.ForgeLocalConfiguration(ctx, c.local.CRClient, c.local.Namespace, c.local.LiqoNamespace)
if err != nil {
s.Fail(fmt.Sprintf("An error occurred while retrieving cluster identity: %v", output.PrettyErr(err)))
s.Fail(fmt.Sprintf("An error occurred while retrieving network configuration: %v", output.PrettyErr(err)))
return err
}
c.clusterIdentity = clusterIdentity
s.Success("Cluster identity correctly retrieved")
c.networkConfiguration = conf
s.Success("Network configuration correctly retrieved")

return nil
}

// SetupConfiguration sets up the network configuration.
func (c *Cluster) SetupConfiguration(ctx context.Context,
conf *networkingv1alpha1.Configuration) error {
func (c *Cluster) SetupConfiguration(ctx context.Context, conf *networkingv1alpha1.Configuration) error {
s := c.local.Printer.StartSpinner("Setting up network configuration")
conf.Namespace = c.local.Namespace
confCopy := conf.DeepCopy()
Expand Down Expand Up @@ -167,15 +199,19 @@ func (c *Cluster) EnsureGatewayClient(ctx context.Context, name string, opts *ga
}

// EnsurePublicKey create or updates a PublicKey.
func (c *Cluster) EnsurePublicKey(ctx context.Context, remoteClusterIdentity *discoveryv1alpha1.ClusterIdentity, key []byte) error {
func (c *Cluster) EnsurePublicKey(ctx context.Context, remoteClusterIdentity *discoveryv1alpha1.ClusterIdentity,
key []byte, ownerGateway metav1.Object) error {
s := c.local.Printer.StartSpinner("Creating PublicKey")
pubKey, err := publickey.ForgePublicKey(remoteClusterIdentity.ClusterName, c.local.Namespace, remoteClusterIdentity.ClusterID, key)
if err != nil {
s.Fail(fmt.Sprintf("An error occurred while forging publickey: %v", output.PrettyErr(err)))
return err
}
_, err = controllerutil.CreateOrUpdate(ctx, c.local.CRClient, pubKey, func() error {
return publickey.MutatePublicKey(pubKey, remoteClusterIdentity.ClusterID, key)
if err := publickey.MutatePublicKey(pubKey, remoteClusterIdentity.ClusterID, key); err != nil {
return err
}
return controllerutil.SetOwnerReference(ownerGateway, pubKey, c.local.CRClient.Scheme())
})
if err != nil {
s.Fail(fmt.Sprintf("An error occurred while creating publickey: %v", output.PrettyErr(err)))
Expand Down
57 changes: 45 additions & 12 deletions pkg/liqoctl/network/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,12 @@ type Options struct {
ServerTemplateNamespace string
ServerServiceType *argsutils.StringEnum
ServerPort int32
ServerMTU int

ClientGatewayType string
ClientTemplateName string
ClientTemplateNamespace string
ClientMTU int

MTU int
DisableSharingKeys bool
Proxy bool
}
Expand Down Expand Up @@ -79,24 +78,34 @@ func (o *Options) RunInit(ctx context.Context) error {
return err
}

// Forges the local Configuration of cluster 1 to be applied on remote clusters.
if err := cluster1.SetLocalConfiguration(ctx); err != nil {
return err
}

// Forges the local Configuration of cluster 2 to be applied on remote clusters.
if err := cluster2.SetLocalConfiguration(ctx); err != nil {
return err
}

// Setup Configurations in cluster 1.
if err := cluster1.SetupConfiguration(ctx, cluster2.NetworkConfiguration); err != nil {
if err := cluster1.SetupConfiguration(ctx, cluster2.networkConfiguration); err != nil {
return err
}

// Setup Configurations in cluster 2.
if err := cluster2.SetupConfiguration(ctx, cluster1.NetworkConfiguration); err != nil {
if err := cluster2.SetupConfiguration(ctx, cluster1.networkConfiguration); err != nil {
return err
}

if o.Wait {
// Wait for cluster 1 to be ready.
if err := cluster1.Waiter.ForConfiguration(ctx, cluster2.NetworkConfiguration); err != nil {
if err := cluster1.Waiter.ForConfiguration(ctx, cluster2.networkConfiguration); err != nil {
return err
}

// Wait for cluster 2 to be ready.
if err := cluster2.Waiter.ForConfiguration(ctx, cluster1.NetworkConfiguration); err != nil {
if err := cluster2.Waiter.ForConfiguration(ctx, cluster1.networkConfiguration); err != nil {
return err
}
}
Expand All @@ -111,13 +120,13 @@ func (o *Options) RunConnect(ctx context.Context) error {

// Create and initialize cluster 1.
cluster1 := NewCluster(o.LocalFactory, o.RemoteFactory)
if err := cluster1.SetClusterIdentity(ctx); err != nil {
if err := cluster1.Init(ctx); err != nil {
return err
}

// Create and initialize cluster 2.
cluster2 := NewCluster(o.RemoteFactory, o.LocalFactory)
if err := cluster2.SetClusterIdentity(ctx); err != nil {
if err := cluster2.Init(ctx); err != nil {
return err
}

Expand Down Expand Up @@ -158,7 +167,7 @@ func (o *Options) RunConnect(ctx context.Context) error {
}

// Create PublicKey of gateway server on cluster 2
if err := cluster2.EnsurePublicKey(ctx, cluster1.clusterIdentity, keyServer); err != nil {
if err := cluster2.EnsurePublicKey(ctx, cluster1.clusterIdentity, keyServer, gwClient); err != nil {
return err
}

Expand All @@ -173,7 +182,31 @@ func (o *Options) RunConnect(ctx context.Context) error {
}

// Create PublicKey of gateway client on cluster 1
return cluster1.EnsurePublicKey(ctx, cluster2.clusterIdentity, keyClient)
if err := cluster1.EnsurePublicKey(ctx, cluster2.clusterIdentity, keyClient, gwServer); err != nil {
return err
}

if o.Wait {
// Wait for Connections on both cluster to be created.
conn1, err := cluster1.Waiter.ForConnection(ctx, gwServer.Namespace, cluster2.clusterIdentity)
if err != nil {
return err
}
conn2, err := cluster2.Waiter.ForConnection(ctx, gwClient.Namespace, cluster1.clusterIdentity)
if err != nil {
return err
}

// Wait for Connections on both cluster cluster to be established
if err := cluster1.Waiter.ForConnectionEstablished(ctx, conn1); err != nil {
return err
}
if err := cluster2.Waiter.ForConnectionEstablished(ctx, conn2); err != nil {
return err
}
}

return nil
}

func (o *Options) newGatewayServerForgeOptions(kubeClient kubernetes.Interface, remoteClusterID string) *gatewayserver.ForgeOptions {
Expand All @@ -184,7 +217,7 @@ func (o *Options) newGatewayServerForgeOptions(kubeClient kubernetes.Interface,
TemplateName: o.ServerTemplateName,
TemplateNamespace: o.ServerTemplateNamespace,
ServiceType: v1.ServiceType(o.ServerServiceType.Value),
MTU: o.ServerMTU,
MTU: o.MTU,
Port: o.ServerPort,
Proxy: o.Proxy,
}
Expand All @@ -198,7 +231,7 @@ func (o *Options) newGatewayClientForgeOptions(kubeClient kubernetes.Interface,
GatewayType: o.ClientGatewayType,
TemplateName: o.ClientTemplateName,
TemplateNamespace: o.ClientTemplateNamespace,
MTU: o.ClientMTU,
MTU: o.MTU,
Addresses: serverEndpoint.Addresses,
Port: serverEndpoint.Port,
Protocol: string(*serverEndpoint.Protocol),
Expand Down
22 changes: 11 additions & 11 deletions pkg/liqoctl/rest/configuration/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const liqoctlCreateConfigurationLongHelp = `Create a Configuration.
The Configuration resource is used to represent a remote cluster network configuration.
Examples:
$ {{ .Executable }} create configuration my-cluster --cluster-id my-cluster-id \
$ {{ .Executable }} create configuration my-cluster --remote-cluster-id remote-cluster-id \
--pod-cidr 10.0.0.0/16 --external-cidr 10.10.0.0/16`

// Create creates a Configuration.
Expand Down Expand Up @@ -71,17 +71,17 @@ func (o *Options) Create(ctx context.Context, options *rest.CreateOptions) *cobr
cmd.Flags().VarP(outputFormat, "output", "o",
"Output format of the resulting Configuration resource. Supported formats: json, yaml")

cmd.Flags().StringVar(&o.ClusterID, "cluster-id", "", "The cluster ID of the remote cluster")
cmd.Flags().StringVar(&o.RemoteClusterID, "remote-cluster-id", "", "The cluster ID of the remote cluster")
cmd.Flags().Var(&o.PodCIDR, "pod-cidr", "The pod CIDR of the remote cluster")
cmd.Flags().Var(&o.ExternalCIDR, "external-cidr", "The external CIDR of the remote cluster")
cmd.Flags().BoolVar(&o.Wait, "wait", false, "Wait for the Configuration to be ready")

runtime.Must(cmd.MarkFlagRequired("cluster-id"))
runtime.Must(cmd.MarkFlagRequired("remote-cluster-id"))
runtime.Must(cmd.MarkFlagRequired("pod-cidr"))
runtime.Must(cmd.MarkFlagRequired("external-cidr"))

runtime.Must(cmd.RegisterFlagCompletionFunc("output", completion.Enumeration(outputFormat.Allowed)))
runtime.Must(cmd.RegisterFlagCompletionFunc("cluster-id", completion.ClusterIDs(ctx,
runtime.Must(cmd.RegisterFlagCompletionFunc("remote-cluster-id", completion.ClusterIDs(ctx,
o.createOptions.Factory, completion.NoLimit)))

return cmd
Expand All @@ -91,7 +91,7 @@ func (o *Options) handleCreate(ctx context.Context) error {
opts := o.createOptions

conf := forgeConfiguration(o.createOptions.Name, o.createOptions.Namespace,
o.ClusterID, o.PodCIDR.String(), o.ExternalCIDR.String())
o.RemoteClusterID, o.PodCIDR.String(), o.ExternalCIDR.String())

if opts.OutputFormat != "" {
opts.Printer.CheckErr(o.output(conf))
Expand All @@ -100,7 +100,7 @@ func (o *Options) handleCreate(ctx context.Context) error {

s := opts.Printer.StartSpinner("Creating configuration")
_, err := controllerutil.CreateOrUpdate(ctx, opts.CRClient, conf, func() error {
mutateConfiguration(conf, o.ClusterID, o.PodCIDR.String(), o.ExternalCIDR.String())
mutateConfiguration(conf, o.RemoteClusterID, o.PodCIDR.String(), o.ExternalCIDR.String())
return nil
})
if err != nil {
Expand Down Expand Up @@ -133,7 +133,7 @@ func (o *Options) handleCreate(ctx context.Context) error {
return nil
}

func forgeConfiguration(name, namespace, clusterID, podCIDR, externalCIDR string) *networkingv1alpha1.Configuration {
func forgeConfiguration(name, namespace, remoteClusterID, podCIDR, externalCIDR string) *networkingv1alpha1.Configuration {
conf := &networkingv1alpha1.Configuration{
TypeMeta: metav1.TypeMeta{
Kind: networkingv1alpha1.ConfigurationKind,
Expand All @@ -143,21 +143,21 @@ func forgeConfiguration(name, namespace, clusterID, podCIDR, externalCIDR string
Name: name,
Namespace: namespace,
Labels: map[string]string{
liqoconsts.RemoteClusterID: clusterID,
liqoconsts.RemoteClusterID: remoteClusterID,
},
},
}
mutateConfiguration(conf, clusterID, podCIDR, externalCIDR)
mutateConfiguration(conf, remoteClusterID, podCIDR, externalCIDR)
return conf
}

func mutateConfiguration(conf *networkingv1alpha1.Configuration, clusterID, podCIDR, externalCIDR string) {
func mutateConfiguration(conf *networkingv1alpha1.Configuration, remoteClusterID, podCIDR, externalCIDR string) {
conf.Kind = networkingv1alpha1.ConfigurationKind
conf.APIVersion = networkingv1alpha1.GroupVersion.String()
if conf.Labels == nil {
conf.Labels = make(map[string]string)
}
conf.Labels[liqoconsts.RemoteClusterID] = clusterID
conf.Labels[liqoconsts.RemoteClusterID] = remoteClusterID
conf.Spec.Remote.CIDR.Pod = networkingv1alpha1.CIDR(podCIDR)
conf.Spec.Remote.CIDR.External = networkingv1alpha1.CIDR(externalCIDR)
}
Expand Down
Loading

0 comments on commit 920a5cc

Please sign in to comment.