main.go (223 lines of code) (raw):
package main
import (
"flag"
"os"
_ "k8s.io/client-go/plugin/pkg/client/auth"
"github.com/go-logr/logr"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
buildInfo "github.com/epam/edp-common/pkg/config"
keycloakApi "github.com/epam/edp-keycloak-operator/api/v1"
gerritApi "github.com/epam/edp-gerrit-operator/v2/api/v1"
gerritContr "github.com/epam/edp-gerrit-operator/v2/controllers/gerrit"
"github.com/epam/edp-gerrit-operator/v2/controllers/gerritgroup"
"github.com/epam/edp-gerrit-operator/v2/controllers/gerritgroupmember"
"github.com/epam/edp-gerrit-operator/v2/controllers/gerritproject"
"github.com/epam/edp-gerrit-operator/v2/controllers/gerritprojectaccess"
"github.com/epam/edp-gerrit-operator/v2/controllers/gerritreplicationconfig"
"github.com/epam/edp-gerrit-operator/v2/controllers/helper"
"github.com/epam/edp-gerrit-operator/v2/controllers/merge_request"
)
var (
scheme = runtime.NewScheme()
setupLog = ctrl.Log.WithName("setup")
)
const (
serverPort = 9443
gerritOperatorLock = "edp-gerrit-operator-lock"
gitWorkDirEnv = "GIT_WORK_DIR"
gitWorkDirDefault = "/tmp/git_tmp"
)
func main() {
var (
metricsAddr string
enableLeaderElection bool
probeAddr string
)
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
flag.BoolVar(&enableLeaderElection, "leader-elect", helper.RunningInCluster(),
"Enable leader election for controller manager. "+
"Enabling this will ensure there is only one active controller manager.")
mode, err := helper.GetDebugMode()
if err != nil {
setupLog.Error(err, "unable to get debug mode value")
os.Exit(1)
}
opts := zap.Options{
Development: mode,
}
opts.BindFlags(flag.CommandLine)
flag.Parse()
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
logBuildInfo(setupLog)
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
utilruntime.Must(gerritApi.AddToScheme(scheme))
utilruntime.Must(keycloakApi.AddToScheme(scheme))
mgr, err := initManager(metricsAddr, probeAddr, enableLeaderElection)
if err != nil {
setupLog.Error(err, "unable to init manager")
os.Exit(1)
}
if err = initControllers(mgr, ctrl.Log.WithName("controllers")); err != nil {
setupLog.Error(err, "error during controllers init")
os.Exit(1)
}
if err = mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
setupLog.Error(err, "unable to set up health check")
os.Exit(1)
}
if err = mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {
setupLog.Error(err, "unable to set up ready check")
os.Exit(1)
}
setupLog.Info("starting manager")
err = mgr.Start(ctrl.SetupSignalHandler())
if err != nil {
setupLog.Error(err, "problem running manager")
os.Exit(1)
}
}
func initManager(metricsAddr, probeAddr string, enableLeaderElection bool) (ctrl.Manager, error) {
ns, err := helper.GetWatchNamespace()
if err != nil {
return nil, errors.Wrap(err, "unable to get watch namespace")
}
cfg := ctrl.GetConfigOrDie()
mgr, err := ctrl.NewManager(cfg, ctrl.Options{
Scheme: scheme,
MetricsBindAddress: metricsAddr,
HealthProbeBindAddress: probeAddr,
Port: serverPort,
LeaderElection: enableLeaderElection,
LeaderElectionID: gerritOperatorLock,
MapperProvider: func(_ *rest.Config) (meta.RESTMapper, error) {
return apiutil.NewDynamicRESTMapper(cfg)
},
Namespace: ns,
})
if err != nil {
return nil, errors.Wrap(err, "unable to start manager")
}
return mgr, nil
}
func initControllers(mgr ctrl.Manager, ctrlLog logr.Logger) error {
controllersInitFuncs := controllerConstructors()
for _, cf := range controllersInitFuncs {
gCtrl, err := cf.Func(mgr.GetClient(), mgr.GetScheme(), ctrlLog)
if err != nil {
return errors.Wrapf(err, "unable to create controller, controller: %s", cf.ControllerName)
}
if err = gCtrl.SetupWithManager(mgr); err != nil {
return errors.Wrapf(err, "unable to create controller, controller: %s", cf.ControllerName)
}
}
setupers := prepareControllers()
for i := range setupers {
setuper := setupers[i]
if err := setuper.PrepareFn(mgr, ctrlLog); err != nil {
return err
}
}
return nil
}
func controllerConstructors() []helper.InitFunc {
return []helper.InitFunc{
{
Func: gerritContr.NewReconcileGerrit,
ControllerName: "gerrit",
},
{
Func: gerritreplicationconfig.NewReconcileGerritReplicationConfig,
ControllerName: "gerrit-replication-config",
},
{
Func: gerritgroup.NewReconcile,
ControllerName: "gerrit-group",
},
{
Func: gerritprojectaccess.NewReconcile,
ControllerName: "gerrit-project-access",
},
{
Func: gerritgroupmember.NewReconcile,
ControllerName: "gerrit-group-member",
},
}
}
type prepareController struct {
PrepareFn func(manager ctrl.Manager, ctrlLog logr.Logger) error
ControllerName string
}
func prepareControllers() []prepareController {
return []prepareController{
{
ControllerName: "gerrit-merge-request",
PrepareFn: prepareMergeRequestReconciler,
},
{
ControllerName: "gerrit-project",
PrepareFn: prepareGerritProjectReconciler,
},
}
}
func prepareMergeRequestReconciler(mgr ctrl.Manager, ctrlLog logr.Logger) error {
workDirectoryOption, err := mergerequest.PrepareWorkDirectoryOption(getEnvDefault(gitWorkDirEnv, gitWorkDirDefault))
if err != nil {
return nil
}
gerritServiceOption, err := mergerequest.PrepareGerritServiceOption(mgr.GetClient(), helper.GetPlatformTypeEnv(),
mgr.GetScheme())
if err != nil {
return err
}
mergeRequestReconcilerOpts := []mergerequest.OptionFunc{
workDirectoryOption,
gerritServiceOption,
}
mergeRequestReconciler := mergerequest.NewReconcile(mgr.GetClient(), ctrlLog, mergeRequestReconcilerOpts...)
err = mergeRequestReconciler.SetupWithManager(mgr)
if err != nil {
return err
}
return nil
}
func prepareGerritProjectReconciler(manager ctrl.Manager, ctrlLog logr.Logger) error {
syncInterval := gerritproject.SyncInterval()
gerritProjectReconciler, err := gerritproject.NewReconcile(manager.GetClient(), manager.GetScheme(), ctrlLog)
if err != nil {
return err
}
err = gerritProjectReconciler.SetupWithManager(manager, syncInterval)
if err != nil {
return err
}
return nil
}
func logBuildInfo(logger logr.Logger) {
v := buildInfo.Get()
logger.Info("Starting the Gerrit Operator",
"version", v.Version,
"git-commit", v.GitCommit,
"git-tag", v.GitTag,
"build-date", v.BuildDate,
"go-version", v.Go,
"go-client", v.KubectlVersion,
"platform", v.Platform,
)
}
func getEnvDefault(key, _default string) string {
val := os.Getenv(key)
if val == "" {
return _default
}
return val
}