From 3c352fb46020b67129069258f2c06e17b9ef20fb Mon Sep 17 00:00:00 2001 From: Felix Kunde Date: Fri, 5 Jun 2020 11:14:17 +0200 Subject: [PATCH] bump pooler image and more coalescing for CRD config (#1004) Co-authored-by: Felix Kunde --- charts/postgres-operator-ui/index.yaml | 8 ++-- .../postgres-operator-ui-1.5.0.tgz | Bin 3799 -> 3512 bytes charts/postgres-operator/index.yaml | 8 ++-- .../postgres-operator-1.5.0.tgz | Bin 15843 -> 15565 bytes charts/postgres-operator/values-crd.yaml | 4 +- charts/postgres-operator/values.yaml | 4 +- manifests/configmap.yaml | 5 +- manifests/operatorconfiguration.crd.yaml | 20 ++++++++ ...gresql-operator-default-configuration.yaml | 4 +- manifests/postgresql.crd.yaml | 32 +++++++++++++ pkg/controller/operator_config.go | 44 +++++++++--------- pkg/util/config/config.go | 2 +- pkg/util/util.go | 44 ++++++++++++++++++ 13 files changed, 136 insertions(+), 39 deletions(-) diff --git a/charts/postgres-operator-ui/index.yaml b/charts/postgres-operator-ui/index.yaml index 2da53497d..5a7b42d80 100644 --- a/charts/postgres-operator-ui/index.yaml +++ b/charts/postgres-operator-ui/index.yaml @@ -3,10 +3,10 @@ entries: postgres-operator-ui: - apiVersion: v1 appVersion: 1.5.0 - created: "2020-05-08T12:07:31.651762139+02:00" + created: "2020-06-04T17:06:37.153522579+02:00" description: Postgres Operator UI provides a graphical interface for a convenient database-as-a-service user experience - digest: d7a36de8a3716f7b7954e2e51ed07863ea764dbb129a2fd3ac6a453f9e98a115 + digest: c91ea39e6d51d57f4048fb1b6ec53b40823f2690eb88e4e4f1a036367b9fdd61 home: https://github.com/zalando/postgres-operator keywords: - postgres @@ -26,7 +26,7 @@ entries: version: 1.5.0 - apiVersion: v1 appVersion: 1.4.0 - created: "2020-05-08T12:07:31.651223951+02:00" + created: "2020-06-04T17:06:37.15302073+02:00" description: Postgres Operator UI provides a graphical interface for a convenient database-as-a-service user experience digest: 00e0eff7056d56467cd5c975657fbb76c8d01accd25a4b7aca81bc42aeac961d @@ -49,4 +49,4 @@ entries: urls: - postgres-operator-ui-1.4.0.tgz version: 1.4.0 -generated: "2020-05-08T12:07:31.650495247+02:00" +generated: "2020-06-04T17:06:37.152369987+02:00" diff --git a/charts/postgres-operator-ui/postgres-operator-ui-1.5.0.tgz b/charts/postgres-operator-ui/postgres-operator-ui-1.5.0.tgz index 4443e15bc739899f370f7c71a2d45e78172c09a1..d8527f293f9ad6864a4c19af3b7980964c1bb0f7 100644 GIT binary patch delta 3487 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 N|NrzppZ)++002&u)<*yU delta 3776 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 diff --git a/charts/postgres-operator/index.yaml b/charts/postgres-operator/index.yaml index 63c7b450d..3c62625a1 100644 --- a/charts/postgres-operator/index.yaml +++ b/charts/postgres-operator/index.yaml @@ -3,10 +3,10 @@ entries: postgres-operator: - apiVersion: v1 appVersion: 1.5.0 - created: "2020-05-04T16:36:19.646719041+02:00" + created: "2020-06-04T17:06:49.41741489+02:00" description: Postgres Operator creates and manages PostgreSQL clusters running in Kubernetes - digest: 43510e4ed7005b2b80708df24cfbb0099b263b4a2954cff4e8f305543760be6d + digest: 198351d5db52e65cdf383d6f3e1745d91ac1e2a01121f8476f8b1be728b09531 home: https://github.com/zalando/postgres-operator keywords: - postgres @@ -25,7 +25,7 @@ entries: version: 1.5.0 - apiVersion: v1 appVersion: 1.4.0 - created: "2020-05-04T16:36:19.645338751+02:00" + created: "2020-06-04T17:06:49.416001109+02:00" description: Postgres Operator creates and manages PostgreSQL clusters running in Kubernetes digest: f8b90fecfc3cb825b94ed17edd9d5cefc36ae61801d4568597b4a79bcd73b2e9 @@ -45,4 +45,4 @@ entries: urls: - postgres-operator-1.4.0.tgz version: 1.4.0 -generated: "2020-05-04T16:36:19.643857452+02:00" +generated: "2020-06-04T17:06:49.414521538+02:00" diff --git a/charts/postgres-operator/postgres-operator-1.5.0.tgz b/charts/postgres-operator/postgres-operator-1.5.0.tgz index f575f7cfd04c55f39bf421afd6ce0a63ddb654db..6e1a48ab772c479d991b518a7a5164311b93a632 100644 GIT binary patch literal 15565 zcmYM*Q*b8H8ZO}2nb@}NWMbR4ZCihA+qP}noN$7PJ()Q9PxjuY&gqM;zF5^)UG=T? zzE2ayz@UTt=K|7z&>2gqFq=xrbIN)1aG0=ZFq^4zSnH_ra4KqOaLQ}i*%&*Rd8;Wq z@=KZ9*@Im5d3)|~rc>_)Zd435th(yB%<7QKde~5|2x_amTbt^eV787(tph#$hh|#YU*r?Y6 zsAq?otuDdIP}MiGgOFx3fI|d9Zux7$$eyv|B5V{4w|tq8yR`;0ib_@5Dtb3qki{*xFuVBLe2{6hp53IQlNaB((pA$6V&wE0$a{+WyT`YKV ztAlfs!5(mnbSsTxV5geIn}UsQtOk_CSm%cDn1&GZijzo_wMR;mGO*lQT31HCO|4Z4 zd8*9^?@>);oC*?tM3UiFL-E2SK`4?QLjQbp{QFF{n)Z`Se=Rl~poPk?3V?~C$g)TZ z`UO5opAtFF0!x!lu2Yx@nh{i-D~|H9P8_{X`r&*)CvszX9($A+tK=C?W}FT9q(@P} zq$csC9z|7bB&Ieu-ZK(2wSmHGf{5~tH9=+Tr`AFFyE$O44E6WqF=CP!;H)532&FCc zgIfVdG9!EDaZx*W8gd!}33kUF(3!5p9=psjoDwPQmqf`KlN((_;&FV!n zFAF1ii#`&_Wael75Mh!3=$(df?<*STET7^JIz);SQXQs&Ujj_>iJ)Se2#3hY<5JO- z<2yer#KO?9{~Jkt@1BPt7_SkE6h}=39n8TW91;?RaSBmUa9HCc$3H`YW2T4X=6#FTxp?bzYj3Y}3Xwc0ULqyqgJ~fQ}k-S>+Vs zNkgD1i`wcJk_fD$&DHMhBEt(xHN%uN?vhZ7C?D4=++vFLz42%@20;c(IQd!st zR-5BOPqbv$oGGv+z_in{aCad%LxvLKN!V4*64y3fUO!PuVz3pQ==*1lA4y3M&%yl5 zvR>v5vF`W=hve&Ff>sb2BvAy(+6RVsbP+K>h>Kw)t9m&fKY5xJ7>sz@9H^su#n z0vUq{xY@rph`O^J$deyQJusPRzmrhy?*HO7XP)h&wG@-lk|T6)YfWoMTf+ULv2+%YVo^9tg@Kjgo|QWn zgrr(yo4G+n`5k!&$0^RExSaWu3GS%?CzTxw)kZt-_z;GDx&`7uh>V9sbv&x*K+S4h zayTSL*nI%mQl?g}`4>Vq$ao~0G)lfg(Fd3o>8yJHy$WVDSUI7-wEaD+V3QJ)qG1gQ zsZHtL((wzXYNk0mhyW-32z=G=EL8AMX-pfO3FB@HX8LQm3vkpXGpK@VtusQH&1xTK zt@e81R7uhdRMEb!Uuqi~sM+@NbPcNUVaM9UZ1v>mqzDvYuZm5`GHmKfGhzPfn;XoZ ztky4<$7%4s)lS~d*>iNKTC^4{B$1S^!`A&`yM1;URYRkxwp)t}(k`+*va8K&s#2z4 zDyT|INsvOr71{t3UbbWkC-U0t;ItyV1yoR9wiu&Kc!%och$n4)3YU@Ozok=#Q?lsig05rV2m}f5!dco%0DXxYXc6sNyU^*8Cu1eB}>|oZ~(kT@U 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%0AoB7p|)ng#7wO(EqN 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 diff --git a/charts/postgres-operator/values-crd.yaml b/charts/postgres-operator/values-crd.yaml index 4be39325f..14287fdaf 100644 --- a/charts/postgres-operator/values-crd.yaml +++ b/charts/postgres-operator/values-crd.yaml @@ -45,7 +45,7 @@ configGeneral: # example: "exampleimage:exampletag" # number of routines the operator spawns to process requests concurrently - workers: 4 + workers: 8 # parameters describing Postgres users configUsers: @@ -271,7 +271,7 @@ configConnectionPooler: # db user for pooler to use connection_pooler_user: "pooler" # docker image - connection_pooler_image: "registry.opensource.zalan.do/acid/pgbouncer:master-7" + connection_pooler_image: "registry.opensource.zalan.do/acid/pgbouncer:master-8" # max db connections the pooler should hold connection_pooler_max_db_connections: 60 # default pooling mode diff --git a/charts/postgres-operator/values.yaml b/charts/postgres-operator/values.yaml index 54461d141..cce0b79c8 100644 --- a/charts/postgres-operator/values.yaml +++ b/charts/postgres-operator/values.yaml @@ -44,7 +44,7 @@ configGeneral: # sidecar_docker_images: "" # number of routines the operator spawns to process requests concurrently - workers: "4" + workers: "8" # parameters describing Postgres users configUsers: @@ -263,7 +263,7 @@ configConnectionPooler: # db user for pooler to use connection_pooler_user: "pooler" # docker image - connection_pooler_image: "registry.opensource.zalan.do/acid/pgbouncer:master-7" + connection_pooler_image: "registry.opensource.zalan.do/acid/pgbouncer:master-8" # max db connections the pooler should hold connection_pooler_max_db_connections: "60" # default pooling mode diff --git a/manifests/configmap.yaml b/manifests/configmap.yaml index 8ec850bae..963aea96b 100644 --- a/manifests/configmap.yaml +++ b/manifests/configmap.yaml @@ -15,7 +15,7 @@ data: # connection_pooler_default_cpu_request: "500m" # connection_pooler_default_memory_limit: 100Mi # connection_pooler_default_memory_request: 100Mi - connection_pooler_image: "registry.opensource.zalan.do/acid/pgbouncer:master-7" + connection_pooler_image: "registry.opensource.zalan.do/acid/pgbouncer:master-8" # connection_pooler_max_db_connections: 60 # connection_pooler_mode: "transaction" # connection_pooler_number_of_instances: 2 @@ -95,6 +95,7 @@ data: secret_name_template: "{username}.{cluster}.credentials" # sidecar_docker_images: "" # set_memory_request_to_limit: "false" + # spilo_fsgroup: 103 spilo_privileged: "false" super_username: postgres # team_admin_role: "admin" @@ -104,4 +105,4 @@ data: # wal_gs_bucket: "" # wal_s3_bucket: "" watched_namespace: "*" # listen to all namespaces - workers: "4" + workers: "8" diff --git a/manifests/operatorconfiguration.crd.yaml b/manifests/operatorconfiguration.crd.yaml index d02ff1682..364ea6d5a 100644 --- a/manifests/operatorconfiguration.crd.yaml +++ b/manifests/operatorconfiguration.crd.yaml @@ -11,6 +11,26 @@ spec: singular: operatorconfiguration shortNames: - opconfig + additionalPrinterColumns: + - name: Image + type: string + description: Spilo image to be used for Pods + JSONPath: .configuration.docker_image + - name: Cluster-Label + type: string + description: Label for K8s resources created by operator + JSONPath: .configuration.kubernetes.cluster_name_label + - name: Service-Account + type: string + description: Name of service account to be used + JSONPath: .configuration.kubernetes.pod_service_account_name + - name: Min-Instances + type: integer + description: Minimum number of instances per Postgres cluster + JSONPath: .configuration.min_instances + - name: Age + type: date + JSONPath: .metadata.creationTimestamp scope: Namespaced subresources: status: {} diff --git a/manifests/postgresql-operator-default-configuration.yaml b/manifests/postgresql-operator-default-configuration.yaml index a7ca8c4ee..ab6a23113 100644 --- a/manifests/postgresql-operator-default-configuration.yaml +++ b/manifests/postgresql-operator-default-configuration.yaml @@ -19,7 +19,7 @@ configuration: # name: global-sidecar-1 # ports: # - containerPort: 80 - workers: 4 + workers: 8 users: replication_username: standby super_username: postgres @@ -128,7 +128,7 @@ configuration: connection_pooler_default_cpu_request: "500m" connection_pooler_default_memory_limit: 100Mi connection_pooler_default_memory_request: 100Mi - connection_pooler_image: "registry.opensource.zalan.do/acid/pgbouncer:master-7" + connection_pooler_image: "registry.opensource.zalan.do/acid/pgbouncer:master-8" # connection_pooler_max_db_connections: 60 connection_pooler_mode: "transaction" connection_pooler_number_of_instances: 2 diff --git a/manifests/postgresql.crd.yaml b/manifests/postgresql.crd.yaml index e62204c40..73382ae5b 100644 --- a/manifests/postgresql.crd.yaml +++ b/manifests/postgresql.crd.yaml @@ -11,6 +11,38 @@ spec: singular: postgresql shortNames: - pg + additionalPrinterColumns: + - name: Team + type: string + description: Team responsible for Postgres CLuster + JSONPath: .spec.teamId + - name: Version + type: string + description: PostgreSQL version + JSONPath: .spec.postgresql.version + - name: Pods + type: integer + description: Number of Pods per Postgres cluster + JSONPath: .spec.numberOfInstances + - name: Volume + type: string + description: Size of the bound volume + JSONPath: .spec.volume.size + - name: CPU-Request + type: string + description: Requested CPU for Postgres containers + JSONPath: .spec.resources.requests.cpu + - name: Memory-Request + type: string + description: Requested memory for Postgres containers + JSONPath: .spec.resources.requests.memory + - name: Age + type: date + JSONPath: .metadata.creationTimestamp + - name: Status + type: string + description: Current sync status of postgresql resource + JSONPath: .status.PostgresClusterStatus scope: Namespaced subresources: status: {} diff --git a/pkg/controller/operator_config.go b/pkg/controller/operator_config.go index 2a3a01fd4..bfb0e6dcc 100644 --- a/pkg/controller/operator_config.go +++ b/pkg/controller/operator_config.go @@ -38,11 +38,11 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur result.EtcdHost = fromCRD.EtcdHost result.KubernetesUseConfigMaps = fromCRD.KubernetesUseConfigMaps result.DockerImage = util.Coalesce(fromCRD.DockerImage, "registry.opensource.zalan.do/acid/spilo-12:1.6-p3") - result.Workers = fromCRD.Workers + result.Workers = util.CoalesceUInt32(fromCRD.Workers, 8) result.MinInstances = fromCRD.MinInstances result.MaxInstances = fromCRD.MaxInstances - result.ResyncPeriod = time.Duration(fromCRD.ResyncPeriod) - result.RepairPeriod = time.Duration(fromCRD.RepairPeriod) + result.ResyncPeriod = util.CoalesceDuration(time.Duration(fromCRD.ResyncPeriod), "30m") + result.RepairPeriod = util.CoalesceDuration(time.Duration(fromCRD.RepairPeriod), "5m") result.SetMemoryRequestToLimit = fromCRD.SetMemoryRequestToLimit result.ShmVolume = util.CoalesceBool(fromCRD.ShmVolume, util.True()) result.SidecarImages = fromCRD.SidecarImages @@ -58,7 +58,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur result.PodServiceAccountDefinition = fromCRD.Kubernetes.PodServiceAccountDefinition result.PodServiceAccountRoleBindingDefinition = fromCRD.Kubernetes.PodServiceAccountRoleBindingDefinition result.PodEnvironmentConfigMap = fromCRD.Kubernetes.PodEnvironmentConfigMap - result.PodTerminateGracePeriod = time.Duration(fromCRD.Kubernetes.PodTerminateGracePeriod) + result.PodTerminateGracePeriod = util.CoalesceDuration(time.Duration(fromCRD.Kubernetes.PodTerminateGracePeriod), "5m") result.SpiloPrivileged = fromCRD.Kubernetes.SpiloPrivileged result.SpiloFSGroup = fromCRD.Kubernetes.SpiloFSGroup result.ClusterDomain = util.Coalesce(fromCRD.Kubernetes.ClusterDomain, "cluster.local") @@ -71,14 +71,14 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur result.OAuthTokenSecretName = fromCRD.Kubernetes.OAuthTokenSecretName result.InfrastructureRolesSecretName = fromCRD.Kubernetes.InfrastructureRolesSecretName result.PodRoleLabel = util.Coalesce(fromCRD.Kubernetes.PodRoleLabel, "spilo-role") - result.ClusterLabels = fromCRD.Kubernetes.ClusterLabels + result.ClusterLabels = util.CoalesceStrMap(fromCRD.Kubernetes.ClusterLabels, map[string]string{"application": "spilo"}) result.InheritedLabels = fromCRD.Kubernetes.InheritedLabels result.DownscalerAnnotations = fromCRD.Kubernetes.DownscalerAnnotations result.ClusterNameLabel = util.Coalesce(fromCRD.Kubernetes.ClusterNameLabel, "cluster-name") result.NodeReadinessLabel = fromCRD.Kubernetes.NodeReadinessLabel result.PodPriorityClassName = fromCRD.Kubernetes.PodPriorityClassName result.PodManagementPolicy = util.Coalesce(fromCRD.Kubernetes.PodManagementPolicy, "ordered_ready") - result.MasterPodMoveTimeout = time.Duration(fromCRD.Kubernetes.MasterPodMoveTimeout) + result.MasterPodMoveTimeout = util.CoalesceDuration(time.Duration(fromCRD.Kubernetes.MasterPodMoveTimeout), "10m") result.EnablePodAntiAffinity = fromCRD.Kubernetes.EnablePodAntiAffinity result.PodAntiAffinityTopologyKey = util.Coalesce(fromCRD.Kubernetes.PodAntiAffinityTopologyKey, "kubernetes.io/hostname") @@ -91,15 +91,15 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur result.MinMemoryLimit = util.Coalesce(fromCRD.PostgresPodResources.MinMemoryLimit, "250Mi") // timeout config - result.ResourceCheckInterval = time.Duration(fromCRD.Timeouts.ResourceCheckInterval) - result.ResourceCheckTimeout = time.Duration(fromCRD.Timeouts.ResourceCheckTimeout) - result.PodLabelWaitTimeout = time.Duration(fromCRD.Timeouts.PodLabelWaitTimeout) - result.PodDeletionWaitTimeout = time.Duration(fromCRD.Timeouts.PodDeletionWaitTimeout) - result.ReadyWaitInterval = time.Duration(fromCRD.Timeouts.ReadyWaitInterval) - result.ReadyWaitTimeout = time.Duration(fromCRD.Timeouts.ReadyWaitTimeout) + result.ResourceCheckInterval = util.CoalesceDuration(time.Duration(fromCRD.Timeouts.ResourceCheckInterval), "3s") + result.ResourceCheckTimeout = util.CoalesceDuration(time.Duration(fromCRD.Timeouts.ResourceCheckTimeout), "10m") + result.PodLabelWaitTimeout = util.CoalesceDuration(time.Duration(fromCRD.Timeouts.PodLabelWaitTimeout), "10m") + result.PodDeletionWaitTimeout = util.CoalesceDuration(time.Duration(fromCRD.Timeouts.PodDeletionWaitTimeout), "10m") + result.ReadyWaitInterval = util.CoalesceDuration(time.Duration(fromCRD.Timeouts.ReadyWaitInterval), "4s") + result.ReadyWaitTimeout = util.CoalesceDuration(time.Duration(fromCRD.Timeouts.ReadyWaitTimeout), "30s") // load balancer config - result.DbHostedZone = fromCRD.LoadBalancer.DbHostedZone + result.DbHostedZone = util.Coalesce(fromCRD.LoadBalancer.DbHostedZone, "db.example.com") result.EnableMasterLoadBalancer = fromCRD.LoadBalancer.EnableMasterLoadBalancer result.EnableReplicaLoadBalancer = fromCRD.LoadBalancer.EnableReplicaLoadBalancer result.CustomServiceAnnotations = fromCRD.LoadBalancer.CustomServiceAnnotations @@ -114,7 +114,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur result.WALGSBucket = fromCRD.AWSGCP.WALGSBucket result.GCPCredentials = fromCRD.AWSGCP.GCPCredentials result.AdditionalSecretMount = fromCRD.AWSGCP.AdditionalSecretMount - result.AdditionalSecretMountPath = fromCRD.AWSGCP.AdditionalSecretMountPath + result.AdditionalSecretMountPath = util.Coalesce(fromCRD.AWSGCP.AdditionalSecretMountPath, "/meta/credentials") // logical backup config result.LogicalBackupSchedule = util.Coalesce(fromCRD.LogicalBackup.Schedule, "30 00 * * *") @@ -132,20 +132,20 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur // Teams API config result.EnableTeamsAPI = fromCRD.TeamsAPI.EnableTeamsAPI - result.TeamsAPIUrl = fromCRD.TeamsAPI.TeamsAPIUrl - result.TeamAPIRoleConfiguration = fromCRD.TeamsAPI.TeamAPIRoleConfiguration + result.TeamsAPIUrl = util.Coalesce(fromCRD.TeamsAPI.TeamsAPIUrl, "https://teams.example.com/api/") + result.TeamAPIRoleConfiguration = util.CoalesceStrMap(fromCRD.TeamsAPI.TeamAPIRoleConfiguration, map[string]string{"log_statement": "all"}) result.EnableTeamSuperuser = fromCRD.TeamsAPI.EnableTeamSuperuser result.EnableAdminRoleForUsers = fromCRD.TeamsAPI.EnableAdminRoleForUsers result.TeamAdminRole = fromCRD.TeamsAPI.TeamAdminRole - result.PamRoleName = fromCRD.TeamsAPI.PamRoleName - result.PamConfiguration = fromCRD.TeamsAPI.PamConfiguration - result.ProtectedRoles = fromCRD.TeamsAPI.ProtectedRoles + result.PamRoleName = util.Coalesce(fromCRD.TeamsAPI.PamRoleName, "zalandos") + result.PamConfiguration = util.Coalesce(fromCRD.TeamsAPI.PamConfiguration, "https://info.example.com/oauth2/tokeninfo?access_token= uid realm=/employees") + result.ProtectedRoles = util.CoalesceStrArr(fromCRD.TeamsAPI.ProtectedRoles, []string{"admin"}) result.PostgresSuperuserTeams = fromCRD.TeamsAPI.PostgresSuperuserTeams // logging REST API config - result.APIPort = fromCRD.LoggingRESTAPI.APIPort - result.RingLogLines = fromCRD.LoggingRESTAPI.RingLogLines - result.ClusterHistoryEntries = fromCRD.LoggingRESTAPI.ClusterHistoryEntries + result.APIPort = util.CoalesceInt(fromCRD.LoggingRESTAPI.APIPort, 8080) + result.RingLogLines = util.CoalesceInt(fromCRD.LoggingRESTAPI.RingLogLines, 100) + result.ClusterHistoryEntries = util.CoalesceInt(fromCRD.LoggingRESTAPI.ClusterHistoryEntries, 1000) // Scalyr config result.ScalyrAPIKey = fromCRD.Scalyr.ScalyrAPIKey diff --git a/pkg/util/config/config.go b/pkg/util/config/config.go index d15c7caa7..01057f236 100644 --- a/pkg/util/config/config.go +++ b/pkg/util/config/config.go @@ -150,7 +150,7 @@ type Config struct { EnablePodDisruptionBudget *bool `name:"enable_pod_disruption_budget" default:"true"` EnableInitContainers *bool `name:"enable_init_containers" default:"true"` EnableSidecars *bool `name:"enable_sidecars" default:"true"` - Workers uint32 `name:"workers" default:"4"` + Workers uint32 `name:"workers" default:"8"` APIPort int `name:"api_port" default:"8080"` RingLogLines int `name:"ring_log_lines" default:"100"` ClusterHistoryEntries int `name:"cluster_history_entries" default:"1000"` diff --git a/pkg/util/util.go b/pkg/util/util.go index 5701429aa..ff1be4e68 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -147,6 +147,30 @@ func Coalesce(val, defaultVal string) string { return val } +// CoalesceStrArr returns the first argument if it is not null, otherwise the second one. +func CoalesceStrArr(val, defaultVal []string) []string { + if len(val) == 0 { + return defaultVal + } + return val +} + +// CoalesceStrMap returns the first argument if it is not null, otherwise the second one. +func CoalesceStrMap(val, defaultVal map[string]string) map[string]string { + if len(val) == 0 { + return defaultVal + } + return val +} + +// CoalesceInt works like coalesce but for int +func CoalesceInt(val, defaultVal int) int { + if val == 0 { + return defaultVal + } + return val +} + // CoalesceInt32 works like coalesce but for *int32 func CoalesceInt32(val, defaultVal *int32) *int32 { if val == nil { @@ -155,6 +179,14 @@ func CoalesceInt32(val, defaultVal *int32) *int32 { return val } +// CoalesceUInt32 works like coalesce but for uint32 +func CoalesceUInt32(val, defaultVal uint32) uint32 { + if val == 0 { + return defaultVal + } + return val +} + // CoalesceBool works like coalesce but for *bool func CoalesceBool(val, defaultVal *bool) *bool { if val == nil { @@ -163,6 +195,18 @@ func CoalesceBool(val, defaultVal *bool) *bool { return val } +// CoalesceDuration works like coalesce but for time.Duration +func CoalesceDuration(val time.Duration, defaultVal string) time.Duration { + if val == 0 { + duration, err := time.ParseDuration(defaultVal) + if err != nil { + panic(err) + } + return duration + } + return val +} + // Test if any of the values is nil func testNil(values ...*int32) bool { for _, v := range values {