diff --git a/contrib/docker-compose.yml.tmpl b/contrib/docker-compose.yml.tmpl new file mode 100644 index 0000000..6c539d3 --- /dev/null +++ b/contrib/docker-compose.yml.tmpl @@ -0,0 +1,330 @@ +--- +version: "3.4" + +x-default-environment: &default-environment + {{- marshalContent 2 .defaultEnvironment }} + +services: + + proxy: + image: {{ or .services.proxy.containerRegistry .defaults.containerRegistry }}/openslides-proxy:{{ or .services.proxy.tag .defaults.tag }} + {{- if not .disableDependsOn }} + depends_on: + - client + - backendAction + - backendPresenter + - autoupdate + - search + - projector + - auth + - media + - icc + - vote + {{- end }} + environment: + << : *default-environment + {{- with .services.proxy.environment }}{{ marshalContent 6 . }}{{- end }} + {{- if .enableLocalHTTPS }} + ENABLE_LOCAL_HTTPS: 1 + HTTPS_CERT_FILE: /run/secrets/cert_crt + HTTPS_KEY_FILE: /run/secrets/cert_key + {{- end }} + {{- if .enableAutoHTTPS }} + ENABLE_AUTO_HTTPS: 1 + {{- end }} + networks: + - uplink + - frontend + ports: + - {{ .host }}:{{ .port }}:8000 + {{- if .enableLocalHTTPS }} + secrets: + - cert_crt + - cert_key + {{- end }} + {{- with .services.proxy.additionalContent }}{{ marshalContent 4 . }}{{- end }} + + client: + image: {{ or .services.client.containerRegistry .defaults.containerRegistry }}/openslides-client:{{ or .services.client.tag .defaults.tag }} + {{- if not .disableDependsOn }} + depends_on: + - backendAction + - backendPresenter + - autoupdate + - search + - projector + - auth + - media + - icc + - vote + {{- end }} + environment: + << : *default-environment + {{- with .services.client.environment }}{{ marshalContent 6 . }}{{- end }} + networks: + - frontend + {{- with .services.client.additionalContent }}{{ marshalContent 4 . }}{{ end }} + + backendAction: + image: {{ or .services.backendAction.containerRegistry .defaults.containerRegistry }}/openslides-backend:{{ or .services.backendAction.tag .defaults.tag }} + {{- if not .disableDependsOn }} + depends_on: + - datastoreWriter + - auth + - media + - vote + - postgres + {{- end }} + environment: + << : *default-environment + {{- with .services.backendAction.environment }}{{ marshalContent 6 . }}{{- end }} + OPENSLIDES_BACKEND_COMPONENT: action + networks: + - frontend + - data + - email + secrets: + - auth_token_key + - auth_cookie_key + - internal_auth_password + - postgres_password + {{- with .services.backendAction.additionalContent }}{{ marshalContent 4 . }}{{- end }} + + backendPresenter: + image: {{ or .services.backendPresenter.containerRegistry .defaults.containerRegistry }}/openslides-backend:{{ or .services.backendPresenter.tag .defaults.tag }} + {{- if not .disableDependsOn }} + depends_on: + - auth + - postgres + {{- end }} + environment: + << : *default-environment + {{- with .services.backendPresenter.environment }}{{ marshalContent 6 . }}{{- end }} + OPENSLIDES_BACKEND_COMPONENT: presenter + networks: + - frontend + - data + secrets: + - auth_token_key + - auth_cookie_key + - postgres_password + {{- with .services.backendPresenter.additionalContent }}{{ marshalContent 4 . }}{{- end }} + + backendManage: + image: {{ or .services.backendManage.containerRegistry .defaults.containerRegistry }}/openslides-backend:{{ or .services.backendManage.tag .defaults.tag }} + {{- if not .disableDependsOn }} + depends_on: + - postgres + {{- end }} + environment: + << : *default-environment + {{- with .services.backendManage.environment }}{{ marshalContent 6 . }}{{- end }} + OPENSLIDES_BACKEND_COMPONENT: action + networks: + - data + - email + secrets: + - auth_token_key + - auth_cookie_key + - internal_auth_password + - postgres_password + - superadmin + {{- with .services.backendManage.additionalContent }}{{ marshalContent 4 . }}{{- end }} + + {{- if not .disablePostgres }} + postgres: + image: postgres:17 + environment: + << : *default-environment + {{- with .services.postgres.environment }}{{ marshalContent 6 . }}{{- end }} + POSTGRES_DB: openslides + POSTGRES_USER: openslides + POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password + volumes: + - postgres-data:/var/lib/postgresql/data + networks: + - data + secrets: + - postgres_password + {{- with .services.postgres.additionalContent }}{{ marshalContent 4 . }}{{- end }} + {{- end }} + + autoupdate: + image: {{ or .services.autoupdate.containerRegistry .defaults.containerRegistry }}/openslides-autoupdate:{{ or .services.autoupdate.tag .defaults.tag }} + {{- if not .disableDependsOn }} + depends_on: + - redis + {{- end }} + environment: + << : *default-environment + {{- with .services.autoupdate.environment }}{{ marshalContent 6 . }}{{- end }} + networks: + - frontend + - data + secrets: + - auth_token_key + - auth_cookie_key + - postgres_password + {{- with .services.autoupdate.additionalContent }}{{ marshalContent 4 . }}{{- end }} + + search: + image: {{ or .services.search.containerRegistry .defaults.containerRegistry }}/openslides-search:{{ or .services.search.tag .defaults.tag }} + {{- if not .disableDependsOn }} + depends_on: + - postgres + - autoupdate + {{- end }} + environment: + << : *default-environment + {{- with .services.search.environment }}{{ marshalContent 6 . }}{{- end }} + networks: + - frontend + - data + secrets: + - auth_token_key + - auth_cookie_key + - postgres_password + {{- with .services.search.additionalContent }}{{ marshalContent 4 . }}{{- end }} + + projector: + image: {{ or .services.projector.containerRegistry .defaults.containerRegistry }}/openslides-projector:{{ or .services.projector.tag .defaults.tag }} + {{- if not .disableDependsOn }} + depends_on: + - postgres + - autoupdate + - backendAction + - postgres + {{- end }} + environment: + << : *default-environment + {{- with .services.projector.environment }}{{ marshalContent 6 . }}{{- end }} + networks: + - frontend + - data + secrets: + - auth_token_key + - auth_cookie_key + - postgres_password + {{- with .services.projector.additionalContent }}{{ marshalContent 4 . }}{{- end }} + + auth: + image: {{ or .services.auth.containerRegistry .defaults.containerRegistry }}/openslides-auth:{{ or .services.auth.tag .defaults.tag }} + {{- if not .disableDependsOn }} + depends_on: + - redis + - postgres + {{- end }} + environment: + << : *default-environment + {{- with .services.auth.environment }}{{ marshalContent 6 . }}{{- end }} + networks: + - frontend + - data + secrets: + - auth_token_key + - auth_cookie_key + - internal_auth_password + - postgres_password + {{- with .services.auth.additionalContent }}{{ marshalContent 4 . }}{{- end }} + + vote: + image: {{ or .services.vote.containerRegistry .defaults.containerRegistry }}/openslides-vote:{{ or .services.vote.tag .defaults.tag }} + {{- if not .disableDependsOn }} + depends_on: + - auth + - autoupdate + - redis + - postgres + {{- end }} + environment: + << : *default-environment + {{- with .services.vote.environment }}{{ marshalContent 6 . }}{{- end }} + networks: + - frontend + - data + secrets: + - auth_token_key + - auth_cookie_key + - postgres_password + {{- with .services.vote.additionalContent }}{{ marshalContent 4 . }}{{- end }} + + redis: + image: redis:alpine + command: redis-server --save "" + environment: + << : *default-environment + {{- with .services.redis.environment }}{{ marshalContent 6 . }}{{- end }} + networks: + - data + {{- with .services.redis.additionalContent }}{{ marshalContent 4 . }}{{- end }} + + media: + image: {{ or .services.media.containerRegistry .defaults.containerRegistry }}/openslides-media:{{ or .services.media.tag .defaults.tag }} + {{- if not .disableDependsOn }} + depends_on: + - postgres + {{- end }} + environment: + << : *default-environment + {{- with .services.media.environment }}{{ marshalContent 6 . }}{{- end }} + networks: + - frontend + - data + secrets: + - auth_token_key + - auth_cookie_key + - postgres_password + {{- with .services.media.additionalContent }}{{ marshalContent 4 . }}{{- end }} + + icc: + image: {{ or .services.icc.containerRegistry .defaults.containerRegistry }}/openslides-icc:{{ or .services.icc.tag .defaults.tag }} + {{- if not .disableDependsOn }} + depends_on: + - postgres + - redis + {{- end }} + environment: + << : *default-environment + {{- with .services.icc.environment }}{{ marshalContent 6 . }}{{- end }} + networks: + - frontend + - data + secrets: + - auth_token_key + - auth_cookie_key + - postgres_password + {{- with .services.icc.additionalContent }}{{ marshalContent 4 . }}{{- end }} + +networks: + uplink: + internal: false + email: + internal: false + frontend: + internal: true + data: + internal: true + +{{- if not .disablePostgres }} + +volumes: + postgres-data: +{{- end }} + +secrets: + auth_token_key: + file: ./secrets/auth_token_key + auth_cookie_key: + file: ./secrets/auth_cookie_key + superadmin: + file: ./secrets/superadmin + internal_auth_password: + file: ./secrets/internal_auth_password + postgres_password: + file: ./secrets/postgres_password +{{- if .enableLocalHTTPS }} + cert_crt: + file: ./secrets/cert_crt + cert_key: + file: ./secrets/cert_key +{{- end }} diff --git a/internal/constants/constants.go b/internal/constants/constants.go index fcd9821..d2da7dd 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -46,6 +46,9 @@ const ( // DefaultConfigFile is the filename used, if none is set in config file(s) DefaultConfigFile string = "os-config.yaml" + // TemplateSuffix is the recognized suffix for template files + TemplateSuffix string = ".tmpl" + // CertCertName is filename for the HTTPS certificate file CertCertName string = "cert_crt" diff --git a/internal/instance/config/config.go b/internal/instance/config/config.go index 117dd41..e701e89 100644 --- a/internal/instance/config/config.go +++ b/internal/instance/config/config.go @@ -166,7 +166,7 @@ func createFromTemplateFile(baseDir string, force bool, tplFile string, cfg map[ } // Extract filename from config if present, otherwise use a default - filename := filepath.Join(baseDir, getFilename(cfg)) + filename := filepath.Join(baseDir, getFilename(cfg, tplFile)) return createDeploymentFile(filename, force, data, cfg, baseDir) } @@ -237,10 +237,13 @@ func createDeploymentFile(filename string, force bool, tplData []byte, cfg map[s } // getFilename extracts the filename from config, or returns a default -func getFilename(cfg map[string]any) string { +func getFilename(cfg map[string]any, tplFile string) string { if fn, ok := cfg["filename"].(string); ok && fn != "" { return fn } + if tplFilePretty, found := strings.CutSuffix(tplFile, constants.TemplateSuffix); found { + return tplFilePretty + } return constants.DefaultConfigFile } diff --git a/internal/instance/config/config_test.go b/internal/instance/config/config_test.go index 68401ae..3478ec6 100644 --- a/internal/instance/config/config_test.go +++ b/internal/instance/config/config_test.go @@ -366,29 +366,36 @@ func TestGetFilename(t *testing.T) { cfg := map[string]any{ "filename": "custom.yml", } - result := getFilename(cfg) + result := getFilename(cfg, "myspecial.yaml.tmpl") if result != "custom.yml" { t.Errorf("Expected custom.yml, got %s", result) } }) - - t.Run("without filename in config", func(t *testing.T) { + t.Run("without filename in config, with template file", func(t *testing.T) { cfg := map[string]any{ "other": "value", } - result := getFilename(cfg) + result := getFilename(cfg, "myspecial.yaml.tmpl") + if result != "myspecial.yaml" { + t.Errorf("Expected myspecial.yaml, got %s", result) + } + }) + t.Run("without filename in config, no template suffix", func(t *testing.T) { + cfg := map[string]any{ + "other": "value", + } + result := getFilename(cfg, "myspecial.yaml") if result != constants.DefaultConfigFile { t.Errorf("Expected %s, got %s", constants.DefaultConfigFile, result) } }) - - t.Run("empty filename in config", func(t *testing.T) { + t.Run("empty filename in config, with template file", func(t *testing.T) { cfg := map[string]any{ "filename": "", } - result := getFilename(cfg) - if result != constants.DefaultConfigFile { - t.Errorf("Expected %s for empty filename, got %s", constants.DefaultConfigFile, result) + result := getFilename(cfg, "myspecial.yaml.tmpl") + if result != "myspecial.yaml" { + t.Errorf("Expected myspecial.yaml for empty filename, got %s", result) } }) @@ -396,9 +403,9 @@ func TestGetFilename(t *testing.T) { cfg := map[string]any{ "filename": 123, } - result := getFilename(cfg) - if result != constants.DefaultConfigFile { - t.Errorf("Expected %s for non-string filename, got %s", constants.DefaultConfigFile, result) + result := getFilename(cfg, "myspecial.yaml.tmpl") + if result != "myspecial.yaml" { + t.Errorf("Expected myspecial.yaml for non-string filename, got %s", result) } }) }