diff --git a/cmd/traefik/traefik.go b/cmd/traefik/traefik.go index 875eff503..47f409a0b 100644 --- a/cmd/traefik/traefik.go +++ b/cmd/traefik/traefik.go @@ -34,6 +34,7 @@ import ( "github.com/traefik/traefik/v2/pkg/pilot" "github.com/traefik/traefik/v2/pkg/provider/acme" "github.com/traefik/traefik/v2/pkg/provider/aggregator" + "github.com/traefik/traefik/v2/pkg/provider/hub" "github.com/traefik/traefik/v2/pkg/provider/traefik" "github.com/traefik/traefik/v2/pkg/safe" "github.com/traefik/traefik/v2/pkg/server" @@ -215,8 +216,6 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err } if staticConfiguration.Pilot != nil { - log.WithoutContext().Warn("Traefik Pilot is deprecated and will be removed soon. Please check our Blog for migration instructions later this year") - version.PilotEnabled = staticConfiguration.Pilot.Dashboard } @@ -363,7 +362,7 @@ func getDefaultsEntrypoints(staticConfiguration *static.Configuration) []string var defaultEntryPoints []string for name, cfg := range staticConfiguration.EntryPoints { // Traefik Hub entryPoint should not be part of the set of default entryPoints. - if staticConfiguration.Hub != nil && staticConfiguration.Hub.EntryPoint == name { + if hub.APIEntrypoint == name || hub.TunnelEntrypoint == name { continue } diff --git a/docs/content/migration/v2.md b/docs/content/migration/v2.md index d3f80dcde..fa5b87112 100644 --- a/docs/content/migration/v2.md +++ b/docs/content/migration/v2.md @@ -457,10 +457,3 @@ the value for the method label becomes `EXTENSION_METHOD`, instead of the reques ### Tracing In `v2.6.1`, the Datadog tags added to a span changed from `service.name` to `traefik.service.name` and from `router.name` to `traefik.router.name`. - -## v2.7 - -### Traefik Pilot - -In `v2.7`, the `pilot.token` and `pilot.dashboard` options are deprecated. -Please check the [feature deprecation page](../deprecation/features.md) and our Blog for migration instructions later this year. diff --git a/docs/content/plugins/index.md b/docs/content/plugins/index.md index 421044278..f5062b21f 100644 --- a/docs/content/plugins/index.md +++ b/docs/content/plugins/index.md @@ -5,11 +5,6 @@ description: "Learn how to connect Traefik Proxy with Pilot, a SaaS platform tha # Plugins and Traefik Pilot -!!! warning "Traefik Pilot Deprecation" - - Traefik Pilot is deprecated and will be removed soon. - Please check our Blog for migration instructions later this year. - Traefik Pilot is a software-as-a-service (SaaS) platform that connects to Traefik to extend its capabilities. It offers a number of features to enhance observability and control of Traefik through a global control plane and dashboard, including: diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index 9345cded4..bcd6fc904 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -222,9 +222,6 @@ The maximal depth of DNS recursive resolving (Default: ```5```) `--hub`: Traefik Hub configuration. (Default: ```false```) -`--hub.entrypoint`: -Entrypoint that exposes data for Traefik Hub. It should be a dedicated one, and not used by any router. (Default: ```traefik-hub```) - `--hub.tls.ca`: The certificate authority authenticates the Traefik Hub Agent certificate. diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index 340917400..ccaacfe1f 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -222,9 +222,6 @@ The maximal depth of DNS recursive resolving (Default: ```5```) `TRAEFIK_HUB`: Traefik Hub configuration. (Default: ```false```) -`TRAEFIK_HUB_ENTRYPOINT`: -Entrypoint that exposes data for Traefik Hub. It should be a dedicated one, and not used by any router. (Default: ```traefik-hub```) - `TRAEFIK_HUB_TLS_CA`: The certificate authority authenticates the Traefik Hub Agent certificate. diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml index cab590f6f..d81a6b7d9 100644 --- a/docs/content/reference/static-configuration/file.toml +++ b/docs/content/reference/static-configuration/file.toml @@ -426,7 +426,6 @@ dashboard = true [hub] - entrypoint = "foobar" [hub.tls] insecure = true ca = "foobar" diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml index 88e602f1d..5da697177 100644 --- a/docs/content/reference/static-configuration/file.yaml +++ b/docs/content/reference/static-configuration/file.yaml @@ -447,7 +447,6 @@ pilot: token: foobar dashboard: true hub: - entrypoint: foobar tls: insecure: true ca: foobar diff --git a/docs/content/traefik-hub/index.md b/docs/content/traefik-hub/index.md deleted file mode 100644 index d6fa92dfe..000000000 --- a/docs/content/traefik-hub/index.md +++ /dev/null @@ -1,295 +0,0 @@ -# Traefik Hub (Experimental) - -## Overview - -Once the Traefik Hub Experimental feature is enabled in Traefik, -Traefik and its local agent communicate together. -This agent can: - -* get the Traefik metrics to display them in the Traefik Hub UI -* secure the Traefik routers -* provide ACME certificates to Traefik -* transfer requests from the SaaS Platform to Traefik (and then avoid the users to expose directly their infrastructure on the internet) - -!!! warning "Traefik Hub EntryPoint" - - When the Traefik Hub feature is enabled, Traefik exposes some services meant for the Traefik Hub Agent on a dedicated entryPoint (on port `9900` by default). - Given their sensitive nature, those services should not be publicly exposed. - Also this dedicated entryPoint, regardless of how it is created (default, or user-defined), should not be used by anything other than the Hub Agent. - -!!! important "Learn More About Traefik Hub" - - This section is intended only as a brief overview for Traefik users who are not familiar with Traefik Hub. - To explore all that Traefik Hub has to offer, please consult the [Traefik Hub Documentation](https://doc.traefik.io/traefik-hub). - -!!! Note "Prerequisites" - - * Traefik Hub is compatible with Traefik Proxy 2.7 or later. - * The Traefik Hub Agent must be installed to connect to the Traefik Hub platform. - * Activate this feature in the experimental section of the static configuration. - -!!! example "Minimal Static Configuration to Activate Traefik Hub" - - ```yaml tab="File (YAML)" - experimental: - hub: true - - hub: - tls: - insecure: true - - metrics: - prometheus: {} - ``` - - ```toml tab="File (TOML)" - [experimental] - hub = true - - [hub] - [hub.tls] - insecure = true - - [metrics] - [metrics.prometheus] - ``` - - ```bash tab="CLI" - --experimental.hub - --hub.tls.insecure=true - --metrics.prometheus=true - ``` - -## Configuration - -### `entryPoint` - -_Optional, Default="traefik-hub"_ - -Defines the entryPoint that exposes data for Traefik Hub Agent. - -!!! info - - * If no entryPoint is defined, a default `traefik-hub` entryPoint is created (on port `9900`). - * If defined, the value must match an existing entryPoint name. - * This dedicated Traefik Hub entryPoint should not be used by anything other than Traefik Hub. - -```yaml tab="File (YAML)" -entryPoints: - hub-ep: ":8000" - -hub: - entryPoint: "hub-ep" -``` - -```toml tab="File (TOML)" -[entryPoints.hub-ep] - address = ":8000" - -[hub] - entryPoint = "hub-ep" -``` - -```bash tab="CLI" ---entrypoints.hub-ep.address=:8000 ---hub.entrypoint=hub-ep -``` - -### `tls` - -_Required, Default=None_ - -This section allows configuring mutual TLS connection between Traefik Proxy and the Traefik Hub Agent. -The key and the certificate are the credentials for Traefik Proxy as a TLS client. -The certificate authority authenticates the Traefik Hub Agent certificate. - -!!! note "Certificate Domain" - - The certificate must be valid for the `proxy.traefik` domain. - -!!! note "Certificates Definition" - - Certificates can be defined either by their content or their path. - -!!! note "Insecure Mode" - - The `insecure` option is mutually exclusive with any other option. - -```yaml tab="File (YAML)" -hub: - tls: - ca: /path/to/ca.pem - cert: /path/to/cert.pem - key: /path/to/key.pem -``` - -```toml tab="File (TOML)" -[hub.tls] - ca= "/path/to/ca.pem" - cert= "/path/to/cert.pem" - key= "/path/to/key.pem" -``` - -```bash tab="CLI" ---hub.tls.ca=/path/to/ca.pem ---hub.tls.cert=/path/to/cert.pem ---hub.tls.key=/path/to/key.pem -``` - -### `tls.ca` - -The certificate authority authenticates the Traefik Hub Agent certificate. - -```yaml tab="File (YAML)" -hub: - tls: - ca: |- - -----BEGIN CERTIFICATE----- - MIIBcjCCARegAwIBAgIQaewCzGdRz5iNnjAiEoO5AzAKBggqhkjOPQQDAjASMRAw - DgYDVQQKEwdBY21lIENvMCAXDTIyMDMyMTE2MTY0NFoYDzIxMjIwMjI1MTYxNjQ0 - WjASMRAwDgYDVQQKEwdBY21lIENvMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE - ZaKYPj2G8Hnmju6jbHt+vODwKqNDVQMH5nxhtAgSUZS61mLWwZvvUhIYLNPwHz8a - x8C7+cuihEC6Tzvn8DeGeKNNMEswDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG - CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwFgYDVR0RBA8wDYILZXhhbXBsZS5jb20w - CgYIKoZIzj0EAwIDSQAwRgIhAO8sucDGY+JOrNgQg1a9ZqqYvbxPFnYsSZr7F/vz - aUX2AiEAilZ+M5eX4RiMFc3nlm9qVs1LZhV3dZW/u80/mPQ/oaY= - -----END CERTIFICATE----- -``` - -```toml tab="File (TOML)" -[hub.tls] - ca = """-----BEGIN CERTIFICATE----- -MIIBcjCCARegAwIBAgIQaewCzGdRz5iNnjAiEoO5AzAKBggqhkjOPQQDAjASMRAw -DgYDVQQKEwdBY21lIENvMCAXDTIyMDMyMTE2MTY0NFoYDzIxMjIwMjI1MTYxNjQ0 -WjASMRAwDgYDVQQKEwdBY21lIENvMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE -ZaKYPj2G8Hnmju6jbHt+vODwKqNDVQMH5nxhtAgSUZS61mLWwZvvUhIYLNPwHz8a -x8C7+cuihEC6Tzvn8DeGeKNNMEswDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG -CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwFgYDVR0RBA8wDYILZXhhbXBsZS5jb20w -CgYIKoZIzj0EAwIDSQAwRgIhAO8sucDGY+JOrNgQg1a9ZqqYvbxPFnYsSZr7F/vz -aUX2AiEAilZ+M5eX4RiMFc3nlm9qVs1LZhV3dZW/u80/mPQ/oaY= ------END CERTIFICATE-----""" -``` - -```bash tab="CLI" ---hub.tls.ca=-----BEGIN CERTIFICATE----- -MIIBcjCCARegAwIBAgIQaewCzGdRz5iNnjAiEoO5AzAKBggqhkjOPQQDAjASMRAw -DgYDVQQKEwdBY21lIENvMCAXDTIyMDMyMTE2MTY0NFoYDzIxMjIwMjI1MTYxNjQ0 -WjASMRAwDgYDVQQKEwdBY21lIENvMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE -ZaKYPj2G8Hnmju6jbHt+vODwKqNDVQMH5nxhtAgSUZS61mLWwZvvUhIYLNPwHz8a -x8C7+cuihEC6Tzvn8DeGeKNNMEswDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG -CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwFgYDVR0RBA8wDYILZXhhbXBsZS5jb20w -CgYIKoZIzj0EAwIDSQAwRgIhAO8sucDGY+JOrNgQg1a9ZqqYvbxPFnYsSZr7F/vz -aUX2AiEAilZ+M5eX4RiMFc3nlm9qVs1LZhV3dZW/u80/mPQ/oaY= ------END CERTIFICATE----- -``` - -### `tls.cert` - -The TLS certificate for Traefik Proxy as a TLS client. - -!!! note "Certificate Domain" - - The certificate must be valid for the `proxy.traefik` domain. - -```yaml tab="File (YAML)" -hub: - tls: - cert: |- - -----BEGIN CERTIFICATE----- - MIIBcjCCARegAwIBAgIQaewCzGdRz5iNnjAiEoO5AzAKBggqhkjOPQQDAjASMRAw - DgYDVQQKEwdBY21lIENvMCAXDTIyMDMyMTE2MTY0NFoYDzIxMjIwMjI1MTYxNjQ0 - WjASMRAwDgYDVQQKEwdBY21lIENvMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE - ZaKYPj2G8Hnmju6jbHt+vODwKqNDVQMH5nxhtAgSUZS61mLWwZvvUhIYLNPwHz8a - x8C7+cuihEC6Tzvn8DeGeKNNMEswDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG - CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwFgYDVR0RBA8wDYILZXhhbXBsZS5jb20w - CgYIKoZIzj0EAwIDSQAwRgIhAO8sucDGY+JOrNgQg1a9ZqqYvbxPFnYsSZr7F/vz - aUX2AiEAilZ+M5eX4RiMFc3nlm9qVs1LZhV3dZW/u80/mPQ/oaY= - -----END CERTIFICATE----- -``` - -```toml tab="File (TOML)" -[hub.tls] - cert = """-----BEGIN CERTIFICATE----- -MIIBcjCCARegAwIBAgIQaewCzGdRz5iNnjAiEoO5AzAKBggqhkjOPQQDAjASMRAw -DgYDVQQKEwdBY21lIENvMCAXDTIyMDMyMTE2MTY0NFoYDzIxMjIwMjI1MTYxNjQ0 -WjASMRAwDgYDVQQKEwdBY21lIENvMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE -ZaKYPj2G8Hnmju6jbHt+vODwKqNDVQMH5nxhtAgSUZS61mLWwZvvUhIYLNPwHz8a -x8C7+cuihEC6Tzvn8DeGeKNNMEswDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG -CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwFgYDVR0RBA8wDYILZXhhbXBsZS5jb20w -CgYIKoZIzj0EAwIDSQAwRgIhAO8sucDGY+JOrNgQg1a9ZqqYvbxPFnYsSZr7F/vz -aUX2AiEAilZ+M5eX4RiMFc3nlm9qVs1LZhV3dZW/u80/mPQ/oaY= ------END CERTIFICATE-----""" -``` - -```bash tab="CLI" ---hub.tls.cert=-----BEGIN CERTIFICATE----- -MIIBcjCCARegAwIBAgIQaewCzGdRz5iNnjAiEoO5AzAKBggqhkjOPQQDAjASMRAw -DgYDVQQKEwdBY21lIENvMCAXDTIyMDMyMTE2MTY0NFoYDzIxMjIwMjI1MTYxNjQ0 -WjASMRAwDgYDVQQKEwdBY21lIENvMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE -ZaKYPj2G8Hnmju6jbHt+vODwKqNDVQMH5nxhtAgSUZS61mLWwZvvUhIYLNPwHz8a -x8C7+cuihEC6Tzvn8DeGeKNNMEswDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG -CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwFgYDVR0RBA8wDYILZXhhbXBsZS5jb20w -CgYIKoZIzj0EAwIDSQAwRgIhAO8sucDGY+JOrNgQg1a9ZqqYvbxPFnYsSZr7F/vz -aUX2AiEAilZ+M5eX4RiMFc3nlm9qVs1LZhV3dZW/u80/mPQ/oaY= ------END CERTIFICATE----- -``` - -### `tls.key` - -The TLS key for Traefik Proxy as a TLS client. - -```yaml tab="File (YAML)" -hub: - tls: - key: |- - -----BEGIN PRIVATE KEY----- - MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgm+XJ3LVrTbbirJea - O+Crj2ADVsVHjMuiyd72VE3lgxihRANCAARlopg+PYbweeaO7qNse3684PAqo0NV - AwfmfGG0CBJRlLrWYtbBm+9SEhgs0/AfPxrHwLv5y6KEQLpPO+fwN4Z4 - -----END PRIVATE KEY----- -``` - -```toml tab="File (TOML)" -[hub.tls] - key = """-----BEGIN PRIVATE KEY----- -MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgm+XJ3LVrTbbirJea -O+Crj2ADVsVHjMuiyd72VE3lgxihRANCAARlopg+PYbweeaO7qNse3684PAqo0NV -AwfmfGG0CBJRlLrWYtbBm+9SEhgs0/AfPxrHwLv5y6KEQLpPO+fwN4Z4 ------END PRIVATE KEY-----""" -``` - -```bash tab="CLI" ---hub.tls.key=-----BEGIN PRIVATE KEY----- -MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgm+XJ3LVrTbbirJea -O+Crj2ADVsVHjMuiyd72VE3lgxihRANCAARlopg+PYbweeaO7qNse3684PAqo0NV -AwfmfGG0CBJRlLrWYtbBm+9SEhgs0/AfPxrHwLv5y6KEQLpPO+fwN4Z4 ------END PRIVATE KEY----- -``` - -### `tls.insecure` - -_Optional, Default=false_ - -Enables an insecure TLS connection that uses default credentials, -and which has no peer authentication between Traefik Proxy and the Traefik Hub Agent. -The `insecure` option is mutually exclusive with any other option. - -!!! warning "Security Consideration" - - Do not use this setup in production. - This option implies sensitive data can be exposed to potential malicious third-party programs. - -```yaml tab="File (YAML)" -hub: - tls: - insecure: true -``` - -```toml tab="File (TOML)" -[hub.tls] - insecure = true -``` - -```bash tab="CLI" ---hub.tls.insecure=true -``` diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index a3a8a0497..08c78cae2 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -136,7 +136,6 @@ nav: - 'InFlightConn': 'middlewares/tcp/inflightconn.md' - 'IpWhitelist': 'middlewares/tcp/ipwhitelist.md' - 'Plugins & Traefik Pilot': 'plugins/index.md' - - 'Traefik Hub': 'traefik-hub/index.md' - 'Operations': - 'CLI': 'operations/cli.md' - 'Dashboard' : 'operations/dashboard.md' diff --git a/pkg/config/static/hub.go b/pkg/config/static/hub.go new file mode 100644 index 000000000..ee78de975 --- /dev/null +++ b/pkg/config/static/hub.go @@ -0,0 +1,53 @@ +package static + +import ( + "errors" + + "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/provider/hub" +) + +func (c *Configuration) initHubProvider() error { + // Hub provider is an experimental feature. It requires the experimental flag to be enabled before continuing. + if c.Experimental == nil || !c.Experimental.Hub { + return errors.New("the experimental flag for Hub is not set") + } + + if _, ok := c.EntryPoints[hub.TunnelEntrypoint]; !ok { + var ep EntryPoint + ep.SetDefaults() + ep.Address = ":9901" + c.EntryPoints[hub.TunnelEntrypoint] = &ep + log.WithoutContext().Infof("The entryPoint %q is created on port 9901 to allow exposition of services.", hub.TunnelEntrypoint) + } + + if c.Hub.TLS == nil { + return nil + } + + if c.Hub.TLS.Insecure && (c.Hub.TLS.CA != "" || c.Hub.TLS.Cert != "" || c.Hub.TLS.Key != "") { + return errors.New("mTLS configuration for Hub and insecure TLS for Hub are mutually exclusive") + } + + if !c.Hub.TLS.Insecure && (c.Hub.TLS.CA == "" || c.Hub.TLS.Cert == "" || c.Hub.TLS.Key == "") { + return errors.New("incomplete mTLS configuration for Hub") + } + + if c.Hub.TLS.Insecure { + log.WithoutContext().Warn("Hub is in `insecure` mode. Do not run in production with this setup.") + } + + if _, ok := c.EntryPoints[hub.APIEntrypoint]; !ok { + var ep EntryPoint + ep.SetDefaults() + ep.Address = ":9900" + c.EntryPoints[hub.APIEntrypoint] = &ep + log.WithoutContext().Infof("The entryPoint %q is created on port 9900 to allow Traefik to communicate with the Hub Agent for Traefik.", hub.APIEntrypoint) + } + + c.EntryPoints[hub.APIEntrypoint].HTTP.TLS = &TLSConfig{ + Options: "traefik-hub", + } + + return nil +} diff --git a/pkg/config/static/pilot.go b/pkg/config/static/pilot.go index f3699a729..147c8917b 100644 --- a/pkg/config/static/pilot.go +++ b/pkg/config/static/pilot.go @@ -1,7 +1,6 @@ package static // Pilot Configuration related to Traefik Pilot. -// Deprecated. type Pilot struct { Token string `description:"Traefik Pilot token." json:"token,omitempty" toml:"token,omitempty" yaml:"token,omitempty" loggable:"false"` Dashboard bool `description:"Enable Traefik Pilot in the dashboard." json:"dashboard,omitempty" toml:"dashboard,omitempty" yaml:"dashboard,omitempty"` diff --git a/pkg/config/static/static_config.go b/pkg/config/static/static_config.go index 961786f94..b285996f8 100644 --- a/pkg/config/static/static_config.go +++ b/pkg/config/static/static_config.go @@ -1,7 +1,6 @@ package static import ( - "errors" "fmt" stdlog "log" "strings" @@ -78,7 +77,6 @@ type Configuration struct { CertificatesResolvers map[string]CertificateResolver `description:"Certificates resolvers configuration." json:"certificatesResolvers,omitempty" toml:"certificatesResolvers,omitempty" yaml:"certificatesResolvers,omitempty" export:"true"` - // Deprecated. Pilot *Pilot `description:"Traefik Pilot configuration." json:"pilot,omitempty" toml:"pilot,omitempty" yaml:"pilot,omitempty" export:"true"` Hub *hub.Provider `description:"Traefik Hub configuration." json:"hub,omitempty" toml:"hub,omitempty" yaml:"hub,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` @@ -201,7 +199,7 @@ type Providers struct { // It also takes care of maintaining backwards compatibility. func (c *Configuration) SetEffectiveConfiguration() { // Creates the default entry point if needed - if len(c.EntryPoints) == 0 || (c.Hub != nil && len(c.EntryPoints) == 1 && c.EntryPoints[c.Hub.EntryPoint] != nil) { + if !c.hasUserDefinedEntrypoint() { ep := &EntryPoint{Address: ":80"} ep.SetDefaults() // TODO: double check this tomorrow @@ -287,6 +285,21 @@ func (c *Configuration) SetEffectiveConfiguration() { c.initACMEProvider() } +func (c *Configuration) hasUserDefinedEntrypoint() bool { + if len(c.EntryPoints) == 0 { + return false + } + + switch len(c.EntryPoints) { + case 1: + return c.EntryPoints[hub.TunnelEntrypoint] == nil + case 2: + return c.EntryPoints[hub.TunnelEntrypoint] == nil || c.EntryPoints[hub.APIEntrypoint] == nil + default: + return true + } +} + func (c *Configuration) initACMEProvider() { for _, resolver := range c.CertificatesResolvers { if resolver.ACME != nil { @@ -297,46 +310,6 @@ func (c *Configuration) initACMEProvider() { legolog.Logger = stdlog.New(log.WithoutContext().WriterLevel(logrus.DebugLevel), "legolog: ", 0) } -func (c *Configuration) initHubProvider() error { - // Hub provider is an experimental feature. Require the experimental flag to be enabled before continuing. - if c.Experimental == nil || !c.Experimental.Hub { - return errors.New("experimental flag for Hub not set") - } - - if c.Hub.TLS == nil { - return errors.New("no TLS configuration defined for Hub") - } - - if c.Hub.TLS.Insecure && (c.Hub.TLS.CA != "" || c.Hub.TLS.Cert != "" || c.Hub.TLS.Key != "") { - return errors.New("mTLS configuration for Hub and insecure TLS for Hub are mutually exclusive") - } - - if !c.Hub.TLS.Insecure && (c.Hub.TLS.CA == "" || c.Hub.TLS.Cert == "" || c.Hub.TLS.Key == "") { - return errors.New("incomplete mTLS configuration for Hub") - } - - if c.Hub.TLS.Insecure { - log.WithoutContext().Warn("Hub is in `insecure` mode. Do not run in production with this setup.") - } - - // Creates the internal Hub entry point if needed. - if c.Hub.EntryPoint == hub.DefaultEntryPointName { - if _, ok := c.EntryPoints[hub.DefaultEntryPointName]; !ok { - var ep EntryPoint - ep.SetDefaults() - ep.Address = ":9900" - c.EntryPoints[hub.DefaultEntryPointName] = &ep - log.WithoutContext().Infof("The entryPoint %q is created on port 9900 to allow Traefik to communicate with the Hub Agent for Traefik.", hub.DefaultEntryPointName) - } - } - - c.EntryPoints[c.Hub.EntryPoint].HTTP.TLS = &TLSConfig{ - Options: "traefik-hub", - } - - return nil -} - // ValidateConfiguration validate that configuration is coherent. func (c *Configuration) ValidateConfiguration() error { var acmeEmail string diff --git a/pkg/config/static/static_config_test.go b/pkg/config/static/static_config_test.go new file mode 100644 index 000000000..9680233dd --- /dev/null +++ b/pkg/config/static/static_config_test.go @@ -0,0 +1,88 @@ +package static + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/traefik/traefik/v2/pkg/provider/hub" +) + +func TestHasEntrypoint(t *testing.T) { + tests := []struct { + desc string + entryPoints map[string]*EntryPoint + assert assert.BoolAssertionFunc + }{ + { + desc: "no user defined entryPoints", + assert: assert.False, + }, + { + desc: "user defined entryPoints", + entryPoints: map[string]*EntryPoint{ + "foo": {}, + }, + assert: assert.True, + }, + { + desc: "user defined entryPoints + hub entryPoint (tunnel)", + entryPoints: map[string]*EntryPoint{ + "foo": {}, + hub.TunnelEntrypoint: {}, + }, + assert: assert.True, + }, + { + desc: "hub entryPoint (tunnel)", + entryPoints: map[string]*EntryPoint{ + hub.TunnelEntrypoint: {}, + }, + assert: assert.False, + }, + { + desc: "user defined entryPoints + hub entryPoint (api)", + entryPoints: map[string]*EntryPoint{ + "foo": {}, + hub.APIEntrypoint: {}, + }, + assert: assert.True, + }, + { + desc: "hub entryPoint (api)", + entryPoints: map[string]*EntryPoint{ + hub.APIEntrypoint: {}, + }, + assert: assert.True, + }, + { + desc: "user defined entryPoints + hub entryPoints (tunnel, api)", + entryPoints: map[string]*EntryPoint{ + "foo": {}, + hub.TunnelEntrypoint: {}, + hub.APIEntrypoint: {}, + }, + assert: assert.True, + }, + { + desc: "hub entryPoints (tunnel, api)", + entryPoints: map[string]*EntryPoint{ + hub.TunnelEntrypoint: {}, + hub.APIEntrypoint: {}, + }, + assert: assert.False, + }, + } + + for _, test := range tests { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + cfg := &Configuration{ + EntryPoints: test.entryPoints, + } + + test.assert(t, cfg.hasUserDefinedEntrypoint()) + }) + } +} diff --git a/pkg/provider/hub/hub.go b/pkg/provider/hub/hub.go index 1643a0980..62e2ace88 100644 --- a/pkg/provider/hub/hub.go +++ b/pkg/provider/hub/hub.go @@ -17,13 +17,15 @@ import ( var _ provider.Provider = (*Provider)(nil) -// DefaultEntryPointName is the name of the default internal entry point. -const DefaultEntryPointName = "traefik-hub" +// Entrypoints created for Hub. +const ( + APIEntrypoint = "traefikhub-api" + TunnelEntrypoint = "traefikhub-tunl" +) // Provider holds configurations of the provider. type Provider struct { - EntryPoint string `description:"Entrypoint that exposes data for Traefik Hub. It should be a dedicated one, and not used by any router." json:"entryPoint,omitempty" toml:"entryPoint,omitempty" yaml:"entryPoint,omitempty" export:"true"` - TLS *TLS `description:"TLS configuration for mTLS communication between Traefik and Hub Agent." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"` + TLS *TLS `description:"TLS configuration for mTLS communication between Traefik and Hub Agent." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"` server *http.Server } @@ -36,11 +38,6 @@ type TLS struct { Key ttls.FileOrContent `description:"The TLS key for Traefik Proxy as a TLS client." json:"key,omitempty" toml:"key,omitempty" yaml:"key,omitempty" loggable:"false"` } -// SetDefaults sets the default values. -func (p *Provider) SetDefaults() { - p.EntryPoint = DefaultEntryPointName -} - // Init the provider. func (p *Provider) Init() error { return nil @@ -59,7 +56,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, _ *safe.Poo return fmt.Errorf("creating Hub Agent HTTP client: %w", err) } - p.server = &http.Server{Handler: newHandler(p.EntryPoint, port, configurationChan, p.TLS, client)} + p.server = &http.Server{Handler: newHandler(APIEntrypoint, port, configurationChan, p.TLS, client)} // TODO: this is going to be leaky (because no context to make it terminate) // if/when Provide lifecycle differs with Traefik lifecycle. @@ -70,7 +67,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, _ *safe.Poo } }() - exposeAPIAndMetrics(configurationChan, p.EntryPoint, port, p.TLS) + exposeAPIAndMetrics(configurationChan, APIEntrypoint, port, p.TLS) return nil } diff --git a/webui/Dockerfile b/webui/Dockerfile index edb9593bc..643f12f8e 100644 --- a/webui/Dockerfile +++ b/webui/Dockerfile @@ -2,6 +2,8 @@ FROM node:14.16 # Current Active LTS release according to (https://nodejs.org/en/about/releases/) ENV WEBUI_DIR /src/webui +ARG ARG_PLATFORM_URL=https://pilot.traefik.io +ENV PLATFORM_URL=${ARG_PLATFORM_URL} RUN mkdir -p $WEBUI_DIR COPY package.json $WEBUI_DIR/ diff --git a/webui/quasar.conf.js b/webui/quasar.conf.js index 07eec1a8d..c7dc90513 100644 --- a/webui/quasar.conf.js +++ b/webui/quasar.conf.js @@ -118,11 +118,13 @@ module.exports = function (ctx) { env: process.env.APP_ENV === 'development' ? { // staging: APP_ENV: JSON.stringify(process.env.APP_ENV), - APP_API: JSON.stringify(process.env.APP_API || '/api') + APP_API: JSON.stringify(process.env.APP_API || '/api'), + PLATFORM_URL: JSON.stringify(process.env.PLATFORM_URL || 'https://pilot.traefik.io') } : { // production: APP_ENV: JSON.stringify(process.env.APP_ENV), - APP_API: JSON.stringify(process.env.APP_API || '/api') + APP_API: JSON.stringify(process.env.APP_API || '/api'), + PLATFORM_URL: JSON.stringify(process.env.PLATFORM_URL || 'https://pilot.traefik.io') }, uglifyOptions: { compress: { diff --git a/webui/src/App.vue b/webui/src/App.vue index d655741b1..bb6e93e60 100644 --- a/webui/src/App.vue +++ b/webui/src/App.vue @@ -1,17 +1,26 @@ + + diff --git a/webui/src/components/platform/PlatformPanel.vue b/webui/src/components/platform/PlatformPanel.vue new file mode 100644 index 000000000..a24f2bb1a --- /dev/null +++ b/webui/src/components/platform/PlatformPanel.vue @@ -0,0 +1,112 @@ +