controllers/gitserver/gitserver_controller.go (105 lines of code) (raw):
package gitserver
import (
"context"
"fmt"
"time"
coreV1 "k8s.io/api/core/v1"
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
codebaseApi "github.com/epam/edp-codebase-operator/v2/api/v1"
"github.com/epam/edp-codebase-operator/v2/pkg/model"
codebasepredicate "github.com/epam/edp-codebase-operator/v2/pkg/predicate"
)
const (
defaultRequeueTime = time.Second * 30
successRequeueTime = time.Minute * 30
)
func NewReconcileGitServer(c client.Client) *ReconcileGitServer {
return &ReconcileGitServer{
client: c,
}
}
type ReconcileGitServer struct {
client client.Client
}
func (r *ReconcileGitServer) SetupWithManager(mgr ctrl.Manager) error {
pause := codebasepredicate.NewPause(ctrl.Log.WithName("git-server-pause-predicate"))
err := ctrl.NewControllerManagedBy(mgr).
For(&codebaseApi.GitServer{}, builder.WithPredicates(pause)).
Complete(r)
if err != nil {
return fmt.Errorf("failed to build GitServer controller: %w", err)
}
return nil
}
//+kubebuilder:rbac:groups=v2.edp.epam.com,namespace=placeholder,resources=gitservers,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=v2.edp.epam.com,namespace=placeholder,resources=gitservers/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=v2.edp.epam.com,namespace=placeholder,resources=gitservers/finalizers,verbs=update
//+kubebuilder:rbac:groups="",namespace=placeholder,resources=secrets,verbs=get;list;watch
//+kubebuilder:rbac:groups="networking.k8s.io",namespace=placeholder,resources=ingresses,verbs=get;list;watch;create
//+kubebuilder:rbac:groups="route.openshift.io",namespace=placeholder,resources=routes,verbs=get;list;watch;create
// Reconcile reads that state of the cluster for a GitServer object and makes changes based on the state.
func (r *ReconcileGitServer) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := ctrl.LoggerFrom(ctx)
log.Info("Reconciling GitServer")
instance := &codebaseApi.GitServer{}
if err := r.client.Get(ctx, request.NamespacedName, instance); err != nil {
if k8sErrors.IsNotFound(err) {
return reconcile.Result{}, nil
}
return reconcile.Result{}, fmt.Errorf("failed to fetch resource %q: %w", request.NamespacedName, err)
}
oldStatus := instance.Status
gitServer := model.ConvertToGitServer(instance)
if err := r.checkConnectionToGitServer(ctx, gitServer); err != nil {
instance.Status.SetFailed(err.Error())
instance.Status.Connected = false
if statusErr := r.updateGitServerStatus(ctx, instance, oldStatus); statusErr != nil {
return reconcile.Result{}, statusErr
}
log.Error(err, "GitServer connection is not established")
return reconcile.Result{RequeueAfter: defaultRequeueTime}, nil
}
instance.Status.Connected = true
if err := NewCreateEventListener(r.client).ServeRequest(ctx, instance); err != nil {
log.Error(err, "Failed to create EventListener")
instance.Status.SetFailed(err.Error())
if statusErr := r.updateGitServerStatus(ctx, instance, oldStatus); statusErr != nil {
return reconcile.Result{}, statusErr
}
return reconcile.Result{RequeueAfter: defaultRequeueTime}, nil
}
instance.Status.SetSuccess()
if err := r.updateGitServerStatus(ctx, instance, oldStatus); err != nil {
return reconcile.Result{}, err
}
log.Info("Reconciling GitServer has been finished")
return reconcile.Result{
RequeueAfter: successRequeueTime,
}, nil
}
func (r *ReconcileGitServer) checkConnectionToGitServer(ctx context.Context, gitServer *model.GitServer) error {
log := ctrl.LoggerFrom(ctx)
log.Info("Start CheckConnectionToGitServer method", "host", gitServer.GitHost)
sshSecret := &coreV1.Secret{}
err := r.client.Get(ctx, types.NamespacedName{
Namespace: gitServer.Namespace,
Name: gitServer.NameSshKeySecret,
}, sshSecret)
if err != nil {
return fmt.Errorf("failed to get secret %s: %w", gitServer.NameSshKeySecret, err)
}
sshData := extractSshData(gitServer, sshSecret)
log.Info("Data from request is extracted", "host", sshData.Host, "port", sshData.Port)
if err = checkGitServerConnection(sshData, log); err != nil {
return fmt.Errorf("failed to establish connection to Git Server %s: %w", sshData.Host, err)
}
log.Info("Git server connection is established", "host", sshData.Host)
return nil
}
func (r *ReconcileGitServer) updateGitServerStatus(ctx context.Context, gitServer *codebaseApi.GitServer, oldStatus codebaseApi.GitServerStatus) error {
if gitServer.Status == oldStatus {
return nil
}
if err := r.client.Status().Update(ctx, gitServer); err != nil {
return fmt.Errorf("failed to update GitServer status: %w", err)
}
return nil
}