Skip to content

Commit

Permalink
Initial composer report command (hyperledger-archives#3194)
Browse files Browse the repository at this point in the history
Simple command to collect node report data and create a composer
report archive file. Provides basic implementation to add further
data collection to in the future

Contributes to #3051

Signed-off-by: Sam Smith <[email protected]>
Signed-off-by: James Taylor <[email protected]>
  • Loading branch information
jt-nti authored and samjsmith committed Jan 22, 2018
1 parent ae00c41 commit 846ce52
Show file tree
Hide file tree
Showing 7 changed files with 263 additions and 0 deletions.
23 changes: 23 additions & 0 deletions packages/composer-cli/lib/cmds/report.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

const Report = require('./report/lib/report.js');

exports.command = 'report';
exports.desc = 'Command for creating a report of the current Composer environment';
exports.handler = function (argv) {
return argv.thePromise = Report.handler(argv);
};
93 changes: 93 additions & 0 deletions packages/composer-cli/lib/cmds/report/lib/report.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';
const fs = require('fs');
const os = require('os');
const { sep } = require('path');
const cmdUtil = require('../../utils/cmdutils');
const chalk = require('chalk');
const moment = require('moment');
const nodereport = require('node-report');
const tar = require('tar');

/**
* Composer "capture" command
* @private
*/
class Report {
/**
* Command implementation.
* @param {Object} args argument list from composer command
* @return {Promise} promise when command complete
*/
static handler(args) {
return this.report(args.file);
}

/**
* Get the current environment data
* @return {Promise} resolved/rejected promise when the command is complete
*/
static report() {
cmdUtil.log(chalk.blue.bold('Creating Composer report\n'));
let tmpDirectory = this._setupReportDir();
this._createNodeReport(tmpDirectory);
return this._archiveReportDir(tmpDirectory);
}

/**
* Sets up the temp directory for the report
* @return {String} the Path to the temporary directory
*/
static _setupReportDir() {
const tmpDir = os.tmpdir();
return fs.mkdtempSync(`${tmpDir}${sep}`);
}

/**
* Trigger node-report to write report in the temp directory
* @param {String} tmpDirectory the temporary directory for collecting report output
*/
static _createNodeReport(tmpDirectory) {
cmdUtil.log(chalk.blue('Triggering node report...'));
nodereport.setDirectory(tmpDirectory);
nodereport.triggerReport();
}

/**
* Creates an archive of the temp directory for the report
* @param {String} tmpDirectory the temporary directory for collecting report output
* @param {String} outputFilename the name of the file that was optionally passed in on the command line
* @return {Promise} resolved/rejected promise when the archive has been created
*/
static _archiveReportDir(tmpDirectory) {
let timestamp = moment().format('YYYYMMDD[T]HHmmss');
let prefix = 'composer-report-' + timestamp;
let filename = prefix + '.tgz';
return tar.c(
{
cwd: tmpDirectory+'/',
prefix: prefix,
gzip: true,
file: filename
},
['.']
).then(() => {
cmdUtil.log(chalk.blue.bold('\nSuccessfully created Composer report file to '));
cmdUtil.log(chalk.blue('\tOutput file: ')+filename);
});
}
}
module.exports = Report;
24 changes: 24 additions & 0 deletions packages/composer-cli/lib/cmds/report/reportCommand.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

const Report = require ('./lib/report.js');

module.exports.command = 'report';
module.exports.describe = 'Create a report of the current execution environment';

module.exports.handler = (argv) => {
return argv.thePromise = Report.handler(argv);
};
3 changes: 3 additions & 0 deletions packages/composer-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,15 @@
"homedir": "0.6.0",
"js-yaml": "3.10.0",
"mkdirp": "0.5.1",
"moment":"2.19.3",
"node-report":"2.2.1",
"npm-paths": "0.1.3",
"nunjucks": "3.0.0",
"ora": "1.2.0",
"prettyjson": "1.2.1",
"prompt": "1.0.0",
"sanitize-filename": "1.6.1",
"tar":"4.3.0",
"yargs": "10.0.3"
},
"license-check-config": {
Expand Down
91 changes: 91 additions & 0 deletions packages/composer-cli/test/report/report.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

const ReportCmd = require('../../lib/cmds/report/reportCommand.js');
const chai = require('chai');
const sinon = require('sinon');
chai.should();
chai.use(require('chai-as-promised'));
const fs = require('fs');
const os = require('os');
const nodereport = require('node-report');
const tar = require('tar');



describe('composer report CLI', function() {
const sandbox = sinon.sandbox.create();
let consoleLogSpy;
let mkdtempSyncStub;
let triggerReportStub;
let setDirectoryStub;
let cStub;

beforeEach(function() {
consoleLogSpy = sandbox.spy(console, 'log');
sandbox.stub(process, 'exit');
mkdtempSyncStub = sandbox.stub(fs,'mkdtempSync').returns('COMPOSER_REPORT_TEMPDIR');
sandbox.stub(os, 'tmpdir').returns('OS_TEMPDIR');
triggerReportStub = sandbox.stub(nodereport, 'triggerReport');
setDirectoryStub = sandbox.stub(nodereport, 'setDirectory');
cStub = sandbox.stub(tar, 'c').returns(Promise.resolve());
});

afterEach(function() {
sandbox.restore();
});

it('should successfully run the composer report command with no arguments specified', function() {
const args = {};
return ReportCmd.handler(args).then(() => {
sinon.assert.calledWith(consoleLogSpy, sinon.match('Creating Composer report'));
});
});

it('should create a temporary directory to store files to create the report archive from', function() {
const args = {};
return ReportCmd.handler(args).then(() => {
sinon.assert.calledOnce(mkdtempSyncStub);
sinon.assert.calledWith(mkdtempSyncStub, 'OS_TEMPDIR/');
});
});

it('should successfully write a node-report report to the temporary directory', function() {
const args = { };
return ReportCmd.handler(args).then(() => {
sinon.assert.calledOnce(setDirectoryStub);
sinon.assert.calledWith(setDirectoryStub, 'COMPOSER_REPORT_TEMPDIR');
sinon.assert.calledOnce(triggerReportStub);
});
});

it('should successfully create a zipped tar archive of the COMPOSER_REPORT_TEMPDIR in the current directory and log the output filename in the console', function() {
const args = { };
return ReportCmd.handler(args).then(() => {
sinon.assert.calledOnce(cStub);
sinon.assert.calledWith(cStub, {
cwd: 'COMPOSER_REPORT_TEMPDIR/',
prefix: sinon.match(/^composer-report-\d{8}T\d{6}$/),
gzip: true,
file: sinon.match(/^composer-report-\d{8}T\d{6}\.tgz$/)
}, ['.']);
sinon.assert.called(consoleLogSpy);
sinon.assert.calledWith(consoleLogSpy, sinon.match('Triggering node report...'));
sinon.assert.calledWith(consoleLogSpy, sinon.match('Successfully created Composer report file to'));
sinon.assert.calledWith(consoleLogSpy, sinon.match(/Output file: .*composer-report-\d{8}T\d{6}\.tgz$/));
});
});
});
6 changes: 6 additions & 0 deletions packages/composer-website/jekylldocs/reference/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ List all identities in a business network: [composer identity list](./composer.i

Revoke an identity from a participant: [composer identity revoke](./composer.identity.revoke.html)

## Support diagnostics

`composer report`

Create a diagnostic report: [composer report](./composer.report)

## Transaction execution

`composer transaction submit`
Expand Down
23 changes: 23 additions & 0 deletions packages/composer-website/jekylldocs/reference/composer.report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
layout: default
title: Hyperledger Composer Report
section: reference-command
sidebar: sidebars/accordion-toc0.md
excerpt: Hyperledger Composer Report
---

# Composer Report

Creates a report archive containing system and environment information to assist with problem determination.

```
composer report
```

## Syntax

```
Options:
--help Show help [boolean]
-v, --version Show version number [boolean]
```

0 comments on commit 846ce52

Please sign in to comment.