func (ap *Platform) TransformOnbuildArtifactPaths(onbuildArtifacts []runtime.Artifact) (map[string]string, error) {
	return ap.ContainerBuilder.TransformOnbuildArtifactPaths(onbuildArtifacts)
}
TransformOnbuildArtifactPaths changes Onbuild artifact paths depending on the type of the builder used
package abstract
import (
	"bufio"
	"context"
	"fmt"
	"net/http"
	"strings"
	"sync"
	"time"
	"github.com/nuclio/nuclio/pkg/common"
	"github.com/nuclio/nuclio/pkg/containerimagebuilderpusher"
	"github.com/nuclio/nuclio/pkg/errgroup"
	"github.com/nuclio/nuclio/pkg/functionconfig"
	"github.com/nuclio/nuclio/pkg/logprocessing"
	"github.com/nuclio/nuclio/pkg/opa"
	"github.com/nuclio/nuclio/pkg/platform"
	"github.com/nuclio/nuclio/pkg/platformconfig"
	"github.com/nuclio/nuclio/pkg/processor/build"
	"github.com/nuclio/nuclio/pkg/processor/build/runtime"
	"github.com/nuclio/nuclio/pkg/processor/trigger"
	"github.com/docker/distribution/reference"
	"github.com/google/go-cmp/cmp"
	"github.com/nuclio/errors"
	"github.com/nuclio/logger"
	"github.com/nuclio/nuclio-sdk-go"
	"k8s.io/api/core/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/util/validation"
)
const (
	FunctionContainerHTTPPort            = 8080
	FunctionContainerWebAdminHTTPPort    = 8081
	FunctionContainerHealthCheckHTTPPort = 8082
	DefaultTargetCPU                     = 75
)
type Platform struct {
	Logger                  logger.Logger
	platform                platform.Platform
	invoker                 *invoker
	Config                  *platformconfig.Config
	ExternalIPAddresses     []string
	DeployLogStreams        *sync.Map
	ContainerBuilder        containerimagebuilderpusher.BuilderPusher
	ImageNamePrefixTemplate string
	DefaultNamespace        string
	OpaClient               opa.Client
}
func NewPlatform(parentLogger logger.Logger,
	platform platform.Platform,
	platformConfiguration *platformconfig.Config,
	defaultNamespace string) (*Platform, error) {
	var err error
	newPlatform := &Platform{
		Logger:           parentLogger.GetChild("platform"),
		platform:         platform,
		Config:           platformConfiguration,
		DeployLogStreams: &sync.Map{},
	}
	newPlatform.invoker, err = newInvoker(newPlatform.Logger, platform)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to create invoker")
	}
	newPlatform.DefaultNamespace = defaultNamespace
	newPlatform.OpaClient = opa.CreateOpaClient(newPlatform.Logger, &platformConfiguration.Opa)
	return newPlatform, nil
}
func (ap *Platform) GetConfig() *platformconfig.Config {
	return ap.Config
}
func (ap *Platform) CreateFunctionBuild(createFunctionBuildOptions *platform.CreateFunctionBuildOptions) (
	*platform.CreateFunctionBuildResult, error) {
	builder, err := build.NewBuilder(createFunctionBuildOptions.Logger, ap.platform, &common.AbstractS3Client{})
	if err != nil {
		return nil, errors.Wrap(err, "Failed to create builder")
	}
	return builder.Build(createFunctionBuildOptions)
}
func (ap *Platform) HandleDeployFunction(existingFunctionConfig *functionconfig.ConfigWithStatus,
	createFunctionOptions *platform.CreateFunctionOptions,
	onAfterConfigUpdated func() error,
	onAfterBuild func(*platform.CreateFunctionBuildResult, error) (*platform.CreateFunctionResult, error)) (
	*platform.CreateFunctionResult, error) {
	createFunctionOptions.Logger.InfoWith("Deploying function",
		"name", createFunctionOptions.FunctionConfig.Meta.Name)
	var buildResult *platform.CreateFunctionBuildResult
	var buildErr error
	onAfterConfigUpdatedWrapper := func(updatedFunctionConfig *functionconfig.Config) error {
		createFunctionOptions.FunctionConfig = *updatedFunctionConfig
		return onAfterConfigUpdated()
	}
	functionBuildRequired, err := ap.functionBuildRequired(&createFunctionOptions.FunctionConfig)
	if err != nil {
		return nil, errors.Wrap(err, "Failed determining whether function should build")
	}
	createFunctionOptions.FunctionConfig.Spec.Build.Mode = ""
	if functionBuildRequired && !functionconfig.ShouldSkipBuild(createFunctionOptions.FunctionConfig.Meta.Annotations) {
		buildResult, buildErr = ap.platform.CreateFunctionBuild(&platform.CreateFunctionBuildOptions{
			Logger:                     createFunctionOptions.Logger,
			FunctionConfig:             createFunctionOptions.FunctionConfig,
			PlatformName:               ap.platform.GetName(),
			OnAfterConfigUpdate:        onAfterConfigUpdatedWrapper,
			DependantImagesRegistryURL: createFunctionOptions.DependantImagesRegistryURL,
		})
		if buildErr == nil {
			createFunctionOptions.FunctionConfig.Spec.Image = buildResult.Image
			if createFunctionOptions.FunctionConfig.Spec.RunRegistry == "" {
				createFunctionOptions.FunctionConfig.Spec.RunRegistry =
					createFunctionOptions.FunctionConfig.Spec.Build.Registry
			}
			createFunctionOptions.FunctionConfig.Spec.Build.Timestamp = time.Now().Unix()
		}
	} else {
		createFunctionOptions.Logger.InfoWith("Skipping build",
			"name", createFunctionOptions.FunctionConfig.Meta.Name)
		if createFunctionOptions.FunctionConfig.Spec.Runtime == "" {
			return nil, errors.New("If image is passed, runtime must be specified")
		}
		if existingFunctionConfig != nil && createFunctionOptions.FunctionConfig.Spec.Image == "" {
			createFunctionOptions.FunctionConfig.Spec.Image = existingFunctionConfig.Spec.Image
		}
		if err = onAfterConfigUpdatedWrapper(&createFunctionOptions.FunctionConfig); err != nil {
			return nil, errors.Wrap(err, "Failed to trigger on after config update")
		}
	}
	deployResult, err := onAfterBuild(buildResult, buildErr)
	if buildErr != nil || err != nil {
		return nil, errors.Wrap(err, "Failed to deploy function")
	}
	if deployResult == nil {
		return nil, errors.New("Deployer returned no error, but nil deploy result")
	}
	if buildResult != nil {
		deployResult.CreateFunctionBuildResult = *buildResult
	}
	createFunctionOptions.Logger.InfoWith("Function deploy complete",
		"functionName", deployResult.UpdatedFunctionConfig.Meta.Name,
		"httpPort", deployResult.Port,
		"internalInvocationURLs", deployResult.FunctionStatus.InternalInvocationURLs,
		"externalInvocationURLs", deployResult.FunctionStatus.ExternalInvocationURLs)
	return deployResult, nil
}
func (ap *Platform) EnrichFunctionConfig(functionConfig *functionconfig.Config) error {
	if functionConfig.Meta.Labels == nil {
		functionConfig.Meta.Labels = map[string]string{}
	}
	ap.EnrichLabelsWithProjectName(functionConfig.Meta.Labels)
	if err := ap.enrichImageName(functionConfig); err != nil {
		return errors.Wrap(err, "Failed enriching image name")
	}
	ap.enrichMinMaxReplicas(functionConfig)
	if functionConfig.Spec.ImagePullSecrets == "" {
		functionConfig.Spec.ImagePullSecrets =
			ap.GetDefaultRegistryCredentialsSecretName()
	}
	if functionConfig.Spec.Runtime == "python" {
		functionConfig.Spec.Runtime = "python:3.6"
	}
	if err := ap.enrichTriggers(functionConfig); err != nil {
		return errors.Wrap(err, "Failed enriching triggers")
	}
	if functionConfig.Spec.SecurityContext == nil {
		functionConfig.Spec.SecurityContext = &v1.PodSecurityContext{}
	}
	if err := ap.enrichVolumes(functionConfig); err != nil {
		return errors.Wrap(err, "Failed enriching volumes")
	}
	return nil
}
func (ap *Platform) EnrichLabelsWithProjectName(labels map[string]string) {
	if labels[common.NuclioResourceLabelKeyProjectName] == "" {
		labels[common.NuclioResourceLabelKeyProjectName] = platform.DefaultProjectName
		ap.Logger.Debug("No project name specified. Setting to default")
	}
}
func (ap *Platform) enrichDefaultHTTPTrigger(functionConfig *functionconfig.Config) {
	if len(functionconfig.GetTriggersByKind(functionConfig.Spec.Triggers, "http")) > 0 {
		return
	}
	if functionConfig.Spec.Triggers == nil {
		functionConfig.Spec.Triggers = map[string]functionconfig.Trigger{}
	}
	defaultHTTPTrigger := functionconfig.GetDefaultHTTPTrigger()
	functionConfig.Spec.Triggers[defaultHTTPTrigger.Name] = defaultHTTPTrigger
}
func (ap *Platform) ValidateCreateFunctionOptionsAgainstExistingFunctionConfig(
	existingFunctionConfig *functionconfig.ConfigWithStatus,
	createFunctionOptions *platform.CreateFunctionOptions) error {
	if existingFunctionConfig == nil &&
		createFunctionOptions.FunctionConfig.Spec.Build.Mode == functionconfig.NeverBuild {
		return errors.New("Non existing function cannot be created with neverBuild mode")
	}
	if err := ap.ValidateResourceVersion(existingFunctionConfig, &createFunctionOptions.FunctionConfig); err != nil {
		return nuclio.WrapErrConflict(err)
	}
	if existingFunctionConfig != nil &&
		existingFunctionConfig.Status.State == functionconfig.FunctionStateImported &&
		createFunctionOptions.FunctionConfig.Spec.Disable {
		return errors.New("Failed to disable function: non-deployed functions cannot be disabled")
	}
	if existingFunctionConfig != nil &&
		len(existingFunctionConfig.Status.APIGateways) > 0 &&
		createFunctionOptions.FunctionConfig.Spec.Disable {
		ap.Logger.WarnWith("Disabling function with assigned api gateway validation failed",
			"functionName", existingFunctionConfig.Meta.Name,
			"apiGateways", existingFunctionConfig.Status.APIGateways)
		return nuclio.NewErrBadRequest("Cannot disable function while used by an API gateway")
	}
	return nil
}
func (ap *Platform) ValidateResourceVersion(functionConfigWithStatus *functionconfig.ConfigWithStatus,
	requestFunctionConfig *functionconfig.Config) error {
	if functionConfigWithStatus == nil {
		return nil
	}
	existingResourceVersion := functionConfigWithStatus.Meta.ResourceVersion
	requestResourceVersion := requestFunctionConfig.Meta.ResourceVersion
	if requestResourceVersion != "" &&
		requestResourceVersion != existingResourceVersion {
		ap.Logger.WarnWith("Function resource version is stale",
			"functionName", functionConfigWithStatus.Meta.Name,
			"requestResourceVersion", requestResourceVersion,
			"existingResourceVersion", existingResourceVersion)
		return errors.New("Function resource version is stale")
	}
	return nil
}
func (ap *Platform) EnrichFunctionsWithDeployLogStream(functions []platform.Function) {
	for _, function := range functions {
		if deployLogStream, exists := ap.DeployLogStreams.Load(function.GetConfig().Meta.GetUniqueID()); exists {
			deployLogStream.(*LogStream).ReadLogs(nil, &function.GetStatus().Logs)
		}
	}
}
func (ap *Platform) ValidateFunctionConfig(functionConfig *functionconfig.Config) error {
	if common.StringInSlice(functionConfig.Meta.Name, ap.ResolveReservedResourceNames()) {
		return nuclio.NewErrPreconditionFailed(fmt.Sprintf("Function name %s is reserved and cannot be used.",
			functionConfig.Meta.Name))
	}
	if err := ap.validateDockerImageFields(functionConfig); err != nil {
		return errors.Wrap(err, "Docker image fields validation failed")
	}
	if err := ap.validateTriggers(functionConfig); err != nil {
		return errors.Wrap(err, "Triggers validation failed")
	}
	if err := ap.validateMinMaxReplicas(functionConfig); err != nil {
		return errors.Wrap(err, "Min max replicas validation failed")
	}
	if err := ap.validateNodeSelector(functionConfig); err != nil {
		return errors.Wrap(err, "Node selector validation failed")
	}
	if err := ap.validateProjectExists(functionConfig); err != nil {
		return errors.Wrap(err, "Project existence validation failed")
	}
	if err := ap.validateVolumes(functionConfig); err != nil {
		return errors.Wrap(err, "Volumes validation failed")
	}
	if err := ap.validatePriorityClassName(functionConfig); err != nil {
		return errors.Wrap(err, "Priority class name validation failed")
	}
	return nil
}
func (ap *Platform) ValidateDeleteProjectOptions(deleteProjectOptions *platform.DeleteProjectOptions) error {
	projectName := deleteProjectOptions.Meta.Name
	switch projectName {
	case platform.DefaultProjectName:
		if ap.Config.ProjectsLeader == nil {
			return nuclio.NewErrPreconditionFailed("Cannot delete the default project")
		}
	case "":
		return nuclio.NewErrBadRequest("Project name cannot be empty")
	}
	switch deleteProjectOptions.Strategy {
	case platform.DeleteProjectStrategyCheck, platform.DeleteProjectStrategyRestricted:
		projects, err := ap.platform.GetProjects(&platform.GetProjectsOptions{
			Meta:              deleteProjectOptions.Meta,
			RequestOrigin:     deleteProjectOptions.RequestOrigin,
			PermissionOptions: deleteProjectOptions.PermissionOptions,
			AuthSession:       deleteProjectOptions.AuthSession,
		})
		if err != nil {
			return errors.Wrap(err, "Failed to get project")
		}
		if len(projects) == 0 {
			return nil
		}
		functions, apiGateways, err := ap.GetProjectResources(&deleteProjectOptions.Meta)
		if err != nil {
			return errors.Wrap(err, "Failed to get project resources")
		}
		if len(functions) > 0 {
			return platform.ErrProjectContainsFunctions
		} else if len(apiGateways) > 0 {
			return platform.ErrProjectContainsAPIGateways
		}
	}
	return nil
}
func (ap *Platform) ValidateDeleteFunctionOptions(deleteFunctionOptions *platform.DeleteFunctionOptions) error {
	functionName := deleteFunctionOptions.FunctionConfig.Meta.Name
	functionNamespace := deleteFunctionOptions.FunctionConfig.Meta.Namespace
	functions, err := ap.platform.GetFunctions(&platform.GetFunctionsOptions{
		Name:              functionName,
		Namespace:         functionNamespace,
		AuthSession:       deleteFunctionOptions.AuthSession,
		PermissionOptions: deleteFunctionOptions.PermissionOptions,
	})
	if err != nil {
		return errors.Wrap(err, "Failed to get functions")
	}
	if len(functions) == 0 {
		ap.Logger.DebugWith("Function is already deleted", "functionName", functionName)
		return nil
	}
	functionToDelete := functions[0]
	if err := ap.ValidateResourceVersion(functionToDelete.GetConfigWithStatus(),
		&deleteFunctionOptions.FunctionConfig); err != nil {
		return nuclio.WrapErrConflict(err)
	}
	if !deleteFunctionOptions.IgnoreFunctionStateValidation {
		if functionconfig.FunctionStateProvisioning(functionToDelete.GetStatus().State) {
			ap.Logger.WarnWith("Function cannot be deleted as it is being provisioned",
				"functionName", functionToDelete.GetConfig().Meta.Name)
			return nuclio.NewErrPreconditionFailed("Function is being provisioned and cannot be deleted")
		}
	}
	permissionOptions := deleteFunctionOptions.PermissionOptions
	permissionOptions.RaiseForbidden = true
	if _, err := ap.QueryOPAFunctionPermissions(functionToDelete.GetConfig().Meta.Labels[common.NuclioResourceLabelKeyProjectName],
		functionToDelete.GetConfig().Meta.Name,
		opa.ActionDelete,
		&permissionOptions); err != nil {
		return errors.Wrap(err, "Failed authorizing OPA permissions for resource")
	}
	return nil
}
func (ap *Platform) ResolveReservedResourceNames() []string {
	return []string{
		"dashboard",
		"controller",
		"dlx",
		"scaler",
	}
}
func (ap *Platform) FilterProjectsByPermissions(permissionOptions *opa.PermissionOptions,
	projects []platform.Project) ([]platform.Project, error) {
	if len(permissionOptions.MemberIds) == 0 || len(projects) == 0 {
		return projects, nil
	}
	resources := make([]string, len(projects))
	for idx, project := range projects {
		projectName := project.GetConfig().Meta.Name
		resources[idx] = opa.GenerateProjectResourceString(projectName)
	}
	allowedList, err := ap.QueryOPAMultipleResources(resources, opa.ActionRead, permissionOptions)
	if err != nil {
		return nil, errors.Wrap(err, "Failed querying OPA for projects permissions")
	}
	var permittedProjects []platform.Project
	var filteredProjectNames []string
	for idx, allowed := range allowedList {
		if allowed {
			permittedProjects = append(permittedProjects, projects[idx])
		} else {
			filteredProjectNames = append(filteredProjectNames, projects[idx].GetConfig().Meta.Name)
		}
	}
	if len(filteredProjectNames) > 0 {
		ap.Logger.DebugWith("Some projects were filtered out", "projectNames", filteredProjectNames)
	}
	return permittedProjects, nil
}
func (ap *Platform) FilterFunctionsByPermissions(permissionOptions *opa.PermissionOptions,
	functions []platform.Function) ([]platform.Function, error) {
	if len(permissionOptions.MemberIds) == 0 || len(functions) == 0 {
		return functions, nil
	}
	resources := make([]string, len(functions))
	for idx, function := range functions {
		functionName := function.GetConfig().Meta.Name
		projectName := function.GetConfig().Meta.Labels[common.NuclioResourceLabelKeyProjectName]
		resources[idx] = opa.GenerateFunctionResourceString(projectName, functionName)
	}
	allowedList, err := ap.QueryOPAMultipleResources(resources, opa.ActionRead, permissionOptions)
	if err != nil {
		return nil, errors.Wrap(err, "Failed querying OPA for function permissions")
	}
	var permittedFunctions []platform.Function
	var filteredFunctionNames []string
	for idx, allowed := range allowedList {
		if allowed {
			permittedFunctions = append(permittedFunctions, functions[idx])
		} else {
			filteredFunctionNames = append(filteredFunctionNames, functions[idx].GetConfig().Meta.Name)
		}
	}
	if len(filteredFunctionNames) > 0 {
		ap.Logger.DebugWith("Some functions were filtered out", "functionNames", filteredFunctionNames)
	}
	return permittedFunctions, nil
}
func (ap *Platform) FilterFunctionEventsByPermissions(permissionOptions *opa.PermissionOptions,
	functionEvents []platform.FunctionEvent) ([]platform.FunctionEvent, error) {
	if len(permissionOptions.MemberIds) == 0 || len(functionEvents) == 0 {
		return functionEvents, nil
	}
	var resources []string
	for _, functionEventInstance := range functionEvents {
		projectName := functionEventInstance.GetConfig().Meta.Labels[common.NuclioResourceLabelKeyProjectName]
		functionName := functionEventInstance.GetConfig().Meta.Labels[common.NuclioResourceLabelKeyFunctionName]
		functionEventName := functionEventInstance.GetConfig().Meta.Name
		resources = append(resources, opa.GenerateFunctionEventResourceString(projectName,
			functionName,
			functionEventName))
	}
	allowedList, err := ap.QueryOPAMultipleResources(resources, opa.ActionRead, permissionOptions)
	if err != nil {
		return nil, errors.Wrap(err, "Failed querying OPA for function events permissions")
	}
	var permittedFunctionEvents []platform.FunctionEvent
	var filteredFunctionEventNames []string
	for idx, allowed := range allowedList {
		if allowed {
			permittedFunctionEvents = append(permittedFunctionEvents, functionEvents[idx])
		} else {
			filteredFunctionEventNames = append(filteredFunctionEventNames, functionEvents[idx].GetConfig().Meta.Name)
		}
	}
	if len(filteredFunctionEventNames) > 0 {
		ap.Logger.DebugWith("Some function events were filtered out",
			"functionEventNames", filteredFunctionEventNames)
	}
	return permittedFunctionEvents, nil
}
func (ap *Platform) CreateFunctionInvocation(
	createFunctionInvocationOptions *platform.CreateFunctionInvocationOptions) (
	*platform.CreateFunctionInvocationResult, error) {
	if createFunctionInvocationOptions.Headers == nil {
		createFunctionInvocationOptions.Headers = http.Header{}
	}
	functions, err := ap.platform.GetFunctions(&platform.GetFunctionsOptions{
		Name:              createFunctionInvocationOptions.Name,
		Namespace:         createFunctionInvocationOptions.Namespace,
		AuthSession:       createFunctionInvocationOptions.AuthSession,
		PermissionOptions: createFunctionInvocationOptions.PermissionOptions,
	})
	if err != nil {
		return nil, errors.Wrap(err, "Failed to get functions")
	}
	if len(functions) == 0 {
		return nil, nuclio.NewErrNotFound(fmt.Sprintf("Function not found: %s @ %s",
			createFunctionInvocationOptions.Name,
			createFunctionInvocationOptions.Namespace))
	}
	function := functions[0]
	if err := function.Initialize(nil); err != nil {
		return nil, errors.Wrap(err, "Failed to initialize function")
	}
	return ap.invoker.invoke(function, createFunctionInvocationOptions)
}
func (ap *Platform) GetHealthCheckMode() platform.HealthCheckMode {
	return platform.HealthCheckModeExternal
}
func (ap *Platform) CreateProject(createProjectOptions *platform.CreateProjectOptions) error {
	return platform.ErrUnsupportedMethod
}
func (ap *Platform) EnrichCreateProjectConfig(createProjectOptions *platform.CreateProjectOptions) error {
	if createProjectOptions.AuthSession != nil && createProjectOptions.ProjectConfig.Spec.Owner == "" {
		createProjectOptions.ProjectConfig.Spec.Owner = createProjectOptions.AuthSession.GetUsername()
	}
	return nil
}
func (ap *Platform) ValidateProjectConfig(projectConfig *platform.ProjectConfig) error {
	if projectConfig.Meta.Name == "" {
		return nuclio.NewErrBadRequest("Project name cannot be empty")
	}
	errorMessages := validation.IsDNS1123Label(projectConfig.Meta.Name)
	if len(errorMessages) != 0 {
		joinedErrorMessage := strings.Join(errorMessages, ", ")
		return nuclio.NewErrBadRequest(
			fmt.Sprintf(`Project name must adhere to Kubernetes naming conventions. Errors: %s`,
				joinedErrorMessage))
	}
	return nil
}
func (ap *Platform) UpdateProject(updateProjectOptions *platform.UpdateProjectOptions) error {
	return platform.ErrUnsupportedMethod
}
func (ap *Platform) DeleteProject(deleteProjectOptions *platform.DeleteProjectOptions) error {
	return platform.ErrUnsupportedMethod
}
func (ap *Platform) GetProjects(getProjectsOptions *platform.GetProjectsOptions) ([]platform.Project, error) {
	return nil, platform.ErrUnsupportedMethod
}
func (ap *Platform) CreateAPIGateway(createAPIGatewayOptions *platform.CreateAPIGatewayOptions) error {
	return platform.ErrUnsupportedMethod
}
func (ap *Platform) UpdateAPIGateway(updateAPIGatewayOptions *platform.UpdateAPIGatewayOptions) error {
	return platform.ErrUnsupportedMethod
}
func (ap *Platform) DeleteAPIGateway(deleteAPIGatewayOptions *platform.DeleteAPIGatewayOptions) error {
	return platform.ErrUnsupportedMethod
}
func (ap *Platform) GetAPIGateways(getAPIGatewaysOptions *platform.GetAPIGatewaysOptions) ([]platform.APIGateway, error) {
	return nil, platform.ErrUnsupportedMethod
}
func (ap *Platform) CreateFunctionEvent(createFunctionEventOptions *platform.CreateFunctionEventOptions) error {
	return platform.ErrUnsupportedMethod
}
func (ap *Platform) EnrichFunctionEvent(functionEventConfig *platform.FunctionEventConfig) error {
	if functionEventConfig.Meta.Labels == nil {
		functionEventConfig.Meta.Labels = map[string]string{}
	}
	if functionEventConfig.Spec.DisplayName == "" {
		functionEventConfig.Spec.DisplayName = functionEventConfig.Meta.Name
	}
	if functionEventConfig.Spec.TriggerKind == "" {
		functionEventConfig.Spec.TriggerKind = platform.DefaultFunctionEventTriggerKind
	}
	if functionEventConfig.Spec.TriggerKind == platform.FunctionEventTriggerKindHTTP {
		if functionEventConfig.Spec.Attributes == nil {
			functionEventConfig.Spec.Attributes = map[string]interface{}{}
		}
		for key, value := range map[string]interface{}{
			"headers": map[string]string{"Content-Type": "text/plain"},
			"method":  http.MethodPost,
			"path":    "",
		} {
			if _, exists := functionEventConfig.Spec.Attributes[key]; !exists {
				functionEventConfig.Spec.Attributes[key] = value
			}
		}
	}
	functionName, functionNameFound := functionEventConfig.Meta.Labels[common.NuclioResourceLabelKeyFunctionName]
	if !functionNameFound {
		return errors.Errorf("Function event has a missing label - `%s`",
			common.NuclioResourceLabelKeyFunctionName)
	}
	projectName, projectNameFound := functionEventConfig.Meta.Labels[common.NuclioResourceLabelKeyProjectName]
	if !projectNameFound {
		ap.Logger.DebugWith("Enriching function event project name",
			"functionEventName", functionEventConfig.Meta.Name,
			"functionEventNamespace", functionEventConfig.Meta.Namespace,
			"functionName", functionName)
		functions, err := ap.platform.GetFunctions(&platform.GetFunctionsOptions{
			Name:      functionName,
			Namespace: functionEventConfig.Meta.Namespace,
		})
		if err != nil {
			return errors.Wrap(err, "Failed to get function")
		}
		if len(functions) == 0 {
			return errors.Errorf("The Function event parent function does not exist")
		}
		function := functions[0]
		projectName = function.GetConfig().Meta.Labels[common.NuclioResourceLabelKeyProjectName]
	}
	functionEventConfig.Meta.Labels[common.NuclioResourceLabelKeyFunctionName] = functionName
	functionEventConfig.Meta.Labels[common.NuclioResourceLabelKeyProjectName] = projectName
	return nil
}
func (ap *Platform) UpdateFunctionEvent(updateFunctionEventOptions *platform.UpdateFunctionEventOptions) error {
	return platform.ErrUnsupportedMethod
}
func (ap *Platform) DeleteFunctionEvent(deleteFunctionEventOptions *platform.DeleteFunctionEventOptions) error {
	return platform.ErrUnsupportedMethod
}
func (ap *Platform) GetFunctionEvents(getFunctionEventsOptions *platform.GetFunctionEventsOptions) ([]platform.FunctionEvent, error) {
	return nil, platform.ErrUnsupportedMethod
}
func (ap *Platform) SetExternalIPAddresses(externalIPAddresses []string) error {
	ap.ExternalIPAddresses = externalIPAddresses
	return nil
}
func (ap *Platform) SetImageNamePrefixTemplate(imageNamePrefixTemplate string) {
	ap.ImageNamePrefixTemplate = imageNamePrefixTemplate
}
func (ap *Platform) GetImageNamePrefixTemplate() string {
	return ap.ImageNamePrefixTemplate
}
func (ap *Platform) RenderImageNamePrefixTemplate(projectName string, functionName string) (string, error) {
	return common.RenderTemplate(ap.ImageNamePrefixTemplate, map[string]interface{}{
		"ProjectName":  projectName,
		"FunctionName": functionName,
	})
}
func (ap *Platform) GetExternalIPAddresses() ([]string, error) {
	return ap.ExternalIPAddresses, nil
}
func (ap *Platform) GetScaleToZeroConfiguration() *platformconfig.ScaleToZero {
	return nil
}
func (ap *Platform) GetAllowedAuthenticationModes() []string {
	return nil
}
func (ap *Platform) ResolveDefaultNamespace(defaultNamespace string) string {
	return ""
}
func (ap *Platform) BuildAndPushContainerImage(buildOptions *containerimagebuilderpusher.BuildOptions) error {
	return ap.ContainerBuilder.BuildAndPushContainerImage(buildOptions,
		ap.platform.ResolveDefaultNamespace("@nuclio.selfNamespace"))
}
func (ap *Platform) GetOnbuildStages(onbuildArtifacts []runtime.Artifact) ([]string, error) {
	return ap.ContainerBuilder.GetOnbuildStages(onbuildArtifacts)
}