-
Notifications
You must be signed in to change notification settings - Fork 106
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
[Feat] liqoctl gateway template check #2791
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ import ( | |
corev1 "k8s.io/api/core/v1" | ||
apierrors "k8s.io/apimachinery/pkg/api/errors" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" | ||
"k8s.io/apimachinery/pkg/types" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" | ||
|
@@ -29,6 +30,7 @@ import ( | |
networkingv1beta1 "github.com/liqotech/liqo/apis/networking/v1beta1" | ||
"github.com/liqotech/liqo/pkg/consts" | ||
gwforge "github.com/liqotech/liqo/pkg/gateway/forge" | ||
enutils "github.com/liqotech/liqo/pkg/liqo-controller-manager/networking/external-network/utils" | ||
"github.com/liqotech/liqo/pkg/liqo-controller-manager/networking/forge" | ||
networkingutils "github.com/liqotech/liqo/pkg/liqo-controller-manager/networking/utils" | ||
"github.com/liqotech/liqo/pkg/liqoctl/factory" | ||
|
@@ -37,6 +39,7 @@ import ( | |
tenantnamespace "github.com/liqotech/liqo/pkg/tenantNamespace" | ||
liqoutils "github.com/liqotech/liqo/pkg/utils" | ||
"github.com/liqotech/liqo/pkg/utils/getters" | ||
"github.com/liqotech/liqo/pkg/utils/maps" | ||
) | ||
|
||
// Cluster contains the information about a cluster. | ||
|
@@ -194,6 +197,123 @@ func (c *Cluster) SetupConfiguration(ctx context.Context, conf *networkingv1beta | |
return nil | ||
} | ||
|
||
// CheckTemplateGwClient checks if the GatewayClient template is correctly set up. | ||
func (c *Cluster) CheckTemplateGwClient(ctx context.Context, opts *Options) error { | ||
templateName := opts.ServerTemplateName | ||
templateNamespace := opts.ServerTemplateNamespace | ||
templateGVR := opts.ServerGatewayType | ||
|
||
s := c.local.Printer.StartSpinner(fmt.Sprintf("Checking gateway client template \"%s/%s\"", templateName, templateNamespace)) | ||
|
||
_, err := c.checkTemplate(ctx, templateName, templateNamespace, templateGVR) | ||
if err != nil { | ||
s.Fail(fmt.Sprintf("An error occurred while checking gateway template \"%s/%s\": %v", templateName, templateNamespace, output.PrettyErr(err))) | ||
return err | ||
} | ||
|
||
s.Success(fmt.Sprintf("Gateway client template \"%s/%s\" correctly checked", templateName, templateNamespace)) | ||
return nil | ||
} | ||
|
||
// CheckTemplateGwServer checks if the GatewayServer template is correctly set up. | ||
func (c *Cluster) CheckTemplateGwServer(ctx context.Context, opts *Options) error { | ||
templateName := opts.ServerTemplateName | ||
templateNamespace := opts.ServerTemplateNamespace | ||
templateGVR := opts.ServerGatewayType | ||
|
||
s := c.local.Printer.StartSpinner(fmt.Sprintf("Checking gateway client template \"%s/%s\"", templateName, templateNamespace)) | ||
|
||
template, err := c.checkTemplate(ctx, templateName, templateNamespace, templateGVR) | ||
if err != nil { | ||
s.Fail(fmt.Sprintf("An error occurred while checking gateway template \"%s/%s\": %v", templateName, templateNamespace, output.PrettyErr(err))) | ||
return err | ||
} | ||
|
||
if err := c.checkTemplateServerService(template, opts); err != nil { | ||
s.Fail(fmt.Sprintf("An error occurred while checking gateway template \"%s/%s\": %v", templateName, templateNamespace, output.PrettyErr(err))) | ||
return err | ||
} | ||
|
||
s.Success(fmt.Sprintf("Gateway client template \"%s/%s\" correctly checked", templateName, templateNamespace)) | ||
return nil | ||
} | ||
|
||
func (c *Cluster) checkTemplate(ctx context.Context, templateName, templateNamespace, templateGvr string) (*unstructured.Unstructured, error) { | ||
// Server Template Reference | ||
gvr, err := enutils.ParseGroupVersionResource(templateGvr) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
template, err := c.local.DynClient.Resource(gvr).Namespace(templateNamespace).Get(ctx, templateName, metav1.GetOptions{}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return template, nil | ||
} | ||
|
||
// checkTemplateServerService checks if the GatewayServer service template is correctly set up. | ||
func (c *Cluster) checkTemplateServerService(template *unstructured.Unstructured, opts *Options) error { | ||
switch corev1.ServiceType(opts.ServerServiceType.Value) { | ||
case corev1.ServiceTypeClusterIP: | ||
return c.checkTemplateServerServiceClusterIP(template, opts) | ||
case corev1.ServiceTypeNodePort: | ||
return c.checkTemplateServerServiceNodePort(template, opts) | ||
case corev1.ServiceTypeLoadBalancer: | ||
return c.checkTemplateServerServiceLoadBalancer(template, opts) | ||
case corev1.ServiceTypeExternalName: | ||
return fmt.Errorf("externalName service type not supported") | ||
} | ||
return nil | ||
} | ||
|
||
func (c *Cluster) checkTemplateServerServiceClusterIP(_ *unstructured.Unstructured, _ *Options) error { | ||
return nil | ||
} | ||
func (c *Cluster) checkTemplateServerServiceNodePort(template *unstructured.Unstructured, opts *Options) error { | ||
if opts.ServerServiceNodePort == 0 { | ||
return nil | ||
} | ||
|
||
path := "spec.template.spec.service.spec.ports" | ||
templateServicePorts, err := maps.GetNestedField(template.Object, path) | ||
if err != nil { | ||
return fmt.Errorf("unable to get %s of the server template", path) | ||
} | ||
|
||
templateServicePortsSlice, ok := templateServicePorts.([]interface{}) | ||
if !ok { | ||
return fmt.Errorf("unable to cast %s to []interface{}", path) | ||
} | ||
|
||
port, ok := templateServicePortsSlice[0].(map[string]interface{}) | ||
if !ok { | ||
return fmt.Errorf("unable to cast %s to map[string]interface{}", path) | ||
} | ||
|
||
_, err = maps.GetNestedField(port, "nodePort") | ||
if err != nil { | ||
return fmt.Errorf("unable to get spec.template.spec.service.spec.ports[0].nodePort int the server template, " + | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Once we add a flag to skip this check (as suggested by aleoli), we can add a suggestion of how to skip this check. Morevoer, we might also add a documentation page explaining the concept of template and how to add a field in the template, so that we can add a link to it in the error message |
||
"since you specified the flag \"--server-service-nodeport\" you need to add the \"nodePort\" field in the template") | ||
} | ||
|
||
return nil | ||
} | ||
func (c *Cluster) checkTemplateServerServiceLoadBalancer(template *unstructured.Unstructured, opts *Options) error { | ||
if opts.ServerServiceLoadBalancerIP == "" { | ||
return nil | ||
} | ||
|
||
path := "spec.template.spec.service.spec.loadBalancerIP" | ||
_, err := maps.GetNestedField(template.Object, path) | ||
if err != nil { | ||
return fmt.Errorf("unable to get %s of the server template, "+ | ||
"since you specified the flag \"--server-service-loadbalancerip\" you need to add the \"loadBalancerIP\" field in the template", path) | ||
} | ||
return nil | ||
} | ||
|
||
// CheckNetworkInitialized checks if the network is initialized correctly. | ||
func (c *Cluster) CheckNetworkInitialized(ctx context.Context, remoteClusterID liqov1beta1.ClusterID) error { | ||
s := c.local.Printer.StartSpinner("Checking network is initialized correctly") | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,13 +38,13 @@ type Options struct { | |
Timeout time.Duration | ||
Wait bool | ||
|
||
ServerGatewayType string | ||
ServerTemplateName string | ||
ServerTemplateNamespace string | ||
ServerServiceType *argsutils.StringEnum | ||
ServerPort int32 | ||
ServerNodePort int32 | ||
ServerLoadBalancerIP string | ||
ServerGatewayType string | ||
ServerTemplateName string | ||
ServerTemplateNamespace string | ||
ServerServiceType *argsutils.StringEnum | ||
ServerServicePort int32 | ||
ServerServiceNodePort int32 | ||
ServerServiceLoadBalancerIP string | ||
|
||
ClientGatewayType string | ||
ClientTemplateName string | ||
|
@@ -165,6 +165,16 @@ func (o *Options) RunConnect(ctx context.Context) error { | |
return err | ||
} | ||
|
||
// Check if the Templates exists and is valid on cluster 1 | ||
if err := cluster1.CheckTemplateGwClient(ctx, o); err != nil { | ||
return err | ||
} | ||
|
||
// Check if the Templates exists and is valid on cluster 2 | ||
if err := cluster2.CheckTemplateGwServer(ctx, o); err != nil { | ||
return err | ||
} | ||
Comment on lines
+169
to
+176
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should add a flag to skip these checks |
||
|
||
// Check if the Networking is initialized on cluster 1 | ||
if err := cluster1.CheckNetworkInitialized(ctx, cluster2.localClusterID); err != nil { | ||
return err | ||
|
@@ -331,9 +341,9 @@ func (o *Options) newGatewayServerForgeOptions(kubeClient kubernetes.Interface, | |
TemplateNamespace: o.ServerTemplateNamespace, | ||
ServiceType: corev1.ServiceType(o.ServerServiceType.Value), | ||
MTU: o.MTU, | ||
Port: o.ServerPort, | ||
NodePort: ptr.To(o.ServerNodePort), | ||
LoadBalancerIP: ptr.To(o.ServerLoadBalancerIP), | ||
Port: o.ServerServicePort, | ||
NodePort: ptr.To(o.ServerServiceNodePort), | ||
LoadBalancerIP: ptr.To(o.ServerServiceLoadBalancerIP), | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should align this file to the eks one also on what concerns empty lines