diff --git a/src/apptask.js b/src/apptask.js index 8564efadc..9db41f171 100644 --- a/src/apptask.js +++ b/src/apptask.js @@ -270,12 +270,12 @@ async function startCommand(app, args, progressCallback) { await services.startAppServices(app); if (app.manifest.id !== constants.PROXY_APP_APPSTORE_ID) { - await progressCallback({ percent: 35, message: 'Starting container' }); + await progressCallback({ percent: 40, message: 'Starting container' }); await docker.startContainer(app.id); } // stopped apps do not renew certs. currently, we don't do DNS to not overwrite existing user settings - await progressCallback({ percent: 80, message: 'Configuring reverse proxy' }); + await progressCallback({ percent: 70, message: 'Configuring reverse proxy' }); await reverseProxy.configureApp(app, AuditSource.APPTASK); await progressCallback({ percent: 100, message: 'Done' }); @@ -308,12 +308,12 @@ async function restartCommand(app, args, progressCallback) { await progressCallback({ percent: 10, message: 'Starting app services' }); await services.startAppServices(app); - await progressCallback({ percent: 20, message: 'Restarting container' }); + await progressCallback({ percent: 30, message: 'Restarting container' }); await docker.restartContainer(app.id); } // stopped apps do not renew certs. currently, we don't do DNS to not overwrite existing user settings - await progressCallback({ percent: 80, message: 'Configuring reverse proxy' }); + await progressCallback({ percent: 70, message: 'Configuring reverse proxy' }); await reverseProxy.configureApp(app, AuditSource.APPTASK); await progressCallback({ percent: 100, message: 'Done' }); @@ -425,22 +425,22 @@ async function installCommand(app, args, progressCallback) { // allocating container ip here, lets the users "repair" an app if allocation fails at apps.add time await allocateContainerIp(app); - await progressCallback({ percent: 20, message: 'Downloading icon' }); + await progressCallback({ percent: 15, message: 'Downloading icon' }); await downloadIcon(app); - await progressCallback({ percent: 25, message: 'Updating checklist' }); + await progressCallback({ percent: 18, message: 'Updating checklist' }); await updateChecklist(app, app.manifest.checklist || {}, restoreConfig ? true : false); if (!skipDnsSetup) { - await progressCallback({ percent: 30, message: 'Registering subdomains' }); + await progressCallback({ percent: 20, message: 'Registering subdomains' }); await dns.registerLocations([ { subdomain: app.subdomain, domain: app.domain }].concat(app.secondaryDomains).concat(app.redirectDomains).concat(app.aliasDomains), { overwriteDns }, progressCallback); } - await progressCallback({ percent: 40, message: 'Downloading image' }); + await progressCallback({ percent: 30, message: 'Downloading image' }); await downloadImage(app.manifest); - await progressCallback({ percent: 50, message: 'Creating app data directory' }); + await progressCallback({ percent: 55, message: 'Setting up app' }); await createAppDir(app); if (!restoreConfig) { // install @@ -515,7 +515,7 @@ async function recreateCommand(app, args, progressCallback) { await progressCallback({ percent: 10, message: 'Deleting old container' }); await deleteContainers(app, { managedOnly: true }); - await progressCallback({ percent: 60, message: 'Creating container' }); + await progressCallback({ percent: 50, message: 'Creating container' }); await createContainer(app); await startApp(app); @@ -699,14 +699,14 @@ async function updateCommand(app, args, progressCallback) { await verifyManifest(updateConfig.manifest); if (!updateConfig.skipBackup) { - await progressCallback({ percent: 15, message: 'Backing up app' }); + await progressCallback({ percent: 10, message: 'Backing up app' }); const sites = await backupSites.listByContentForUpdates(app.id); if (sites.length === 0) throw new BoxError(BoxError.BAD_STATE, 'App has no backup site for updates', { backupError: true }); for (const site of sites) { // preserve update backups for 3 weeks const [error] = await safe(backuptask.backupApp(app, site, { preserveSecs: 3*7*24*60*60 }, (progress) => { - progressCallback({ percent: 15, message: `Backup - ${progress.message}` }); + progressCallback({ percent: Math.round(10 + (progress.percent || 0) * 10 / 100), message: `Backup - ${progress.message}` }); })); if (error) { error.backupError = true; diff --git a/src/backupcleaner.js b/src/backupcleaner.js index 6d7b91a1f..0c44fcff0 100644 --- a/src/backupcleaner.js +++ b/src/backupcleaner.js @@ -328,17 +328,17 @@ async function run(siteId, progressCallback) { return {}; } - await progressCallback({ percent: 10, message: 'Cleaning box backups' }); + await progressCallback({ percent: 5, message: 'Cleaning box backups' }); const { removedBoxBackupPaths, referencedBackupIds } = await cleanupBoxBackups(site, progressCallback); // references is app or mail backup ids - await progressCallback({ percent: 20, message: 'Cleaning mail backups' }); + await progressCallback({ percent: 15, message: 'Cleaning mail backups' }); const removedMailBackupPaths = await cleanupMailBackups(site, referencedBackupIds, progressCallback); - await progressCallback({ percent: 40, message: 'Cleaning app backups' }); + await progressCallback({ percent: 25, message: 'Cleaning app backups' }); const archivedBackupIds = await archives.listBackupIds(); const removedAppBackupPaths = await cleanupAppBackups(site, referencedBackupIds.concat(archivedBackupIds), progressCallback); - await progressCallback({ percent: 70, message: 'Checking storage backend and removing stale entries in database' }); + await progressCallback({ percent: 60, message: 'Checking storage backend and removing stale entries in database' }); const missingBackupPaths = await cleanupMissingBackups(site, progressCallback); await progressCallback({ percent: 80, message: 'Removing snapshots of uninstalled apps' }); diff --git a/src/dashboard.js b/src/dashboard.js index 385f0a255..35f243503 100644 --- a/src/dashboard.js +++ b/src/dashboard.js @@ -84,6 +84,7 @@ async function prepareLocation(subdomain, domain, auditSource, progressCallback) await dns.waitForLocations([location], progressCallback); progressCallback({ percent: 60, message: `Getting certificate of ${fqdn}` }); await reverseProxy.ensureCertificate(location, {}, auditSource); + progressCallback({ percent: 100, message: 'Done' }); } async function startPrepareLocation(domain, auditSource) { diff --git a/src/dns.js b/src/dns.js index a9fde4241..a89e5d995 100644 --- a/src/dns.js +++ b/src/dns.js @@ -332,7 +332,7 @@ async function syncDnsRecords(options, progressCallback) { // we sync by domain only to get some nice progress for (const domain of allDomains) { progressCallback({ percent: progress, message: `Updating DNS of ${domain.domain}`}); - progress += Math.round(100/(1+allDomains.length)); + progress = Math.min(progress + Math.round(90 / (1 + allDomains.length)), 95); let locations = []; if (domain.domain === dashboardLocation.domain) locations.push({ subdomain: dashboardLocation.subdomain, domain: dashboardLocation.domain }); @@ -355,6 +355,8 @@ async function syncDnsRecords(options, progressCallback) { } } + progressCallback({ percent: 100, message: 'Done' }); + return { errors }; } diff --git a/src/dyndns.js b/src/dyndns.js index d414c58b4..06a211763 100644 --- a/src/dyndns.js +++ b/src/dyndns.js @@ -70,7 +70,7 @@ async function sync(ipv4, ipv6, auditSource, progressCallback) { const result = await apps.list(); for (const app of result) { - percent += Math.round(90/result.length); + percent = Math.min(percent + Math.round(85 / result.length), 99); progressCallback({ percent, message: `Updating app ${app.fqdn}`}); const locations = [{ domain: app.domain, subdomain: app.subdomain }] @@ -84,7 +84,7 @@ async function sync(ipv4, ipv6, auditSource, progressCallback) { } } - progressCallback({ percent: 100, message: 'refreshDNS: updated apps' }); + progressCallback({ percent: 100, message: 'Done' }); } export default { diff --git a/src/externalldap.js b/src/externalldap.js index 49aebb55b..5e7471a8c 100644 --- a/src/externalldap.js +++ b/src/externalldap.js @@ -356,15 +356,15 @@ async function syncUsers(config, progressCallback) { debug(`syncUsers: Found ${ldapUsers.length} users`); let percent = 10; - const step = 30/(ldapUsers.length+1); // ensure no divide by 0 + const step = 28 / (ldapUsers.length + 1); // we ignore all errors here and just log them for now for (let i = 0; i < ldapUsers.length; i++) { const ldapUser = translateUser(config, ldapUsers[i]); if (!ldapUser) continue; - percent += step; - progressCallback({ percent, message: `Syncing... ${ldapUser.username}` }); + percent = Math.min(percent + step, 39); + progressCallback({ percent: Math.round(percent), message: `Syncing user ${ldapUser.username}` }); const user = await users.getByUsername(ldapUser.username); @@ -398,7 +398,7 @@ async function syncGroups(config, progressCallback) { if (!config.syncGroups) { debug('syncGroups: Group sync is disabled'); - progressCallback({ percent: 70, message: 'Skipping group sync...' }); + progressCallback({ percent: 70, message: 'Skipping group sync' }); return []; } @@ -408,7 +408,7 @@ async function syncGroups(config, progressCallback) { debug(ldapGroups); let percent = 40; - const step = 30/(ldapGroups.length+1); // ensure no divide by 0 + const step = 28 / (ldapGroups.length + 1); for (const ldapGroup of ldapGroups) { let groupName = ldapGroup[config.groupnameField]; @@ -417,8 +417,8 @@ async function syncGroups(config, progressCallback) { groupName = groupName.toLowerCase(); - percent += step; - progressCallback({ percent, message: `Syncing... ${groupName}` }); + percent = Math.min(percent + step, 69); + progressCallback({ percent: Math.round(percent), message: `Syncing group ${groupName}` }); const result = await groups.getByName(groupName); @@ -444,7 +444,7 @@ async function syncGroupMembers(config, progressCallback) { if (!config.syncGroups) { debug('syncGroupMembers: Group users sync is disabled'); - progressCallback({ percent: 99, message: 'Skipping group users sync...' }); + progressCallback({ percent: 98, message: 'Skipping group member sync' }); return []; } @@ -452,7 +452,12 @@ async function syncGroupMembers(config, progressCallback) { const ldapGroups = allGroups.filter(function (g) { return g.source === 'ldap'; }); debug(`syncGroupMembers: Found ${ldapGroups.length} groups to sync users`); + let percent = 70; + const step = 28 / (ldapGroups.length + 1); + for (const ldapGroup of ldapGroups) { + percent = Math.min(percent + step, 98); + progressCallback({ percent: Math.round(percent), message: `Syncing members of ${ldapGroup.name}` }); debug(`syncGroupMembers: Sync users for group ${ldapGroup.name}`); const result = await ldapGroupSearch(config, {}); diff --git a/src/mailserver.js b/src/mailserver.js index 088051066..e427244d9 100644 --- a/src/mailserver.js +++ b/src/mailserver.js @@ -239,18 +239,21 @@ async function changeLocation(auditSource, progressCallback) { const location = await getLocation(); const fqdn = dns.fqdn(location.subdomain, location.domain); - let progress = 20; - progressCallback({ percent: progress, message: `Setting up DNS of certs of mail server ${fqdn}` }); - + progressCallback({ percent: 10, message: `Registering DNS for ${fqdn}` }); await dns.registerLocations([location], { overwriteDns: true }, progressCallback); + + progressCallback({ percent: 25, message: `Waiting for DNS propagation of ${fqdn}` }); await dns.waitForLocations([location], progressCallback); + + progressCallback({ percent: 40, message: `Getting certificate for ${fqdn}` }); await reverseProxy.ensureCertificate(location, {}, auditSource); const allDomains = await domains.list(); + let progress = 45; for (let idx = 0; idx < allDomains.length; idx++) { const domainObject = allDomains[idx]; progressCallback({ percent: progress, message: `Updating DNS of ${domainObject.domain}` }); - progress += Math.round(70/allDomains.length); + progress = Math.min(progress + Math.round(40 / allDomains.length), 88); const [error] = await safe(mail.upsertDnsRecords(domainObject.domain, fqdn)); // ignore any errors. we anyway report dns errors in status tab progressCallback({ percent: progress, message: `Updated DNS of ${domainObject.domain}: ${error ? error.message : 'success'}` }); diff --git a/src/reverseproxy.js b/src/reverseproxy.js index 9022d2d54..75f85edc7 100644 --- a/src/reverseproxy.js +++ b/src/reverseproxy.js @@ -598,13 +598,13 @@ async function checkCerts(options, auditSource, progressCallback) { let percent = 1; for (const location of locations) { - percent += Math.round(100/locations.length); + percent = Math.min(percent + Math.round(80 / locations.length), 85); progressCallback({ percent, message: `Ensuring certs of ${location.fqdn}` }); await ensureCertificate(location, options, auditSource); } if (options.rebuild || fs.existsSync(paths.REVERSE_PROXY_REBUILD_FILE)) { - progressCallback( { message: 'Rebuilding app configs' }); + progressCallback({ percent: 90, message: 'Rebuilding app configs' }); for (const app of allApps) { await writeAppConfigs(app); } @@ -612,6 +612,7 @@ async function checkCerts(options, auditSource, progressCallback) { await notifyCertChange(); // this allows user to "rebuild" using UI just in case we crashed and went out of sync safe.fs.unlinkSync(paths.REVERSE_PROXY_REBUILD_FILE); } else { + progressCallback({ percent: 90, message: 'Syncing certificates' }); // sync all locations and not just the ones that changed. this helps with 0 length certs when disk is full and also // if renewal task crashed midway. for (const location of locations) { @@ -621,6 +622,7 @@ async function checkCerts(options, auditSource, progressCallback) { await notifyCertChange(); // propagate any cert changes to services } + progressCallback({ percent: 95, message: 'Cleaning up expired certs' }); await cleanupCerts(locations, auditSource, progressCallback); }