Skip to content

Commit

Permalink
Liqoctl network connect
Browse files Browse the repository at this point in the history
  • Loading branch information
fra98 committed Oct 19, 2023
1 parent 2e5df6e commit 9b15e8b
Show file tree
Hide file tree
Showing 32 changed files with 1,831 additions and 34 deletions.
93 changes: 76 additions & 17 deletions cmd/liqoctl/cmd/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,67 +16,126 @@ package cmd

import (
"context"
"fmt"
"time"

"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/util/runtime"

"github.com/liqotech/liqo/pkg/liqoctl/completion"
"github.com/liqotech/liqo/pkg/liqoctl/factory"
"github.com/liqotech/liqo/pkg/liqoctl/network"
"github.com/liqotech/liqo/pkg/liqoctl/output"
"github.com/liqotech/liqo/pkg/liqoctl/rest/gatewayclient"
"github.com/liqotech/liqo/pkg/liqoctl/rest/gatewayserver"
)

const liqoctlNetworkLongHelp = `Manage liqo networking.`

const liqoctlNetworkInitLongHelp = `Initialize the liqo networking between two clusters.`

const liqoctlNetworConnectLongHelp = `Connect two clusters using liqo networking.
Run this command after inizialiting the network using the *network init* command.`

func newNetworkCommand(ctx context.Context, f *factory.Factory) *cobra.Command {
options := &network.Options{LocalFactory: f}
options := network.NewOptions(f)
options.RemoteFactory = factory.NewForRemote()

cmd := &cobra.Command{
Use: "network",
Short: "Manage liqo networking",
Long: WithTemplate(liqoctlNetworkLongHelp),
Args: cobra.NoArgs,

PersistentPreRun: func(cmd *cobra.Command, args []string) {
twoClustersPersistentPreRun(cmd, options.LocalFactory, options.RemoteFactory, factory.WithScopedPrinter)
},
}

cmd.PersistentFlags().DurationVar(&options.Timeout, "timeout", 120*time.Second, "Timeout for completion")
cmd.PersistentFlags().BoolVar(&options.Wait, "wait", false, "Wait for completion")

options.LocalFactory.AddFlags(cmd.PersistentFlags(), cmd.RegisterFlagCompletionFunc)
options.RemoteFactory.AddFlags(cmd.PersistentFlags(), cmd.RegisterFlagCompletionFunc)

options.LocalFactory.AddNamespaceFlag(cmd.PersistentFlags())
options.RemoteFactory.AddNamespaceFlag(cmd.PersistentFlags())

options.LocalFactory.AddLiqoNamespaceFlag(cmd.PersistentFlags())
options.RemoteFactory.AddLiqoNamespaceFlag(cmd.PersistentFlags())

options.LocalFactory.Printer.CheckErr(cmd.RegisterFlagCompletionFunc("namespace",
completion.Namespaces(ctx, options.LocalFactory, completion.NoLimit)))
options.LocalFactory.Printer.CheckErr(cmd.RegisterFlagCompletionFunc("remote-namespace",
completion.Namespaces(ctx, options.RemoteFactory, completion.NoLimit)))
options.LocalFactory.Printer.CheckErr(cmd.RegisterFlagCompletionFunc("liqo-namespace",
completion.Namespaces(ctx, options.LocalFactory, completion.NoLimit)))
options.LocalFactory.Printer.CheckErr(cmd.RegisterFlagCompletionFunc("remote-liqo-namespace",
completion.Namespaces(ctx, options.RemoteFactory, completion.NoLimit)))

cmd.AddCommand(newNetworkInitCommand(ctx, options))
cmd.AddCommand(newNetworkConnectCommand(ctx, options))

return cmd
}

func newNetworkInitCommand(ctx context.Context, options *network.Options) *cobra.Command {
options.RemoteFactory = factory.NewForRemote()

cmd := &cobra.Command{
Use: "init",
Short: "Initialize the liqo networking between two clusters",
Long: WithTemplate(liqoctlNetworkInitLongHelp),
Args: cobra.NoArgs,

PersistentPreRun: func(cmd *cobra.Command, args []string) {
twoClustersPersistentPreRun(cmd, options.LocalFactory, options.RemoteFactory, factory.WithScopedPrinter)
},

Run: func(cmd *cobra.Command, args []string) {
output.ExitOnErr(options.RunInit(ctx))
},
}

options.LocalFactory.AddFlags(cmd.Flags(), cmd.RegisterFlagCompletionFunc)
options.RemoteFactory.AddFlags(cmd.Flags(), cmd.RegisterFlagCompletionFunc)
return cmd
}

options.LocalFactory.AddNamespaceFlag(cmd.Flags())
options.RemoteFactory.AddNamespaceFlag(cmd.Flags())
func newNetworkConnectCommand(ctx context.Context, options *network.Options) *cobra.Command {
cmd := &cobra.Command{
Use: "connect",
Short: "Connect two clusters using liqo networking",
Long: WithTemplate(liqoctlNetworConnectLongHelp),
Args: cobra.NoArgs,

options.LocalFactory.AddLiqoNamespaceFlag(cmd.Flags())
options.RemoteFactory.AddLiqoNamespaceFlag(cmd.Flags())
Run: func(cmd *cobra.Command, args []string) {
output.ExitOnErr(options.RunConnect(ctx))
},
}

options.LocalFactory.Printer.CheckErr(cmd.RegisterFlagCompletionFunc("namespace",
completion.Namespaces(ctx, options.LocalFactory, completion.NoLimit)))
options.LocalFactory.Printer.CheckErr(cmd.RegisterFlagCompletionFunc("remote-namespace",
completion.Namespaces(ctx, options.RemoteFactory, completion.NoLimit)))
// Server flags
cmd.Flags().StringVar(&options.ServerGatewayType, "server-type", gatewayserver.DefaultGatewayType,
"Type of Gateway Server. Leave empty to use default Liqo implementation of WireGuard")
cmd.Flags().StringVar(&options.ServerTemplateName, "server-template-name", gatewayserver.DefaultTemplateName,
"Name of the Gateway Server template")
cmd.Flags().StringVar(&options.ServerTemplateNamespace, "server-template-namespace", gatewayserver.DefaultTemplateNamespace,
"Namespace of the Gateway Server template")
cmd.Flags().Var(options.ServerServiceType, "server-service-type",
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,
"Type of Gateway Client. Leave empty to use default Liqo implementation of WireGuard")
cmd.Flags().StringVar(&options.ClientTemplateName, "client-template-name", gatewayclient.DefaultTemplateName,
"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().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")

runtime.Must(cmd.RegisterFlagCompletionFunc("server-service-type", completion.Enumeration(options.ServerServiceType.Allowed)))

return cmd
}
6 changes: 6 additions & 0 deletions cmd/liqoctl/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ import (
"github.com/liqotech/liqo/pkg/liqoctl/get"
"github.com/liqotech/liqo/pkg/liqoctl/rest"
"github.com/liqotech/liqo/pkg/liqoctl/rest/configuration"
"github.com/liqotech/liqo/pkg/liqoctl/rest/gatewayclient"
"github.com/liqotech/liqo/pkg/liqoctl/rest/gatewayserver"
"github.com/liqotech/liqo/pkg/liqoctl/rest/publickey"
"github.com/liqotech/liqo/pkg/liqoctl/rest/virtualnode"
)

Expand All @@ -44,6 +47,9 @@ var liqoctl string
var liqoResources = []rest.APIProvider{
virtualnode.VirtualNode,
configuration.Configuration,
gatewayserver.GatewayServer,
gatewayclient.GatewayClient,
publickey.PublicKey,
}

func init() {
Expand Down
17 changes: 17 additions & 0 deletions pkg/liqo-controller-manager/external-network/utils/getters.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes"

networkingv1alpha1 "github.com/liqotech/liqo/apis/networking/v1alpha1"
)
Expand Down Expand Up @@ -124,3 +125,19 @@ func KindToResource(kind string) string {
// lowercased and pluralized
return strings.ToLower(kind) + "s"
}

// ResourceToKind returns the kind name for a given resource.
func ResourceToKind(gvr schema.GroupVersionResource, kubeClient kubernetes.Interface) (string, error) {
res, err := kubeClient.Discovery().ServerResourcesForGroupVersion(gvr.GroupVersion().String())
if err != nil {
return "", err
}

for i := range res.APIResources {
if gvr.Resource == KindToResource(res.APIResources[i].Kind) {
return res.APIResources[i].Kind, nil
}
}

return "", fmt.Errorf("unable to find Kind name associated to resources %q", gvr.Resource)
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/predicate"

"github.com/liqotech/liqo/pkg/consts"
tunnel "github.com/liqotech/liqo/pkg/gateway/tunnel/wireguard"
liqolabels "github.com/liqotech/liqo/pkg/utils/labels"
)

Expand All @@ -51,17 +52,12 @@ func wireGuardSecretEnquerer(_ context.Context, obj client.Object) []ctrl.Reques
{
NamespacedName: types.NamespacedName{
Namespace: secret.Namespace,
Name: mapSecretToWireGuardResource(secret.Name),
Name: tunnel.GenerateResourceName(secret.Name),
},
},
}
}

// TODO:: use generic map function after merge.
func mapSecretToWireGuardResource(secretName string) string {
return secretName
}

func getWireGuardSecret(ctx context.Context, cl client.Client, wgObj metav1.Object) (*corev1.Secret, error) {
wgObjNsName := types.NamespacedName{Name: wgObj.GetName(), Namespace: wgObj.GetNamespace()}

Expand Down
27 changes: 27 additions & 0 deletions pkg/liqoctl/completion/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"

discoveryv1alpha1 "github.com/liqotech/liqo/apis/discovery/v1alpha1"
networkingv1alpha1 "github.com/liqotech/liqo/apis/networking/v1alpha1"
offloadingv1alpha1 "github.com/liqotech/liqo/apis/offloading/v1alpha1"
virtualkubeletv1alpha1 "github.com/liqotech/liqo/apis/virtualkubelet/v1alpha1"
identitymanager "github.com/liqotech/liqo/pkg/identityManager"
Expand Down Expand Up @@ -281,3 +282,29 @@ func PVCs(ctx context.Context, f *factory.Factory, argsLimit int) FnType {

return common(ctx, f, argsLimit, retriever)
}

// Gateway returns a function to autocomplete Gateway (server or client) names.
func Gateway(ctx context.Context, f *factory.Factory, argsLimit int) FnType {
retriever := func(ctx context.Context, f *factory.Factory) ([]string, error) {
var names []string

var gwServers networkingv1alpha1.GatewayServerList
if err := f.CRClient.List(ctx, &gwServers, client.InNamespace(f.Namespace)); err != nil {
return nil, err
}
for i := range gwServers.Items {
names = append(names, gwServers.Items[i].Name)
}

var gwClients networkingv1alpha1.GatewayClientList
if err := f.CRClient.List(ctx, &gwClients, client.InNamespace(f.Namespace)); err != nil {
return nil, err
}
for i := range gwClients.Items {
names = append(names, gwClients.Items[i].Name)
}
return names, nil
}

return common(ctx, f, argsLimit, retriever)
}
94 changes: 83 additions & 11 deletions pkg/liqoctl/network/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ import (
"github.com/liqotech/liqo/pkg/liqoctl/factory"
"github.com/liqotech/liqo/pkg/liqoctl/output"
"github.com/liqotech/liqo/pkg/liqoctl/rest/configuration"
"github.com/liqotech/liqo/pkg/liqoctl/rest/gatewayclient"
"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"
Expand Down Expand Up @@ -54,6 +57,26 @@ func NewCluster(local, remote *factory.Factory) *Cluster {

// Init initializes the cluster struct.
func (c *Cluster) Init(ctx context.Context) error {
// Set cluster identity.
if err := c.SetClusterIdentity(ctx); err != nil {
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)
if err != nil {
s.Fail(fmt.Sprintf("An error occurred while retrieving network configuration: %v", output.PrettyErr(err)))
return err
}
c.NetworkConfiguration = conf
s.Success("Network configuration 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)
Expand All @@ -73,17 +96,6 @@ func (c *Cluster) Init(ctx context.Context) error {
}
c.clusterIdentity = clusterIdentity
s.Success("Cluster identity correctly retrieved")

// 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 network configuration: %v", output.PrettyErr(err)))
return err
}
c.NetworkConfiguration = conf
s.Success("Network configuration correctly retrieved")

return nil
}

Expand Down Expand Up @@ -113,3 +125,63 @@ func (c *Cluster) SetupConfiguration(ctx context.Context,
s.Success("Network configuration correctly set up")
return nil
}

// EnsureGatewayServer create or updates a GatewayServer.
func (c *Cluster) EnsureGatewayServer(ctx context.Context, name string, opts *gatewayserver.ForgeOptions) (*networkingv1alpha1.GatewayServer, error) {
s := c.local.Printer.StartSpinner("Setting up Gateway Server")
gwServer, err := gatewayserver.ForgeGatewayServer(name, c.local.Namespace, opts)
if err != nil {
s.Fail(fmt.Sprintf("An error occurred while forging gatewayserver: %v", output.PrettyErr(err)))
return nil, err
}
_, err = controllerutil.CreateOrUpdate(ctx, c.local.CRClient, gwServer, func() error {
return gatewayserver.MutateGatewayServer(gwServer, opts)
})
if err != nil {
s.Fail(fmt.Sprintf("An error occurred while setting up gatewayserver: %v", output.PrettyErr(err)))
return nil, err
}

s.Success("Gatewayserver correctly set up")
return gwServer, nil
}

// EnsureGatewayClient create or updates a GatewayClient.
func (c *Cluster) EnsureGatewayClient(ctx context.Context, name string, opts *gatewayclient.ForgeOptions) (*networkingv1alpha1.GatewayClient, error) {
s := c.local.Printer.StartSpinner("Setting up Gateway Client")
gwClient, err := gatewayclient.ForgeGatewayClient(name, c.local.Namespace, opts)
if err != nil {
s.Fail(fmt.Sprintf("An error occurred while forging gatewayclient: %v", output.PrettyErr(err)))
return nil, err
}
_, err = controllerutil.CreateOrUpdate(ctx, c.local.CRClient, gwClient, func() error {
return gatewayclient.MutateGatewayClient(gwClient, opts)
})
if err != nil {
s.Fail(fmt.Sprintf("An error occurred while setting up gatewayclient: %v", output.PrettyErr(err)))
return nil, err
}

s.Success("Gatewayclient correctly set up")
return gwClient, nil
}

// EnsurePublicKey create or updates a PublicKey.
func (c *Cluster) EnsurePublicKey(ctx context.Context, remoteClusterIdentity *discoveryv1alpha1.ClusterIdentity, key []byte) 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 != nil {
s.Fail(fmt.Sprintf("An error occurred while creating publickey: %v", output.PrettyErr(err)))
return err
}

s.Success("PublicKey correctly created")
return nil
}
Loading

0 comments on commit 9b15e8b

Please sign in to comment.