diff --git a/controllers/networktopology.go b/controllers/networktopology.go index b6f4d6b..a44b52b 100644 --- a/controllers/networktopology.go +++ b/controllers/networktopology.go @@ -2,22 +2,20 @@ package controllers import ( "context" - "errors" "time" - gsannotation "github.com/giantswarm/k8smetadata/pkg/annotation" "github.com/giantswarm/microerror" k8sErrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" capa "sigs.k8s.io/cluster-api-provider-aws/api/v1beta1" capi "sigs.k8s.io/cluster-api/api/v1beta1" - "sigs.k8s.io/cluster-api/util/annotations" + capiannotations "sigs.k8s.io/cluster-api/util/annotations" capiconditions "sigs.k8s.io/cluster-api/util/conditions" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/log" + "github.com/giantswarm/aws-network-topology-operator/pkg/conditions" "github.com/giantswarm/aws-network-topology-operator/pkg/registrar" - nettopAnnotations "github.com/giantswarm/aws-network-topology-operator/pkg/util/annotations" ) const ( @@ -74,7 +72,7 @@ func (r *NetworkTopologyReconciler) Reconcile(ctx context.Context, req ctrl.Requ return ctrl.Result{}, microerror.Mask(err) } - if annotations.IsPaused(cluster, cluster) { + if capiannotations.IsPaused(cluster, cluster) { logger.Info("Core cluster is marked as paused. Won't reconcile") return ctrl.Result{}, nil } @@ -105,24 +103,10 @@ func (r *NetworkTopologyReconciler) reconcileNormal(ctx context.Context, cluster err = r.registrar.Register(ctx, cluster) if err != nil { - if errors.Is(err, ®istrar.ModeNotSupportedError{}) { - capiconditions.MarkFalse(cluster, networkTopologyCondition, "ModeNotSupported", capi.ConditionSeverityInfo, "The provided mode '%s' is not supported", nettopAnnotations.GetAnnotation(cluster, gsannotation.NetworkTopologyModeAnnotation)) - return ctrl.Result{Requeue: false}, nil - } else if errors.Is(err, ®istrar.TransitGatewayNotAvailableError{}) { - capiconditions.MarkFalse(cluster, networkTopologyCondition, "TransitGatewayNotAvailable", capi.ConditionSeverityWarning, "The transit gateway is not yet available for attachment") - return ctrl.Result{Requeue: true, RequeueAfter: time.Minute * 1}, nil - } else if errors.Is(err, ®istrar.VPCNotReadyError{}) { - capiconditions.MarkFalse(cluster, networkTopologyCondition, "VPCNotReady", capi.ConditionSeverityInfo, "The cluster's VPC is not yet ready") - return ctrl.Result{Requeue: true, RequeueAfter: time.Minute * 1}, nil - } else if errors.Is(err, ®istrar.IDNotProvidedError{}) { - capiconditions.MarkFalse(cluster, networkTopologyCondition, "RequiredIDMissing", capi.ConditionSeverityError, "The %s ID is missing from the annotations", err.(*registrar.IDNotProvidedError).ID) - return ctrl.Result{Requeue: false}, nil - } - - return ctrl.Result{Requeue: true, RequeueAfter: time.Minute * 10}, microerror.Mask(err) + return markErrorConditions(cluster, err) } - capiconditions.MarkTrue(cluster, networkTopologyCondition) + conditions.MarkReady(cluster) return ctrl.Result{Requeue: true, RequeueAfter: time.Minute * 10}, nil } @@ -143,3 +127,33 @@ func (r *NetworkTopologyReconciler) reconcileDelete(ctx context.Context, cluster return ctrl.Result{}, nil } + +func markErrorConditions(cluster *capi.Cluster, err error) (ctrl.Result, error) { + // TODO: Log errors + + if registrar.IsModeNotSupportedError(err) { + conditions.MarkModeNotSupported(cluster) + return ctrl.Result{Requeue: false}, nil + } + + if registrar.IsTransitGatewayNotAvailableError(err) { + // TODO: why no condition here? + return ctrl.Result{Requeue: true, RequeueAfter: time.Minute * 1}, nil + } + + if registrar.IsVPCNotReadyError(err) { + conditions.MarkVPCNotReady(cluster) + return ctrl.Result{Requeue: true, RequeueAfter: time.Minute * 1}, nil + } + + if registrar.IsIDNotProvidedError(err) { + id := err.(*registrar.IDNotProvidedError).ID + + conditions.MarkIDNotProvided(cluster, id) + return ctrl.Result{Requeue: false}, nil + } + + // TODO: is this necessary? Why do we requeue after 10 minutes for a + // generic error. I'd rather have the exponential backoff handle this. + return ctrl.Result{Requeue: true, RequeueAfter: time.Minute * 10}, microerror.Mask(err) +} diff --git a/pkg/registrar/errors.go b/pkg/registrar/errors.go index 9e5c5b1..6d5362b 100644 --- a/pkg/registrar/errors.go +++ b/pkg/registrar/errors.go @@ -1,6 +1,7 @@ package registrar import ( + "errors" "fmt" "reflect" ) @@ -18,9 +19,12 @@ func (e *ModeNotSupportedError) Is(target error) bool { return reflect.TypeOf(target) == reflect.TypeOf(e) } -type TransitGatewayNotAvailableError struct { +func IsModeNotSupportedError(err error) bool { + return errors.Is(err, &ModeNotSupportedError{}) } +type TransitGatewayNotAvailableError struct{} + func (e *TransitGatewayNotAvailableError) Error() string { return "transit gateway not available" } @@ -29,9 +33,12 @@ func (e *TransitGatewayNotAvailableError) Is(target error) bool { return reflect.TypeOf(target) == reflect.TypeOf(e) } -type VPCNotReadyError struct { +func IsTransitGatewayNotAvailableError(err error) bool { + return errors.Is(err, &TransitGatewayNotAvailableError{}) } +type VPCNotReadyError struct{} + func (e *VPCNotReadyError) Error() string { return "transit gateway not available" } @@ -40,6 +47,10 @@ func (e *VPCNotReadyError) Is(target error) bool { return reflect.TypeOf(target) == reflect.TypeOf(e) } +func IsVPCNotReadyError(err error) bool { + return errors.Is(err, &VPCNotReadyError{}) +} + type IDNotProvidedError struct { error ID string @@ -52,3 +63,7 @@ func (e *IDNotProvidedError) Error() string { func (e *IDNotProvidedError) Is(target error) bool { return reflect.TypeOf(target) == reflect.TypeOf(e) } + +func IsIDNotProvidedError(err error) bool { + return errors.Is(err, &IDNotProvidedError{}) +}