Skip to content

Commit

Permalink
Merge pull request #122 from dappnode/v0.1.15
Browse files Browse the repository at this point in the history
v0.1.15

Former-commit-id: 2cf0b9a
  • Loading branch information
eduadiez authored Oct 26, 2018
2 parents 711d6c3 + cf9f016 commit 5171d5b
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 126 deletions.
12 changes: 5 additions & 7 deletions build/src/src/calls/fetchPackageData.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const logs = require('logs.js')(module);
const getManifest = require('modules/getManifest');
const getAvatar = require('modules/getAvatar');
const isSyncing = require('utils/isSyncing');
const isIpfsRequest = require('utils/isIpfsRequest');

/**
* Fetches the manifest of the latest version and its avatar.
Expand All @@ -21,20 +22,17 @@ const isSyncing = require('utils/isSyncing');
const fetchPackageData = async ({
id,
}) => {
if (await isSyncing()) {
const packageReq = parse.packageReq(id);

// Make sure the chain is synced
if (!isIpfsRequest(packageReq) && await isSyncing()) {
return {
message: `Mainnet is still syncing`,
result: {},
logMessage: true,
};
}

const packageReq = parse.packageReq(id);

// Make sure the chain is synced
// if (await ethchain.isSyncing()) {
// return res.success('Mainnet is syncing', []);
// }

const manifest = await getManifest(packageReq);

Expand Down
7 changes: 4 additions & 3 deletions build/src/src/calls/fetchPackageVersions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const parse = require('utils/parse');
const apm = require('modules/apm');
const getManifest = require('modules/getManifest');
const isSyncing = require('utils/isSyncing');
const isIpfsRequest = require('utils/isIpfsRequest');

/**
* Fetches all available version manifests from a package APM repo
Expand All @@ -22,16 +23,16 @@ const isSyncing = require('utils/isSyncing');
const fetchPackageVersions = async ({
id,
}) => {
if (await isSyncing()) {
const packageReq = parse.packageReq(id);

if (!isIpfsRequest(packageReq) && await isSyncing()) {
return {
message: `Mainnet is still syncing`,
result: [],
logMessage: true,
};
}

const packageReq = parse.packageReq(id);

if (packageReq.name.endsWith('.eth')) {
let packageVersions = await getPackageVersions(packageReq);

Expand Down
85 changes: 64 additions & 21 deletions build/src/src/calls/installPackage.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ const parse = require('utils/parse');
const {download, run} = require('modules/packages');
const dappGet = require('modules/dappGet');
const logUI = require('utils/logUI');
const isIpfsRequest = require('utils/isIpfsRequest');
const getManifest = require('modules/getManifest');
const dockerList = require('modules/dockerList');
const {eventBus, eventBusTag} = require('eventBus');
const isSyncing = require('utils/isSyncing');
const logs = require('logs.js')(module);


/**
Expand Down Expand Up @@ -33,35 +36,75 @@ const installPackage = async ({
logId,
options = {},
}) => {
if (await isSyncing()) {
throw Error('Mainnet is syncing');
}

// 1. Parse the id into a request
// id = '[email protected]'
// req = { name: 'otpweb.dnp.dappnode.eth', ver: '0.1.4' }
const req = parse.packageReq(id);

// 2. Resolve the request
try {
await dappGet.update(req);
} catch (e) {
throw Error(`Error updating DNP repo: ${e.stack || e.message}`);
// If the request is not from IPFS, check if the chain is syncing
if (!isIpfsRequest(req) && await isSyncing()) {
throw Error('Mainnet is syncing');
}

// 2. Resolve the request
let result;
// res = {
// success: {'bind.dnp.dappnode.eth': '0.1.4'}
// state: {'bind.dnp.dappnode.eth': '0.1.2'}
// }
try {
result = await dappGet.resolve(req);
} catch (e) {
throw Error(`Error resolving dependencies: ${e.stack || e.message}`);
}
// Return error if the req couldn't be resolved
if (!result.success) {
throw Error('Request could not be resolved: '+req.name+'@'+req.ver);
if (options.BYPASS_RESOLVER) {
/**
* The dappGet resolver may cause errors.
* Updating the core will never require dependency resolution,
* therefore for a system update the dappGet resolver will be emitted
*
* If BYPASS_RESOLVER == true, just fetch the first level dependencies of the request
*/
const reqManifest = await getManifest(req);
// reqManifest.dependencies = {
// 'bind.dnp.dappnode.eth': '0.1.4',
// 'admin.dnp.dappnode.eth': '/ipfs/Qm...',
// }

// Append dependencies in the list of packages to install
result = {
success: (reqManifest || {}).dependencies || {},
state: {},
};
// Add current request to pacakages to install
result.success[req.name] = req.ver;

// The function below does not directly affect funcionality.
// However it would prevent already installed packages from installing
try {
(await dockerList.listContainers()).forEach((pkg) => {
if (pkg.name && pkg.version
&& result.success && result.success[pkg.name]
&& result.success[pkg.name] === pkg.version) {
delete result.success[pkg.name];
}
});
} catch (e) {
logs.error('Error listing current containers: '+e);
}
} else {
/**
* If BYPASS_RESOLVER == false, use the resolver
*/
try {
await dappGet.update(req);
} catch (e) {
throw Error(`Error updating DNP repo: ${e.stack || e.message}`);
}
// res = {
// success: {'bind.dnp.dappnode.eth': '0.1.4'}
// state: {'bind.dnp.dappnode.eth': '0.1.2'}
// }
try {
result = await dappGet.resolve(req);
} catch (e) {
throw Error(`Error resolving dependencies: ${e.stack || e.message}`);
}
// Return error if the req couldn't be resolved
if (!result.success) {
throw Error('Request could not be resolved: '+req.name+'@'+req.ver);
}
}

const {success: newState, state} = result;
Expand Down
98 changes: 5 additions & 93 deletions build/src/src/calls/installPackageSafe.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,8 @@
const parse = require('utils/parse');
const {download, run} = require('modules/packages');
const {eventBus, eventBusTag} = require('eventBus');
const getManifest = require('modules/getManifest');
const dockerList = require('modules/dockerList');
const logs = require('logs.js')(module);
const installPackage = require('./installPackage');


/**
* Installs a package. It resolves dependencies, downloads
* manifests and images, loads the images to docker, and calls
* docker up on each package.
* It has extra functionality for special cases
* - allowCore: If a manifest requests a package to be core
* it will only be granted if
* 1. Its manifest comes from APM and .dnp.dappnode.eth
* 2. It comes from IPFS and the BYPASS_CORE_RESTRICTION env is true
* - Special versions: It needs to deal with two cases
* 1. ver = 'latest'
* 2. ver = '/ipfs/QmZ87fb2...'
* Installs a package in safe mode, by setting options.BYPASS_RESOLVER = true
*
* @param {Object} kwargs: {
* id: package .eth name (string)
Expand All @@ -28,85 +13,12 @@ const logs = require('logs.js')(module);
*/
const installPackageSafe = async ({
id,
vols = {},
logId,
options = {},
}) => {
// 1. Parse the id into a request
// id = '[email protected]'
// req = { name: 'otpweb.dnp.dappnode.eth', ver: '0.1.4' }
const req = parse.packageReq(id);

// 2. Only get first order dependencies
const manifest = await getManifest(req);
if (!manifest) {
throw Error('Manifest could not be found for: '+req.name+'@'+req.ver);
}
let pkgs = [
{
name: req.name,
ver: req.ver,
manifest,
},
];
const dependencies = manifest.dependencies || {};
await Promise.all(Object.keys(dependencies).map(async (dep) => {
const depManifest = await getManifest(parse.packageReq(dep));
if (!depManifest) {
throw Error('Manifest could not be found for: '+dep);
}
pkgs.push({
name: dep,
ver: depManifest.version,
manifest: depManifest,
});
}));

// 3. Only install packages that have to be updated
let dnpList = [];
try {
dnpList = await dockerList.listContainers();
} catch (e) {
logs.error('Error listing current containers: '+e);
}

pkgs = pkgs.filter((pkg) => {
const currentPkg = dnpList.find((_pkg) => _pkg.name === pkg.name);
if (currentPkg && currentPkg.version && pkg.ver) {
return currentPkg.version !== pkg.ver;
} else {
return true;
}
});


// 4. Download requested packages
await Promise.all(pkgs.map((pkg) => download({pkg, logId})));

// 5. Run requested packages
// Patch, install the dappmanager the last always
let dappmanagerPkg;
await Promise.all(pkgs
.filter((pkg) => {
if (pkg.manifest.name.includes('dappmanager.dnp.dappnode.eth')) {
dappmanagerPkg = pkg;
return false;
} else {
return true;
}
}).map((pkg) => run({pkg, logId})));

if (dappmanagerPkg) await run({pkg: dappmanagerPkg, logId});

// 6. Clean install files

// Emit packages update
eventBus.emit(eventBusTag.emitPackages);

return {
message: 'Installed ' + req.req,
logMessage: true,
userAction: true,
};
options.BYPASS_RESOLVER = true;
return await installPackage({id, vols, logId, options});
};


Expand Down
4 changes: 3 additions & 1 deletion build/src/src/modules/packages.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ async function download({pkg, logId}) {
);

// Define the logging function
const log = (percent) =>
const log = (percent) => {
if (percent > 99) percent = 99;
logUI({logId, name, msg: 'Downloading '+percent+'%'});
};
// Define the rounding function to not spam updates
const displayRes = 2;
const round = (x) => displayRes*Math.ceil(100*x/imageSize/displayRes);
Expand Down
14 changes: 14 additions & 0 deletions build/src/src/utils/isIpfsRequest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const isIpfsHash = require('./isIpfsHash');

const isIpfsRequest = (req) => {
if (req && typeof req === 'object') {
return req.name && isIpfsHash(req.name)
|| req.ver && isIpfsHash(req.ver);
} else if (req && typeof req === 'string') {
return isIpfsHash(req);
} else {
return false;
}
};

module.exports = isIpfsRequest;
2 changes: 1 addition & 1 deletion dappnode_package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dappmanager.dnp.dappnode.eth",
"version": "0.1.14",
"version": "0.1.15",
"description": "Dappnode package responsible for providing the DappNode Package Manager",
"avatar": "/ipfs/QmdT2GX9ybaoE25HBk7is8CDnfn2KaFTpZVkLdfkAQs1PN",
"type": "dncore",
Expand Down

0 comments on commit 5171d5b

Please sign in to comment.