func (o *Operator) makeDeploymentConfigAndDeps(apiObject *api.ArangoDeployment) (deployment.Config, deployment.Dependencies) {
	cfg := deployment.Config{
		ServiceAccount: o.Config.ServiceAccount,
		OperatorImage:  o.Config.OperatorImage,
		ArangoImage:    o.ArangoImage,
		AllowChaos:     o.Config.AllowChaos,
		Scope:          o.Scope,
	}
	deps := deployment.Dependencies{
		Log: o.Dependencies.LogService.MustGetLogger(logging.LoggerNameDeployment).With().
			Str("deployment", apiObject.GetName()).
			Logger(),
		KubeCli:           o.Dependencies.KubeCli,
		KubeMonitoringCli: o.Dependencies.KubeMonitoringCli,
		KubeExtCli:        o.Dependencies.KubeExtCli,
		DatabaseCRCli:     o.Dependencies.CRCli,
		EventRecorder:     o.Dependencies.EventRecorder,
	}
	return cfg, deps
}
makeDeploymentConfigAndDeps creates a Config & Dependencies object for a new Deployment.
package operator
import (
	deploymentType "github.com/arangodb/kube-arangodb/pkg/apis/deployment"
	"github.com/arangodb/kube-arangodb/pkg/logging"
	"github.com/arangodb/kube-arangodb/pkg/util/errors"
	kwatch "k8s.io/apimachinery/pkg/watch"
	"k8s.io/client-go/tools/cache"
	api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
	"github.com/arangodb/kube-arangodb/pkg/deployment"
	"github.com/arangodb/kube-arangodb/pkg/metrics"
	"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
)
var (
	deploymentsCreated  = metrics.MustRegisterCounter("controller", "deployments_created", "Number of deployments that have been created")
	deploymentsDeleted  = metrics.MustRegisterCounter("controller", "deployments_deleted", "Number of deployments that have been deleted")
	deploymentsFailed   = metrics.MustRegisterCounter("controller", "deployments_failed", "Number of deployments that have failed")
	deploymentsModified = metrics.MustRegisterCounter("controller", "deployments_modified", "Number of deployment modifications")
	deploymentsCurrent  = metrics.MustRegisterGauge("controller", "deployments", "Number of deployments currently being managed")
)
func (o *Operator) runDeployments(stop <-chan struct{}) {
	rw := k8sutil.NewResourceWatcher(
		o.log,
		o.Dependencies.CRCli.DatabaseV1().RESTClient(),
		deploymentType.ArangoDeploymentResourcePlural,
		o.Config.Namespace,
		&api.ArangoDeployment{},
		cache.ResourceEventHandlerFuncs{
			AddFunc:    o.onAddArangoDeployment,
			UpdateFunc: o.onUpdateArangoDeployment,
			DeleteFunc: o.onDeleteArangoDeployment,
		})
	o.Dependencies.DeploymentProbe.SetReady()
	rw.Run(stop)
}
func (o *Operator) onAddArangoDeployment(obj interface{}) {
	o.Dependencies.LivenessProbe.Lock()
	defer o.Dependencies.LivenessProbe.Unlock()
	apiObject := obj.(*api.ArangoDeployment)
	o.log.Debug().
		Str("name", apiObject.GetObjectMeta().GetName()).
		Msg("ArangoDeployment added")
	o.syncArangoDeployment(apiObject)
}
func (o *Operator) onUpdateArangoDeployment(oldObj, newObj interface{}) {
	o.Dependencies.LivenessProbe.Lock()
	defer o.Dependencies.LivenessProbe.Unlock()
	apiObject := newObj.(*api.ArangoDeployment)
	o.log.Debug().
		Str("name", apiObject.GetObjectMeta().GetName()).
		Msg("ArangoDeployment updated")
	o.syncArangoDeployment(apiObject)
}
func (o *Operator) onDeleteArangoDeployment(obj interface{}) {
	o.Dependencies.LivenessProbe.Lock()
	defer o.Dependencies.LivenessProbe.Unlock()
	log := o.log
	apiObject, ok := obj.(*api.ArangoDeployment)
	if !ok {
		tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
		if !ok {
			log.Error().Interface("event-object", obj).Msg("unknown object from ArangoDeployment delete event")
			return
		}
		apiObject, ok = tombstone.Obj.(*api.ArangoDeployment)
		if !ok {
			log.Error().Interface("event-object", obj).Msg("Tombstone contained object that is not an ArangoDeployment")
			return
		}
	}
	log.Debug().
		Str("name", apiObject.GetObjectMeta().GetName()).
		Msg("ArangoDeployment deleted")
	ev := &Event{
		Type:       kwatch.Deleted,
		Deployment: apiObject,
	}
	err := o.handleDeploymentEvent(ev)
	if err != nil {
		log.Warn().Err(err).Msg("Failed to handle event")
	}
}
func (o *Operator) syncArangoDeployment(apiObject *api.ArangoDeployment) {
	ev := &Event{
		Type:       kwatch.Added,
		Deployment: apiObject,
	}
	if _, ok := o.deployments[apiObject.Name]; ok {
		ev.Type = kwatch.Modified
	}
	err := o.handleDeploymentEvent(ev)
	if err != nil {
		o.log.Warn().Err(err).Msg("Failed to handle event")
	}
}
func (o *Operator) handleDeploymentEvent(event *Event) error {
	apiObject := event.Deployment
	if apiObject.Status.Phase.IsFailed() {
		deploymentsFailed.Inc()
		if event.Type == kwatch.Deleted {
			delete(o.deployments, apiObject.Name)
			return nil
		}
		return errors.WithStack(errors.Newf("ignore failed deployment (%s). Please delete its CR", apiObject.Name))
	}
	switch event.Type {
	case kwatch.Added:
		if _, ok := o.deployments[apiObject.Name]; ok {
			return errors.WithStack(errors.Newf("unsafe state. deployment (%s) was created before but we received event (%s)", apiObject.Name, event.Type))
		}
		apiObject.Spec.SetDefaults(apiObject.GetName())
		if err := apiObject.Spec.Validate(); err != nil {
			return errors.WithStack(errors.Wrapf(err, "invalid deployment spec. please fix the following problem with the deployment spec: %v", err))
		}
		cfg, deps := o.makeDeploymentConfigAndDeps(apiObject)
		nc, err := deployment.New(cfg, deps, apiObject)
		if err != nil {
			return errors.WithStack(errors.Newf("failed to create deployment: %s", err))
		}
		o.deployments[apiObject.Name] = nc
		deploymentsCreated.Inc()
		deploymentsCurrent.Set(float64(len(o.deployments)))
	case kwatch.Modified:
		depl, ok := o.deployments[apiObject.Name]
		if !ok {
			return errors.WithStack(errors.Newf("unsafe state. deployment (%s) was never created but we received event (%s)", apiObject.Name, event.Type))
		}
		depl.Update(apiObject)
		deploymentsModified.Inc()
	case kwatch.Deleted:
		depl, ok := o.deployments[apiObject.Name]
		if !ok {
			return errors.WithStack(errors.Newf("unsafe state. deployment (%s) was never created but we received event (%s)", apiObject.Name, event.Type))
		}
		depl.Delete()
		delete(o.deployments, apiObject.Name)
		deploymentsDeleted.Inc()
		deploymentsCurrent.Set(float64(len(o.deployments)))
	}
	return nil
}