Add Traefik Hub access and remove Pilot access
This commit is contained in:
parent
dad76e0478
commit
0d58e8d1ad
13 changed files with 27 additions and 222 deletions
4
Makefile
4
Makefile
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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"`
|
||||
|
|
|
@ -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"`
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
Loading…
Reference in a new issue