| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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 controllers |
| |
| import ( |
| "context" |
| "reflect" |
| "time" |
| |
| "github.com/apache/lucene-solr-operator/controllers/util" |
| "github.com/go-logr/logr" |
| "k8s.io/apimachinery/pkg/api/errors" |
| metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
| "k8s.io/apimachinery/pkg/runtime" |
| "k8s.io/apimachinery/pkg/types" |
| ctrl "sigs.k8s.io/controller-runtime" |
| "sigs.k8s.io/controller-runtime/pkg/client" |
| "sigs.k8s.io/controller-runtime/pkg/reconcile" |
| |
| solrv1beta1 "github.com/apache/lucene-solr-operator/api/v1beta1" |
| ) |
| |
| // SolrCollectionAliasReconciler reconciles a SolrCollectionAlias object |
| type SolrCollectionAliasReconciler struct { |
| client.Client |
| Log logr.Logger |
| Scheme *runtime.Scheme |
| } |
| |
| // +kubebuilder:rbac:groups=solr.apache.org,resources=solrcollectionaliases,verbs=get;list;watch;create;update;patch;delete |
| // +kubebuilder:rbac:groups=solr.apache.org,resources=solrcollectionaliases/status,verbs=get;update;patch |
| // +kubebuilder:rbac:groups=solr.apache.org,resources=solrcloud,verbs=get;list;watch |
| // +kubebuilder:rbac:groups=solr.apache.org,resources=solrcloud/status,verbs=get |
| |
| func (r *SolrCollectionAliasReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { |
| _ = context.Background() |
| _ = r.Log.WithValues("solrcollectionalias", req.NamespacedName) |
| |
| alias := &solrv1beta1.SolrCollectionAlias{} |
| aliasFinalizer := "alias.finalizers.bloomberg.com" |
| |
| err := r.Get(context.TODO(), req.NamespacedName, alias) |
| if err != nil { |
| if errors.IsNotFound(err) { |
| // Object not found, return. Created objects are automatically garbage collected. |
| // For additional cleanup logic use finalizers. |
| return reconcile.Result{}, nil |
| } |
| // Error reading the object - requeue the req. |
| return reconcile.Result{}, err |
| } |
| |
| oldStatus := alias.Status.DeepCopy() |
| requeueOrNot := reconcile.Result{Requeue: true, RequeueAfter: time.Second * 5} |
| |
| solrCloud := &solrv1beta1.SolrCloud{} |
| err = r.Get(context.TODO(), types.NamespacedName{Namespace: alias.Namespace, Name: alias.Spec.SolrCloud}, solrCloud) |
| if err != nil { |
| return reconcile.Result{}, err |
| } |
| |
| aliasCreationStatus := reconcileSolrCollectionAlias(r, alias, solrCloud, alias.Name, alias.Spec.AliasType, alias.Spec.Collections) |
| |
| if err != nil { |
| r.Log.Error(err, "Error while creating SolrCloud alias") |
| } |
| |
| if alias.ObjectMeta.DeletionTimestamp.IsZero() { |
| // The object is not being deleted, so if it does not have our finalizer, |
| // then lets add the finalizer and update the object |
| if !util.ContainsString(alias.ObjectMeta.Finalizers, aliasFinalizer) { |
| alias.ObjectMeta.Finalizers = append(alias.ObjectMeta.Finalizers, aliasFinalizer) |
| if err := r.Update(context.Background(), alias); err != nil { |
| return reconcile.Result{}, err |
| } |
| } |
| } else { |
| if util.ContainsString(alias.ObjectMeta.Finalizers, aliasFinalizer) && aliasCreationStatus { |
| r.Log.Info("Deleting Solr collection alias", "cloud", alias.Spec.SolrCloud, "namespace", alias.Namespace, "Collection Name", alias.Name) |
| // our finalizer is present, along with the associated SolrCloud and alias lets delete alias |
| delete, err := util.DeleteCollectionAlias(solrCloud, alias.Name) |
| if err != nil { |
| r.Log.Error(err, "Failed to delete Solr collection") |
| return reconcile.Result{}, err |
| } |
| |
| r.Log.Info("Deleted Solr collection", "cloud", alias.Spec.SolrCloud, "namespace", alias.Namespace, "Alias", alias.Name, "Deleted", delete) |
| |
| } |
| |
| // remove our finalizer from the list and update it. |
| alias.ObjectMeta.Finalizers = util.RemoveString(alias.ObjectMeta.Finalizers, aliasFinalizer) |
| if err := r.Update(context.Background(), alias); err != nil { |
| return reconcile.Result{}, err |
| } |
| } |
| |
| if alias.Status.CreatedTime == nil { |
| now := metav1.Now() |
| alias.Status.CreatedTime = &now |
| alias.Status.Created = aliasCreationStatus |
| } |
| |
| if !reflect.DeepEqual(oldStatus, alias.Status) { |
| r.Log.Info("Updating status for collection alias", "alias", alias, "namespace", alias.Namespace, "name", alias.Name) |
| err = r.Status().Update(context.TODO(), alias) |
| } |
| |
| if aliasCreationStatus { |
| requeueOrNot = reconcile.Result{} |
| } |
| |
| return requeueOrNot, nil |
| } |
| |
| func reconcileSolrCollectionAlias(r *SolrCollectionAliasReconciler, alias *solrv1beta1.SolrCollectionAlias, cloud *solrv1beta1.SolrCloud, aliasName string, aliasType string, collections []string) (aliasCreationStatus bool) { |
| success, aliasCollections := util.CurrentCollectionAliasDetails(cloud, aliasName) |
| |
| // If not created, or if alias status differs from spec requirements create alias |
| if !success || !reflect.DeepEqual(alias.Status.Collections, aliasCollections) { |
| r.Log.Info("Applying collection alias", "alias", alias) |
| err := util.CreateCollectionAlias(cloud, aliasName, aliasType, collections) |
| if err == nil { |
| alias.Status.Created = true |
| alias.Status.Collections = collections |
| return alias.Status.Created |
| } |
| } |
| |
| return alias.Status.Created |
| } |
| |
| func (r *SolrCollectionAliasReconciler) SetupWithManager(mgr ctrl.Manager) error { |
| return ctrl.NewControllerManagedBy(mgr). |
| For(&solrv1beta1.SolrCollectionAlias{}). |
| Complete(r) |
| } |