| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453 |
- package validate
- import (
- "fmt"
- "strings"
- )
- type RequestResources struct {
- cpu string
- memory string
- }
- type Resources struct {
- requests RequestResources
- }
- type Container struct {
- command string
- port string
- }
- type ServiceDef struct {
- port string
- }
- type Ingress struct {
- enabled bool
- custom_domain bool
- hosts []string
- porter_hosts []string
- annotations map[string]string
- }
- type HealthProbe struct {
- enabled bool
- failureThreshold int
- path string
- periodSeconds int
- }
- type HealthChecks struct {
- startupProbe HealthProbe
- livenessProbe HealthProbe
- readinessProbe HealthProbe
- }
- type AutoScaling struct {
- enabled bool
- minReplicas int
- maxReplicas int
- targetCPUUtilizationPercentage int
- targetMemoryUtilizationPercentage int
- }
- type CloudSql struct {
- enabled bool
- connectionName string
- dbPort int
- serviceAccountJSON string
- }
- type JobSchedule struct {
- enabled bool
- value string
- }
- type WebServiceConfig struct {
- replicaCount *string
- resources *Resources
- container *Container
- autoscaling *AutoScaling
- ingress *Ingress
- service *ServiceDef
- health *HealthChecks
- cloudsql *CloudSql
- }
- type WorkerServiceConfig struct {
- replicaCount *string
- container *Container
- resources *Resources
- autoscaling *AutoScaling
- cloudsql *CloudSql
- }
- type JobServiceConfig struct {
- allowConcurrent *bool
- container *Container
- resources *Resources
- schedule *JobSchedule
- paused *bool
- cloudsql *CloudSql
- }
- func getType(name string, service Service) string {
- if service.Type != "" {
- return service.Type
- }
- if strings.Contains(name, "web") {
- return "web"
- }
- if strings.Contains(name, "wkr") {
- return "worker"
- }
- return "job"
- }
- func HydrateService(current Service, previous Service, name string) (Service, error) {
- service := Service{}
- serviceType := getType(name, current)
- switch serviceType {
- case "web":
- service, err := hydrateWebService(current, previous)
- if err != nil {
- return service, err
- }
- case "worker":
- service, err := hydrateWorkerService(current, previous)
- if err != nil {
- return service, err
- }
- case "job":
- service, err := hydrateJobService(current, previous)
- if err != nil {
- return service, err
- }
- }
- return service, nil
- }
- func hydrateWebService(current, previous Service) (Service, error) {
- service := Service{
- Type: "web",
- Run: previous.Run,
- }
- if current.Run != "" {
- service.Run = current.Run
- }
- validatedConfig := WebServiceConfig{}
- currentConfig := WebServiceConfig{}
- // check if current.Config exists
- if current.Config != nil {
- // cast current.Config to WebServiceConfig
- config, ok := current.Config.(WebServiceConfig)
- if !ok {
- return service, fmt.Errorf("unable to cast current service config to web service config")
- }
- currentConfig = config
- }
- previousConfig := WebServiceConfig{}
- // check if previous.Config exists
- if previous.Config != nil {
- // cast previous.Config to WebServiceConfig
- config, ok := previous.Config.(WebServiceConfig)
- if !ok {
- return service, fmt.Errorf("unable to cast existing service config to web service config")
- }
- previousConfig = config
- }
- container, err := validateContainer(currentConfig.container, previousConfig.container)
- if err != nil {
- return service, fmt.Errorf("unable to validate container for web service: %w", err)
- }
- validatedConfig.container = container
- resources, err := validateResources(currentConfig.resources, previousConfig.resources)
- if err != nil {
- return service, fmt.Errorf("unable to validate resources for web service: %w", err)
- }
- validatedConfig.resources = resources
- autoScaling, err := validateAutoScaling(currentConfig.autoscaling, previousConfig.autoscaling)
- if err != nil {
- return service, fmt.Errorf("unable to validate autoscaling for web service: %w", err)
- }
- validatedConfig.autoscaling = autoScaling
- ingress, err := validateIngress(currentConfig.ingress, previousConfig.ingress)
- if err != nil {
- return service, fmt.Errorf("unable to validate ingress for web service: %w", err)
- }
- validatedConfig.ingress = ingress
- serviceDef, err := validateService(currentConfig.service, previousConfig.service)
- if err != nil {
- return service, fmt.Errorf("unable to validate service for web service: %w", err)
- }
- validatedConfig.service = serviceDef
- fmt.Printf("validatedConfig: %+v\n", validatedConfig)
- service.Config = validatedConfig
- return service, nil
- }
- func hydrateWorkerService(current, previous Service) (Service, error) {
- service := Service{
- Type: "worker",
- Run: previous.Run,
- }
- if current.Run != "" {
- service.Run = current.Run
- }
- validatedConfig := WorkerServiceConfig{}
- currentConfig := WorkerServiceConfig{}
- // check if current.Config exists
- if current.Config != nil {
- // cast current.Config to WorkerServiceConfig
- config, ok := current.Config.(WorkerServiceConfig)
- if !ok {
- return service, fmt.Errorf("unable to cast current config to worker service config")
- }
- currentConfig = config
- }
- previousConfig := WorkerServiceConfig{}
- // check if previous.Config exists
- if previous.Config != nil {
- // cast previous.Config to WorkerServiceConfig
- config, ok := previous.Config.(WorkerServiceConfig)
- if !ok {
- return service, fmt.Errorf("unable to cast previous config to worker service config")
- }
- previousConfig = config
- }
- container, err := validateContainer(currentConfig.container, previousConfig.container)
- if err != nil {
- return service, fmt.Errorf("unable to validate container for worker service: %w", err)
- }
- validatedConfig.container = container
- resources, err := validateResources(currentConfig.resources, previousConfig.resources)
- if err != nil {
- return service, fmt.Errorf("unable to validate resources for worker service: %w", err)
- }
- validatedConfig.resources = resources
- autoScaling, err := validateAutoScaling(currentConfig.autoscaling, previousConfig.autoscaling)
- if err != nil {
- return service, fmt.Errorf("unable to validate autoscaling for worker service: %w", err)
- }
- validatedConfig.autoscaling = autoScaling
- cloudsql, err := validateCloudSql(currentConfig.cloudsql, previousConfig.cloudsql)
- if err != nil {
- return service, fmt.Errorf("unable to validate cloudsql for worker service: %w", err)
- }
- validatedConfig.cloudsql = cloudsql
- service.Config = validatedConfig
- return service, nil
- }
- func hydrateJobService(current, previous Service) (Service, error) {
- service := Service{}
- return service, nil
- }
- func validateContainer(current, previous *Container) (*Container, error) {
- container := &Container{
- command: "",
- port: "80",
- }
- if previous != nil {
- container = previous
- }
- // merge current into container
- if current != nil {
- if current.command != "" {
- container.command = current.command
- }
- if current.port != "" {
- container.port = current.port
- }
- }
- return container, nil
- }
- func validateResources(current, previous *Resources) (*Resources, error) {
- resources := &Resources{
- requests: RequestResources{
- cpu: "100m",
- memory: "256Mi",
- },
- }
- if previous != nil {
- resources = previous
- }
- // merge current into resources
- if current != nil {
- if current.requests.cpu != "" {
- resources.requests.cpu = current.requests.cpu
- }
- if current.requests.memory != "" {
- resources.requests.memory = current.requests.memory
- }
- }
- return resources, nil
- }
- func validateAutoScaling(current, previous *AutoScaling) (*AutoScaling, error) {
- autoScaling := &AutoScaling{
- enabled: false,
- minReplicas: 1,
- maxReplicas: 10,
- targetCPUUtilizationPercentage: 50,
- targetMemoryUtilizationPercentage: 50,
- }
- if previous != nil {
- autoScaling = previous
- }
- // merge current into autoScaling
- if current != nil {
- if current.enabled {
- autoScaling.enabled = current.enabled
- }
- if current.minReplicas != 0 {
- autoScaling.minReplicas = current.minReplicas
- }
- if current.maxReplicas != 0 {
- autoScaling.maxReplicas = current.maxReplicas
- }
- if current.targetCPUUtilizationPercentage != 0 {
- autoScaling.targetCPUUtilizationPercentage = current.targetCPUUtilizationPercentage
- }
- if current.targetMemoryUtilizationPercentage != 0 {
- autoScaling.targetMemoryUtilizationPercentage = current.targetMemoryUtilizationPercentage
- }
- }
- return autoScaling, nil
- }
- func validateIngress(current, previous *Ingress) (*Ingress, error) {
- ingress := &Ingress{
- enabled: false,
- custom_domain: false,
- hosts: []string{},
- porter_hosts: []string{},
- annotations: map[string]string{},
- }
- if previous != nil {
- ingress = previous
- }
- // merge current into ingress
- if current != nil {
- if current.enabled {
- ingress.enabled = current.enabled
- }
- if current.custom_domain {
- ingress.custom_domain = current.custom_domain
- }
- if len(current.hosts) > 0 {
- ingress.hosts = current.hosts
- }
- if len(current.porter_hosts) > 0 {
- ingress.porter_hosts = current.porter_hosts
- }
- if len(current.annotations) > 0 {
- ingress.annotations = current.annotations
- }
- }
- return ingress, nil
- }
- func validateService(current, previous *ServiceDef) (*ServiceDef, error) {
- service := &ServiceDef{
- port: "80",
- }
- if previous != nil {
- service = previous
- }
- // merge current into service
- if current != nil {
- if current.port != "" {
- service.port = current.port
- }
- }
- return service, nil
- }
- func validateCloudSql(current, previous *CloudSql) (*CloudSql, error) {
- cloudsql := &CloudSql{
- enabled: false,
- connectionName: "",
- dbPort: 5432,
- serviceAccountJSON: "",
- }
- if previous != nil {
- cloudsql = previous
- }
- // merge current into cloudsql
- if current != nil {
- if current.enabled {
- cloudsql.enabled = current.enabled
- }
- if current.connectionName != "" {
- cloudsql.connectionName = current.connectionName
- }
- if current.dbPort != 0 {
- cloudsql.dbPort = current.dbPort
- }
- if current.serviceAccountJSON != "" {
- cloudsql.serviceAccountJSON = current.serviceAccountJSON
- }
- }
- return cloudsql, nil
- }
|