Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

External Network: liqoctl network fixes #2110

Merged
merged 1 commit into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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