func (s *Status) DeepCopyInto(out *Status) {
	*out = *s
}
DeepCopyInto copies to appease k8s
package functionconfig
import (
	"fmt"
	"strconv"
	"time"
	"github.com/v3io/scaler/pkg/scalertypes"
	appsv1 "k8s.io/api/apps/v1"
	autosv2 "k8s.io/api/autoscaling/v2beta1"
	"k8s.io/api/core/v1"
)
const (
	NvidiaGPUResourceName = "nvidia.com/gpu"
)
type DataBinding struct {
	Name       string                 `json:"name,omitempty"`
	Class      string                 `json:"class"`
	Kind       string                 `json:"kind"`
	URL        string                 `json:"url"`
	Path       string                 `json:"path,omitempty"`
	Query      string                 `json:"query,omitempty"`
	Secret     string                 `json:"secret,omitempty"`
	Attributes map[string]interface{} `json:"attributes,omitempty"`
}
type Checkpoint *string
type Partition struct {
	ID         string     `json:"id"`
	Checkpoint Checkpoint `json:"checkpoint,omitempty"`
}
type Volume struct {
	Volume      v1.Volume      `json:"volume,omitempty"`
	VolumeMount v1.VolumeMount `json:"volumeMount,omitempty"`
}
type Trigger struct {
	Class                                 string            `json:"class"`
	Kind                                  string            `json:"kind"`
	Name                                  string            `json:"name"`
	Disabled                              bool              `json:"disabled,omitempty"`
	MaxWorkers                            int               `json:"maxWorkers,omitempty"`
	URL                                   string            `json:"url,omitempty"`
	Paths                                 []string          `json:"paths,omitempty"`
	Username                              string            `json:"username,omitempty"`
	Password                              string            `json:"password,omitempty"`
	Secret                                string            `json:"secret,omitempty"`
	Partitions                            []Partition       `json:"partitions,omitempty"`
	Annotations                           map[string]string `json:"annotations,omitempty"`
	WorkerAvailabilityTimeoutMilliseconds *int              `json:"workerAvailabilityTimeoutMilliseconds,omitempty"`
	WorkerAllocatorName                   string            `json:"workerAllocatorName,omitempty"`
	TotalTasks        int `json:"total_tasks,omitempty"`
	MaxTaskAllocation int `json:"max_task_allocation,omitempty"`
	Attributes map[string]interface{} `json:"attributes,omitempty"`
}
func GetTriggersByKind(triggers map[string]Trigger, kind string) map[string]Trigger {
	matchingTrigger := map[string]Trigger{}
	for triggerName, trigger := range triggers {
		if trigger.Kind == kind {
			matchingTrigger[triggerName] = trigger
		}
	}
	return matchingTrigger
}
func ResolveFunctionServiceType(functionSpec *Spec, defaultServiceType v1.ServiceType) v1.ServiceType {
	functionHTTPTriggers := GetTriggersByKind(functionSpec.Triggers, "http")
	for _, trigger := range functionHTTPTriggers {
		if serviceTypeInterface, serviceTypeExists := trigger.Attributes["serviceType"]; serviceTypeExists {
			if serviceType, serviceTypeIsString := serviceTypeInterface.(string); serviceTypeIsString {
				return v1.ServiceType(serviceType)
			}
		}
	}
	if functionSpec.ServiceType != "" {
		return functionSpec.ServiceType
	}
	return defaultServiceType
}
func GetFunctionIngresses(config *Config) map[string]Ingress {
	ingresses := map[string]Ingress{}
	for _, httpTrigger := range GetTriggersByKind(config.Spec.Triggers, "http") {
		if encodedIngresses, found := httpTrigger.Attributes["ingresses"]; found {
			encodedIngresses := encodedIngresses.(map[string]interface{})
			for encodedIngressName, encodedIngress := range encodedIngresses {
				encodedIngressMap := encodedIngress.(map[string]interface{})
				var ingress Ingress
				if host, ok := encodedIngressMap["host"].(string); ok {
					ingress.Host = host
				}
				switch typedPaths := encodedIngressMap["paths"].(type) {
				case []string:
					ingress.Paths = typedPaths
				case []interface{}:
					for _, path := range typedPaths {
						ingress.Paths = append(ingress.Paths, path.(string))
					}
				}
				var ingressTLS IngressTLS
				if secretName, ok := encodedIngressMap["secretName"].(string); ok {
					hostsList := []string{ingress.Host}
					ingressTLS.Hosts = hostsList
					ingressTLS.SecretName = secretName
				}
				ingress.TLS = ingressTLS
				ingresses[encodedIngressName] = ingress
			}
		}
	}
	return ingresses
}
func GetDefaultHTTPTrigger() Trigger {
	return Trigger{
		Kind:       "http",
		Name:       "default-http",
		MaxWorkers: 1,
	}
}
type Ingress struct {
	Host  string     `json:"host,omitempty"`
	Paths []string   `json:"paths,omitempty"`
	TLS   IngressTLS `json:"tls,omitempty"`
}
type IngressTLS struct {
	Hosts      []string `json:"hosts,omitempty"`
	SecretName string   `json:"secretName,omitempty"`
}
type LoggerSink struct {
	Level string `json:"level,omitempty"`
	Sink  string `json:"sink,omitempty"`
}
type Platform struct {
	Attributes map[string]interface{} `json:"attributes,omitempty"`
}
type Directive struct {
	Kind  string `json:"kind,omitempty"`
	Value string `json:"value,omitempty"`
}
type Metric struct {
	SourceType     string `json:"sourceType,omitempty"`
	ThresholdValue int64  `json:"thresholdValue,omitempty"`
	WindowSize     string `json:"windowSize,omitempty"`
}
type BuildMode string
const (
	NeverBuild  BuildMode = "neverBuild"
	AlwaysBuild BuildMode = "alwaysBuild"
)
type Build struct {
	Path                string                 `json:"path,omitempty"`
	FunctionSourceCode  string                 `json:"functionSourceCode,omitempty"`
	FunctionConfigPath  string                 `json:"functionConfigPath,omitempty"`
	TempDir             string                 `json:"tempDir,omitempty"`
	Registry            string                 `json:"registry,omitempty"`
	BaseImageRegistry   string                 `json:"baseImageRegistry,omitempty"`
	Image               string                 `json:"image,omitempty"`
	NoBaseImagesPull    bool                   `json:"noBaseImagesPull,omitempty"`
	NoCache             bool                   `json:"noCache,omitempty"`
	NoCleanup           bool                   `json:"noCleanup,omitempty"`
	BaseImage           string                 `json:"baseImage,omitempty"`
	Commands            []string               `json:"commands,omitempty"`
	Directives          map[string][]Directive `json:"directives,omitempty"`
	ScriptPaths         []string               `json:"scriptPaths,omitempty"`
	AddedObjectPaths    map[string]string      `json:"addedPaths,omitempty"`
	Dependencies        []string               `json:"dependencies,omitempty"`
	OnbuildImage        string                 `json:"onbuildImage,omitempty"`
	Offline             bool                   `json:"offline,omitempty"`
	RuntimeAttributes   map[string]interface{} `json:"runtimeAttributes,omitempty"`
	CodeEntryType       string                 `json:"codeEntryType,omitempty"`
	CodeEntryAttributes map[string]interface{} `json:"codeEntryAttributes,omitempty"`
	Timestamp           int64                  `json:"timestamp,omitempty"`
	BuildTimeoutSeconds *int64                 `json:"buildTimeoutSeconds,omitempty"`
	Mode                BuildMode              `json:"mode,omitempty"`
	Args                map[string]string      `json:"args,omitempty"`
}
type Spec struct {
	Description             string                  `json:"description,omitempty"`
	Disable                 bool                    `json:"disable,omitempty"`
	Publish                 bool                    `json:"publish,omitempty"`
	Handler                 string                  `json:"handler,omitempty"`
	Runtime                 string                  `json:"runtime,omitempty"`
	Env                     []v1.EnvVar             `json:"env,omitempty"`
	Resources               v1.ResourceRequirements `json:"resources,omitempty"`
	Image                   string                  `json:"image,omitempty"`
	ImageHash               string                  `json:"imageHash,omitempty"`
	Replicas                *int                    `json:"replicas,omitempty"`
	MinReplicas             *int                    `json:"minReplicas,omitempty"`
	MaxReplicas             *int                    `json:"maxReplicas,omitempty"`
	TargetCPU               int                     `json:"targetCPU,omitempty"`
	DataBindings            map[string]DataBinding  `json:"dataBindings,omitempty"`
	Triggers                map[string]Trigger      `json:"triggers,omitempty"`
	Volumes                 []Volume                `json:"volumes,omitempty"`
	Version                 int                     `json:"version,omitempty"`
	Alias                   string                  `json:"alias,omitempty"`
	Build                   Build                   `json:"build,omitempty"`
	RunRegistry             string                  `json:"runRegistry,omitempty"`
	ImagePullSecrets        string                  `json:"imagePullSecrets,omitempty"`
	RuntimeAttributes       map[string]interface{}  `json:"runtimeAttributes,omitempty"`
	LoggerSinks             []LoggerSink            `json:"loggerSinks,omitempty"`
	DealerURI               string                  `json:"dealerURI,omitempty"`
	Platform                Platform                `json:"platform,omitempty"`
	ReadinessTimeoutSeconds int                     `json:"readinessTimeoutSeconds,omitempty"`
	Avatar                  string                  `json:"avatar,omitempty"`
	ServiceType             v1.ServiceType          `json:"serviceType,omitempty"`
	ImagePullPolicy         v1.PullPolicy           `json:"imagePullPolicy,omitempty"`
	SecurityContext         *v1.PodSecurityContext  `json:"securityContext,omitempty"`
	ServiceAccount          string                  `json:"serviceAccount,omitempty"`
	ScaleToZero             *ScaleToZeroSpec        `json:"scaleToZero,omitempty"`
	Affinity     *v1.Affinity      `json:"affinity,omitempty"`
	NodeSelector map[string]string `json:"nodeSelector,omitempty"`
	NodeName     string            `json:"nodeName,omitempty"`
	PriorityClassName string               `json:"priorityClassName,omitempty"`
	PreemptionPolicy  *v1.PreemptionPolicy `json:"preemptionPolicy,omitempty"`
	DeploymentStrategy *appsv1.DeploymentStrategy `json:"deploymentStrategy,omitempty"`
	HostIPC bool `json:"hostIPC,omitempty"`
	CustomScalingMetricSpecs []autosv2.MetricSpec `json:"customScalingMetricSpecs,omitempty"`
	WaitReadinessTimeoutBeforeFailure bool `json:"waitReadinessTimeoutBeforeFailure,omitempty"`
	EventTimeout string `json:"eventTimeout"`
}
type ScaleToZeroSpec struct {
	ScaleResources []ScaleResource `json:"scaleResources,omitempty"`
}
type ScaleResource struct {
	MetricName string `json:"metricName,omitempty"`
	WindowSize string `json:"windowSize,omitempty"`
	Threshold  int    `json:"threshold"`
}
func (s *Spec) DeepCopyInto(out *Spec) {
	*out = *s
}
func (s *Spec) GetHTTPPort() int {
	if s.Triggers == nil {
		return 0
	}
	for _, trigger := range s.Triggers {
		if trigger.Kind == "http" {
			httpPort, httpPortValid := trigger.Attributes["port"]
			if httpPortValid {
				switch typedHTTPPort := httpPort.(type) {
				case int8:
					return int(typedHTTPPort)
				case int16:
					return int(typedHTTPPort)
				case int32:
					return int(typedHTTPPort)
				case int64:
					return int(typedHTTPPort)
				case uint:
					return int(typedHTTPPort)
				case uint8:
					return int(typedHTTPPort)
				case uint16:
					return int(typedHTTPPort)
				case uint32:
					return int(typedHTTPPort)
				case uint64:
					return int(typedHTTPPort)
				case float32:
					return int(typedHTTPPort)
				case float64:
					return int(typedHTTPPort)
				case int:
					return typedHTTPPort
				}
			}
		}
	}
	return 0
}
func (s *Spec) GetEventTimeout() (time.Duration, error) {
	timeout, err := time.ParseDuration(s.EventTimeout)
	if err == nil && timeout <= 0 {
		err = fmt.Errorf("eventTimeout <= 0 (%s)", timeout)
	}
	return timeout, err
}
func (s *Spec) PositiveGPUResourceLimit() bool {
	if gpuResourceLimit, found := s.Resources.Limits[NvidiaGPUResourceName]; found {
		return !gpuResourceLimit.IsZero()
	}
	return false
}
const (
	FunctionAnnotationSkipBuild  = "skip-build"
	FunctionAnnotationSkipDeploy = "skip-deploy"
)
type Meta struct {
	Name        string            `json:"name,omitempty"`
	Namespace   string            `json:"namespace,omitempty"`
	Labels      map[string]string `json:"labels,omitempty"`
	Annotations map[string]string `json:"annotations,omitempty"`
	ResourceVersion string `json:"resourceVersion,omitempty"`
}
func (m *Meta) GetUniqueID() string {
	return m.Namespace + ":" + m.Name
}
func (m *Meta) AddSkipDeployAnnotation() {
	m.Annotations[FunctionAnnotationSkipDeploy] = strconv.FormatBool(true)
}
func (m *Meta) AddSkipBuildAnnotation() {
	m.Annotations[FunctionAnnotationSkipBuild] = strconv.FormatBool(true)
}
func (m *Meta) RemoveSkipDeployAnnotation() {
	delete(m.Annotations, FunctionAnnotationSkipDeploy)
}
func (m *Meta) RemoveSkipBuildAnnotation() {
	delete(m.Annotations, FunctionAnnotationSkipBuild)
}
func ShouldSkipDeploy(annotations map[string]string) bool {
	var skipFunctionDeploy bool
	if skipFunctionBuildDeploy, ok := annotations[FunctionAnnotationSkipDeploy]; ok {
		skipFunctionDeploy, _ = strconv.ParseBool(skipFunctionBuildDeploy)
	}
	return skipFunctionDeploy
}
func ShouldSkipBuild(annotations map[string]string) bool {
	var skipFunctionBuild bool
	if skipFunctionBuildStr, ok := annotations[FunctionAnnotationSkipBuild]; ok {
		skipFunctionBuild, _ = strconv.ParseBool(skipFunctionBuildStr)
	}
	return skipFunctionBuild
}
type Config struct {
	Meta Meta `json:"metadata,omitempty"`
	Spec Spec `json:"spec,omitempty"`
}
func NewConfig() *Config {
	return &Config{
		Meta: Meta{
			Namespace: "default",
		},
	}
}
func (c *Config) CleanFunctionSpec() {
	c.Spec.RunRegistry = ""
	c.Spec.Build.Registry = ""
	if c.Spec.Build.FunctionSourceCode != "" {
		c.Spec.Image = ""
	}
}
func (c *Config) PrepareFunctionForExport(noScrub bool) {
	if !noScrub {
		c.scrubFunctionData()
	}
	c.AddSkipAnnotations()
}
func (c *Config) AddSkipAnnotations() {
	if c.Meta.Annotations == nil {
		c.Meta.Annotations = map[string]string{}
	}
	c.Meta.AddSkipBuildAnnotation()
	c.Meta.AddSkipDeployAnnotation()
}
func (c *Config) scrubFunctionData() {
	c.CleanFunctionSpec()
	c.Meta.Namespace = ""
	c.Meta.ResourceVersion = ""
	newTriggers := c.Spec.Triggers
	for triggerName, trigger := range newTriggers {
		trigger.Password = ""
		trigger.Secret = ""
		newTriggers[triggerName] = trigger
	}
	c.Spec.Triggers = newTriggers
}
type FunctionState string
const (
	FunctionStateWaitingForBuild                  FunctionState = "waitingForBuild"
	FunctionStateBuilding                         FunctionState = "building"
	FunctionStateWaitingForResourceConfiguration  FunctionState = "waitingForResourceConfiguration"
	FunctionStateWaitingForScaleResourcesFromZero FunctionState = "waitingForScaleResourceFromZero"
	FunctionStateWaitingForScaleResourcesToZero   FunctionState = "waitingForScaleResourceToZero"
	FunctionStateConfiguringResources             FunctionState = "configuringResources"
	FunctionStateReady                            FunctionState = "ready"
	FunctionStateError                            FunctionState = "error"
	FunctionStateUnhealthy                        FunctionState = "unhealthy"
	FunctionStateScaledToZero                     FunctionState = "scaledToZero"
	FunctionStateImported                         FunctionState = "imported"
)
func FunctionStateInSlice(functionState FunctionState, functionStates []FunctionState) bool {
	for _, state := range functionStates {
		if functionState == state {
			return true
		}
	}
	return false
}
func FunctionStateProvisioned(functionState FunctionState) bool {
	return FunctionStateInSlice(functionState,
		[]FunctionState{
			FunctionStateReady,
			FunctionStateError,
			FunctionStateUnhealthy,
			FunctionStateScaledToZero,
			FunctionStateImported,
		})
}
func FunctionStateProvisioning(functionState FunctionState) bool {
	return !FunctionStateProvisioned(functionState)
}
type Status struct {
	State       FunctionState            `json:"state,omitempty"`
	Message     string                   `json:"message,omitempty"`
	Logs        []map[string]interface{} `json:"logs,omitempty"`
	ScaleToZero *ScaleToZeroStatus       `json:"scaleToZero,omitempty"`
	APIGateways []string                 `json:"apiGateways,omitempty"`
	HTTPPort    int                      `json:"httpPort,omitempty"`
	InternalInvocationURLs []string `json:"internalInvocationUrls,omitempty"`
	ExternalInvocationURLs []string `json:"externalInvocationUrls,omitempty"`
}
func (s *Status) InvocationURLs() []string {
	return append(s.InternalInvocationURLs, s.ExternalInvocationURLs...)
}
type ScaleToZeroStatus struct {
	LastScaleEvent     scalertypes.ScaleEvent `json:"lastScaleEvent,omitempty"`
	LastScaleEventTime *time.Time             `json:"lastScaleEventTime,omitempty"`
}