Add Traefik Hub access and remove Pilot access

This commit is contained in:
Tom Moulard 2022-03-18 11:06:08 +01:00 committed by GitHub
parent dad76e0478
commit 0d58e8d1ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 27 additions and 222 deletions

View file

@ -36,8 +36,6 @@ DOCKER_RUN_TRAEFIK_NOTTY := docker run $(INTEGRATION_OPTS) $(if $(DOCKER_NON_INT
IN_DOCKER ?= true
PLATFORM_URL := $(if $(PLATFORM_URL),$(PLATFORM_URL),"https://pilot.traefik.io")
default: binary
## Build Dev Docker image
@ -54,7 +52,7 @@ dist:
## Build WebUI Docker image
build-webui-image:
docker build -t traefik-webui --build-arg ARG_PLATFORM_URL=$(PLATFORM_URL) -f webui/Dockerfile webui
docker build -t traefik-webui -f webui/Dockerfile webui
## Clean WebUI static generated assets
clean-webui:

View file

@ -215,6 +215,8 @@ 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
}

View file

@ -452,3 +452,10 @@ 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 our Blog for migration instructions later this year.

View file

@ -1,5 +1,10 @@
# 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:

View file

@ -1,6 +1,7 @@
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"`

View file

@ -76,6 +76,7 @@ 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"`
Experimental *Experimental `description:"experimental features." json:"experimental,omitempty" toml:"experimental,omitempty" yaml:"experimental,omitempty" export:"true"`

View file

@ -2,8 +2,6 @@ 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/

View file

@ -118,13 +118,11 @@ 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'),
PLATFORM_URL: JSON.stringify(process.env.PLATFORM_URL || 'https://pilot.traefik.io')
APP_API: JSON.stringify(process.env.APP_API || '/api')
}
: { // production:
APP_ENV: JSON.stringify(process.env.APP_ENV),
APP_API: JSON.stringify(process.env.APP_API || '/api'),
PLATFORM_URL: JSON.stringify(process.env.PLATFORM_URL || 'https://pilot.traefik.io')
APP_API: JSON.stringify(process.env.APP_API || '/api')
},
uglifyOptions: {
compress: {

View file

@ -1,26 +1,17 @@
<template>
<div id="q-app">
<router-view />
<platform-panel
v-if="pilotEnabled" />
</div>
</template>
<script>
import { APP } from './_helpers/APP'
import PlatformPanel from './components/platform/PlatformPanel'
import { mapGetters } from 'vuex'
export default {
name: 'App',
components: {
PlatformPanel
},
computed: {
...mapGetters('core', { coreVersion: 'version' }),
pilotEnabled () {
return this.coreVersion.pilotEnabled
}
...mapGetters('core', { coreVersion: 'version' })
},
beforeCreate () {
// Set vue instance

View file

@ -1,8 +1,7 @@
const APP = {
config: {
env: process.env.APP_ENV,
apiUrl: process.env.APP_API,
platformUrl: process.env.PLATFORM_URL
apiUrl: process.env.APP_API
}
}

View file

@ -15,6 +15,7 @@
</q-tabs>
<div class="right-menu">
<q-tabs>
<q-btn type="a" href="https://hub.traefik.io/" target="_blank" flat no-caps label="Go to Hub Dashboard →" class="btn-menu btn-hub" />
<q-btn @click="$q.dark.toggle()" stretch flat no-caps icon="invert_colors" :label="`${$q.dark.isActive ? 'Light' : 'Dark'} theme`" class="btn-menu" />
<q-btn stretch flat icon="eva-question-mark-circle-outline">
<q-menu anchor="bottom left" auto-close>
@ -28,8 +29,6 @@
</q-menu>
</q-btn>
</q-tabs>
<platform-auth-state
v-if="pilotEnabled" />
</div>
</q-toolbar>
</div>
@ -45,12 +44,10 @@
<script>
import config from '../../../package'
import PlatformAuthState from '../platform/PlatformAuthState'
import { mapActions, mapGetters } from 'vuex'
export default {
name: 'NavBar',
components: { PlatformAuthState },
computed: {
...mapGetters('core', { coreVersion: 'version' }),
version () {
@ -59,9 +56,6 @@ export default {
? this.coreVersion.Version
: this.coreVersion.Version.substring(0, 7)
},
pilotEnabled () {
return this.coreVersion.pilotEnabled
},
parsedVersion () {
if (!this.version) {
return 'master'
@ -144,6 +138,11 @@ export default {
font-weight: 600;
}
.btn-hub {
color: #0e204c;
background: #deea48;
}
.q-item {
padding: 0;
}

View file

@ -1,82 +0,0 @@
<template>
<div class="iframe-wrapper" v-if="isOnline">
<iframe
id="platform-auth-state"
:src="iFrameUrl"
v-if="renderIrame"
v-resize="resizeOpts"
height="64px"
frameBorder="0"
/>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
import qs from 'query-string'
import '../../_directives/resize'
export default {
name: 'PlatformPanel',
data () {
return {
renderIrame: true,
resizeOpts: {
log: false,
onMessage: ({ iframe, message }) => {
if (typeof message === 'string') {
// 1st condition for backward compatibility
if (message === 'open:profile') {
this.openPlatform('/')
} else if (message.includes('open:')) {
this.openPlatform(message.split('open:')[1])
} else if (message === 'logout') {
this.closePlatform()
}
}
}
}
}
},
created () {
this.getInstanceInfos()
},
computed: {
...mapGetters('platform', { isPlatformOpen: 'isOpen', platformPath: 'path' }),
...mapGetters('core', { instanceInfos: 'version' }),
isOnline () {
return window.navigator.onLine
},
iFrameUrl () {
const instanceInfos = JSON.stringify(this.instanceInfos)
const authRedirectUrl = `${window.location.href.split('?')[0]}?platform=${this.platformPath}`
return qs.stringifyUrl({ url: `${this.platformUrl}/partials/auth-state`, query: { authRedirectUrl, instanceInfos } })
}
},
methods: {
...mapActions('platform', { openPlatform: 'open' }, { closePlatform: 'close' }),
...mapActions('core', { getInstanceInfos: 'getVersion' })
},
watch: {
isPlatformOpen (isOpen, wasOpen) {
if (!isOpen && wasOpen) {
this.renderIrame = false
this.$nextTick().then(() => {
this.renderIrame = true
})
}
}
}
}
</script>
<style scoped lang="scss">
@import "../../css/sass/variables";
#platform-auth-state {
width: 1px;
min-width: 296px;
}
</style>

View file

@ -1,112 +0,0 @@
<template>
<side-panel
:isOpen="isPlatformOpen"
@onClose="closePlatform()"
v-if="isOnline"
>
<div class="iframe-wrapper">
<iframe
id="platform-iframe"
:src="iFrameUrl"
v-resize="resizeOpts"
style="position: relative; height: 100%; width: 100%;"
frameBorder="0"
scrolling="yes"
@load="onIFrameLoad"
/>
</div>
</side-panel>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
import qs from 'query-string'
import SidePanel from '../_commons/SidePanel'
import Helps from '../../_helpers/Helps'
import '../../_directives/resize'
export default {
name: 'PlatformPanel',
components: {
SidePanel
},
data () {
return {
resizeOpts: {
log: false,
resize: false,
scrolling: true,
onMessage: ({ iframe, message }) => {
if (typeof message === 'string') {
// 1st condition for backward compatibility
if (message === 'open:profile') {
this.openPlatform('/')
} else if (message.includes('open:')) {
this.openPlatform(message.split('open:')[1])
} else if (message === 'logout') {
this.closePlatform()
}
} else if (message.type) {
switch (message.type) {
case 'copy-to-clipboard':
navigator.clipboard.writeText(message.value)
break
}
} else if (message.isAuthenticated) {
this.isAuthenticated = message.isAuthenticated
}
}
}
}
},
created () {
this.getInstanceInfos()
},
computed: {
...mapGetters('platform', { isPlatformOpen: 'isOpen', platformPath: 'path' }),
...mapGetters('core', { instanceInfos: 'version' }),
iFrameUrl () {
const instanceInfos = JSON.stringify(this.instanceInfos)
const authRedirectUrl = `${window.location.href.split('?')[0]}?platform=${this.platformPath}`
return qs.stringifyUrl({ url: `${this.platformUrl}${this.platformPath}`, query: { authRedirectUrl, instanceInfos } })
},
isOnline () {
return window.navigator.onLine
}
},
methods: {
...mapActions('platform', { openPlatform: 'open', closePlatform: 'close' }),
...mapActions('core', { getInstanceInfos: 'getVersion' })
},
watch: {
$route (to, from) {
const wasOpen = from.query && from.query.platform
const isOpen = to.query && to.query.platform
if (!wasOpen && isOpen) {
this.openPlatform(to.query.platform)
}
},
isPlatformOpen (newValue, oldValue) {
if (newValue !== oldValue) {
document.querySelector('body').style.overflow = newValue ? 'hidden' : 'visible'
this.$router.push({
path: this.$route.path,
query: Helps.removeEmptyObjects({
...this.$route.query,
platform: this.platformPath ? this.platformPath : undefined
})
})
}
}
}
}
</script>
<style scoped>
.iframe-wrapper {
height: 100%;
}
</style>