From a90c68bf5e340a9aaa79a027fbda5e2402c563e5 Mon Sep 17 00:00:00 2001 From: Tom Wiesing Date: Thu, 2 Nov 2023 13:31:54 +0100 Subject: [PATCH] Allow exposing graphdb and phpmyadmin via config --- internal/config/config.yml | 7 ++++ internal/config/http.go | 41 ++++++++++++++++++- .../component/server/admin/html/index.html | 40 +++++++++++++----- internal/dis/component/sql/sql.go | 20 +++++++++ .../dis/component/sql/sql/docker-compose.yml | 9 ++++ .../dis/component/triplestore/triplestore.go | 21 ++++++++++ .../triplestore/triplestore/Dockerfile | 2 +- .../triplestore/docker-compose.yml | 13 ++++++ 8 files changed, 139 insertions(+), 14 deletions(-) diff --git a/internal/config/config.yml b/internal/config/config.yml index dbaafc1..22964ed 100644 --- a/internal/config/config.yml +++ b/internal/config/config.yml @@ -43,6 +43,13 @@ http: # In the future, it will be enabled by default, but at this point it is not. api: null + # Enable serving the triplestore webinterface publically under the "_ts" domain + ts: null + + # Enable serving the phpmyadmin webinterface publically under the "_phymyadmin" domain + phpmyadmin: null + + # Configuration for the (public) homepage of the distillery. home: # the title of the distillery to be set diff --git a/internal/config/http.go b/internal/config/http.go index 2a56771..c09dfaa 100644 --- a/internal/config/http.go +++ b/internal/config/http.go @@ -2,6 +2,7 @@ package config import ( "fmt" + "html/template" "net/url" "strings" @@ -27,6 +28,38 @@ type HTTPConfig struct { // API determines if the API is enabled. // In a future version of the distillery, it will be enabled by default. API validators.NullableBool `yaml:"api" validate:"bool" default:"false"` + + // TS determintes if the special Triplestore domain is enabled. + TS validators.NullableBool `yaml:"ts" validate:"bool" default:"false"` + + // PhpMyAdmin determines if the special PhpMyAdmin domain is enabled. + PhpMyAdmin validators.NullableBool `yaml:"phpmyadmin" validate:"bool" default:"false"` +} + +// TSDomain returns the full url to the triplestore, if any +func (hcfg HTTPConfig) TSURL() template.URL { + return hcfg.optionalURL(TriplestoreDomain.Domain(), hcfg.TS) +} + +func (hcfg HTTPConfig) PhpMyAdminURL() template.URL { + return hcfg.optionalURL(PHPMyAdminDomain.Domain(), hcfg.PhpMyAdmin) +} + +// optionalURL returns the public-facing url to domain if enabled is true. +func (hcfg HTTPConfig) optionalURL(domain string, enabled validators.NullableBool) template.URL { + if !(enabled.Set && enabled.Value) { + return "" + } + + u := url.URL{ + Scheme: "http", + Host: hcfg.Domains(domain)[0], + Path: "/", + } + if hcfg.HTTPSEnabled() { + u.Scheme = "https" + } + return template.URL(u.String()) } // JoinPath returns the root public url joined with the provided parts. @@ -56,20 +89,24 @@ func (hcfg HTTPConfig) HTTPSEnabled() bool { return hcfg.CertbotEmail != "" } +// SpecialDomain represents a reserved domain type SpecialDomain string var ( TriplestoreDomain SpecialDomain = "ts" + PHPMyAdminDomain SpecialDomain = "phpmyadmin" ) -func (hcfg HTTPConfig) SpecialDomain(domain SpecialDomain) string { - return fmt.Sprintf("%s.%s", string(domain)+"_", hcfg.PrimaryDomain) +func (sd SpecialDomain) Domain() string { + return "_" + string(sd) } // Domains adds the given subdomain to the primary and alias domains. // If sub is empty, returns only the domains. // // sub is not otherwise validated, and should be normalized by the caller. +// +// It is guaranteed that the first domain returned will always be the primary domain. func (hcfg HTTPConfig) Domains(sub string) []string { domains := append([]string{hcfg.PrimaryDomain}, hcfg.ExtraDomains...) if sub == "" { diff --git a/internal/dis/component/server/admin/html/index.html b/internal/dis/component/server/admin/html/index.html index 659655d..1e3960e 100644 --- a/internal/dis/component/server/admin/html/index.html +++ b/internal/dis/component/server/admin/html/index.html @@ -32,22 +32,14 @@ -
-

Distillery Configuration

-
-
-        {{ .Config.MarshalSensitive }}
-    
-
- -
-

Distillery Passwords

+

Distillery Services

+ @@ -57,6 +49,14 @@ + @@ -68,6 +68,14 @@ + @@ -77,4 +85,14 @@
ServiceInterface Username Password
SQL + {{ $pma := .Config.HTTP.PhpMyAdminURL }} + {{ if $pma }} + PHPMyAdmin + {{ else }} + (accessible via SSH) + {{ end }} + {{ .Config.SQL.AdminUsername }} Triplestore + {{ $ts := .Config.HTTP.TSURL }} + {{ if $ts }} + Workbench + {{ else }} + (accessible via SSH) + {{ end }} + {{ .Config.TS.AdminUsername }}
-
\ No newline at end of file + + +
+

Distillery Configuration

+
+ +
+
+        {{ .Config.MarshalSensitive }}
+    
+
diff --git a/internal/dis/component/sql/sql.go b/internal/dis/component/sql/sql.go index 46e96ff..39c5dad 100644 --- a/internal/dis/component/sql/sql.go +++ b/internal/dis/component/sql/sql.go @@ -5,8 +5,11 @@ import ( "path/filepath" "time" + "github.com/FAU-CDI/wisski-distillery/internal/config" "github.com/FAU-CDI/wisski-distillery/internal/dis/component" "github.com/tkw1536/pkglib/fsx/umaskfree" + "github.com/tkw1536/pkglib/yamlx" + "gopkg.in/yaml.v3" ) type SQL struct { @@ -47,6 +50,23 @@ func (sql *SQL) Stack() component.StackWithResources { EnvContext: map[string]string{ "DOCKER_NETWORK_NAME": sql.Config.Docker.Network(), "HTTPS_ENABLED": sql.Config.HTTP.HTTPSEnabledEnv(), + "HOST_RULE": sql.Config.HTTP.HostRule(config.PHPMyAdminDomain.Domain()), + }, + + ComposerYML: func(root *yaml.Node) (*yaml.Node, error) { + // phpmyadmin is exposed => everything is fine + if sql.Config.HTTP.PhpMyAdmin.Set && sql.Config.HTTP.PhpMyAdmin.Value { + return root, nil + } + + // not exposed => remove the appropriate labels + if err := yamlx.ReplaceWith(root, []string{ + "eu.wiss-ki.barrel.distillery=${DOCKER_NETWORK_NAME}", + }, "services", "phpmyadmin", "labels"); err != nil { + return nil, err + } + + return root, nil }, MakeDirsPerm: umaskfree.DefaultDirPerm, diff --git a/internal/dis/component/sql/sql/docker-compose.yml b/internal/dis/component/sql/sql/docker-compose.yml index 2016648..cd4de92 100644 --- a/internal/dis/component/sql/sql/docker-compose.yml +++ b/internal/dis/component/sql/sql/docker-compose.yml @@ -29,6 +29,15 @@ services: - 127.0.0.1:8080:80 labels: - "eu.wiss-ki.barrel.distillery=${DOCKER_NETWORK_NAME}" + + # expose phpmyadmin (removed when disabled in global config) + - "traefik.enable=True" + + - "traefik.http.routers.core_phpmyadmin.rule=${HOST_RULE}" + - "traefik.http.routers.core_phpmyadmin.tls=${HTTPS_ENABLED}" + - "traefik.http.routers.core_phpmyadmin.tls.certresolver=distillery" + + - "traefik.http.services.core_phpmyadmin.loadbalancer.server.port=80" depends_on: - sql restart: always diff --git a/internal/dis/component/triplestore/triplestore.go b/internal/dis/component/triplestore/triplestore.go index 921f916..1bb6c52 100644 --- a/internal/dis/component/triplestore/triplestore.go +++ b/internal/dis/component/triplestore/triplestore.go @@ -5,7 +5,10 @@ import ( "path/filepath" "time" + "github.com/FAU-CDI/wisski-distillery/internal/config" "github.com/FAU-CDI/wisski-distillery/internal/dis/component" + "github.com/tkw1536/pkglib/yamlx" + "gopkg.in/yaml.v3" ) type Triplestore struct { @@ -43,6 +46,24 @@ func (ts *Triplestore) Stack() component.StackWithResources { EnvContext: map[string]string{ "DOCKER_NETWORK_NAME": ts.Config.Docker.Network(), + "HOST_RULE": ts.Config.HTTP.HostRule(config.TriplestoreDomain.Domain()), + "HTTPS_ENABLED": ts.Config.HTTP.HTTPSEnabledEnv(), + }, + + ComposerYML: func(root *yaml.Node) (*yaml.Node, error) { + // ts is exposed => everything is fine + if ts.Config.HTTP.TS.Set && ts.Config.HTTP.TS.Value { + return root, nil + } + + // not exposed => remove the appropriate labels + if err := yamlx.ReplaceWith(root, []string{ + "eu.wiss-ki.barrel.distillery=${DOCKER_NETWORK_NAME}", + }, "services", "triplestore", "labels"); err != nil { + return nil, err + } + + return root, nil }, MakeDirs: []string{ diff --git a/internal/dis/component/triplestore/triplestore/Dockerfile b/internal/dis/component/triplestore/triplestore/Dockerfile index 38747b4..0f00c3d 100644 --- a/internal/dis/component/triplestore/triplestore/Dockerfile +++ b/internal/dis/component/triplestore/triplestore/Dockerfile @@ -51,7 +51,7 @@ EXPOSE 7200 # setup a healthcheck, that checks if the server is up. RUN apt-get update && apt-get install -y curl -HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 CMD curl --fail 127.0.0.1:7200/rest/repositories || exit 1 +# HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 CMD curl --fail 127.0.0.1:7200/rest/repositories || exit 1 # Add volumes for data, work and logs as these might be accessible from the outside. # To add your own configuration, manually mount a config file into /opt/graphdb/work diff --git a/internal/dis/component/triplestore/triplestore/docker-compose.yml b/internal/dis/component/triplestore/triplestore/docker-compose.yml index f557d87..690b354 100644 --- a/internal/dis/component/triplestore/triplestore/docker-compose.yml +++ b/internal/dis/component/triplestore/triplestore/docker-compose.yml @@ -15,6 +15,19 @@ services: GDB_HEAP_SIZE: 16G labels: - "eu.wiss-ki.barrel.distillery=${DOCKER_NETWORK_NAME}" + + # expose the triplestore (removed when disabled in global config) + - "traefik.enable=True" + + - "traefik.http.routers.core_ts.rule=${HOST_RULE}" + - "traefik.http.routers.core_ts.tls=${HTTPS_ENABLED}" + - "traefik.http.routers.core_ts.tls.certresolver=distillery" + - "traefik.http.routers.core_ts.middlewares=core_ts@docker" + + - "traefik.http.services.core_ts.loadbalancer.server.port=7200" + - "traefik.http.services.core_ts.loadbalancer.passHostHeader=false" + + - "traefik.http.middlewares.core_ts.headers.customRequestHeaders.host=localhost" restart: always