Skip to content

Commit

Permalink
Added rest gatewayclient
Browse files Browse the repository at this point in the history
  • Loading branch information
fra98 committed Oct 11, 2023
1 parent 5625e81 commit c93ea4f
Show file tree
Hide file tree
Showing 12 changed files with 417 additions and 11 deletions.
2 changes: 1 addition & 1 deletion apis/networking/v1alpha1/gatewayclient_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ type GatewayClientSpec struct {
// MTU specifies the MTU of the tunnel.
MTU int `json:"mtu,omitempty"`
// Endpoint specifies the endpoint of the tunnel.
Endpoint Endpoint `json:"endpoint,omitempty"`
Endpoint EndpointStatus `json:"endpoint,omitempty"`
}

// GatewayClientStatus defines the observed state of GatewayClient.
Expand Down
4 changes: 2 additions & 2 deletions apis/networking/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions cmd/liqoctl/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ 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 @@ -47,6 +48,7 @@ var liqoResources = []rest.APIProvider{
virtualnode.VirtualNode,
configuration.Configuration,
gatewayserver.GatewayServer,
gatewayclient.GatewayClient,
publickey.PublicKey,
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,21 @@ spec:
endpoint:
description: Endpoint specifies the endpoint of the tunnel.
properties:
addresses:
description: Addresses specifies the addresses of the endpoint.
items:
type: string
type: array
port:
description: Port specifies the port of the endpoint.
format: int32
type: integer
serviceType:
default: ClusterIP
description: ServiceType specifies the type of the service.
protocol:
default: TCP
description: Protocol specifies the protocol of the endpoint.
enum:
- ClusterIP
- NodePort
- LoadBalancer
- ExternalName
- TCP
- UDP
type: string
type: object
mtu:
Expand Down
224 changes: 224 additions & 0 deletions pkg/liqoctl/rest/gatewayclient/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
// Copyright 2019-2023 The Liqo Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package gatewayclient

import (
"context"
"fmt"
"os"
"time"

"github.com/spf13/cobra"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/cli-runtime/pkg/printers"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"

networkingv1alpha1 "github.com/liqotech/liqo/apis/networking/v1alpha1"
liqoconsts "github.com/liqotech/liqo/pkg/consts"
enutils "github.com/liqotech/liqo/pkg/liqo-controller-manager/external-network/utils"
"github.com/liqotech/liqo/pkg/liqoctl/completion"
"github.com/liqotech/liqo/pkg/liqoctl/output"
"github.com/liqotech/liqo/pkg/liqoctl/rest"
"github.com/liqotech/liqo/pkg/utils/args"
)

const liqoctlCreateGatewayClientLongHelp = `Create a Gateway Client.
The GatewayClient resource is used to define a Gateway Client for the external network.
Examples:
$ {{ .Executable }} create gatewayclient my-gw-client \
--cluster-id my-cluster-id \
--type networking.liqo.io/v1alpha1/wggatewayclients`

// Create creates a GatewayClient.
func (o *Options) Create(ctx context.Context, options *rest.CreateOptions) *cobra.Command {
outputFormat := args.NewEnum([]string{"json", "yaml"}, "")

o.createOptions = options

cmd := &cobra.Command{
Use: "gatewayclient",
Aliases: []string{"gatewayclients", "client", "clients", "gwc"},
Short: "Create a Gateway Client",
Long: liqoctlCreateGatewayClientLongHelp,
Args: cobra.ExactArgs(1),

PreRun: func(cmd *cobra.Command, args []string) {
options.OutputFormat = outputFormat.Value
options.Name = args[0]
o.createOptions = options
},

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

cmd.Flags().VarP(outputFormat, "output", "o",
"Output the resulting GatewayClient resource, instead of applying it. Supported formats: json, yaml")

cmd.Flags().StringVar(&o.ClusterID, "cluster-id", "", "The cluster ID of the remote cluster")
cmd.Flags().StringVar(&o.GatewayType, "type", "networking.liqo.io/v1alpha1/wggatewayclienttemplates", "Type of Gateway Client. Default: wireguard")
cmd.Flags().StringVar(&o.TemplateName, "template-name", "wg-client-template", "Name of the Gateway Client template")
cmd.Flags().StringVar(&o.TemplateNamespace, "template-namespace", "liqo", "Namespace of the Gateway Client template")
cmd.Flags().IntVar(&o.MTU, "mtu", 1450, "MTU of Gateway Client")
cmd.Flags().StringSliceVar(&o.Addresses, "addresses", []string{}, "Addresses of Gateway Server")
cmd.Flags().Int32Var(&o.Port, "port", 0, "Port of Gateway Server")
cmd.Flags().StringVar(&o.Protocol, "protocol", "UDP", "Gateway Protocol")
cmd.Flags().BoolVar(&o.Wait, "wait", false, "Wait for the Gateway Client to be ready")

runtime.Must(cmd.MarkFlagRequired("cluster-id"))
runtime.Must(cmd.MarkFlagRequired("addresses"))
runtime.Must(cmd.MarkFlagRequired("port"))

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

return cmd
}

func (o *Options) handleCreate(ctx context.Context) error {
opts := o.createOptions

gwClient, err := forgeGatewayClient(opts.Name, opts.Namespace, o)
if err != nil {
opts.Printer.CheckErr(err)
return err
}

if opts.OutputFormat != "" {
opts.Printer.CheckErr(o.output(gwClient))
return nil
}

s := opts.Printer.StartSpinner("Creating gatewayclient")

_, err = controllerutil.CreateOrUpdate(ctx, opts.CRClient, gwClient, func() error {
return mutateGatewayClient(gwClient, o)
})
if err != nil {
s.Fail("Unable to create gatewayclient: %v", output.PrettyErr(err))
return err
}
s.Success("Gatewayclient created")

if o.Wait {
s = opts.Printer.StartSpinner("Waiting for gatewayclient to be ready")
interval := 1 * time.Second
if err := wait.PollUntilContextCancel(ctx, interval, false, func(context.Context) (done bool, err error) {
var appliedGwClient networkingv1alpha1.GatewayClient
err = opts.CRClient.Get(ctx, types.NamespacedName{
Namespace: gwClient.Namespace,
Name: gwClient.Name,
}, &appliedGwClient)
if err != nil {
return false, err
}

return appliedGwClient.Status.ClientRef != nil, nil
}); err != nil {
s.Fail("Unable to wait for gatewayclient to be ready: %v", output.PrettyErr(err))
return err
}
s.Success("gatewayclient is ready")
}

return nil
}

func forgeGatewayClient(name, namespace string, o *Options) (*networkingv1alpha1.GatewayClient, error) {
gwClient := &networkingv1alpha1.GatewayClient{
TypeMeta: metav1.TypeMeta{
Kind: networkingv1alpha1.GatewayClientKind,
APIVersion: networkingv1alpha1.GroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Labels: map[string]string{
liqoconsts.RemoteClusterID: o.ClusterID,
},
},
}
err := mutateGatewayClient(gwClient, o)
if err != nil {
return nil, err
}
return gwClient, nil
}

func mutateGatewayClient(gwClient *networkingv1alpha1.GatewayClient, o *Options) error {
gwClient.Kind = networkingv1alpha1.GatewayClientKind
gwClient.APIVersion = networkingv1alpha1.GroupVersion.String()

if gwClient.Labels == nil {
gwClient.Labels = make(map[string]string)
}
gwClient.Labels[liqoconsts.RemoteClusterID] = o.ClusterID

gwClient.Spec.MTU = o.MTU

protocol := v1.Protocol(o.Protocol)
gwClient.Spec.Endpoint = networkingv1alpha1.EndpointStatus{
Addresses: o.Addresses,
Port: o.Port,
Protocol: &protocol,
}

gvr, err := enutils.ParseGroupVersionResource(o.GatewayType)
if err != nil {
return err
}
kind, err := enutils.ResourceToKind(gvr, o.createOptions.RESTConfig)
if err != nil {
return err
}
gwClient.Spec.ClientTemplateRef = v1.ObjectReference{
Name: o.TemplateName,
Namespace: o.TemplateNamespace,
Kind: kind,
APIVersion: gvr.GroupVersion().String(),
}

return nil
}

// output implements the logic to output the generated Gateway Client resource.
func (o *Options) output(gwClient *networkingv1alpha1.GatewayClient) error {
var outputFormat string
switch {
case o.createOptions != nil:
outputFormat = o.createOptions.OutputFormat
default:
return fmt.Errorf("unable to determine output format")
}
var printer printers.ResourcePrinter
switch outputFormat {
case "yaml":
printer = &printers.YAMLPrinter{}
case "json":
printer = &printers.JSONPrinter{}
default:
return fmt.Errorf("unsupported output format %q", outputFormat)
}

return printer.PrintObj(gwClient, os.Stdout)
}
28 changes: 28 additions & 0 deletions pkg/liqoctl/rest/gatewayclient/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2019-2023 The Liqo Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package gatewayclient

import (
"context"

"github.com/spf13/cobra"

"github.com/liqotech/liqo/pkg/liqoctl/rest"
)

// Delete deletes a GatewayClient.
func (o *Options) Delete(_ context.Context, _ *rest.DeleteOptions) *cobra.Command {
panic("not implemented")
}
16 changes: 16 additions & 0 deletions pkg/liqoctl/rest/gatewayclient/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright 2019-2023 The Liqo Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package gatewayclient contains the logic to manage GatewayClients.
package gatewayclient
28 changes: 28 additions & 0 deletions pkg/liqoctl/rest/gatewayclient/generate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2019-2023 The Liqo Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package gatewayclient

import (
"context"

"github.com/spf13/cobra"

"github.com/liqotech/liqo/pkg/liqoctl/rest"
)

// Generate generates a GatewayClient.
func (o *Options) Generate(_ context.Context, _ *rest.GenerateOptions) *cobra.Command {
panic("not implemented")
}
Loading

0 comments on commit c93ea4f

Please sign in to comment.