fix: enable faster db recovery (#1020)

diff --git a/roles/barbican/vars/main.yml b/roles/barbican/vars/main.yml
index 7eb2c78..701df96 100644
--- a/roles/barbican/vars/main.yml
+++ b/roles/barbican/vars/main.yml
@@ -23,6 +23,9 @@
     barbican:
       DEFAULT:
         log_config_append: null
+      database:
+        connection_recycle_time: 10
+        max_pool_size: 1
       oslo_messaging_notifications:
         driver: noop
       simple_crypto_plugin:
diff --git a/roles/barbican/vars_test.go b/roles/barbican/vars_test.go
new file mode 100644
index 0000000..8a0dccc
--- /dev/null
+++ b/roles/barbican/vars_test.go
@@ -0,0 +1,39 @@
+package barbican
+
+import (
+	_ "embed"
+	"os"
+	"testing"
+
+	"github.com/goccy/go-yaml"
+	"github.com/stretchr/testify/require"
+
+	"github.com/vexxhost/atmosphere/internal/openstack_helm"
+	"github.com/vexxhost/atmosphere/internal/testutils"
+)
+
+var (
+	//go:embed vars/main.yml
+	varsFile []byte
+	vars     Vars
+)
+
+type Vars struct {
+	openstack_helm.HelmValues `yaml:"_barbican_helm_values"`
+}
+
+func TestMain(m *testing.M) {
+	t := &testing.T{}
+	err := yaml.UnmarshalWithOptions(varsFile, &vars)
+	require.NoError(t, err)
+
+	code := m.Run()
+	os.Exit(code)
+}
+
+func TestHelmValues(t *testing.T) {
+	vals, err := openstack_helm.CoalescedHelmValues("../../charts/barbican", &vars.HelmValues)
+	require.NoError(t, err)
+
+	testutils.TestDatabaseConf(t, vals.Conf.Barbican.Database)
+}
diff --git a/roles/cinder/vars/main.yml b/roles/cinder/vars/main.yml
index f0d1630..179f34e 100644
--- a/roles/cinder/vars/main.yml
+++ b/roles/cinder/vars/main.yml
@@ -36,6 +36,9 @@
         barbican_endpoint_type: internal
       cors:
         allowed_origins: "*"
+      database:
+        connection_recycle_time: 10
+        max_pool_size: 1
       oslo_messaging_notifications:
         driver: noop
   manifests:
diff --git a/roles/cinder/vars_test.go b/roles/cinder/vars_test.go
new file mode 100644
index 0000000..c501802
--- /dev/null
+++ b/roles/cinder/vars_test.go
@@ -0,0 +1,39 @@
+package cinder
+
+import (
+	_ "embed"
+	"os"
+	"testing"
+
+	"github.com/goccy/go-yaml"
+	"github.com/stretchr/testify/require"
+
+	"github.com/vexxhost/atmosphere/internal/openstack_helm"
+	"github.com/vexxhost/atmosphere/internal/testutils"
+)
+
+var (
+	//go:embed vars/main.yml
+	varsFile []byte
+	vars     Vars
+)
+
+type Vars struct {
+	openstack_helm.HelmValues `yaml:"__cinder_helm_values"`
+}
+
+func TestMain(m *testing.M) {
+	t := &testing.T{}
+	err := yaml.UnmarshalWithOptions(varsFile, &vars)
+	require.NoError(t, err)
+
+	code := m.Run()
+	os.Exit(code)
+}
+
+func TestHelmValues(t *testing.T) {
+	vals, err := openstack_helm.CoalescedHelmValues("../../charts/cinder", &vars.HelmValues)
+	require.NoError(t, err)
+
+	testutils.TestDatabaseConf(t, vals.Conf.Cinder.Database)
+}
diff --git a/roles/designate/vars/main.yml b/roles/designate/vars/main.yml
index 09ac03c..5e4e174 100644
--- a/roles/designate/vars/main.yml
+++ b/roles/designate/vars/main.yml
@@ -18,6 +18,9 @@
     tags: "{{ atmosphere_images | vexxhost.atmosphere.openstack_helm_image_tags('designate') }}"
   conf:
     designate:
+      database:
+        connection_recycle_time: 10
+        max_pool_size: 1
       service:central:
         managed_resource_tenant_id: "{{ _designate_project_info.openstack_projects[0].id }}"
     pools: "{{ designate_pools | to_yaml }}"
diff --git a/roles/designate/vars_test.go b/roles/designate/vars_test.go
new file mode 100644
index 0000000..e3ec382
--- /dev/null
+++ b/roles/designate/vars_test.go
@@ -0,0 +1,39 @@
+package designate
+
+import (
+	_ "embed"
+	"os"
+	"testing"
+
+	"github.com/goccy/go-yaml"
+	"github.com/stretchr/testify/require"
+
+	"github.com/vexxhost/atmosphere/internal/openstack_helm"
+	"github.com/vexxhost/atmosphere/internal/testutils"
+)
+
+var (
+	//go:embed vars/main.yml
+	varsFile []byte
+	vars     Vars
+)
+
+type Vars struct {
+	openstack_helm.HelmValues `yaml:"_designate_helm_values"`
+}
+
+func TestMain(m *testing.M) {
+	t := &testing.T{}
+	err := yaml.UnmarshalWithOptions(varsFile, &vars)
+	require.NoError(t, err)
+
+	code := m.Run()
+	os.Exit(code)
+}
+
+func TestHelmValues(t *testing.T) {
+	vals, err := openstack_helm.CoalescedHelmValues("../../charts/designate", &vars.HelmValues)
+	require.NoError(t, err)
+
+	testutils.TestDatabaseConf(t, vals.Conf.Designate.Database)
+}
diff --git a/roles/glance/vars/main.yml b/roles/glance/vars/main.yml
index 9f62885..7774bb6 100644
--- a/roles/glance/vars/main.yml
+++ b/roles/glance/vars/main.yml
@@ -43,6 +43,9 @@
         workers: 8
       cors:
         allowed_origins: "*"
+      database:
+        connection_recycle_time: 10
+        max_pool_size: 1
       image_format:
         disk_formats: "qcow2,raw"
       oslo_messaging_notifications:
diff --git a/roles/glance/vars_test.go b/roles/glance/vars_test.go
new file mode 100644
index 0000000..aa0455c
--- /dev/null
+++ b/roles/glance/vars_test.go
@@ -0,0 +1,39 @@
+package glance
+
+import (
+	_ "embed"
+	"os"
+	"testing"
+
+	"github.com/goccy/go-yaml"
+	"github.com/stretchr/testify/require"
+
+	"github.com/vexxhost/atmosphere/internal/openstack_helm"
+	"github.com/vexxhost/atmosphere/internal/testutils"
+)
+
+var (
+	//go:embed vars/main.yml
+	varsFile []byte
+	vars     Vars
+)
+
+type Vars struct {
+	openstack_helm.HelmValues `yaml:"_glance_helm_values"`
+}
+
+func TestMain(m *testing.M) {
+	t := &testing.T{}
+	err := yaml.UnmarshalWithOptions(varsFile, &vars)
+	require.NoError(t, err)
+
+	code := m.Run()
+	os.Exit(code)
+}
+
+func TestHelmValues(t *testing.T) {
+	vals, err := openstack_helm.CoalescedHelmValues("../../charts/glance", &vars.HelmValues)
+	require.NoError(t, err)
+
+	testutils.TestDatabaseConf(t, vals.Conf.Glance.Database)
+}
diff --git a/roles/heat/vars/main.yml b/roles/heat/vars/main.yml
index 3104161..10202f3 100644
--- a/roles/heat/vars/main.yml
+++ b/roles/heat/vars/main.yml
@@ -35,6 +35,9 @@
         server_keystone_endpoint_type: public
       clients_keystone:
         endpoint_type: publicURL
+      database:
+        connection_recycle_time: 10
+        max_pool_size: 1
       ec2authtoken:
         auth_uri: http://keystone-api.openstack.svc.cluster.local:5000
       heat_api:
diff --git a/roles/heat/vars_test.go b/roles/heat/vars_test.go
new file mode 100644
index 0000000..a87f90c
--- /dev/null
+++ b/roles/heat/vars_test.go
@@ -0,0 +1,39 @@
+package heat
+
+import (
+	_ "embed"
+	"os"
+	"testing"
+
+	"github.com/goccy/go-yaml"
+	"github.com/stretchr/testify/require"
+
+	"github.com/vexxhost/atmosphere/internal/openstack_helm"
+	"github.com/vexxhost/atmosphere/internal/testutils"
+)
+
+var (
+	//go:embed vars/main.yml
+	varsFile []byte
+	vars     Vars
+)
+
+type Vars struct {
+	openstack_helm.HelmValues `yaml:"_heat_helm_values"`
+}
+
+func TestMain(m *testing.M) {
+	t := &testing.T{}
+	err := yaml.UnmarshalWithOptions(varsFile, &vars)
+	require.NoError(t, err)
+
+	code := m.Run()
+	os.Exit(code)
+}
+
+func TestHelmValues(t *testing.T) {
+	vals, err := openstack_helm.CoalescedHelmValues("../../charts/heat", &vars.HelmValues)
+	require.NoError(t, err)
+
+	testutils.TestDatabaseConf(t, vals.Conf.Heat.Database)
+}
diff --git a/roles/keystone/vars/main.yml b/roles/keystone/vars/main.yml
index 4ed3565..625ff2f 100644
--- a/roles/keystone/vars/main.yml
+++ b/roles/keystone/vars/main.yml
@@ -35,6 +35,9 @@
         methods: password,token,openid,application_credential
       cors:
         allowed_origins: "*"
+      database:
+        connection_recycle_time: 10
+        max_pool_size: 1
       openid:
         remote_id_attribute: HTTP_OIDC_ISS
       federation:
diff --git a/roles/keystone/vars_test.go b/roles/keystone/vars_test.go
new file mode 100644
index 0000000..c5bfe19
--- /dev/null
+++ b/roles/keystone/vars_test.go
@@ -0,0 +1,32 @@
+package keystone
+
+import (
+	_ "embed"
+	"testing"
+
+	"github.com/goccy/go-yaml"
+	"github.com/stretchr/testify/require"
+
+	"github.com/vexxhost/atmosphere/internal/openstack_helm"
+	"github.com/vexxhost/atmosphere/internal/testutils"
+)
+
+var (
+	//go:embed vars/main.yml
+	varsFile []byte
+	vars     Vars
+)
+
+type Vars struct {
+	openstack_helm.HelmValues `yaml:"_keystone_helm_values"`
+}
+
+func TestHelmValues(t *testing.T) {
+	err := yaml.UnmarshalWithOptions(varsFile, &vars)
+	require.NoError(t, err)
+
+	vals, err := openstack_helm.CoalescedHelmValues("../../charts/keystone", &vars.HelmValues)
+	require.NoError(t, err)
+
+	testutils.TestDatabaseConf(t, vals.Conf.Keystone.Database)
+}
diff --git a/roles/magnum/vars/main.yml b/roles/magnum/vars/main.yml
index 8bc7fa3..eeee431 100644
--- a/roles/magnum/vars/main.yml
+++ b/roles/magnum/vars/main.yml
@@ -33,6 +33,9 @@
         kubernetes_default_network_driver: calico
       conductor:
         workers: 4
+      database:
+        connection_recycle_time: 10
+        max_pool_size: 1
       drivers:
         verify_ca: false
       glance_client:
diff --git a/roles/magnum/vars_test.go b/roles/magnum/vars_test.go
new file mode 100644
index 0000000..21e8fd6
--- /dev/null
+++ b/roles/magnum/vars_test.go
@@ -0,0 +1,39 @@
+package magnum
+
+import (
+	_ "embed"
+	"os"
+	"testing"
+
+	"github.com/goccy/go-yaml"
+	"github.com/stretchr/testify/require"
+
+	"github.com/vexxhost/atmosphere/internal/openstack_helm"
+	"github.com/vexxhost/atmosphere/internal/testutils"
+)
+
+var (
+	//go:embed vars/main.yml
+	varsFile []byte
+	vars     Vars
+)
+
+type Vars struct {
+	openstack_helm.HelmValues `yaml:"_magnum_helm_values"`
+}
+
+func TestMain(m *testing.M) {
+	t := &testing.T{}
+	err := yaml.UnmarshalWithOptions(varsFile, &vars)
+	require.NoError(t, err)
+
+	code := m.Run()
+	os.Exit(code)
+}
+
+func TestHelmValues(t *testing.T) {
+	vals, err := openstack_helm.CoalescedHelmValues("../../charts/magnum", &vars.HelmValues)
+	require.NoError(t, err)
+
+	testutils.TestDatabaseConf(t, vals.Conf.Magnum.Database)
+}
diff --git a/roles/manila/vars/main.yml b/roles/manila/vars/main.yml
index 01b8541..40e738f 100644
--- a/roles/manila/vars/main.yml
+++ b/roles/manila/vars/main.yml
@@ -47,6 +47,9 @@
       DEFAULT:
         host: manila-share-worker
         osapi_share_workers: 4
+      database:
+        connection_recycle_time: 10
+        max_pool_size: 1
       generic:
         connect_share_server_to_tenant_network: true
         limit_ssh_access: true
diff --git a/roles/manila/vars_test.go b/roles/manila/vars_test.go
new file mode 100644
index 0000000..627920b
--- /dev/null
+++ b/roles/manila/vars_test.go
@@ -0,0 +1,39 @@
+package manila
+
+import (
+	_ "embed"
+	"os"
+	"testing"
+
+	"github.com/goccy/go-yaml"
+	"github.com/stretchr/testify/require"
+
+	"github.com/vexxhost/atmosphere/internal/openstack_helm"
+	"github.com/vexxhost/atmosphere/internal/testutils"
+)
+
+var (
+	//go:embed vars/main.yml
+	varsFile []byte
+	vars     Vars
+)
+
+type Vars struct {
+	openstack_helm.HelmValues `yaml:"_manila_helm_values"`
+}
+
+func TestMain(m *testing.M) {
+	t := &testing.T{}
+	err := yaml.UnmarshalWithOptions(varsFile, &vars)
+	require.NoError(t, err)
+
+	code := m.Run()
+	os.Exit(code)
+}
+
+func TestHelmValues(t *testing.T) {
+	vals, err := openstack_helm.CoalescedHelmValues("../../charts/manila", &vars.HelmValues)
+	require.NoError(t, err)
+
+	testutils.TestDatabaseConf(t, vals.Conf.Manila.Database)
+}
diff --git a/roles/neutron/vars/main.yml b/roles/neutron/vars/main.yml
index 3ccd02e..151363d 100644
--- a/roles/neutron/vars/main.yml
+++ b/roles/neutron/vars/main.yml
@@ -33,6 +33,9 @@
         external_dns_driver: "{{ _neutron_external_dns_driver | default(omit) }}"
       cors:
         allowed_origin: "*"
+      database:
+        connection_recycle_time: 10
+        max_pool_size: 1
       nova:
         live_migration_events: true
       placement:
diff --git a/roles/neutron/vars_test.go b/roles/neutron/vars_test.go
new file mode 100644
index 0000000..8358366
--- /dev/null
+++ b/roles/neutron/vars_test.go
@@ -0,0 +1,39 @@
+package neutron
+
+import (
+	_ "embed"
+	"os"
+	"testing"
+
+	"github.com/goccy/go-yaml"
+	"github.com/stretchr/testify/require"
+
+	"github.com/vexxhost/atmosphere/internal/openstack_helm"
+	"github.com/vexxhost/atmosphere/internal/testutils"
+)
+
+var (
+	//go:embed vars/main.yml
+	varsFile []byte
+	vars     Vars
+)
+
+type Vars struct {
+	openstack_helm.HelmValues `yaml:"__neutron_helm_values"`
+}
+
+func TestMain(m *testing.M) {
+	t := &testing.T{}
+	err := yaml.UnmarshalWithOptions(varsFile, &vars)
+	require.NoError(t, err)
+
+	code := m.Run()
+	os.Exit(code)
+}
+
+func TestHelmValues(t *testing.T) {
+	vals, err := openstack_helm.CoalescedHelmValues("../../charts/neutron", &vars.HelmValues)
+	require.NoError(t, err)
+
+	testutils.TestDatabaseConf(t, vals.Conf.Neutron.Database)
+}
diff --git a/roles/nova/vars/main.yml b/roles/nova/vars/main.yml
index 1b9c802..b7a93c2 100644
--- a/roles/nova/vars/main.yml
+++ b/roles/nova/vars/main.yml
@@ -72,6 +72,9 @@
       cors:
         allowed_origin: "*"
         allow_headers: "X-Auth-Token,X-OpenStack-Nova-API-Version"
+      database:
+        connection_recycle_time: 10
+        max_pool_size: 1
       filter_scheduler:
         enabled_filters:
           AvailabilityZoneFilter,
diff --git a/roles/nova/vars_test.go b/roles/nova/vars_test.go
new file mode 100644
index 0000000..716b946
--- /dev/null
+++ b/roles/nova/vars_test.go
@@ -0,0 +1,39 @@
+package nova
+
+import (
+	_ "embed"
+	"os"
+	"testing"
+
+	"github.com/goccy/go-yaml"
+	"github.com/stretchr/testify/require"
+
+	"github.com/vexxhost/atmosphere/internal/openstack_helm"
+	"github.com/vexxhost/atmosphere/internal/testutils"
+)
+
+var (
+	//go:embed vars/main.yml
+	varsFile []byte
+	vars     Vars
+)
+
+type Vars struct {
+	openstack_helm.HelmValues `yaml:"_nova_helm_values"`
+}
+
+func TestMain(m *testing.M) {
+	t := &testing.T{}
+	err := yaml.UnmarshalWithOptions(varsFile, &vars)
+	require.NoError(t, err)
+
+	code := m.Run()
+	os.Exit(code)
+}
+
+func TestHelmValues(t *testing.T) {
+	vals, err := openstack_helm.CoalescedHelmValues("../../charts/nova", &vars.HelmValues)
+	require.NoError(t, err)
+
+	testutils.TestDatabaseConf(t, vals.Conf.Nova.Database)
+}
diff --git a/roles/octavia/vars/main.yml b/roles/octavia/vars/main.yml
index f83ae85..5cb3f1d 100644
--- a/roles/octavia/vars/main.yml
+++ b/roles/octavia/vars/main.yml
@@ -105,6 +105,9 @@
         client_ca: /etc/octavia/certs/client/ca.crt
         volume_driver: volume_cinder_driver
         workers: 4
+      database:
+        connection_recycle_time: 10
+        max_pool_size: 1
       glance:
         endpoint_type: internalURL
       haproxy_amphora:
diff --git a/roles/octavia/vars_test.go b/roles/octavia/vars_test.go
new file mode 100644
index 0000000..8c99a14
--- /dev/null
+++ b/roles/octavia/vars_test.go
@@ -0,0 +1,39 @@
+package octavia
+
+import (
+	_ "embed"
+	"os"
+	"testing"
+
+	"github.com/goccy/go-yaml"
+	"github.com/stretchr/testify/require"
+
+	"github.com/vexxhost/atmosphere/internal/openstack_helm"
+	"github.com/vexxhost/atmosphere/internal/testutils"
+)
+
+var (
+	//go:embed vars/main.yml
+	varsFile []byte
+	vars     Vars
+)
+
+type Vars struct {
+	openstack_helm.HelmValues `yaml:"_octavia_helm_values"`
+}
+
+func TestMain(m *testing.M) {
+	t := &testing.T{}
+	err := yaml.UnmarshalWithOptions(varsFile, &vars)
+	require.NoError(t, err)
+
+	code := m.Run()
+	os.Exit(code)
+}
+
+func TestHelmValues(t *testing.T) {
+	vals, err := openstack_helm.CoalescedHelmValues("../../charts/octavia", &vars.HelmValues)
+	require.NoError(t, err)
+
+	testutils.TestDatabaseConf(t, vals.Conf.Octavia.Database)
+}
diff --git a/roles/placement/vars/main.yml b/roles/placement/vars/main.yml
index 322a0ba..58082d8 100644
--- a/roles/placement/vars/main.yml
+++ b/roles/placement/vars/main.yml
@@ -23,6 +23,10 @@
     placement:
       DEFAULT:
         log_config_append: null
+      database:
+        connection_recycle_time: 10
+        max_pool_size: 1
+        max_retries: -1
       oslo_messaging_notifications:
         driver: noop
   manifests:
diff --git a/roles/placement/vars_test.go b/roles/placement/vars_test.go
new file mode 100644
index 0000000..fa3fac3
--- /dev/null
+++ b/roles/placement/vars_test.go
@@ -0,0 +1,39 @@
+package placement
+
+import (
+	_ "embed"
+	"os"
+	"testing"
+
+	"github.com/goccy/go-yaml"
+	"github.com/stretchr/testify/require"
+
+	"github.com/vexxhost/atmosphere/internal/openstack_helm"
+	"github.com/vexxhost/atmosphere/internal/testutils"
+)
+
+var (
+	//go:embed vars/main.yml
+	varsFile []byte
+	vars     Vars
+)
+
+type Vars struct {
+	openstack_helm.HelmValues `yaml:"_placement_helm_values"`
+}
+
+func TestMain(m *testing.M) {
+	t := &testing.T{}
+	err := yaml.UnmarshalWithOptions(varsFile, &vars)
+	require.NoError(t, err)
+
+	code := m.Run()
+	os.Exit(code)
+}
+
+func TestHelmValues(t *testing.T) {
+	vals, err := openstack_helm.CoalescedHelmValues("../../charts/placement", &vars.HelmValues)
+	require.NoError(t, err)
+
+	testutils.TestDatabaseConf(t, vals.Conf.Placement.Database)
+}
diff --git a/roles/senlin/vars/main.yml b/roles/senlin/vars/main.yml
index e0b9887..d1fcbdc 100644
--- a/roles/senlin/vars/main.yml
+++ b/roles/senlin/vars/main.yml
@@ -26,6 +26,9 @@
     senlin:
       DEFAULT:
         log_config_append: null
+      database:
+        connection_recycle_time: 10
+        max_pool_size: 1
       oslo_messaging_notifications:
         driver: noop
       senlin_api:
diff --git a/roles/senlin/vars_test.go b/roles/senlin/vars_test.go
index d872627..f399407 100644
--- a/roles/senlin/vars_test.go
+++ b/roles/senlin/vars_test.go
@@ -8,6 +8,9 @@
 	"github.com/goccy/go-yaml"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
+
+	"github.com/vexxhost/atmosphere/internal/openstack_helm"
+	"github.com/vexxhost/atmosphere/internal/testutils"
 )
 
 var (
@@ -17,23 +20,7 @@
 )
 
 type Vars struct {
-	SenlinHelmValues `yaml:"_senlin_helm_values"`
-}
-
-type SenlinHelmValues struct {
-	Conf `yaml:"conf"`
-}
-
-type Conf struct {
-	Senlin SenlinConf `yaml:"senlin"`
-}
-
-type SenlinConf struct {
-	API SenlinAPIConf `yaml:"senlin_api"`
-}
-
-type SenlinAPIConf struct {
-	Workers int32 `yaml:"workers"`
+	openstack_helm.HelmValues `yaml:"_senlin_helm_values"`
 }
 
 func TestMain(m *testing.M) {
@@ -45,6 +32,11 @@
 	os.Exit(code)
 }
 
-func TestSenlinHelmValues(t *testing.T) {
-	assert.Equal(t, int32(2), vars.SenlinHelmValues.Conf.Senlin.API.Workers)
+func TestHelmValues(t *testing.T) {
+	vals, err := openstack_helm.CoalescedHelmValues("../../charts/senlin", &vars.HelmValues)
+	require.NoError(t, err)
+
+	assert.Equal(t, int32(2), vals.Conf.Senlin.API.Workers)
+
+	testutils.TestDatabaseConf(t, vals.Conf.Senlin.Database)
 }
diff --git a/roles/staffeln/vars/main.yml b/roles/staffeln/vars/main.yml
index c0be4b3..d23c9b1 100644
--- a/roles/staffeln/vars/main.yml
+++ b/roles/staffeln/vars/main.yml
@@ -25,6 +25,9 @@
       conductor:
         backup_metadata_key: "{{ staffeln_backup_metadata_key }}"
         retention_metadata_key: "{{ staffeln_retention_metadata_key }}"
+      database:
+        connection_recycle_time: 10
+        max_pool_size: 1
   manifests:
     ingress_api: false
     service_ingress_api: false
diff --git a/roles/staffeln/vars_test.go b/roles/staffeln/vars_test.go
new file mode 100644
index 0000000..07ec9ab
--- /dev/null
+++ b/roles/staffeln/vars_test.go
@@ -0,0 +1,39 @@
+package staffeln
+
+import (
+	_ "embed"
+	"os"
+	"testing"
+
+	"github.com/goccy/go-yaml"
+	"github.com/stretchr/testify/require"
+
+	"github.com/vexxhost/atmosphere/internal/openstack_helm"
+	"github.com/vexxhost/atmosphere/internal/testutils"
+)
+
+var (
+	//go:embed vars/main.yml
+	varsFile []byte
+	vars     Vars
+)
+
+type Vars struct {
+	openstack_helm.HelmValues `yaml:"_staffeln_helm_values"`
+}
+
+func TestMain(m *testing.M) {
+	t := &testing.T{}
+	err := yaml.UnmarshalWithOptions(varsFile, &vars)
+	require.NoError(t, err)
+
+	code := m.Run()
+	os.Exit(code)
+}
+
+func TestHelmValues(t *testing.T) {
+	vals, err := openstack_helm.CoalescedHelmValues("../../charts/staffeln", &vars.HelmValues)
+	require.NoError(t, err)
+
+	testutils.TestDatabaseConf(t, vals.Conf.Staffeln.Database)
+}