Skip to content

Commit

Permalink
Add offload command
Browse files Browse the repository at this point in the history
  • Loading branch information
palexster committed Nov 4, 2021
1 parent 529c90a commit e650e39
Show file tree
Hide file tree
Showing 11 changed files with 589 additions and 11 deletions.
56 changes: 56 additions & 0 deletions cmd/liqoctl/cmd/offload.go
@@ -0,0 +1,56 @@
// Copyright 2019-2021 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 cmd

import (
"context"

"github.com/spf13/cobra"

offloadingv1alpha1 "github.com/liqotech/liqo/apis/offloading/v1alpha1"
"github.com/liqotech/liqo/pkg/liqoctl/offload"
"github.com/liqotech/liqo/pkg/utils/args"
)

func newOffloadCommand(ctx context.Context) *cobra.Command {
var offloadClusterCmd = &cobra.Command{
Use: offload.UseCommand,
SilenceUsage: true,
Short: offload.LiqoctlOffloadShortHelp,
Long: offload.LiqoctlOffloadLongHelp,
Args: cobra.MinimumNArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
return offload.HandleOffloadCommand(ctx, cmd, args)
},
}
podOffloadingStrategy := args.NewEnum([]string{string(offloadingv1alpha1.LocalAndRemotePodOffloadingStrategyType),
string(offloadingv1alpha1.RemotePodOffloadingStrategyType),
string(offloadingv1alpha1.LocalPodOffloadingStrategyType)},
string(offloadingv1alpha1.LocalAndRemotePodOffloadingStrategyType))

offloadClusterCmd.PersistentFlags().Var(podOffloadingStrategy,
offload.PodOffloadingStrategyFlag, offload.PodOffloadingStrategyHelp)
namespaceMappingStrategy := args.NewEnum([]string{string(offloadingv1alpha1.EnforceSameNameMappingStrategyType),
string(offloadingv1alpha1.DefaultNameMappingStrategyType)},
string(offloadingv1alpha1.DefaultNameMappingStrategyType))

offloadClusterCmd.PersistentFlags().Var(namespaceMappingStrategy, offload.NamespaceMappingStrategyFlag,
offload.NamespaceMappingStrategyHelp)
offloadClusterCmd.PersistentFlags().String(offload.AcceptedLabelsFlag,
offload.AcceptedLabelsDefault, offload.AcceptedLabelsHelp)
offloadClusterCmd.PersistentFlags().String(offload.DeniedLabelsFlag,
offload.DeniedLabelDefault, offload.DeniedLabelsHelp)
return offloadClusterCmd
}
1 change: 1 addition & 0 deletions cmd/liqoctl/cmd/root.go
Expand Up @@ -55,5 +55,6 @@ func NewRootCommand(ctx context.Context) *cobra.Command {
rootCmd.AddCommand(newDocsCommand(ctx))
rootCmd.AddCommand(newVersionCommand())
rootCmd.AddCommand(newStatusCommand(ctx))
rootCmd.AddCommand(newOffloadCommand(ctx))
return rootCmd
}
8 changes: 6 additions & 2 deletions cmd/liqoctl/main.go
Expand Up @@ -21,11 +21,11 @@ import (
"syscall"
"time"

"github.com/spf13/cobra"
"k8s.io/client-go/kubernetes/scheme"
_ "k8s.io/client-go/plugin/pkg/client/auth"

discoveryv1alpha1 "github.com/liqotech/liqo/apis/discovery/v1alpha1"
offloadingv1alpha1 "github.com/liqotech/liqo/apis/offloading/v1alpha1"
liqocmd "github.com/liqotech/liqo/cmd/liqoctl/cmd"
)

Expand All @@ -35,6 +35,7 @@ const (

func init() {
_ = discoveryv1alpha1.AddToScheme(scheme.Scheme)
_ = offloadingv1alpha1.AddToScheme(scheme.Scheme)
}

func main() {
Expand All @@ -47,5 +48,8 @@ func main() {
}()

cmd := liqocmd.NewRootCommand(ctx)
cobra.CheckErr(cmd.ExecuteContext(ctx))
msg := cmd.ExecuteContext(ctx)
if msg != nil {
os.Exit(1)
}
}
4 changes: 2 additions & 2 deletions pkg/liqoctl/add/handler.go
Expand Up @@ -29,7 +29,7 @@ import (
discoveryv1alpha1 "github.com/liqotech/liqo/apis/discovery/v1alpha1"
"github.com/liqotech/liqo/pkg/discovery"
"github.com/liqotech/liqo/pkg/liqoctl/common"
utils2 "github.com/liqotech/liqo/pkg/utils"
"github.com/liqotech/liqo/pkg/utils"
authenticationtokenutils "github.com/liqotech/liqo/pkg/utils/authenticationtoken"
foreigncluster "github.com/liqotech/liqo/pkg/utils/foreignCluster"
)
Expand Down Expand Up @@ -89,7 +89,7 @@ func processAddCluster(ctx context.Context, t *ClusterArgs, clientSet kubernetes
return err
}

clusterID, err := utils2.GetClusterIDWithControllerClient(ctx, k8sClient, t.Namespace)
clusterID, err := utils.GetClusterIDWithControllerClient(ctx, k8sClient, t.Namespace)
if err != nil {
return err
}
Expand Down
17 changes: 10 additions & 7 deletions pkg/liqoctl/generate/handler.go
Expand Up @@ -45,7 +45,10 @@ func HandleGenerateAddCommand(ctx context.Context, liqoNamespace string, printOn
return err
}

commandString := processGenerateCommand(ctx, clientSet, liqoNamespace, commandName)
commandString, err := processGenerateCommand(ctx, clientSet, liqoNamespace, commandName)
if err != nil {
return err
}

if printOnlyCommand {
fmt.Println(commandString)
Expand All @@ -56,21 +59,21 @@ func HandleGenerateAddCommand(ctx context.Context, liqoNamespace string, printOn
return nil
}

func processGenerateCommand(ctx context.Context, clientSet client.Client, liqoNamespace, commandName string) string {
func processGenerateCommand(ctx context.Context, clientSet client.Client, liqoNamespace, commandName string) (string, error) {
localToken, err := auth.GetToken(ctx, clientSet, liqoNamespace)
if err != nil {
klog.Fatalf(err.Error())
return "", err
}

clusterID, err := utils.GetClusterIDWithControllerClient(ctx, clientSet, liqoNamespace)
if err != nil {
klog.Fatalf(err.Error())
return "", err
}

// Retrieve the liqo controller manager deployment args
args, err := RetrieveLiqoControllerManagerDeploymentArgs(ctx, clientSet, liqoNamespace)
if err != nil {
klog.Fatalf(err.Error())
return "", err
}

// The error is discarded, since an empty string is returned in case the key is not found, which is fine.
Expand All @@ -81,9 +84,9 @@ func processGenerateCommand(ctx context.Context, clientSet client.Client, liqoNa
authEP, err := foreigncluster.GetHomeAuthURL(ctx, clientSet,
authServiceAddressOverride, authServicePortOverride, liqoNamespace)
if err != nil {
klog.Fatalf("an error occurred while retrieving the liqo-auth service: %s", err)
klog.Fatalf(err.Error())
}
return generateCommandString(commandName, authEP, clusterID, localToken, clusterName)
return generateCommandString(commandName, authEP, clusterID, localToken, clusterName), nil
}

func generateCommandString(commandName, authEP, clusterID, localToken, clusterName string) string {
Expand Down
59 changes: 59 additions & 0 deletions pkg/liqoctl/offload/consts.go
@@ -0,0 +1,59 @@
// Copyright 2019-2021 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 offload

const (
// LiqoctlOffloadShortHelp contains the short help string for liqoctl Offload command.
LiqoctlOffloadShortHelp = "Offload a namespace to remote clusters"
// LiqoctlOffloadLongHelp contains the Long help string for liqoctl Offload command.
LiqoctlOffloadLongHelp = `Offload a namespace to remote clusters with the default values:
$ liqoctl Offload cluster my-cluster
To just enable service reflection, offload a namespace with the EnforceSameName namespace mapping strategy and
and a Local --pod-offloading-strategy.
$ liqoctl offload namespace liqo-demo --namespace-mapping-strategy=EnforceSameName --pod-offloading-strategy=Local
`
// UseCommand contains the verb of the Offload command.
UseCommand = "offload"
// ClusterResourceName contains the name of the resource offloaded in liqoctl Offload.
ClusterResourceName = "namespace"
// SuccessfulMessage is printed when a Offload cluster command has scucceded.
SuccessfulMessage = `
Success 👌!
`
// PodOffloadingStrategyFlag specifies the pod offloading strategy flag name.
PodOffloadingStrategyFlag = "pod-offloading-strategy"
// PodOffloadingStrategyHelp specifies the help message for the PodOffloadingStrategy flag.
PodOffloadingStrategyHelp = "Select the desired pod offloading strategy"
// NamespaceMappingStrategyFlag specifies the namespace mapping flag name.
NamespaceMappingStrategyFlag = "namespace-mapping-strategy"
// NamespaceMappingStrategyHelp specifies the help message for the NamespaceMappingStrategy flag.
NamespaceMappingStrategyHelp = "Select the desired pod offloading strategy"

// AcceptedLabelsFlag specifies the accepted labels flag name.
AcceptedLabelsFlag = "accepted-cluster-labels"
// AcceptedLabelsDefault specifies the accepted default labels used to forge the clusterSelector field.
AcceptedLabelsDefault = "liqo.io/type=virtual-node"
// AcceptedLabelsHelp specifies the help message for the AcceptedLabels flag.
AcceptedLabelsHelp = "The set of labels accepted as valid clusterLabels for the clusterSelector field"
// DeniedLabelsFlag specifies the accepted labels flag name.
DeniedLabelsFlag = "denied-cluster-labels"
// DeniedLabelDefault specifies the denied default labels used to forge the clusterSelector field.
DeniedLabelDefault = ""
// DeniedLabelsHelp specifies the help message for the DeniedLabels flag.
DeniedLabelsHelp = "The set of labels identified as forbidden clusterLabels for the clusterSelector field"
)
16 changes: 16 additions & 0 deletions pkg/liqoctl/offload/doc.go
@@ -0,0 +1,16 @@
// Copyright 2019-2021 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 offload includes the logic for the `liqoctl offload` command
package offload
137 changes: 137 additions & 0 deletions pkg/liqoctl/offload/namespace.go
@@ -0,0 +1,137 @@
// Copyright 2019-2021 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 offload

import (
"context"

"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/klog/v2"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"

offloadingv1alpha1 "github.com/liqotech/liqo/apis/offloading/v1alpha1"
"github.com/liqotech/liqo/pkg/consts"
"github.com/liqotech/liqo/pkg/liqoctl/common"
argsutils "github.com/liqotech/liqo/pkg/utils/args"
logsutils "github.com/liqotech/liqo/pkg/utils/logs"
)

// HandleOffloadCommand implements the "offload namespace" command.
// It forges and createOrUpdate a namespaceOffloading resource for a given namespace according to the flag values.
func HandleOffloadCommand(ctx context.Context, command *cobra.Command, args []string) error {
if !klog.V(4).Enabled() {
klog.SetLogFilter(logsutils.LogFilter{})
}

config, err := common.GetLiqoctlRestConf()
if err != nil {
return err
}

k8sClient, err := client.New(config, client.Options{})
if err != nil {
return err
}

var acceptedClusterLabels argsutils.StringMap
if err := acceptedClusterLabels.Set(command.Flag(AcceptedLabelsFlag).Value.String()); err != nil {
return err
}
var deniedClusterLabels argsutils.StringMap
if err := deniedClusterLabels.Set(command.Flag(DeniedLabelsFlag).Value.String()); err != nil {
return err
}

nsOffloading := forgeNamespaceOffloading(command, args, acceptedClusterLabels, deniedClusterLabels)

_, err = controllerutil.CreateOrUpdate(ctx, k8sClient, nsOffloading, func() error {
nsOffloading.Spec.PodOffloadingStrategy = forgePodOffloadingStrategy(command)
nsOffloading.Spec.NamespaceMappingStrategy = forgeNamespaceMappingStrategy(command)
nsOffloading.Spec.ClusterSelector = forgeClusterSelector(acceptedClusterLabels, deniedClusterLabels)
return nil
})
if err != nil {
return err
}

return nil
}

func forgeNamespaceOffloading(command *cobra.Command, args []string,
acceptedLabels, deniedLabels argsutils.StringMap) *offloadingv1alpha1.NamespaceOffloading {
return &offloadingv1alpha1.NamespaceOffloading{
ObjectMeta: metav1.ObjectMeta{
Name: consts.DefaultNamespaceOffloadingName,
Namespace: args[1],
},
Spec: offloadingv1alpha1.NamespaceOffloadingSpec{
NamespaceMappingStrategy: forgeNamespaceMappingStrategy(command),
PodOffloadingStrategy: forgePodOffloadingStrategy(command),
ClusterSelector: forgeClusterSelector(acceptedLabels, deniedLabels),
},
}
}

func forgeClusterSelector(acceptedLabels, deniedLabels argsutils.StringMap) corev1.NodeSelector {
var l []corev1.NodeSelectorTerm

// No acceptedLabels are defined, backing to the default behavior
if len(acceptedLabels.StringMap) == 0 && len(deniedLabels.StringMap) == 0 {
return corev1.NodeSelector{
NodeSelectorTerms: []corev1.NodeSelectorTerm{{
MatchExpressions: []corev1.NodeSelectorRequirement{{
Key: consts.TypeLabel,
Operator: corev1.NodeSelectorOpIn,
Values: []string{consts.TypeNode},
}}},
},
}
}

for k, v := range acceptedLabels.StringMap {
l = append(l, corev1.NodeSelectorTerm{
MatchExpressions: []corev1.NodeSelectorRequirement{{
Key: k,
Operator: corev1.NodeSelectorOpIn,
Values: []string{v},
},
},
})
}

for k, v := range deniedLabels.StringMap {
l = append(l, corev1.NodeSelectorTerm{
MatchExpressions: []corev1.NodeSelectorRequirement{{
Key: k,
Operator: corev1.NodeSelectorOpNotIn,
Values: []string{v},
},
},
})
}

return corev1.NodeSelector{NodeSelectorTerms: l}
}

func forgePodOffloadingStrategy(command *cobra.Command) offloadingv1alpha1.PodOffloadingStrategyType {
return offloadingv1alpha1.PodOffloadingStrategyType(command.Flag(PodOffloadingStrategyFlag).Value.String())
}

func forgeNamespaceMappingStrategy(command *cobra.Command) offloadingv1alpha1.NamespaceMappingStrategyType {
return offloadingv1alpha1.NamespaceMappingStrategyType(command.Flag(NamespaceMappingStrategyFlag).Value.String())
}

0 comments on commit e650e39

Please sign in to comment.