diff --git a/controllers/perses/configmap_controller.go b/controllers/perses/configmap_controller.go index 31d239f..ecb5c59 100644 --- a/controllers/perses/configmap_controller.go +++ b/controllers/perses/configmap_controller.go @@ -19,19 +19,21 @@ package perses import ( "context" "fmt" - "time" - "github.com/perses/perses-operator/api/v1alpha1" - "github.com/perses/perses-operator/internal/perses/common" - "github.com/perses/perses-operator/internal/subreconciler" logger "github.com/sirupsen/logrus" "gopkg.in/yaml.v2" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/perses/perses-operator/api/v1alpha1" + "github.com/perses/perses-operator/internal/perses/common" + "github.com/perses/perses-operator/internal/subreconciler" ) var cmlog = logger.WithField("module", "configmap_controller") @@ -39,29 +41,33 @@ var cmlog = logger.WithField("module", "configmap_controller") func (r *PersesReconciler) reconcileConfigMap(ctx context.Context, req ctrl.Request) (*ctrl.Result, error) { perses := &v1alpha1.Perses{} - if r, err := r.getLatestPerses(ctx, req, perses); subreconciler.ShouldHaltOrRequeue(r, err) { - return r, err + if result, err := r.getLatestPerses(ctx, req, perses); subreconciler.ShouldHaltOrRequeue(result, err) { + return result, err } configName := common.GetConfigName(perses.Name) found := &corev1.ConfigMap{} - err := r.Get(ctx, types.NamespacedName{Name: configName, Namespace: perses.Namespace}, found) - if err != nil && apierrors.IsNotFound(err) { - cm, err := createPersesConfigMap(r, perses) - if err != nil { - cmlog.WithError(err).Error("Failed to define new ConfigMap resource for perses") + if err := r.Get(ctx, types.NamespacedName{Name: configName, Namespace: perses.Namespace}, found); err != nil { + if !apierrors.IsNotFound(err) { + cmlog.WithError(err).Error("Failed to get ConfigMap") + return subreconciler.RequeueWithError(err) + } + + cm, err2 := r.createPersesConfigMap(perses) + if err2 != nil { + cmlog.WithError(err2).Error("Failed to define new ConfigMap resource for perses") meta.SetStatusCondition(&perses.Status.Conditions, metav1.Condition{Type: common.TypeAvailablePerses, Status: metav1.ConditionFalse, Reason: "Reconciling", - Message: fmt.Sprintf("Failed to create ConfigMap for the custom resource (%s): (%s)", perses.Name, err)}) + Message: fmt.Sprintf("Failed to create ConfigMap for the custom resource (%s): (%s)", perses.Name, err2)}) - if err := r.Status().Update(ctx, perses); err != nil { + if err = r.Status().Update(ctx, perses); err != nil { cmlog.WithError(err).Error("Failed to update perses status") return subreconciler.RequeueWithError(err) } - return subreconciler.RequeueWithError(err) + return subreconciler.RequeueWithError(err2) } cmlog.Infof("Creating a new ConfigMap: ConfigMap.Namespace %s ConfigMap.Name %s", cm.Namespace, cm.Name) @@ -70,18 +76,32 @@ func (r *PersesReconciler) reconcileConfigMap(ctx context.Context, req ctrl.Requ return subreconciler.RequeueWithError(err) } - return subreconciler.RequeueWithDelay(time.Minute) + return subreconciler.ContinueReconciling() } + cm, err := r.createPersesConfigMap(perses) if err != nil { - cmlog.WithError(err).Error("Failed to get ConfigMap") + cmlog.WithError(err).Error("Failed to define new ConfigMap resource for perses") + return subreconciler.RequeueWithError(err) + } + + // call update with dry run to fill out fields that are also returned via the k8s api + if err := r.Update(ctx, cm, client.DryRunAll); err != nil { + cmlog.Error(err, "Failed to update ConfigMap with dry run") return subreconciler.RequeueWithError(err) } + if !equality.Semantic.DeepEqual(found, cm) { + if err := r.Update(ctx, cm); err != nil { + cmlog.Error(err, "Failed to update ConfigMap") + return subreconciler.RequeueWithError(err) + } + } + return subreconciler.ContinueReconciling() } -func createPersesConfigMap(r *PersesReconciler, perses *v1alpha1.Perses) (*corev1.ConfigMap, error) { +func (r *PersesReconciler) createPersesConfigMap(perses *v1alpha1.Perses) (*corev1.ConfigMap, error) { configName := common.GetConfigName(perses.Name) ls, err := common.LabelsForPerses(r.Config.PersesImage, configName, perses.Name, perses.Spec.Metadata) diff --git a/controllers/perses/deployment_controller.go b/controllers/perses/deployment_controller.go index 4a91ce9..1c177a4 100644 --- a/controllers/perses/deployment_controller.go +++ b/controllers/perses/deployment_controller.go @@ -19,14 +19,11 @@ package perses import ( "context" "fmt" - "time" - "github.com/perses/perses-operator/api/v1alpha1" - "github.com/perses/perses-operator/internal/perses/common" - "github.com/perses/perses-operator/internal/subreconciler" logger "github.com/sirupsen/logrus" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -34,6 +31,11 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/utils/ptr" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/perses/perses-operator/api/v1alpha1" + "github.com/perses/perses-operator/internal/perses/common" + "github.com/perses/perses-operator/internal/subreconciler" ) var dlog = logger.WithField("module", "deployment_controller") @@ -41,8 +43,8 @@ var dlog = logger.WithField("module", "deployment_controller") func (r *PersesReconciler) reconcileDeployment(ctx context.Context, req ctrl.Request) (*ctrl.Result, error) { perses := &v1alpha1.Perses{} - if r, err := r.getLatestPerses(ctx, req, perses); subreconciler.ShouldHaltOrRequeue(r, err) { - return r, err + if result, err := r.getLatestPerses(ctx, req, perses); subreconciler.ShouldHaltOrRequeue(result, err) { + return result, err } if perses.Spec.Config.Database.SQL == nil { @@ -62,11 +64,14 @@ func (r *PersesReconciler) reconcileDeployment(ctx context.Context, req ctrl.Req } found := &appsv1.Deployment{} - err := r.Get(ctx, types.NamespacedName{Name: perses.Name, Namespace: perses.Namespace}, found) - if err != nil && apierrors.IsNotFound(err) { + if err := r.Get(ctx, types.NamespacedName{Name: perses.Name, Namespace: perses.Namespace}, found); err != nil { + if !apierrors.IsNotFound(err) { + dlog.WithError(err).Error("Failed to get Deployment") + return subreconciler.RequeueWithError(err) + } - dep, err := r.createPersesDeployment(perses) - if err != nil { + dep, err2 := r.createPersesDeployment(perses) + if err2 != nil { dlog.WithError(err).Error("Failed to define new Deployment resource for perses") meta.SetStatusCondition(&perses.Status.Conditions, metav1.Condition{Type: common.TypeAvailablePerses, @@ -87,13 +92,28 @@ func (r *PersesReconciler) reconcileDeployment(ctx context.Context, req ctrl.Req return subreconciler.RequeueWithError(err) } - return subreconciler.RequeueWithDelay(time.Minute) - } else if err != nil { - dlog.WithError(err).Error("Failed to get Deployment") + return subreconciler.ContinueReconciling() + } + + dep, err := r.createPersesDeployment(perses) + if err != nil { + dlog.WithError(err).Error("Failed to define new Deployment resource for perses") + return subreconciler.RequeueWithError(err) + } + // call update with dry run to fill out fields that are also returned via the k8s api + if err = r.Update(ctx, dep, client.DryRunAll); err != nil { + dlog.Error(err, "Failed to update Deployment with dry run") return subreconciler.RequeueWithError(err) } + if !equality.Semantic.DeepEqual(found.Spec, dep.Spec) { + if err = r.Update(ctx, dep); err != nil { + dlog.Error(err, "Failed to update Deployment") + return subreconciler.RequeueWithError(err) + } + } + return subreconciler.ContinueReconciling() } diff --git a/controllers/perses/service_controller.go b/controllers/perses/service_controller.go index 10efb19..3b433db 100644 --- a/controllers/perses/service_controller.go +++ b/controllers/perses/service_controller.go @@ -19,19 +19,21 @@ package perses import ( "context" "fmt" - "time" - "github.com/perses/perses-operator/api/v1alpha1" - "github.com/perses/perses-operator/internal/perses/common" - "github.com/perses/perses-operator/internal/subreconciler" logger "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/perses/perses-operator/api/v1alpha1" + "github.com/perses/perses-operator/internal/perses/common" + "github.com/perses/perses-operator/internal/subreconciler" ) var slog = logger.WithField("module", "service_controller") @@ -39,28 +41,32 @@ var slog = logger.WithField("module", "service_controller") func (r *PersesReconciler) reconcileService(ctx context.Context, req ctrl.Request) (*ctrl.Result, error) { perses := &v1alpha1.Perses{} - if r, err := r.getLatestPerses(ctx, req, perses); subreconciler.ShouldHaltOrRequeue(r, err) { - return r, err + if result, err := r.getLatestPerses(ctx, req, perses); subreconciler.ShouldHaltOrRequeue(result, err) { + return result, err } found := &corev1.Service{} - err := r.Get(ctx, types.NamespacedName{Name: perses.Name, Namespace: perses.Namespace}, found) - if err != nil && apierrors.IsNotFound(err) { + if err := r.Get(ctx, types.NamespacedName{Name: perses.Name, Namespace: perses.Namespace}, found); err != nil { + if !apierrors.IsNotFound(err) { + log.WithError(err).Error("Failed to get Service") + + return subreconciler.RequeueWithError(err) + } - ser, err := r.createPersesService(perses) - if err != nil { - slog.WithError(err).Error("Failed to define new Service resource for perses") + ser, err2 := r.createPersesService(perses) + if err2 != nil { + slog.WithError(err2).Error("Failed to define new Service resource for perses") meta.SetStatusCondition(&perses.Status.Conditions, metav1.Condition{Type: common.TypeAvailablePerses, Status: metav1.ConditionFalse, Reason: "Reconciling", - Message: fmt.Sprintf("Failed to create Service for the custom resource (%s): (%s)", perses.Name, err)}) + Message: fmt.Sprintf("Failed to create Service for the custom resource (%s): (%s)", perses.Name, err2)}) - if err := r.Status().Update(ctx, perses); err != nil { + if err = r.Status().Update(ctx, perses); err != nil { slog.Error(err, "Failed to update perses status") return subreconciler.RequeueWithError(err) } - return subreconciler.RequeueWithError(err) + return subreconciler.RequeueWithError(err2) } slog.Infof("Creating a new Service: Service.Namespace %s Service.Name %s", ser.Namespace, ser.Name) @@ -69,13 +75,28 @@ func (r *PersesReconciler) reconcileService(ctx context.Context, req ctrl.Reques return subreconciler.RequeueWithError(err) } - return subreconciler.RequeueWithDelay(time.Minute) - } else if err != nil { - slog.WithError(err).Error("Failed to get Service") + return subreconciler.ContinueReconciling() + } + + svc, err := r.createPersesService(perses) + if err != nil { + slog.WithError(err).Error("Failed to define new Service resource for perses") + return subreconciler.RequeueWithError(err) + } + // call update with dry run to fill out fields that are also returned via the k8s api + if err = r.Update(ctx, svc, client.DryRunAll); err != nil { + slog.Error(err, "Failed to update Service with dry run") return subreconciler.RequeueWithError(err) } + if !equality.Semantic.DeepEqual(found, svc) { + if err = r.Update(ctx, svc); err != nil { + slog.Error(err, "Failed to update Service") + return subreconciler.RequeueWithError(err) + } + } + return subreconciler.ContinueReconciling() } @@ -105,7 +126,7 @@ func (r *PersesReconciler) createPersesService( Name: "http", Port: 8080, Protocol: corev1.ProtocolTCP, - TargetPort: intstr.FromInt(8080), + TargetPort: intstr.FromInt32(8080), }}, Selector: ls, }, diff --git a/controllers/perses/statefulset_controller.go b/controllers/perses/statefulset_controller.go index ee02562..ab50c1d 100644 --- a/controllers/perses/statefulset_controller.go +++ b/controllers/perses/statefulset_controller.go @@ -21,12 +21,10 @@ import ( "fmt" "time" - "github.com/perses/perses-operator/api/v1alpha1" - "github.com/perses/perses-operator/internal/perses/common" - "github.com/perses/perses-operator/internal/subreconciler" logger "github.com/sirupsen/logrus" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/resource" @@ -34,6 +32,11 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/utils/ptr" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/perses/perses-operator/api/v1alpha1" + "github.com/perses/perses-operator/internal/perses/common" + "github.com/perses/perses-operator/internal/subreconciler" ) var stlog = logger.WithField("module", "statefulset_controller") @@ -41,8 +44,8 @@ var stlog = logger.WithField("module", "statefulset_controller") func (r *PersesReconciler) reconcileStatefulSet(ctx context.Context, req ctrl.Request) (*ctrl.Result, error) { perses := &v1alpha1.Perses{} - if r, err := r.getLatestPerses(ctx, req, perses); subreconciler.ShouldHaltOrRequeue(r, err) { - return r, err + if result, err := r.getLatestPerses(ctx, req, perses); subreconciler.ShouldHaltOrRequeue(result, err) { + return result, err } if perses.Spec.Config.Database.File == nil { @@ -62,23 +65,27 @@ func (r *PersesReconciler) reconcileStatefulSet(ctx context.Context, req ctrl.Re } found := &appsv1.StatefulSet{} - err := r.Get(ctx, types.NamespacedName{Name: perses.Name, Namespace: perses.Namespace}, found) - if err != nil && apierrors.IsNotFound(err) { + if err := r.Get(ctx, types.NamespacedName{Name: perses.Name, Namespace: perses.Namespace}, found); err != nil { + if !apierrors.IsNotFound(err) { + stlog.WithError(err).Error("Failed to get StatefulSet") + + return subreconciler.RequeueWithError(err) + } - dep, err := r.createPersesStatefulSet(perses) - if err != nil { - stlog.WithError(err).Error("Failed to define new StatefulSet resource for perses") + dep, err2 := r.createPersesStatefulSet(perses) + if err2 != nil { + stlog.WithError(err2).Error("Failed to define new StatefulSet resource for perses") meta.SetStatusCondition(&perses.Status.Conditions, metav1.Condition{Type: common.TypeAvailablePerses, Status: metav1.ConditionFalse, Reason: "Reconciling", Message: fmt.Sprintf("Failed to create StatefulSet for the custom resource (%s): (%s)", perses.Name, err)}) - if err := r.Status().Update(ctx, perses); err != nil { + if err = r.Status().Update(ctx, perses); err != nil { stlog.Error(err, "Failed to update perses status") return subreconciler.RequeueWithError(err) } - return subreconciler.RequeueWithError(err) + return subreconciler.RequeueWithError(err2) } stlog.Infof("Creating a new StatefulSet: StatefulSet.Namespace %s StatefulSet.Name %s", dep.Namespace, dep.Name) @@ -88,12 +95,27 @@ func (r *PersesReconciler) reconcileStatefulSet(ctx context.Context, req ctrl.Re } return subreconciler.RequeueWithDelay(time.Minute) - } else if err != nil { - stlog.WithError(err).Error("Failed to get StatefulSet") + } + + sts, err := r.createPersesStatefulSet(perses) + if err != nil { + stlog.WithError(err).Error("Failed to define new StatefulSet resource for perses") + return subreconciler.RequeueWithError(err) + } + // call update with dry run to fill out fields that are also returned via the k8s api + if err = r.Update(ctx, sts, client.DryRunAll); err != nil { + stlog.Error(err, "Failed to update StatefulSet with dry run") return subreconciler.RequeueWithError(err) } + if !equality.Semantic.DeepEqual(found, sts) { + if err = r.Update(ctx, sts); err != nil { + stlog.Error(err, "Failed to update StatefulSet") + return subreconciler.RequeueWithError(err) + } + } + return subreconciler.ContinueReconciling() }