github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/cmd/director/main.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"crypto/tls"
     6  	"encoding/json"
     7  	"github.com/kyma-incubator/compass/components/director/internal/domain/destination"
     8  	"net/http"
     9  	"net/url"
    10  	"os"
    11  	"time"
    12  
    13  	"github.com/kyma-incubator/compass/components/director/internal/domain/destination/destinationcreator"
    14  	"github.com/kyma-incubator/compass/components/director/internal/domain/formationconstraint/operators"
    15  
    16  	"github.com/kyma-incubator/compass/components/director/internal/domain/formationconstraint"
    17  	"github.com/kyma-incubator/compass/components/director/internal/domain/formationtemplateconstraintreferences"
    18  
    19  	"github.com/kyma-incubator/compass/components/director/pkg/applicationtenancy"
    20  
    21  	databuilder "github.com/kyma-incubator/compass/components/director/internal/domain/webhook/datainputbuilder"
    22  
    23  	"github.com/kyma-incubator/compass/components/director/internal/domain/formationassignment"
    24  	"github.com/kyma-incubator/compass/components/director/internal/formationmapping"
    25  
    26  	"github.com/kyma-incubator/compass/components/director/internal/domain/apptemplate"
    27  
    28  	authpkg "github.com/kyma-incubator/compass/components/director/pkg/auth"
    29  	webhookclient "github.com/kyma-incubator/compass/components/director/pkg/webhook_client"
    30  
    31  	"github.com/kyma-incubator/compass/components/director/pkg/retry"
    32  
    33  	runtimectx "github.com/kyma-incubator/compass/components/director/internal/domain/runtime_context"
    34  
    35  	"github.com/kyma-incubator/compass/components/director/internal/domain/formationtemplate"
    36  
    37  	"github.com/kyma-incubator/compass/components/director/internal/domain/formation"
    38  	"github.com/kyma-incubator/compass/components/director/internal/domain/subscription"
    39  
    40  	kube "github.com/kyma-incubator/compass/components/director/pkg/kubernetes"
    41  	v1 "k8s.io/api/core/v1"
    42  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    43  	"k8s.io/apimachinery/pkg/watch"
    44  	"k8s.io/client-go/kubernetes"
    45  
    46  	"github.com/kyma-incubator/compass/components/director/pkg/accessstrategy"
    47  	"github.com/kyma-incubator/compass/components/director/pkg/certloader"
    48  
    49  	"github.com/kyma-incubator/compass/components/director/internal/info"
    50  
    51  	"github.com/kyma-incubator/compass/components/director/internal/authenticator/claims"
    52  	mp_authenticator "github.com/kyma-incubator/compass/components/director/pkg/auth-middleware"
    53  
    54  	gqlgen "github.com/99designs/gqlgen/graphql"
    55  	"github.com/99designs/gqlgen/graphql/handler"
    56  	"github.com/99designs/gqlgen/graphql/playground"
    57  	"github.com/dlmiddlecote/sqlstats"
    58  	"github.com/gorilla/mux"
    59  	dataloader "github.com/kyma-incubator/compass/components/director/internal/dataloaders"
    60  	"github.com/kyma-incubator/compass/components/director/internal/domain"
    61  	"github.com/kyma-incubator/compass/components/director/internal/domain/api"
    62  	"github.com/kyma-incubator/compass/components/director/internal/domain/application"
    63  	"github.com/kyma-incubator/compass/components/director/internal/domain/auth"
    64  	"github.com/kyma-incubator/compass/components/director/internal/domain/bundle"
    65  	"github.com/kyma-incubator/compass/components/director/internal/domain/bundleinstanceauth"
    66  	"github.com/kyma-incubator/compass/components/director/internal/domain/bundlereferences"
    67  	"github.com/kyma-incubator/compass/components/director/internal/domain/document"
    68  	"github.com/kyma-incubator/compass/components/director/internal/domain/eventdef"
    69  	"github.com/kyma-incubator/compass/components/director/internal/domain/fetchrequest"
    70  	"github.com/kyma-incubator/compass/components/director/internal/domain/integrationsystem"
    71  	"github.com/kyma-incubator/compass/components/director/internal/domain/label"
    72  	"github.com/kyma-incubator/compass/components/director/internal/domain/labeldef"
    73  	"github.com/kyma-incubator/compass/components/director/internal/domain/oauth20"
    74  	"github.com/kyma-incubator/compass/components/director/internal/domain/onetimetoken"
    75  	"github.com/kyma-incubator/compass/components/director/internal/domain/runtime"
    76  	"github.com/kyma-incubator/compass/components/director/internal/domain/scenarioassignment"
    77  	"github.com/kyma-incubator/compass/components/director/internal/domain/schema"
    78  	"github.com/kyma-incubator/compass/components/director/internal/domain/spec"
    79  	"github.com/kyma-incubator/compass/components/director/internal/domain/tenant"
    80  	"github.com/kyma-incubator/compass/components/director/internal/domain/version"
    81  	"github.com/kyma-incubator/compass/components/director/internal/domain/webhook"
    82  	errorpresenter "github.com/kyma-incubator/compass/components/director/internal/error_presenter"
    83  	"github.com/kyma-incubator/compass/components/director/internal/features"
    84  	"github.com/kyma-incubator/compass/components/director/internal/healthz"
    85  	"github.com/kyma-incubator/compass/components/director/internal/metrics"
    86  	"github.com/kyma-incubator/compass/components/director/internal/model"
    87  	"github.com/kyma-incubator/compass/components/director/internal/packagetobundles"
    88  	panichandler "github.com/kyma-incubator/compass/components/director/internal/panic_handler"
    89  	"github.com/kyma-incubator/compass/components/director/internal/statusupdate"
    90  	"github.com/kyma-incubator/compass/components/director/internal/uid"
    91  	pkgadapters "github.com/kyma-incubator/compass/components/director/pkg/adapters"
    92  	configprovider "github.com/kyma-incubator/compass/components/director/pkg/config"
    93  	"github.com/kyma-incubator/compass/components/director/pkg/correlation"
    94  	"github.com/kyma-incubator/compass/components/director/pkg/executor"
    95  	"github.com/kyma-incubator/compass/components/director/pkg/graphql"
    96  	timeouthandler "github.com/kyma-incubator/compass/components/director/pkg/handler"
    97  	"github.com/kyma-incubator/compass/components/director/pkg/header"
    98  	httputil "github.com/kyma-incubator/compass/components/director/pkg/http"
    99  	"github.com/kyma-incubator/compass/components/director/pkg/inputvalidation"
   100  	"github.com/kyma-incubator/compass/components/director/pkg/log"
   101  	"github.com/kyma-incubator/compass/components/director/pkg/normalizer"
   102  	"github.com/kyma-incubator/compass/components/director/pkg/operation"
   103  	"github.com/kyma-incubator/compass/components/director/pkg/operation/k8s"
   104  	panicrecovery "github.com/kyma-incubator/compass/components/director/pkg/panic_recovery"
   105  	"github.com/kyma-incubator/compass/components/director/pkg/persistence"
   106  	"github.com/kyma-incubator/compass/components/director/pkg/resource"
   107  	"github.com/kyma-incubator/compass/components/director/pkg/scenario"
   108  	"github.com/kyma-incubator/compass/components/director/pkg/scope"
   109  	"github.com/kyma-incubator/compass/components/director/pkg/signal"
   110  	"github.com/kyma-incubator/compass/components/operations-controller/client"
   111  	"github.com/pkg/errors"
   112  	"github.com/prometheus/client_golang/prometheus"
   113  	"github.com/prometheus/client_golang/prometheus/promhttp"
   114  	"github.com/vrischmann/envconfig"
   115  	cr "sigs.k8s.io/controller-runtime"
   116  )
   117  
   118  const envPrefix = "APP"
   119  
   120  type config struct {
   121  	Address string `envconfig:"default=127.0.0.1:3000"`
   122  
   123  	InternalAddress string `envconfig:"default=127.0.0.1:3002"`
   124  	AppURL          string `envconfig:"APP_URL"`
   125  
   126  	ClientTimeout time.Duration `envconfig:"default=105s"`
   127  	ServerTimeout time.Duration `envconfig:"default=110s"`
   128  
   129  	Database                persistence.DatabaseConfig
   130  	APIEndpoint             string `envconfig:"default=/graphql"`
   131  	OperationPath           string `envconfig:"default=/operation"`
   132  	LastOperationPath       string `envconfig:"default=/last_operation"`
   133  	PlaygroundAPIEndpoint   string `envconfig:"default=/graphql"`
   134  	ConfigurationFile       string
   135  	ConfigurationFileReload time.Duration `envconfig:"default=1m"`
   136  
   137  	Log log.Config
   138  
   139  	MetricsAddress string `envconfig:"default=127.0.0.1:3003"`
   140  	MetricsConfig  metrics.Config
   141  
   142  	JWKSEndpoint          string        `envconfig:"default=file://hack/default-jwks.json"`
   143  	JWKSSyncPeriod        time.Duration `envconfig:"default=5m"`
   144  	AllowJWTSigningNone   bool          `envconfig:"default=false"`
   145  	ClientIDHTTPHeaderKey string        `envconfig:"default=client_user,APP_CLIENT_ID_HTTP_HEADER"`
   146  
   147  	RuntimeJWKSCachePeriod time.Duration `envconfig:"default=5m"`
   148  
   149  	PairingAdapterCfg configprovider.PairingAdapterConfig
   150  
   151  	OneTimeToken onetimetoken.Config
   152  	OAuth20      oauth20.Config
   153  
   154  	Features features.Config
   155  
   156  	SelfRegConfig configprovider.SelfRegConfig
   157  
   158  	OperationsNamespace string `envconfig:"default=compass-system"`
   159  
   160  	DisableAsyncMode bool `envconfig:"default=false"`
   161  
   162  	HealthConfig healthz.Config `envconfig:"APP_HEALTH_CONFIG_INDICATORS"`
   163  
   164  	ReadyConfig healthz.ReadyConfig
   165  
   166  	InfoConfig info.Config
   167  
   168  	FormationMappingCfg formationmapping.Config
   169  
   170  	DataloaderMaxBatch int           `envconfig:"default=200"`
   171  	DataloaderWait     time.Duration `envconfig:"default=10ms"`
   172  
   173  	CertLoaderConfig certloader.Config
   174  
   175  	SubscriptionConfig subscription.Config
   176  
   177  	TenantOnDemandConfig tenant.FetchOnDemandAPIConfig
   178  
   179  	RetryConfig retry.Config
   180  
   181  	DestinationCreatorConfig *destinationcreator.Config
   182  
   183  	SkipSSLValidation bool `envconfig:"default=false,APP_HTTP_CLIENT_SKIP_SSL_VALIDATION"`
   184  
   185  	ORDWebhookMappings       string `envconfig:"APP_ORD_WEBHOOK_MAPPINGS"`
   186  	TenantMappingConfigPath  string `envconfig:"APP_TENANT_MAPPING_CONFIG_PATH"`
   187  	TenantMappingCallbackURL string `envconfig:"APP_TENANT_MAPPING_CALLBACK_URL"`
   188  
   189  	ExternalClientCertSecretName string `envconfig:"APP_EXTERNAL_CLIENT_CERT_SECRET_NAME"`
   190  	ExtSvcClientCertSecretName   string `envconfig:"APP_EXT_SVC_CLIENT_CERT_SECRET_NAME"`
   191  
   192  	ApplicationTemplateProductLabel string `envconfig:"APP_APPLICATION_TEMPLATE_PRODUCT_LABEL"`
   193  }
   194  
   195  func main() {
   196  	ctx, cancel := context.WithCancel(context.Background())
   197  
   198  	defer cancel()
   199  
   200  	term := make(chan os.Signal)
   201  	signal.HandleInterrupts(ctx, cancel, term)
   202  
   203  	cfg := config{}
   204  	err := envconfig.InitWithPrefix(&cfg, envPrefix)
   205  	exitOnError(err, "Error while loading app config")
   206  
   207  	ctx, err = log.Configure(ctx, &cfg.Log)
   208  	exitOnError(err, "Failed to configure Logger")
   209  	logger := log.C(ctx)
   210  
   211  	ordWebhookMapping, err := application.UnmarshalMappings(cfg.ORDWebhookMappings)
   212  	exitOnError(err, "Error while loading ORD Webhook Mappings")
   213  
   214  	tenantMappingConfig, err := apptemplate.UnmarshalTenantMappingConfig(cfg.TenantMappingConfigPath)
   215  	exitOnError(err, "Error while loading Tenant mapping config")
   216  
   217  	transact, closeFunc, err := persistence.Configure(ctx, cfg.Database)
   218  	exitOnError(err, "Error while establishing the connection to the database")
   219  
   220  	defer func() {
   221  		err := closeFunc()
   222  		exitOnError(err, "Error while closing the connection to the database")
   223  	}()
   224  
   225  	cfgProvider := createAndRunConfigProvider(ctx, cfg)
   226  
   227  	logger.Infof("Registering metrics collectors...")
   228  	metricsCollector := metrics.NewCollector(cfg.MetricsConfig)
   229  	dbStatsCollector := sqlstats.NewStatsCollector("director", transact)
   230  	prometheus.MustRegister(metricsCollector, dbStatsCollector)
   231  
   232  	k8sClient, err := kube.NewKubernetesClientSet(ctx, time.Second, time.Minute, time.Minute)
   233  	exitOnError(err, "Error while creating kubernetes client")
   234  
   235  	pa, err := getPairingAdaptersMapping(ctx, k8sClient, cfg.PairingAdapterCfg)
   236  	exitOnError(err, "Error while getting pairing adapters configuration")
   237  
   238  	startPairingAdaptersWatcher(ctx, k8sClient, pa, cfg.PairingAdapterCfg)
   239  
   240  	httpClient := &http.Client{
   241  		Timeout:   cfg.ClientTimeout,
   242  		Transport: httputil.NewCorrelationIDTransport(httputil.NewHTTPTransportWrapper(http.DefaultTransport.(*http.Transport))),
   243  		CheckRedirect: func(req *http.Request, via []*http.Request) error {
   244  			return http.ErrUseLastResponse
   245  		},
   246  	}
   247  
   248  	securedHTTPClient := authpkg.PrepareHTTPClientWithSSLValidation(cfg.ClientTimeout, cfg.SkipSSLValidation)
   249  
   250  	cfg.SelfRegConfig.ClientTimeout = cfg.ClientTimeout
   251  
   252  	internalClientTransport := &http.Transport{
   253  		TLSClientConfig: &tls.Config{
   254  			InsecureSkipVerify: cfg.SkipSSLValidation,
   255  		},
   256  	}
   257  
   258  	internalFQDNHTTPClient := &http.Client{
   259  		Timeout:   cfg.ClientTimeout,
   260  		Transport: httputil.NewCorrelationIDTransport(httputil.NewServiceAccountTokenTransport(httputil.NewHTTPTransportWrapper(http.DefaultTransport.(*http.Transport)))),
   261  	}
   262  
   263  	internalGatewayHTTPClient := &http.Client{
   264  		Timeout:   cfg.ClientTimeout,
   265  		Transport: httputil.NewCorrelationIDTransport(httputil.NewServiceAccountTokenTransportWithHeader(httputil.NewHTTPTransportWrapper(internalClientTransport), mp_authenticator.AuthorizationHeaderKey)),
   266  	}
   267  
   268  	appRepo := applicationRepo()
   269  
   270  	adminURL, err := url.Parse(cfg.OAuth20.URL)
   271  	exitOnError(err, "Error while parsing Hydra URL")
   272  
   273  	certCache, err := certloader.StartCertLoader(ctx, cfg.CertLoaderConfig)
   274  	exitOnError(err, "Failed to initialize certificate loader")
   275  
   276  	accessStrategyExecutorProvider := accessstrategy.NewDefaultExecutorProvider(certCache, cfg.ExternalClientCertSecretName, cfg.ExtSvcClientCertSecretName)
   277  	retryHTTPExecutor := retry.NewHTTPExecutor(&cfg.RetryConfig)
   278  
   279  	mtlsHTTPClient := authpkg.PrepareMTLSClientWithSSLValidation(cfg.ClientTimeout, certCache, cfg.SkipSSLValidation, cfg.ExternalClientCertSecretName)
   280  	extSvcMtlsHTTPClient := authpkg.PrepareMTLSClient(cfg.ClientTimeout, certCache, cfg.ExtSvcClientCertSecretName)
   281  	rootResolver, err := domain.NewRootResolver(
   282  		&normalizer.DefaultNormalizator{},
   283  		transact,
   284  		cfgProvider,
   285  		cfg.OneTimeToken,
   286  		cfg.OAuth20,
   287  		pa,
   288  		cfg.Features,
   289  		metricsCollector,
   290  		retryHTTPExecutor,
   291  		httpClient,
   292  		internalFQDNHTTPClient,
   293  		internalGatewayHTTPClient,
   294  		securedHTTPClient,
   295  		mtlsHTTPClient,
   296  		extSvcMtlsHTTPClient,
   297  		cfg.SelfRegConfig,
   298  		cfg.OneTimeToken.Length,
   299  		adminURL,
   300  		accessStrategyExecutorProvider,
   301  		cfg.SubscriptionConfig,
   302  		cfg.TenantOnDemandConfig,
   303  		ordWebhookMapping,
   304  		tenantMappingConfig,
   305  		cfg.TenantMappingCallbackURL,
   306  		cfg.ApplicationTemplateProductLabel,
   307  		cfg.DestinationCreatorConfig,
   308  	)
   309  	exitOnError(err, "Failed to initialize root resolver")
   310  
   311  	gqlCfg := graphql.Config{
   312  		Resolvers: rootResolver,
   313  		Directives: graphql.DirectiveRoot{
   314  			Async:                         getAsyncDirective(ctx, cfg, transact, appRepo, tenantMappingConfig),
   315  			HasScenario:                   scenario.NewDirective(transact, label.NewRepository(label.NewConverter()), bundleRepo(), bundleInstanceAuthRepo()).HasScenario,
   316  			HasScopes:                     scope.NewDirective(cfgProvider, &scope.HasScopesErrorProvider{}).VerifyScopes,
   317  			Sanitize:                      scope.NewDirective(cfgProvider, &scope.SanitizeErrorProvider{}).VerifyScopes,
   318  			Validate:                      inputvalidation.NewDirective().Validate,
   319  			SynchronizeApplicationTenancy: applicationtenancy.NewDirective(transact, tenant.NewService(tenant.NewRepository(tenant.NewConverter()), uid.NewService(), tenant.NewConverter()), applicationSvc(transact, cfg, securedHTTPClient, mtlsHTTPClient, extSvcMtlsHTTPClient, certCache, ordWebhookMapping)).SynchronizeApplicationTenancy,
   320  		},
   321  	}
   322  
   323  	executableSchema := graphql.NewExecutableSchema(gqlCfg)
   324  	claimsValidator := claims.NewValidator(transact, runtimeSvc(transact, cfg, tenantMappingConfig, httpClient, mtlsHTTPClient, extSvcMtlsHTTPClient), runtimeCtxSvc(transact, cfg, httpClient, mtlsHTTPClient, extSvcMtlsHTTPClient), appTemplateSvc(), applicationSvc(transact, cfg, httpClient, mtlsHTTPClient, extSvcMtlsHTTPClient, certCache, ordWebhookMapping), intSystemSvc(), cfg.Features.SubscriptionProviderLabelKey, cfg.Features.ConsumerSubaccountLabelKey, cfg.Features.TokenPrefix)
   325  
   326  	logger.Infof("Registering GraphQL endpoint on %s...", cfg.APIEndpoint)
   327  	authMiddleware := mp_authenticator.New(httpClient, cfg.JWKSEndpoint, cfg.AllowJWTSigningNone, cfg.ClientIDHTTPHeaderKey, claimsValidator)
   328  
   329  	if cfg.JWKSSyncPeriod != 0 {
   330  		logger.Infof("JWKS synchronization enabled. Sync period: %v", cfg.JWKSSyncPeriod)
   331  		periodicExecutor := executor.NewPeriodic(cfg.JWKSSyncPeriod, func(ctx context.Context) {
   332  			err := authMiddleware.SynchronizeJWKS(ctx)
   333  			if err != nil {
   334  				logger.WithError(err).Errorf("An error has occurred while synchronizing JWKS: %v", err)
   335  			}
   336  		})
   337  		go periodicExecutor.Run(ctx)
   338  	}
   339  
   340  	packageToBundlesMiddleware := packagetobundles.NewHandler(transact)
   341  
   342  	statusMiddleware := statusupdate.New(transact, statusupdate.NewRepository())
   343  
   344  	const (
   345  		healthzEndpoint = "/healthz"
   346  		livezEndpoint   = "/livez"
   347  		readyzEndpoint  = "/readyz"
   348  	)
   349  
   350  	mainRouter := mux.NewRouter()
   351  	mainRouter.HandleFunc("/", playground.Handler("Dataloader", cfg.PlaygroundAPIEndpoint))
   352  
   353  	mainRouter.Use(panicrecovery.NewPanicRecoveryMiddleware(), correlation.AttachCorrelationIDToContext(), log.RequestLogger(
   354  		healthzEndpoint, livezEndpoint, readyzEndpoint,
   355  	), header.AttachHeadersToContext())
   356  	presenter := errorpresenter.NewPresenter(uid.NewService())
   357  
   358  	gqlAPIRouter := mainRouter.PathPrefix(cfg.APIEndpoint).Subrouter()
   359  	gqlAPIRouter.Use(authMiddleware.Handler())
   360  	gqlAPIRouter.Use(packageToBundlesMiddleware.Handler())
   361  	gqlAPIRouter.Use(statusMiddleware.Handler())
   362  	gqlAPIRouter.Use(dataloader.HandlerBundle(rootResolver.BundlesDataloader, cfg.DataloaderMaxBatch, cfg.DataloaderWait))
   363  	gqlAPIRouter.Use(dataloader.HandlerAPIDef(rootResolver.APIDefinitionsDataloader, cfg.DataloaderMaxBatch, cfg.DataloaderWait))
   364  	gqlAPIRouter.Use(dataloader.HandlerEventDef(rootResolver.EventDefinitionsDataloader, cfg.DataloaderMaxBatch, cfg.DataloaderWait))
   365  	gqlAPIRouter.Use(dataloader.HandlerDocument(rootResolver.DocumentsDataloader, cfg.DataloaderMaxBatch, cfg.DataloaderWait))
   366  	gqlAPIRouter.Use(dataloader.HandlerFetchRequestAPIDef(rootResolver.FetchRequestAPIDefDataloader, cfg.DataloaderMaxBatch, cfg.DataloaderWait))
   367  	gqlAPIRouter.Use(dataloader.HandlerFetchRequestEventDef(rootResolver.FetchRequestEventDefDataloader, cfg.DataloaderMaxBatch, cfg.DataloaderWait))
   368  	gqlAPIRouter.Use(dataloader.HandlerFetchRequestDocument(rootResolver.FetchRequestDocumentDataloader, cfg.DataloaderMaxBatch, cfg.DataloaderWait))
   369  	gqlAPIRouter.Use(dataloader.HandlerRuntimeContext(rootResolver.RuntimeContextsDataloader, cfg.DataloaderMaxBatch, cfg.DataloaderWait))
   370  	gqlAPIRouter.Use(dataloader.HandlerFormationAssignment(rootResolver.FormationAssignmentsDataLoader, cfg.DataloaderMaxBatch, cfg.DataloaderWait))
   371  	gqlAPIRouter.Use(dataloader.HandlerFormationStatus(rootResolver.StatusDataLoader, cfg.DataloaderMaxBatch, cfg.DataloaderWait))
   372  	gqlAPIRouter.Use(dataloader.HandlerFormationConstraint(rootResolver.FormationConstraintsDataLoader, cfg.DataloaderMaxBatch, cfg.DataloaderWait))
   373  	operationMiddleware := operation.NewMiddleware(cfg.AppURL + cfg.LastOperationPath)
   374  
   375  	gqlServ := handler.NewDefaultServer(executableSchema)
   376  	gqlServ.Use(log.NewGqlLoggingInterceptor())
   377  	gqlServ.Use(metrics.NewInstrumentGraphqlRequestInterceptor(metricsCollector))
   378  
   379  	gqlServ.Use(operationMiddleware)
   380  	gqlServ.SetErrorPresenter(presenter.Do)
   381  	gqlServ.SetRecoverFunc(panichandler.RecoverFn)
   382  
   383  	gqlAPIRouter.HandleFunc("", metricsCollector.GraphQLHandlerWithInstrumentation(gqlServ))
   384  
   385  	operationHandler := operation.NewHandler(transact, func(ctx context.Context, tenantID, resourceID string) (model.Entity, error) {
   386  		return appRepo.GetByID(ctx, tenantID, resourceID)
   387  	}, tenant.LoadFromContext)
   388  
   389  	operationsAPIRouter := mainRouter.PathPrefix(cfg.LastOperationPath).Subrouter()
   390  	operationsAPIRouter.Use(authMiddleware.Handler())
   391  	operationsAPIRouter.HandleFunc("/{resource_type}/{resource_id}", operationHandler.ServeHTTP)
   392  
   393  	operationUpdaterHandler := operation.NewUpdateOperationHandler(transact, map[resource.Type]operation.ResourceUpdaterFunc{
   394  		resource.Application: appUpdaterFunc(appRepo),
   395  	}, map[resource.Type]operation.ResourceDeleterFunc{
   396  		resource.Application: func(ctx context.Context, id string) error {
   397  			return appRepo.DeleteGlobal(ctx, id)
   398  		},
   399  	})
   400  
   401  	internalRouter := mux.NewRouter()
   402  	internalRouter.Use(correlation.AttachCorrelationIDToContext(), log.RequestLogger(), header.AttachHeadersToContext())
   403  	internalOperationsAPIRouter := internalRouter.PathPrefix(cfg.OperationPath).Subrouter()
   404  	internalOperationsAPIRouter.HandleFunc("", operationUpdaterHandler.ServeHTTP)
   405  
   406  	logger.Infof("Registering readiness endpoint...")
   407  	schemaRepo := schema.NewRepository()
   408  	ready := healthz.NewReady(transact, cfg.ReadyConfig, schemaRepo)
   409  	mainRouter.HandleFunc(readyzEndpoint, healthz.NewReadinessHandler(ready))
   410  
   411  	logger.Infof("Registering liveness endpoint...")
   412  	mainRouter.HandleFunc(livezEndpoint, healthz.NewLivenessHandler())
   413  
   414  	logger.Infof("Registering health endpoint...")
   415  	health, err := healthz.New(ctx, cfg.HealthConfig)
   416  	exitOnError(err, "Could not initialize health")
   417  	health.RegisterIndicator(healthz.NewIndicator(healthz.DBIndicatorName, healthz.NewDBIndicatorFunc(transact))).Start()
   418  	mainRouter.HandleFunc(healthzEndpoint, healthz.NewHealthHandler(health))
   419  
   420  	logger.Infof("Registering info endpoint...")
   421  	mainRouter.HandleFunc(cfg.InfoConfig.APIEndpoint, info.NewInfoHandler(ctx, cfg.InfoConfig, certCache))
   422  
   423  	fmAuthMiddleware := createFormationMappingAuthenticator(transact, cfg, cfg.DestinationCreatorConfig, appRepo, httpClient, mtlsHTTPClient, extSvcMtlsHTTPClient)
   424  	fmHandler := createFormationMappingHandler(transact, appRepo, cfg, cfg.DestinationCreatorConfig, httpClient, mtlsHTTPClient, extSvcMtlsHTTPClient)
   425  
   426  	asyncFormationAssignmentStatusRouter := mainRouter.PathPrefix(cfg.FormationMappingCfg.AsyncAPIPathPrefix).Subrouter()
   427  	asyncFormationAssignmentStatusRouter.Use(authMiddleware.Handler(), fmAuthMiddleware.FormationAssignmentHandler()) // order is important
   428  
   429  	asyncFormationStatusRouter := mainRouter.PathPrefix(cfg.FormationMappingCfg.AsyncAPIPathPrefix).Subrouter()
   430  	asyncFormationStatusRouter.Use(authMiddleware.Handler(), fmAuthMiddleware.FormationHandler()) // order is important
   431  
   432  	logger.Infof("Registering formation tenant mapping endpoints...")
   433  	asyncFormationAssignmentStatusRouter.HandleFunc(cfg.FormationMappingCfg.AsyncFormationAssignmentStatusAPIEndpoint, fmHandler.UpdateFormationAssignmentStatus).Methods(http.MethodPatch)
   434  	asyncFormationStatusRouter.HandleFunc(cfg.FormationMappingCfg.AsyncFormationStatusAPIEndpoint, fmHandler.UpdateFormationStatus).Methods(http.MethodPatch)
   435  
   436  	examplesServer := http.FileServer(http.Dir("./examples/"))
   437  	mainRouter.PathPrefix("/examples/").Handler(http.StripPrefix("/examples/", examplesServer))
   438  
   439  	metricsHandler := http.NewServeMux()
   440  	metricsHandler.Handle("/metrics", promhttp.Handler())
   441  
   442  	runMetricsSrv, shutdownMetricsSrv := createServer(ctx, cfg.MetricsAddress, metricsHandler, "metrics", cfg.ServerTimeout)
   443  	runMainSrv, shutdownMainSrv := createServer(ctx, cfg.Address, mainRouter, "main", cfg.ServerTimeout)
   444  	runInternalSrv, shutdownInternalSrv := createServer(ctx, cfg.InternalAddress, internalRouter, "internal", cfg.ServerTimeout)
   445  
   446  	go func() {
   447  		<-ctx.Done()
   448  		// Interrupt signal received - shut down the servers
   449  		shutdownMetricsSrv()
   450  		shutdownInternalSrv()
   451  		shutdownMainSrv()
   452  	}()
   453  
   454  	go runMetricsSrv()
   455  	go runInternalSrv()
   456  	runMainSrv()
   457  }
   458  
   459  func getPairingAdaptersMapping(ctx context.Context, k8sClient *kubernetes.Clientset, adaptersCfg configprovider.PairingAdapterConfig) (*pkgadapters.Adapters, error) {
   460  	logger := log.C(ctx)
   461  	logger.Infof("Getting pairing adapter configuration from the cluster...")
   462  	cm, err := k8sClient.CoreV1().ConfigMaps(adaptersCfg.ConfigmapNamespace).Get(ctx, adaptersCfg.ConfigmapName, metav1.GetOptions{})
   463  	if err != nil {
   464  		return nil, err
   465  	}
   466  
   467  	adaptersMap := make(map[string]string)
   468  	if err = json.Unmarshal([]byte(cm.Data[adaptersCfg.ConfigmapKey]), &adaptersMap); err != nil {
   469  		return nil, err
   470  	}
   471  
   472  	logger.Infof("Successfully read pairing adapters configuration from the cluster")
   473  
   474  	a := pkgadapters.NewAdapters()
   475  	a.Update(adaptersMap)
   476  
   477  	logger.Infof("Successfully updated pairing adapters configuration")
   478  
   479  	return a, nil
   480  }
   481  
   482  func startPairingAdaptersWatcher(ctx context.Context, k8sClient *kubernetes.Clientset, adapters *pkgadapters.Adapters, adaptersCfg configprovider.PairingAdapterConfig) {
   483  	processEventsFunc := func(ctx context.Context, events <-chan watch.Event) {
   484  		for {
   485  			select {
   486  			case <-ctx.Done():
   487  				return
   488  			case ev, ok := <-events:
   489  				if !ok {
   490  					return
   491  				}
   492  				switch ev.Type {
   493  				case watch.Added:
   494  					fallthrough
   495  				case watch.Modified:
   496  					log.C(ctx).Info("Updating pairing adapter configuration...")
   497  					cm, ok := ev.Object.(*v1.ConfigMap)
   498  					if !ok {
   499  						log.C(ctx).Error("Unexpected error: object is not configmap. Try again")
   500  						continue
   501  					}
   502  					aCfg, found := cm.Data[adaptersCfg.ConfigmapKey]
   503  					if !found {
   504  						log.C(ctx).Errorf("Did not find the expected key: %s in the pairing adapter configmap", adaptersCfg.ConfigmapKey)
   505  						return
   506  					}
   507  					adaptersCM := make(map[string]string)
   508  					if err := json.Unmarshal([]byte(aCfg), &adaptersCM); err != nil {
   509  						log.C(ctx).Error("error while unmarshalling adapters configuration")
   510  						return
   511  					}
   512  					adapters.Update(adaptersCM)
   513  					log.C(ctx).Info("Successfully updated in memory pairing adapter configuration")
   514  				case watch.Deleted:
   515  					log.C(ctx).Info("Delete event is received, removing pairing adapter configuration")
   516  					adapters.Update(nil)
   517  				case watch.Error:
   518  					log.C(ctx).Error("Error event is received, stop pairing adapter configmap watcher and try again...")
   519  					return
   520  				}
   521  			}
   522  		}
   523  	}
   524  
   525  	cmManager := k8sClient.CoreV1().ConfigMaps(adaptersCfg.ConfigmapNamespace)
   526  	w := kube.NewWatcher(ctx, cmManager, processEventsFunc, time.Second, adaptersCfg.ConfigmapName, adaptersCfg.WatcherCorrelationID)
   527  	go w.Run(ctx)
   528  }
   529  
   530  func createAndRunConfigProvider(ctx context.Context, cfg config) *configprovider.Provider {
   531  	provider := configprovider.NewProvider(cfg.ConfigurationFile)
   532  	err := provider.Load()
   533  	exitOnError(err, "Error on loading configuration file")
   534  	executor.NewPeriodic(cfg.ConfigurationFileReload, func(ctx context.Context) {
   535  		if err := provider.Load(); err != nil {
   536  			exitOnError(err, "Error from Reloader watch")
   537  		}
   538  		log.C(ctx).Infof("Successfully reloaded configuration file.")
   539  	}).Run(ctx)
   540  
   541  	return provider
   542  }
   543  
   544  func exitOnError(err error, context string) {
   545  	if err != nil {
   546  		wrappedError := errors.Wrap(err, context)
   547  		log.D().Fatal(wrappedError)
   548  	}
   549  }
   550  
   551  func createServer(ctx context.Context, address string, handler http.Handler, name string, timeout time.Duration) (func(), func()) {
   552  	handlerWithTimeout, err := timeouthandler.WithTimeout(handler, timeout)
   553  	exitOnError(err, "Error while configuring tenant mapping handler")
   554  
   555  	srv := &http.Server{
   556  		Addr:              address,
   557  		Handler:           handlerWithTimeout,
   558  		ReadHeaderTimeout: timeout,
   559  	}
   560  
   561  	runFn := func() {
   562  		log.C(ctx).Infof("Running %s server on %s...", name, address)
   563  		if err := srv.ListenAndServe(); err != http.ErrServerClosed {
   564  			log.C(ctx).WithError(err).Errorf("An error has occurred with %s HTTP server when ListenAndServe: %v", name, err)
   565  		}
   566  	}
   567  
   568  	shutdownFn := func() {
   569  		log.C(ctx).Infof("Shutting down %s server...", name)
   570  		if err := srv.Shutdown(context.Background()); err != nil {
   571  			log.C(ctx).WithError(err).Errorf("An error has occurred while shutting down HTTP server %s: %v", name, err)
   572  		}
   573  	}
   574  
   575  	return runFn, shutdownFn
   576  }
   577  
   578  func bundleInstanceAuthRepo() bundleinstanceauth.Repository {
   579  	authConverter := auth.NewConverter()
   580  
   581  	return bundleinstanceauth.NewRepository(bundleinstanceauth.NewConverter(authConverter))
   582  }
   583  
   584  func bundleRepo() bundle.BundleRepository {
   585  	authConverter := auth.NewConverter()
   586  	frConverter := fetchrequest.NewConverter(authConverter)
   587  	versionConverter := version.NewConverter()
   588  	specConverter := spec.NewConverter(frConverter)
   589  	eventAPIConverter := eventdef.NewConverter(versionConverter, specConverter)
   590  	docConverter := document.NewConverter(frConverter)
   591  	apiConverter := api.NewConverter(versionConverter, specConverter)
   592  
   593  	return bundle.NewRepository(bundle.NewConverter(authConverter, apiConverter, eventAPIConverter, docConverter))
   594  }
   595  
   596  func applicationRepo() application.ApplicationRepository {
   597  	authConverter := auth.NewConverter()
   598  
   599  	versionConverter := version.NewConverter()
   600  	frConverter := fetchrequest.NewConverter(authConverter)
   601  	specConverter := spec.NewConverter(frConverter)
   602  
   603  	apiConverter := api.NewConverter(versionConverter, specConverter)
   604  	eventAPIConverter := eventdef.NewConverter(versionConverter, specConverter)
   605  	docConverter := document.NewConverter(frConverter)
   606  
   607  	webhookConverter := webhook.NewConverter(authConverter)
   608  	bundleConverter := bundle.NewConverter(authConverter, apiConverter, eventAPIConverter, docConverter)
   609  
   610  	appConverter := application.NewConverter(webhookConverter, bundleConverter)
   611  
   612  	return application.NewRepository(appConverter)
   613  }
   614  
   615  func webhookService(tenantMappingConfig map[string]interface{}, callbackURL string) webhook.WebhookService {
   616  	uidSvc := uid.NewService()
   617  	authConverter := auth.NewConverter()
   618  
   619  	webhookConverter := webhook.NewConverter(authConverter)
   620  	webhookRepo := webhook.NewRepository(webhookConverter)
   621  
   622  	tenantConverter := tenant.NewConverter()
   623  	tenantRepo := tenant.NewRepository(tenantConverter)
   624  
   625  	labelConverter := label.NewConverter()
   626  	labelRepo := label.NewRepository(labelConverter)
   627  	labelDefinitionConverter := labeldef.NewConverter()
   628  	labelDefinitionRepo := labeldef.NewRepository(labelDefinitionConverter)
   629  	labelSvc := label.NewLabelService(labelRepo, labelDefinitionRepo, uidSvc)
   630  
   631  	tenantSvc := tenant.NewServiceWithLabels(tenantRepo, uidSvc, labelRepo, labelSvc, tenantConverter)
   632  	return webhook.NewService(webhookRepo, applicationRepo(), uidSvc, tenantSvc, tenantMappingConfig, callbackURL)
   633  }
   634  
   635  func getAsyncDirective(ctx context.Context, cfg config, transact persistence.Transactioner, appRepo application.ApplicationRepository, tenantMappingConfig map[string]interface{}) func(context.Context, interface{}, gqlgen.Resolver, graphql.OperationType, *graphql.WebhookType, *string) (res interface{}, err error) {
   636  	resourceFetcherFunc := func(ctx context.Context, tenantID, resourceID string) (model.Entity, error) {
   637  		return appRepo.GetByID(ctx, tenantID, resourceID)
   638  	}
   639  
   640  	scheduler, err := buildScheduler(ctx, cfg)
   641  	exitOnError(err, "Error while creating operations scheduler")
   642  
   643  	return operation.NewDirective(transact, webhookService(tenantMappingConfig, cfg.TenantMappingCallbackURL).ListAllApplicationWebhooks, resourceFetcherFunc, appUpdaterFunc(appRepo), tenant.LoadFromContext, scheduler).HandleOperation
   644  }
   645  
   646  func buildScheduler(ctx context.Context, config config) (operation.Scheduler, error) {
   647  	if config.DisableAsyncMode {
   648  		log.C(ctx).Info("Async operations are disabled")
   649  		return &operation.DisabledScheduler{}, nil
   650  	}
   651  
   652  	cfg, err := cr.GetConfig()
   653  	exitOnError(err, "Failed to get cluster config for operations k8s client")
   654  
   655  	cfg.Timeout = config.ClientTimeout
   656  	k8sClient, err := client.NewForConfig(cfg)
   657  	if err != nil {
   658  		return nil, err
   659  	}
   660  	operationsK8sClient := k8sClient.Operations(config.OperationsNamespace)
   661  
   662  	return k8s.NewScheduler(operationsK8sClient), nil
   663  }
   664  
   665  func appUpdaterFunc(appRepo application.ApplicationRepository) operation.ResourceUpdaterFunc {
   666  	return func(ctx context.Context, id string, ready bool, errorMsg *string, appStatusCondition model.ApplicationStatusCondition) error {
   667  		app, err := appRepo.GetGlobalByID(ctx, id)
   668  		if err != nil {
   669  			return err
   670  		}
   671  		app.Status = &model.ApplicationStatus{
   672  			Condition: appStatusCondition,
   673  			Timestamp: time.Now(),
   674  		}
   675  		app.Ready = ready
   676  		app.Error = errorMsg
   677  		return appRepo.TechnicalUpdate(ctx, app)
   678  	}
   679  }
   680  
   681  func runtimeSvc(transact persistence.Transactioner, cfg config, tenantMappingConfig map[string]interface{}, securedHTTPClient, mtlsHTTPClient, extSvcMtlsHTTPClient *http.Client) claims.RuntimeService {
   682  	asaConverter := scenarioassignment.NewConverter()
   683  	authConverter := auth.NewConverter()
   684  	webhookConverter := webhook.NewConverter(authConverter)
   685  	frConverter := fetchrequest.NewConverter(authConverter)
   686  	versionConverter := version.NewConverter()
   687  	docConverter := document.NewConverter(frConverter)
   688  	specConverter := spec.NewConverter(frConverter)
   689  	apiConverter := api.NewConverter(versionConverter, specConverter)
   690  	eventAPIConverter := eventdef.NewConverter(versionConverter, specConverter)
   691  	bundleConverter := bundle.NewConverter(authConverter, apiConverter, eventAPIConverter, docConverter)
   692  	appConverter := application.NewConverter(webhookConverter, bundleConverter)
   693  	appTemplateConverter := apptemplate.NewConverter(appConverter, webhookConverter)
   694  	labelConverter := label.NewConverter()
   695  	labelDefinitionConverter := labeldef.NewConverter()
   696  	runtimeContextConverter := runtimectx.NewConverter()
   697  	runtimeConverter := runtime.NewConverter(webhookConverter)
   698  	tenantConverter := tenant.NewConverter()
   699  	formationConv := formation.NewConverter()
   700  	formationTemplateConverter := formationtemplate.NewConverter(webhookConverter)
   701  	formationConstraintConverter := formationconstraint.NewConverter()
   702  	formationTemplateConstraintReferencesConverter := formationtemplateconstraintreferences.NewConverter()
   703  	formationAssignmentConv := formationassignment.NewConverter()
   704  
   705  	appRepo := application.NewRepository(appConverter)
   706  	webhookRepo := webhook.NewRepository(webhookConverter)
   707  	appTemplateRepo := apptemplate.NewRepository(appTemplateConverter)
   708  	asaRepo := scenarioassignment.NewRepository(asaConverter)
   709  	labelRepo := label.NewRepository(labelConverter)
   710  	labelDefinitionRepo := labeldef.NewRepository(labelDefinitionConverter)
   711  	runtimeRepo := runtime.NewRepository(runtimeConverter)
   712  	runtimeContextRepo := runtimectx.NewRepository(runtimeContextConverter)
   713  	tenantRepo := tenant.NewRepository(tenantConverter)
   714  	formationRepo := formation.NewRepository(formationConv)
   715  	formationTemplateRepo := formationtemplate.NewRepository(formationTemplateConverter)
   716  	formationConstraintRepo := formationconstraint.NewRepository(formationConstraintConverter)
   717  	formationTemplateConstraintReferencesRepo := formationtemplateconstraintreferences.NewRepository(formationTemplateConstraintReferencesConverter)
   718  	formationAssignmentRepo := formationassignment.NewRepository(formationAssignmentConv)
   719  
   720  	webhookClient := webhookclient.NewClient(securedHTTPClient, mtlsHTTPClient, extSvcMtlsHTTPClient)
   721  	webhookDataInputBuilder := databuilder.NewWebhookDataInputBuilder(appRepo, appTemplateRepo, runtimeRepo, runtimeContextRepo, labelRepo)
   722  
   723  	uidSvc := uid.NewService()
   724  	labelSvc := label.NewLabelService(labelRepo, labelDefinitionRepo, uidSvc)
   725  	labelDefinitionSvc := labeldef.NewService(labelDefinitionRepo, labelRepo, asaRepo, tenantRepo, uidSvc)
   726  	asaSvc := scenarioassignment.NewService(asaRepo, labelDefinitionSvc)
   727  	tenantSvc := tenant.NewServiceWithLabels(tenantRepo, uidSvc, labelRepo, labelSvc, tenantConverter)
   728  	formationConstraintSvc := formationconstraint.NewService(formationConstraintRepo, formationTemplateConstraintReferencesRepo, uidSvc, formationConstraintConverter)
   729  	constraintEngine := operators.NewConstraintEngine(transact, formationConstraintSvc, tenantSvc, asaSvc, nil, formationRepo, labelRepo, labelSvc, appRepo, runtimeContextRepo, formationTemplateRepo, formationAssignmentRepo, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
   730  	notificationsBuilder := formation.NewNotificationsBuilder(webhookConverter, constraintEngine, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
   731  	notificationsGenerator := formation.NewNotificationsGenerator(appRepo, appTemplateRepo, runtimeRepo, runtimeContextRepo, labelRepo, webhookRepo, webhookDataInputBuilder, notificationsBuilder)
   732  	notificationSvc := formation.NewNotificationService(tenantRepo, webhookClient, notificationsGenerator, constraintEngine, webhookConverter, formationTemplateRepo)
   733  	faNotificationSvc := formationassignment.NewFormationAssignmentNotificationService(formationAssignmentRepo, webhookConverter, webhookRepo, tenantRepo, webhookDataInputBuilder, formationRepo, notificationsBuilder, runtimeContextRepo, labelSvc, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
   734  	formationAssignmentStatusSvc := formationassignment.NewFormationAssignmentStatusService(formationAssignmentRepo, constraintEngine, faNotificationSvc)
   735  	formationAssignmentSvc := formationassignment.NewService(formationAssignmentRepo, uidSvc, appRepo, runtimeRepo, runtimeContextRepo, notificationSvc, faNotificationSvc, labelSvc, formationRepo, formationAssignmentStatusSvc, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
   736  	formationStatusSvc := formation.NewFormationStatusService(formationRepo, labelDefinitionRepo, labelDefinitionSvc, notificationSvc, constraintEngine)
   737  	formationSvc := formation.NewService(transact, appRepo, labelDefinitionRepo, labelRepo, formationRepo, formationTemplateRepo, labelSvc, uidSvc, labelDefinitionSvc, asaRepo, asaSvc, tenantSvc, runtimeRepo, runtimeContextRepo, formationAssignmentSvc, faNotificationSvc, notificationSvc, constraintEngine, webhookRepo, formationStatusSvc, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
   738  	runtimeContextSvc := runtimectx.NewService(runtimeContextRepo, labelRepo, runtimeRepo, labelSvc, formationSvc, tenantSvc, uidSvc)
   739  
   740  	return runtime.NewService(runtimeRepo, labelRepo, labelSvc, uidSvc, formationSvc, tenantSvc, webhookService(tenantMappingConfig, cfg.TenantMappingCallbackURL), runtimeContextSvc, cfg.Features.ProtectedLabelPattern, cfg.Features.ImmutableLabelPattern, cfg.Features.RuntimeTypeLabelKey, cfg.Features.KymaRuntimeTypeLabelValue, cfg.Features.KymaApplicationNamespaceValue)
   741  }
   742  
   743  func runtimeCtxSvc(transact persistence.Transactioner, cfg config, securedHTTPClient, mtlsHTTPClient, extSvcMtlsHTTPClient *http.Client) claims.RuntimeCtxService {
   744  	runtimeContextConverter := runtimectx.NewConverter()
   745  	labelConverter := label.NewConverter()
   746  	labelDefinitionConverter := labeldef.NewConverter()
   747  	asaConverter := scenarioassignment.NewConverter()
   748  	tenantConverter := tenant.NewConverter()
   749  	authConverter := auth.NewConverter()
   750  	webhookConverter := webhook.NewConverter(authConverter)
   751  	runtimeConverter := runtime.NewConverter(webhookConverter)
   752  	formationConv := formation.NewConverter()
   753  	formationTemplateConverter := formationtemplate.NewConverter(webhookConverter)
   754  	frConverter := fetchrequest.NewConverter(authConverter)
   755  	versionConverter := version.NewConverter()
   756  	docConverter := document.NewConverter(frConverter)
   757  	specConverter := spec.NewConverter(frConverter)
   758  	apiConverter := api.NewConverter(versionConverter, specConverter)
   759  	eventAPIConverter := eventdef.NewConverter(versionConverter, specConverter)
   760  	bundleConverter := bundle.NewConverter(authConverter, apiConverter, eventAPIConverter, docConverter)
   761  	appConverter := application.NewConverter(webhookConverter, bundleConverter)
   762  	appRepo := application.NewRepository(appConverter)
   763  	webhookRepo := webhook.NewRepository(webhookConverter)
   764  	appTemplateConverter := apptemplate.NewConverter(appConverter, webhookConverter)
   765  	formationConstraintConverter := formationconstraint.NewConverter()
   766  	formationTemplateConstraintReferencesConverter := formationtemplateconstraintreferences.NewConverter()
   767  
   768  	appTemplateRepo := apptemplate.NewRepository(appTemplateConverter)
   769  	runtimeContextRepo := runtimectx.NewRepository(runtimeContextConverter)
   770  	labelRepo := label.NewRepository(labelConverter)
   771  	labelDefinitionRepo := labeldef.NewRepository(labelDefinitionConverter)
   772  	asaRepo := scenarioassignment.NewRepository(asaConverter)
   773  	tenantRepo := tenant.NewRepository(tenantConverter)
   774  	runtimeRepo := runtime.NewRepository(runtimeConverter)
   775  	formationRepo := formation.NewRepository(formationConv)
   776  	formationTemplateRepo := formationtemplate.NewRepository(formationTemplateConverter)
   777  	formationConstraintRepo := formationconstraint.NewRepository(formationConstraintConverter)
   778  	formationTemplateConstraintReferencesRepo := formationtemplateconstraintreferences.NewRepository(formationTemplateConstraintReferencesConverter)
   779  
   780  	uidSvc := uid.NewService()
   781  	labelSvc := label.NewLabelService(labelRepo, labelDefinitionRepo, uidSvc)
   782  	labelDefinitionSvc := labeldef.NewService(labelDefinitionRepo, labelRepo, asaRepo, tenantRepo, uidSvc)
   783  	asaSvc := scenarioassignment.NewService(asaRepo, labelDefinitionSvc)
   784  	tenantSvc := tenant.NewServiceWithLabels(tenantRepo, uidSvc, labelRepo, labelSvc, tenantConverter)
   785  	webhookClient := webhookclient.NewClient(securedHTTPClient, mtlsHTTPClient, extSvcMtlsHTTPClient)
   786  	formationAssignmentConv := formationassignment.NewConverter()
   787  	formationAssignmentRepo := formationassignment.NewRepository(formationAssignmentConv)
   788  	webhookDataInputBuilder := databuilder.NewWebhookDataInputBuilder(appRepo, appTemplateRepo, runtimeRepo, runtimeContextRepo, labelRepo)
   789  	formationConstraintSvc := formationconstraint.NewService(formationConstraintRepo, formationTemplateConstraintReferencesRepo, uidSvc, formationConstraintConverter)
   790  	constraintEngine := operators.NewConstraintEngine(transact, formationConstraintSvc, tenantSvc, asaSvc, nil, formationRepo, labelRepo, labelSvc, appRepo, runtimeContextRepo, formationTemplateRepo, formationAssignmentRepo, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
   791  	notificationsBuilder := formation.NewNotificationsBuilder(webhookConverter, constraintEngine, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
   792  	notificationsGenerator := formation.NewNotificationsGenerator(appRepo, appTemplateRepo, runtimeRepo, runtimeContextRepo, labelRepo, webhookRepo, webhookDataInputBuilder, notificationsBuilder)
   793  	notificationSvc := formation.NewNotificationService(tenantRepo, webhookClient, notificationsGenerator, constraintEngine, webhookConverter, formationTemplateRepo)
   794  	faNotificationSvc := formationassignment.NewFormationAssignmentNotificationService(formationAssignmentRepo, webhookConverter, webhookRepo, tenantRepo, webhookDataInputBuilder, formationRepo, notificationsBuilder, runtimeContextRepo, labelSvc, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
   795  	formationAssignmentStatusSvc := formationassignment.NewFormationAssignmentStatusService(formationAssignmentRepo, constraintEngine, faNotificationSvc)
   796  	formationAssignmentSvc := formationassignment.NewService(formationAssignmentRepo, uidSvc, appRepo, runtimeRepo, runtimeContextRepo, notificationSvc, faNotificationSvc, labelSvc, formationRepo, formationAssignmentStatusSvc, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
   797  	formationStatusSvc := formation.NewFormationStatusService(formationRepo, labelDefinitionRepo, labelDefinitionSvc, notificationSvc, constraintEngine)
   798  	formationSvc := formation.NewService(transact, appRepo, labelDefinitionRepo, labelRepo, formationRepo, formationTemplateRepo, labelSvc, uidSvc, labelDefinitionSvc, asaRepo, asaSvc, tenantSvc, runtimeRepo, runtimeContextRepo, formationAssignmentSvc, faNotificationSvc, notificationSvc, constraintEngine, webhookRepo, formationStatusSvc, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
   799  
   800  	return runtimectx.NewService(runtimeContextRepo, labelRepo, runtimeRepo, labelSvc, formationSvc, tenantSvc, uidSvc)
   801  }
   802  
   803  func appTemplateSvc() claims.ApplicationTemplateService {
   804  	uidSvc := uid.NewService()
   805  	authConverter := auth.NewConverter()
   806  	versionConverter := version.NewConverter()
   807  
   808  	frConverter := fetchrequest.NewConverter(authConverter)
   809  	specConverter := spec.NewConverter(frConverter)
   810  	eventAPIConverter := eventdef.NewConverter(versionConverter, specConverter)
   811  	docConverter := document.NewConverter(frConverter)
   812  	apiConverter := api.NewConverter(versionConverter, specConverter)
   813  	bundleConverter := bundle.NewConverter(authConverter, apiConverter, eventAPIConverter, docConverter)
   814  	webhookConverter := webhook.NewConverter(authConverter)
   815  	appConverter := application.NewConverter(webhookConverter, bundleConverter)
   816  	appTemplateConv := apptemplate.NewConverter(appConverter, webhookConverter)
   817  	appTemplateRepo := apptemplate.NewRepository(appTemplateConv)
   818  
   819  	webhookRepo := webhook.NewRepository(webhookConverter)
   820  
   821  	labelConverter := label.NewConverter()
   822  	labelRepo := label.NewRepository(labelConverter)
   823  	labelDefConverter := labeldef.NewConverter()
   824  	labelDefRepo := labeldef.NewRepository(labelDefConverter)
   825  	labelSvc := label.NewLabelService(labelRepo, labelDefRepo, uidSvc)
   826  	appRepo := application.NewRepository(appConverter)
   827  
   828  	return apptemplate.NewService(appTemplateRepo, webhookRepo, uidSvc, labelSvc, labelRepo, appRepo)
   829  }
   830  
   831  func applicationSvc(transact persistence.Transactioner, cfg config, securedHTTPClient, mtlsHTTPClient, extSvcMtlsHTTPClient *http.Client, certCache certloader.Cache, ordWebhookMapping []application.ORDWebhookMapping) claims.ApplicationService {
   832  	uidSvc := uid.NewService()
   833  	authConverter := auth.NewConverter()
   834  	webhookConverter := webhook.NewConverter(authConverter)
   835  	runtimeConverter := runtime.NewConverter(webhookConverter)
   836  	runtimeRepo := runtime.NewRepository(runtimeConverter)
   837  
   838  	intSysConverter := integrationsystem.NewConverter()
   839  	intSysRepo := integrationsystem.NewRepository(intSysConverter)
   840  
   841  	webhookRepo := webhook.NewRepository(webhookConverter)
   842  
   843  	labelConverter := label.NewConverter()
   844  	labelRepo := label.NewRepository(labelConverter)
   845  	labelDefConverter := labeldef.NewConverter()
   846  	labelDefRepo := labeldef.NewRepository(labelDefConverter)
   847  	labelSvc := label.NewLabelService(labelRepo, labelDefRepo, uidSvc)
   848  	assignmentConv := scenarioassignment.NewConverter()
   849  	scenarioAssignmentRepo := scenarioassignment.NewRepository(assignmentConv)
   850  	tenantConverter := tenant.NewConverter()
   851  	tenantRepo := tenant.NewRepository(tenantConverter)
   852  
   853  	scenariosSvc := labeldef.NewService(labelDefRepo, labelRepo, scenarioAssignmentRepo, tenantRepo, uidSvc)
   854  
   855  	frConverter := fetchrequest.NewConverter(authConverter)
   856  	docConverter := document.NewConverter(frConverter)
   857  	docRepo := document.NewRepository(docConverter)
   858  
   859  	fetchRequestRepo := fetchrequest.NewRepository(frConverter)
   860  
   861  	docSvc := document.NewService(docRepo, fetchRequestRepo, uidSvc)
   862  	versionConverter := version.NewConverter()
   863  	specConverter := spec.NewConverter(frConverter)
   864  	apiConverter := api.NewConverter(versionConverter, specConverter)
   865  	apiRepo := api.NewRepository(apiConverter)
   866  	specRepo := spec.NewRepository(specConverter)
   867  	fetchRequestSvc := fetchrequest.NewService(fetchRequestRepo, securedHTTPClient, accessstrategy.NewDefaultExecutorProvider(certCache, cfg.ExternalClientCertSecretName, cfg.ExtSvcClientCertSecretName))
   868  	specSvc := spec.NewService(specRepo, fetchRequestRepo, uidSvc, fetchRequestSvc)
   869  	bundleReferenceConv := bundlereferences.NewConverter()
   870  	bundleReferenceRepo := bundlereferences.NewRepository(bundleReferenceConv)
   871  	bundleReferenceSvc := bundlereferences.NewService(bundleReferenceRepo, uidSvc)
   872  	apiSvc := api.NewService(apiRepo, uidSvc, specSvc, bundleReferenceSvc)
   873  	eventAPIConverter := eventdef.NewConverter(versionConverter, specConverter)
   874  	eventAPIRepo := eventdef.NewRepository(eventAPIConverter)
   875  
   876  	eventAPISvc := eventdef.NewService(eventAPIRepo, uidSvc, specSvc, bundleReferenceSvc)
   877  	bundleConverter := bundle.NewConverter(authConverter, apiConverter, eventAPIConverter, docConverter)
   878  	bundleRepo := bundle.NewRepository(bundleConverter)
   879  
   880  	bundleSvc := bundle.NewService(bundleRepo, apiSvc, eventAPISvc, docSvc, uidSvc)
   881  	formationConv := formation.NewConverter()
   882  	formationTemplateConverter := formationtemplate.NewConverter(webhookConverter)
   883  	formationRepo := formation.NewRepository(formationConv)
   884  	formationTemplateRepo := formationtemplate.NewRepository(formationTemplateConverter)
   885  
   886  	scenarioAssignmentSvc := scenarioassignment.NewService(scenarioAssignmentRepo, scenariosSvc)
   887  	tntSvc := tenant.NewServiceWithLabels(tenantRepo, uidSvc, labelRepo, labelSvc, tenantConverter)
   888  
   889  	runtimeContextConv := runtimectx.NewConverter()
   890  	runtimeContextRepo := runtimectx.NewRepository(runtimeContextConv)
   891  
   892  	appConverter := application.NewConverter(webhookConverter, bundleConverter)
   893  	applicationRepo := application.NewRepository(appConverter)
   894  
   895  	appTemplateConverter := apptemplate.NewConverter(appConverter, webhookConverter)
   896  	appTemplateRepo := apptemplate.NewRepository(appTemplateConverter)
   897  
   898  	formationConstraintConverter := formationconstraint.NewConverter()
   899  	formationConstraintRepo := formationconstraint.NewRepository(formationConstraintConverter)
   900  
   901  	formationTemplateConstraintReferencesConverter := formationtemplateconstraintreferences.NewConverter()
   902  	formationTemplateConstraintReferencesRepo := formationtemplateconstraintreferences.NewRepository(formationTemplateConstraintReferencesConverter)
   903  
   904  	webhookClient := webhookclient.NewClient(securedHTTPClient, mtlsHTTPClient, extSvcMtlsHTTPClient)
   905  	formationAssignmentConv := formationassignment.NewConverter()
   906  	formationAssignmentRepo := formationassignment.NewRepository(formationAssignmentConv)
   907  	webhookDataInputBuilder := databuilder.NewWebhookDataInputBuilder(applicationRepo, appTemplateRepo, runtimeRepo, runtimeContextRepo, labelRepo)
   908  	formationConstraintSvc := formationconstraint.NewService(formationConstraintRepo, formationTemplateConstraintReferencesRepo, uidSvc, formationConstraintConverter)
   909  	constraintEngine := operators.NewConstraintEngine(transact, formationConstraintSvc, tntSvc, scenarioAssignmentSvc, nil, formationRepo, labelRepo, labelSvc, applicationRepo, runtimeContextRepo, formationTemplateRepo, formationAssignmentRepo, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
   910  	notificationsBuilder := formation.NewNotificationsBuilder(webhookConverter, constraintEngine, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
   911  	notificationsGenerator := formation.NewNotificationsGenerator(applicationRepo, appTemplateRepo, runtimeRepo, runtimeContextRepo, labelRepo, webhookRepo, webhookDataInputBuilder, notificationsBuilder)
   912  	notificationSvc := formation.NewNotificationService(tenantRepo, webhookClient, notificationsGenerator, constraintEngine, webhookConverter, formationTemplateRepo)
   913  	faNotificationSvc := formationassignment.NewFormationAssignmentNotificationService(formationAssignmentRepo, webhookConverter, webhookRepo, tenantRepo, webhookDataInputBuilder, formationRepo, notificationsBuilder, runtimeContextRepo, labelSvc, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
   914  	formationAssignmentStatusSvc := formationassignment.NewFormationAssignmentStatusService(formationAssignmentRepo, constraintEngine, faNotificationSvc)
   915  	formationAssignmentSvc := formationassignment.NewService(formationAssignmentRepo, uidSvc, applicationRepo, runtimeRepo, runtimeContextRepo, notificationSvc, faNotificationSvc, labelSvc, formationRepo, formationAssignmentStatusSvc, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
   916  	formationStatusSvc := formation.NewFormationStatusService(formationRepo, labelDefRepo, scenariosSvc, notificationSvc, constraintEngine)
   917  	formationSvc := formation.NewService(transact, applicationRepo, labelDefRepo, labelRepo, formationRepo, formationTemplateRepo, labelSvc, uidSvc, scenariosSvc, scenarioAssignmentRepo, scenarioAssignmentSvc, tntSvc, runtimeRepo, runtimeContextRepo, formationAssignmentSvc, faNotificationSvc, notificationSvc, constraintEngine, webhookRepo, formationStatusSvc, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
   918  
   919  	return application.NewService(&normalizer.DefaultNormalizator{}, nil, applicationRepo, webhookRepo, runtimeRepo, labelRepo, intSysRepo, labelSvc, bundleSvc, uidSvc, formationSvc, cfg.SelfRegConfig.SelfRegisterDistinguishLabelKey, ordWebhookMapping)
   920  }
   921  
   922  func intSystemSvc() claims.IntegrationSystemService {
   923  	intSysConverter := integrationsystem.NewConverter()
   924  	intSysRepo := integrationsystem.NewRepository(intSysConverter)
   925  	return integrationsystem.NewService(intSysRepo, uid.NewService())
   926  }
   927  
   928  func createFormationMappingAuthenticator(transact persistence.Transactioner, cfg config, destinationCreatorConfig *destinationcreator.Config, appRepo application.ApplicationRepository, securedHTTPClient, mtlsHTTPClient, extSvcMtlsHTTPClient *http.Client) *formationmapping.Authenticator {
   929  	formationAssignmentConv := formationassignment.NewConverter()
   930  	authConverter := auth.NewConverter()
   931  	webhookConverter := webhook.NewConverter(authConverter)
   932  	frConverter := fetchrequest.NewConverter(authConverter)
   933  	versionConverter := version.NewConverter()
   934  	specConverter := spec.NewConverter(frConverter)
   935  	docConverter := document.NewConverter(frConverter)
   936  	eventAPIConverter := eventdef.NewConverter(versionConverter, specConverter)
   937  	apiConverter := api.NewConverter(versionConverter, specConverter)
   938  	bundleConverter := bundle.NewConverter(authConverter, apiConverter, eventAPIConverter, docConverter)
   939  	appConverter := application.NewConverter(webhookConverter, bundleConverter)
   940  	appTemplateConverter := apptemplate.NewConverter(appConverter, webhookConverter)
   941  	tenantConverter := tenant.NewConverter()
   942  	formationConv := formation.NewConverter()
   943  	formationTemplateConverter := formationtemplate.NewConverter(webhookConverter)
   944  	destinationConv := destination.NewConverter()
   945  
   946  	appTemplateRepo := apptemplate.NewRepository(appTemplateConverter)
   947  	labelRepo := label.NewRepository(label.NewConverter())
   948  	formationAssignmentRepo := formationassignment.NewRepository(formationAssignmentConv)
   949  	runtimeContextRepo := runtimectx.NewRepository(runtimectx.NewConverter())
   950  	webhookRepo := webhook.NewRepository(webhookConverter)
   951  	runtimeRepo := runtime.NewRepository(runtime.NewConverter(webhook.NewConverter(auth.NewConverter())))
   952  	tenantRepo := tenant.NewRepository(tenantConverter)
   953  	formationRepo := formation.NewRepository(formationConv)
   954  	formationTemplateRepo := formationtemplate.NewRepository(formationTemplateConverter)
   955  	destinationRepo := destination.NewRepository(destinationConv)
   956  
   957  	webhookClient := webhookclient.NewClient(securedHTTPClient, mtlsHTTPClient, extSvcMtlsHTTPClient)
   958  	webhookDataInputBuilder := databuilder.NewWebhookDataInputBuilder(appRepo, appTemplateRepo, runtimeRepo, runtimeContextRepo, labelRepo)
   959  
   960  	labelDefinitionConverter := labeldef.NewConverter()
   961  	asaConverter := scenarioassignment.NewConverter()
   962  	formationConstraintConverter := formationconstraint.NewConverter()
   963  	formationTemplateConstraintReferencesConverter := formationtemplateconstraintreferences.NewConverter()
   964  	labelDefinitionRepo := labeldef.NewRepository(labelDefinitionConverter)
   965  	asaRepo := scenarioassignment.NewRepository(asaConverter)
   966  	formationConstraintRepo := formationconstraint.NewRepository(formationConstraintConverter)
   967  	formationTemplateConstraintReferencesRepo := formationtemplateconstraintreferences.NewRepository(formationTemplateConstraintReferencesConverter)
   968  	uidSvc := uid.NewService()
   969  	labelDefinitionSvc := labeldef.NewService(labelDefinitionRepo, labelRepo, asaRepo, tenantRepo, uidSvc)
   970  	asaSvc := scenarioassignment.NewService(asaRepo, labelDefinitionSvc)
   971  	labelSvc := label.NewLabelService(labelRepo, labelDefinitionRepo, uidSvc)
   972  	tenantSvc := tenant.NewServiceWithLabels(tenantRepo, uidSvc, labelRepo, labelSvc, tenantConverter)
   973  	formationConstraintSvc := formationconstraint.NewService(formationConstraintRepo, formationTemplateConstraintReferencesRepo, uidSvc, formationConstraintConverter)
   974  	destinationSvc := destination.NewService(mtlsHTTPClient, destinationCreatorConfig, transact, applicationRepo(), runtimeRepo, runtimeContextRepo, labelRepo, destinationRepo, tenantRepo, uidSvc)
   975  	constraintEngine := operators.NewConstraintEngine(transact, formationConstraintSvc, tenantSvc, asaSvc, destinationSvc, formationRepo, labelRepo, labelSvc, appRepo, runtimeContextRepo, formationTemplateRepo, formationAssignmentRepo, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
   976  	notificationsBuilder := formation.NewNotificationsBuilder(webhookConverter, constraintEngine, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
   977  	notificationSvc := formation.NewNotificationService(tenantRepo, webhookClient, nil, constraintEngine, webhookConverter, formationTemplateRepo)
   978  	faNotificationSvc := formationassignment.NewFormationAssignmentNotificationService(formationAssignmentRepo, webhookConverter, webhookRepo, tenantRepo, webhookDataInputBuilder, formationRepo, notificationsBuilder, runtimeContextRepo, labelSvc, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
   979  	formationAssignmentStatusSvc := formationassignment.NewFormationAssignmentStatusService(formationAssignmentRepo, constraintEngine, faNotificationSvc)
   980  	formationAssignmentSvc := formationassignment.NewService(formationAssignmentRepo, uid.NewService(), appRepo, runtimeRepo, runtimeContextRepo, notificationSvc, faNotificationSvc, labelSvc, formationRepo, formationAssignmentStatusSvc, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
   981  
   982  	return formationmapping.NewFormationMappingAuthenticator(transact, formationAssignmentSvc, runtimeRepo, runtimeContextRepo, appRepo, appTemplateRepo, labelRepo, formationRepo, formationTemplateRepo, tenantRepo, cfg.SubscriptionConfig.ConsumerSubaccountLabelKey)
   983  }
   984  
   985  func createFormationMappingHandler(transact persistence.Transactioner, appRepo application.ApplicationRepository, cfg config, destinationCreatorConfig *destinationcreator.Config, securedHTTPClient, mtlsHTTPClient, extSvcMtlsHTTPClient *http.Client) *formationmapping.Handler {
   986  	formationAssignmentConv := formationassignment.NewConverter()
   987  	authConverter := auth.NewConverter()
   988  	webhookConverter := webhook.NewConverter(authConverter)
   989  	frConverter := fetchrequest.NewConverter(authConverter)
   990  	versionConverter := version.NewConverter()
   991  	specConverter := spec.NewConverter(frConverter)
   992  	docConverter := document.NewConverter(frConverter)
   993  	apiConverter := api.NewConverter(versionConverter, specConverter)
   994  	eventAPIConverter := eventdef.NewConverter(versionConverter, specConverter)
   995  	bundleConverter := bundle.NewConverter(authConverter, apiConverter, eventAPIConverter, docConverter)
   996  	appConverter := application.NewConverter(webhookConverter, bundleConverter)
   997  	appTemplateConverter := apptemplate.NewConverter(appConverter, webhookConverter)
   998  	formationConv := formation.NewConverter()
   999  	formationTemplateConverter := formationtemplate.NewConverter(webhookConverter)
  1000  	labelDefinitionConverter := labeldef.NewConverter()
  1001  	asaConverter := scenarioassignment.NewConverter()
  1002  	tenantConverter := tenant.NewConverter()
  1003  	formationConstraintConverter := formationconstraint.NewConverter()
  1004  	formationTemplateConstraintReferencesConverter := formationtemplateconstraintreferences.NewConverter()
  1005  	destinationConv := destination.NewConverter()
  1006  
  1007  	labelRepo := label.NewRepository(label.NewConverter())
  1008  	formationAssignmentRepo := formationassignment.NewRepository(formationAssignmentConv)
  1009  	appTemplateRepo := apptemplate.NewRepository(appTemplateConverter)
  1010  	runtimeRepo := runtime.NewRepository(runtime.NewConverter(webhook.NewConverter(auth.NewConverter())))
  1011  	runtimeContextRepo := runtimectx.NewRepository(runtimectx.NewConverter())
  1012  	webhookRepo := webhook.NewRepository(webhookConverter)
  1013  	labelDefRepo := labeldef.NewRepository(labeldef.NewConverter())
  1014  	formationRepo := formation.NewRepository(formationConv)
  1015  	formationTemplateRepo := formationtemplate.NewRepository(formationTemplateConverter)
  1016  	labelDefinitionRepo := labeldef.NewRepository(labelDefinitionConverter)
  1017  	asaRepo := scenarioassignment.NewRepository(asaConverter)
  1018  	tenantRepo := tenant.NewRepository(tenantConverter)
  1019  	formationConstraintRepo := formationconstraint.NewRepository(formationConstraintConverter)
  1020  	formationTemplateConstraintReferencesRepo := formationtemplateconstraintreferences.NewRepository(formationTemplateConstraintReferencesConverter)
  1021  	destinationRepo := destination.NewRepository(destinationConv)
  1022  
  1023  	webhookClient := webhookclient.NewClient(securedHTTPClient, mtlsHTTPClient, extSvcMtlsHTTPClient)
  1024  	webhookDataInputBuilder := databuilder.NewWebhookDataInputBuilder(appRepo, appTemplateRepo, runtimeRepo, runtimeContextRepo, labelRepo)
  1025  
  1026  	uidSvc := uid.NewService()
  1027  	labelDefinitionSvc := labeldef.NewService(labelDefinitionRepo, labelRepo, asaRepo, tenantRepo, uidSvc)
  1028  	asaSvc := scenarioassignment.NewService(asaRepo, labelDefinitionSvc)
  1029  	labelSvc := label.NewLabelService(labelRepo, labelDefinitionRepo, uidSvc)
  1030  	tenantSvc := tenant.NewServiceWithLabels(tenantRepo, uidSvc, labelRepo, labelSvc, tenantConverter)
  1031  	formationConstraintSvc := formationconstraint.NewService(formationConstraintRepo, formationTemplateConstraintReferencesRepo, uidSvc, formationConstraintConverter)
  1032  	destinationSvc := destination.NewService(mtlsHTTPClient, destinationCreatorConfig, transact, applicationRepo(), runtimeRepo, runtimeContextRepo, labelRepo, destinationRepo, tenantRepo, uidSvc)
  1033  	constraintEngine := operators.NewConstraintEngine(transact, formationConstraintSvc, tenantSvc, asaSvc, destinationSvc, formationRepo, labelRepo, labelSvc, appRepo, runtimeContextRepo, formationTemplateRepo, formationAssignmentRepo, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
  1034  	notificationsBuilder := formation.NewNotificationsBuilder(webhookConverter, constraintEngine, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
  1035  	notificationsGenerator := formation.NewNotificationsGenerator(appRepo, appTemplateRepo, runtimeRepo, runtimeContextRepo, labelRepo, webhookRepo, webhookDataInputBuilder, notificationsBuilder)
  1036  	notificationSvc := formation.NewNotificationService(tenantRepo, webhookClient, notificationsGenerator, constraintEngine, webhookConverter, formationTemplateRepo)
  1037  	faNotificationSvc := formationassignment.NewFormationAssignmentNotificationService(formationAssignmentRepo, webhookConverter, webhookRepo, tenantRepo, webhookDataInputBuilder, formationRepo, notificationsBuilder, runtimeContextRepo, labelSvc, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
  1038  	formationAssignmentStatusSvc := formationassignment.NewFormationAssignmentStatusService(formationAssignmentRepo, constraintEngine, faNotificationSvc)
  1039  	formationAssignmentSvc := formationassignment.NewService(formationAssignmentRepo, uid.NewService(), appRepo, runtimeRepo, runtimeContextRepo, notificationSvc, faNotificationSvc, labelSvc, formationRepo, formationAssignmentStatusSvc, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
  1040  	formationStatusSvc := formation.NewFormationStatusService(formationRepo, labelDefRepo, labelDefinitionSvc, notificationSvc, constraintEngine)
  1041  	formationSvc := formation.NewService(transact, appRepo, labelDefRepo, labelRepo, formationRepo, formationTemplateRepo, labelSvc, uidSvc, labelDefinitionSvc, asaRepo, asaSvc, tenantSvc, runtimeRepo, runtimeContextRepo, formationAssignmentSvc, faNotificationSvc, notificationSvc, constraintEngine, webhookRepo, formationStatusSvc, cfg.Features.RuntimeTypeLabelKey, cfg.Features.ApplicationTypeLabelKey)
  1042  
  1043  	fmHandler := formationmapping.NewFormationMappingHandler(transact, formationAssignmentSvc, formationAssignmentStatusSvc, faNotificationSvc, formationSvc, formationStatusSvc)
  1044  
  1045  	return fmHandler
  1046  }