feat: docker auto upgrade
This commit is contained in:
@@ -27,6 +27,16 @@
|
|||||||
v-list-item-subtitle {{ info.latestVersion }}
|
v-list-item-subtitle {{ info.latestVersion }}
|
||||||
v-list-item-action
|
v-list-item-action
|
||||||
v-list-item-action-text {{ $t('admin:system.published') }} {{ info.latestVersionReleaseDate | moment('from') }}
|
v-list-item-action-text {{ $t('admin:system.published') }} {{ info.latestVersionReleaseDate | moment('from') }}
|
||||||
|
v-card-actions(v-if='upgradeCapable && !isLatestVersion && info.platform === `docker`', :class='$vuetify.theme.dark ? `grey darken-3-d5` : `indigo lighten-5`')
|
||||||
|
.caption.indigo--text.pl-3(:class='$vuetify.theme.dark ? `text--lighten-4` : ``') Wiki.js can perform the upgrade to the latest version for you.
|
||||||
|
v-spacer
|
||||||
|
v-btn.px-3(
|
||||||
|
color='indigo'
|
||||||
|
dark
|
||||||
|
@click='performUpgrade'
|
||||||
|
)
|
||||||
|
v-icon(left) mdi-upload
|
||||||
|
span Perform Upgrade
|
||||||
|
|
||||||
v-card.mt-4.animated.fadeInUp.wait-p2s
|
v-card.mt-4.animated.fadeInUp.wait-p2s
|
||||||
v-subheader {{ $t('admin:system.hostInfo') }}
|
v-subheader {{ $t('admin:system.hostInfo') }}
|
||||||
@@ -92,24 +102,58 @@
|
|||||||
v-list-item-subtitle {{ info.dbHost }}
|
v-list-item-subtitle {{ info.dbHost }}
|
||||||
|
|
||||||
v-alert.mt-3.mx-4(:value='isDbLimited', color='deep-orange darken-2', icon='mdi-alert', dark) {{ $t('admin:system.dbPartialSupport') }}
|
v-alert.mt-3.mx-4(:value='isDbLimited', color='deep-orange darken-2', icon='mdi-alert', dark) {{ $t('admin:system.dbPartialSupport') }}
|
||||||
|
|
||||||
|
v-dialog(
|
||||||
|
v-model='isUpgrading'
|
||||||
|
persistent
|
||||||
|
width='450'
|
||||||
|
)
|
||||||
|
v-card.blue.darken-5(dark)
|
||||||
|
v-card-text.text-center.pa-10
|
||||||
|
self-building-square-spinner(
|
||||||
|
:animation-duration='4000'
|
||||||
|
:size='40'
|
||||||
|
color='#FFF'
|
||||||
|
style='margin: 0 auto;'
|
||||||
|
)
|
||||||
|
.body-2.mt-5.blue--text.text--lighten-4 Your Wiki.js container is being upgraded...
|
||||||
|
.caption.blue--text.text--lighten-2 Please wait
|
||||||
|
v-progress-linear.mt-5(
|
||||||
|
color='blue lighten-2'
|
||||||
|
:value='upgradeProgress'
|
||||||
|
:buffer-value='upgradeProgress'
|
||||||
|
rounded
|
||||||
|
:stream='isUpgradingStarted'
|
||||||
|
query
|
||||||
|
:indeterminate='!isUpgradingStarted'
|
||||||
|
)
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
|
||||||
|
import { SelfBuildingSquareSpinner } from 'epic-spinners'
|
||||||
|
|
||||||
import systemInfoQuery from 'gql/admin/system/system-query-info.gql'
|
import systemInfoQuery from 'gql/admin/system/system-query-info.gql'
|
||||||
|
import performUpgradeMutation from 'gql/admin/system/system-mutation-upgrade.gql'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
components: {
|
||||||
|
SelfBuildingSquareSpinner
|
||||||
|
},
|
||||||
|
data () {
|
||||||
return {
|
return {
|
||||||
|
isUpgrading: false,
|
||||||
|
isUpgradingStarted: false,
|
||||||
|
upgradeProgress: 0,
|
||||||
info: {}
|
info: {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
dbVersion() {
|
dbVersion () {
|
||||||
return _.get(this.info, 'dbVersion', '').replace(/(?:\r\n|\r|\n)/g, '<br />')
|
return _.get(this.info, 'dbVersion', '').replace(/(?:\r\n|\r|\n)/g, '<br />')
|
||||||
},
|
},
|
||||||
platformLogo() {
|
platformLogo () {
|
||||||
switch (this.info.platform) {
|
switch (this.info.platform) {
|
||||||
case 'docker':
|
case 'docker':
|
||||||
return 'mdi-docker'
|
return 'mdi-docker'
|
||||||
@@ -127,18 +171,49 @@ export default {
|
|||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
isDbLimited() {
|
isDbLimited () {
|
||||||
return this.info.dbType === 'MySQL' && this.dbVersion.indexOf('5.') === 0
|
return this.info.dbType === 'MySQL' && this.dbVersion.indexOf('5.') === 0
|
||||||
|
},
|
||||||
|
isLatestVersion () {
|
||||||
|
return this.info.currentVersion === this.info.latestVersion
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async refresh() {
|
async refresh () {
|
||||||
await this.$apollo.queries.info.refetch()
|
await this.$apollo.queries.info.refetch()
|
||||||
this.$store.commit('showNotification', {
|
this.$store.commit('showNotification', {
|
||||||
message: this.$t('admin:system.refreshSuccess'),
|
message: this.$t('admin:system.refreshSuccess'),
|
||||||
style: 'success',
|
style: 'success',
|
||||||
icon: 'cached'
|
icon: 'cached'
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
async performUpgrade () {
|
||||||
|
this.isUpgrading = true
|
||||||
|
this.isUpgradingStarted = false
|
||||||
|
this.upgradeProgress = 0
|
||||||
|
this.$store.commit(`loadingStart`, 'admin-system-upgrade')
|
||||||
|
try {
|
||||||
|
const respRaw = await this.$apollo.mutate({
|
||||||
|
mutation: performUpgradeMutation
|
||||||
|
})
|
||||||
|
const resp = _.get(respRaw, 'data.system.performUpgrade.responseResult', {})
|
||||||
|
if (resp.succeeded) {
|
||||||
|
this.isUpgradingStarted = true
|
||||||
|
let progressInterval = setInterval(() => {
|
||||||
|
this.upgradeProgress += 0.83
|
||||||
|
}, 500)
|
||||||
|
_.delay(() => {
|
||||||
|
clearInterval(progressInterval)
|
||||||
|
window.location.reload(true)
|
||||||
|
}, 60000)
|
||||||
|
} else {
|
||||||
|
throw new Error(resp.message)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
this.$store.commit('pushGraphError', err)
|
||||||
|
this.$store.commit(`loadingStop`, 'admin-system-upgrade')
|
||||||
|
this.isUpgrading = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
apollo: {
|
apollo: {
|
||||||
|
|||||||
@@ -169,16 +169,16 @@
|
|||||||
v-toolbar(dense, flat, color='light-green darken-3')
|
v-toolbar(dense, flat, color='light-green darken-3')
|
||||||
v-spacer
|
v-spacer
|
||||||
.caption.mr-1 or convert from
|
.caption.mr-1 or convert from
|
||||||
v-btn.mx-1(depressed, color='light-green darken-2', @click='', disabled)
|
v-btn.mx-1.animated.fadeInUp(depressed, color='light-green darken-2', @click='', disabled)
|
||||||
v-icon(left) mdi-alpha-a-circle
|
v-icon(left) mdi-alpha-a-circle
|
||||||
.body-2.text-none AsciiDoc
|
.body-2.text-none AsciiDoc
|
||||||
v-btn.mx-1(depressed, color='light-green darken-2', @click='', disabled)
|
v-btn.mx-1.animated.fadeInUp.wait-p1s(depressed, color='light-green darken-2', @click='', disabled)
|
||||||
v-icon(left) mdi-alpha-c-circle
|
v-icon(left) mdi-alpha-c-circle
|
||||||
.body-2.text-none CREOLE
|
.body-2.text-none CREOLE
|
||||||
v-btn.mx-1(depressed, color='light-green darken-2', @click='', disabled)
|
v-btn.mx-1.animated.fadeInUp.wait-p2s(depressed, color='light-green darken-2', @click='', disabled)
|
||||||
v-icon(left) mdi-alpha-t-circle
|
v-icon(left) mdi-alpha-t-circle
|
||||||
.body-2.text-none Textile
|
.body-2.text-none Textile
|
||||||
v-btn.mx-1(depressed, color='light-green darken-2', @click='', disabled)
|
v-btn.mx-1.animated.fadeInUp.wait-p3s(depressed, color='light-green darken-2', @click='', disabled)
|
||||||
v-icon(left) mdi-alpha-w-circle
|
v-icon(left) mdi-alpha-w-circle
|
||||||
.body-2.text-none WikiText
|
.body-2.text-none WikiText
|
||||||
v-spacer
|
v-spacer
|
||||||
|
|||||||
@@ -168,10 +168,12 @@ export default {
|
|||||||
}).then(res => res.json())
|
}).then(res => res.json())
|
||||||
|
|
||||||
if (resp.ok === true) {
|
if (resp.ok === true) {
|
||||||
this.success = true
|
|
||||||
_.delay(() => {
|
_.delay(() => {
|
||||||
window.location.assign('/login')
|
this.success = true
|
||||||
}, 3000)
|
_.delay(() => {
|
||||||
|
window.location.assign('/login')
|
||||||
|
}, 3000)
|
||||||
|
}, 10000)
|
||||||
} else {
|
} else {
|
||||||
this.error = true
|
this.error = true
|
||||||
this.errorMessage = resp.error
|
this.errorMessage = resp.error
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
mutation {
|
||||||
|
system {
|
||||||
|
performUpgrade {
|
||||||
|
responseResult {
|
||||||
|
succeeded
|
||||||
|
errorCode
|
||||||
|
slug
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,19 +2,20 @@ query {
|
|||||||
system {
|
system {
|
||||||
info {
|
info {
|
||||||
configFile
|
configFile
|
||||||
|
cpuCores
|
||||||
currentVersion
|
currentVersion
|
||||||
|
dbHost
|
||||||
dbType
|
dbType
|
||||||
dbVersion
|
dbVersion
|
||||||
dbHost
|
hostname
|
||||||
latestVersion
|
latestVersion
|
||||||
latestVersionReleaseDate
|
latestVersionReleaseDate
|
||||||
|
nodeVersion
|
||||||
operatingSystem
|
operatingSystem
|
||||||
platform
|
platform
|
||||||
hostname
|
|
||||||
cpuCores
|
|
||||||
ramTotal
|
ramTotal
|
||||||
|
upgradeCapable
|
||||||
workingDirectory
|
workingDirectory
|
||||||
nodeVersion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,7 @@
|
|||||||
"dependency-graph": "0.8.0",
|
"dependency-graph": "0.8.0",
|
||||||
"diff": "4.0.1",
|
"diff": "4.0.1",
|
||||||
"diff2html": "2.11.3",
|
"diff2html": "2.11.3",
|
||||||
|
"dockerode": "2.5.8",
|
||||||
"dotize": "0.3.0",
|
"dotize": "0.3.0",
|
||||||
"elasticsearch6": "npm:@elastic/elasticsearch@6",
|
"elasticsearch6": "npm:@elastic/elasticsearch@6",
|
||||||
"elasticsearch7": "npm:@elastic/elasticsearch@7",
|
"elasticsearch7": "npm:@elastic/elasticsearch@7",
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ const path = require('path')
|
|||||||
const fs = require('fs-extra')
|
const fs = require('fs-extra')
|
||||||
const moment = require('moment')
|
const moment = require('moment')
|
||||||
const graphHelper = require('../../helpers/graph')
|
const graphHelper = require('../../helpers/graph')
|
||||||
|
const Docker = require('dockerode')
|
||||||
|
|
||||||
/* global WIKI */
|
/* global WIKI */
|
||||||
|
|
||||||
@@ -20,13 +21,13 @@ const dbTypes = {
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
Query: {
|
Query: {
|
||||||
async system() { return {} }
|
async system () { return {} }
|
||||||
},
|
},
|
||||||
Mutation: {
|
Mutation: {
|
||||||
async system() { return {} }
|
async system () { return {} }
|
||||||
},
|
},
|
||||||
SystemQuery: {
|
SystemQuery: {
|
||||||
flags() {
|
flags () {
|
||||||
return _.transform(WIKI.config.flags, (result, value, key) => {
|
return _.transform(WIKI.config.flags, (result, value, key) => {
|
||||||
result.push({ key, value })
|
result.push({ key, value })
|
||||||
}, [])
|
}, [])
|
||||||
@@ -34,7 +35,7 @@ module.exports = {
|
|||||||
async info() { return {} }
|
async info() { return {} }
|
||||||
},
|
},
|
||||||
SystemMutation: {
|
SystemMutation: {
|
||||||
async updateFlags(obj, args, context) {
|
async updateFlags (obj, args, context) {
|
||||||
WIKI.config.flags = _.transform(args.flags, (result, row) => {
|
WIKI.config.flags = _.transform(args.flags, (result, row) => {
|
||||||
_.set(result, row.key, row.value)
|
_.set(result, row.key, row.value)
|
||||||
}, {})
|
}, {})
|
||||||
@@ -44,7 +45,7 @@ module.exports = {
|
|||||||
responseResult: graphHelper.generateSuccess('System Flags applied successfully')
|
responseResult: graphHelper.generateSuccess('System Flags applied successfully')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async resetTelemetryClientId(obj, args, context) {
|
async resetTelemetryClientId (obj, args, context) {
|
||||||
try {
|
try {
|
||||||
WIKI.telemetry.generateClientId()
|
WIKI.telemetry.generateClientId()
|
||||||
await WIKI.configSvc.saveToDb(['telemetry'])
|
await WIKI.configSvc.saveToDb(['telemetry'])
|
||||||
@@ -55,7 +56,7 @@ module.exports = {
|
|||||||
return graphHelper.generateError(err)
|
return graphHelper.generateError(err)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async setTelemetry(obj, args, context) {
|
async setTelemetry (obj, args, context) {
|
||||||
try {
|
try {
|
||||||
_.set(WIKI.config, 'telemetry.isEnabled', args.enabled)
|
_.set(WIKI.config, 'telemetry.isEnabled', args.enabled)
|
||||||
WIKI.telemetry.enabled = args.enabled
|
WIKI.telemetry.enabled = args.enabled
|
||||||
@@ -66,22 +67,44 @@ module.exports = {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
return graphHelper.generateError(err)
|
return graphHelper.generateError(err)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
async performUpgrade (obj, args, context) {
|
||||||
|
try {
|
||||||
|
const dockerEngine = new Docker({ socketPath: '/var/run/docker.sock' })
|
||||||
|
await dockerEngine.run('containrrr/watchtower', ['--cleanup', '--run-once', 'wiki'], process.stdout, {
|
||||||
|
HostConfig: {
|
||||||
|
AutoRemove: true,
|
||||||
|
Mounts: [
|
||||||
|
{
|
||||||
|
Target: '/var/run/docker.sock',
|
||||||
|
Source: '/var/run/docker.sock',
|
||||||
|
Type: 'bind'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
responseResult: graphHelper.generateSuccess('Upgrade has started.')
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
return graphHelper.generateError(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
SystemInfo: {
|
SystemInfo: {
|
||||||
configFile() {
|
configFile () {
|
||||||
return path.join(process.cwd(), 'config.yml')
|
return path.join(process.cwd(), 'config.yml')
|
||||||
},
|
},
|
||||||
cpuCores() {
|
cpuCores () {
|
||||||
return os.cpus().length
|
return os.cpus().length
|
||||||
},
|
},
|
||||||
currentVersion() {
|
currentVersion () {
|
||||||
return WIKI.version
|
return WIKI.version
|
||||||
},
|
},
|
||||||
dbType() {
|
dbType () {
|
||||||
return _.get(dbTypes, WIKI.config.db.type, 'Unknown DB')
|
return _.get(dbTypes, WIKI.config.db.type, 'Unknown DB')
|
||||||
},
|
},
|
||||||
async dbVersion() {
|
async dbVersion () {
|
||||||
let version = 'Unknown Version'
|
let version = 'Unknown Version'
|
||||||
switch (WIKI.config.db.type) {
|
switch (WIKI.config.db.type) {
|
||||||
case 'mariadb':
|
case 'mariadb':
|
||||||
@@ -102,26 +125,26 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
return version
|
return version
|
||||||
},
|
},
|
||||||
dbHost() {
|
dbHost () {
|
||||||
if (WIKI.config.db.type === 'sqlite') {
|
if (WIKI.config.db.type === 'sqlite') {
|
||||||
return WIKI.config.db.storage
|
return WIKI.config.db.storage
|
||||||
} else {
|
} else {
|
||||||
return WIKI.config.db.host
|
return WIKI.config.db.host
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hostname() {
|
hostname () {
|
||||||
return os.hostname()
|
return os.hostname()
|
||||||
},
|
},
|
||||||
latestVersion() {
|
latestVersion () {
|
||||||
return WIKI.system.updates.version
|
return WIKI.system.updates.version
|
||||||
},
|
},
|
||||||
latestVersionReleaseDate() {
|
latestVersionReleaseDate () {
|
||||||
return moment.utc(WIKI.system.updates.releaseDate)
|
return moment.utc(WIKI.system.updates.releaseDate)
|
||||||
},
|
},
|
||||||
nodeVersion() {
|
nodeVersion () {
|
||||||
return process.version.substr(1)
|
return process.version.substr(1)
|
||||||
},
|
},
|
||||||
async operatingSystem() {
|
async operatingSystem () {
|
||||||
let osLabel = `${os.type()} (${os.platform()}) ${os.release()} ${os.arch()}`
|
let osLabel = `${os.type()} (${os.platform()}) ${os.release()} ${os.arch()}`
|
||||||
if (os.platform() === 'linux') {
|
if (os.platform() === 'linux') {
|
||||||
const osInfo = await getos()
|
const osInfo = await getos()
|
||||||
@@ -136,27 +159,30 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
return os.platform()
|
return os.platform()
|
||||||
},
|
},
|
||||||
ramTotal() {
|
ramTotal () {
|
||||||
return filesize(os.totalmem())
|
return filesize(os.totalmem())
|
||||||
},
|
},
|
||||||
telemetry() {
|
telemetry () {
|
||||||
return WIKI.telemetry.enabled
|
return WIKI.telemetry.enabled
|
||||||
},
|
},
|
||||||
telemetryClientId() {
|
telemetryClientId () {
|
||||||
return WIKI.config.telemetry.clientId
|
return WIKI.config.telemetry.clientId
|
||||||
},
|
},
|
||||||
workingDirectory() {
|
async upgradeCapable () {
|
||||||
|
return fs.pathExists('/var/run/docker.sock')
|
||||||
|
},
|
||||||
|
workingDirectory () {
|
||||||
return process.cwd()
|
return process.cwd()
|
||||||
},
|
},
|
||||||
async groupsTotal() {
|
async groupsTotal () {
|
||||||
const total = await WIKI.models.groups.query().count('* as total').first().pluck('total')
|
const total = await WIKI.models.groups.query().count('* as total').first().pluck('total')
|
||||||
return _.toSafeInteger(total)
|
return _.toSafeInteger(total)
|
||||||
},
|
},
|
||||||
async pagesTotal() {
|
async pagesTotal () {
|
||||||
const total = await WIKI.models.pages.query().count('* as total').first().pluck('total')
|
const total = await WIKI.models.pages.query().count('* as total').first().pluck('total')
|
||||||
return _.toSafeInteger(total)
|
return _.toSafeInteger(total)
|
||||||
},
|
},
|
||||||
async usersTotal() {
|
async usersTotal () {
|
||||||
const total = await WIKI.models.users.query().count('* as total').first().pluck('total')
|
const total = await WIKI.models.users.query().count('* as total').first().pluck('total')
|
||||||
return _.toSafeInteger(total)
|
return _.toSafeInteger(total)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ type SystemMutation {
|
|||||||
setTelemetry(
|
setTelemetry(
|
||||||
enabled: Boolean!
|
enabled: Boolean!
|
||||||
): DefaultResponse @auth(requires: ["manage:system"])
|
): DefaultResponse @auth(requires: ["manage:system"])
|
||||||
|
|
||||||
|
performUpgrade: DefaultResponse @auth(requires: ["manage:system"])
|
||||||
}
|
}
|
||||||
|
|
||||||
# -----------------------------------------------
|
# -----------------------------------------------
|
||||||
@@ -67,6 +69,7 @@ type SystemInfo {
|
|||||||
ramTotal: String @auth(requires: ["manage:system"])
|
ramTotal: String @auth(requires: ["manage:system"])
|
||||||
telemetry: Boolean @auth(requires: ["manage:system"])
|
telemetry: Boolean @auth(requires: ["manage:system"])
|
||||||
telemetryClientId: String @auth(requires: ["manage:system"])
|
telemetryClientId: String @auth(requires: ["manage:system"])
|
||||||
|
upgradeCapable: Boolean @auth(requires: ["manage:system"])
|
||||||
usersTotal: Int @auth(requires: ["manage:system", "manage:navigation", "manage:groups", "write:groups", "manage:users", "write:users"])
|
usersTotal: Int @auth(requires: ["manage:system", "manage:navigation", "manage:groups", "write:groups", "manage:users", "write:users"])
|
||||||
workingDirectory: String @auth(requires: ["manage:system"])
|
workingDirectory: String @auth(requires: ["manage:system"])
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user