Skip to content

Commit

Permalink
Adds support for logging the last --count activations (#71)
Browse files Browse the repository at this point in the history
* shuffled logging around, there were issues with the previous implementation
* log count
* Coverage 100%
* drop node@8 tests
  • Loading branch information
purplecabbage authored Dec 6, 2019
1 parent 1166e73 commit d22673f
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 32 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/nodejs.yml.disabled
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:

strategy:
matrix:
node-version: [8.x, 10.x, 12.x]
node-version: [10.x, 12.x]
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- uses: actions/checkout@v1
Expand Down
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ os:
- linux

node_js:
- "8"
- "10"
- "12"

Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -497,8 +497,9 @@ USAGE
$ ./bin/run runtime:activation:logs [ACTIVATIONID]
OPTIONS
-c, --count=count [default: 1] used with --last, return the last `count` activation logs. Max 5
-i, --insecure bypass certificate check
-l, --last retrieves the most recent activation log
-l, --last retrieves the most recent activation logs
-r, --strip strip timestamp information and output first line only
-u, --auth=auth whisk auth
-v, --verbose Verbose output
Expand Down
37 changes: 23 additions & 14 deletions src/commands/runtime/activation/logs.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,47 +13,56 @@ governing permissions and limitations under the License.
const { flags } = require('@oclif/command')
const RuntimeBaseCommand = require('../../../RuntimeBaseCommand')
const { printLogs } = require('../../../runtime-helpers')
const chalk = require('chalk')

class ActivationLogs extends RuntimeBaseCommand {
async run () {
const { args, flags } = this.parse(ActivationLogs)
let id = args.activationID // note: could be null, but we wait to check
// note: could be null, but we wait to check
let activations = [{ activationId: args.activationId }]
const ow = await this.wsk()

if (flags.last) {
const ax = await ow.activations.list({ limit: 1, skip: 0 })
id = ax[0].activationId
this.log('activation logs %s', id)
const limit = Math.max(1, Math.min(flags.count, 5))
activations = await ow.activations.list({ limit: limit, skip: 0 })
}
if (!id) {
if (!activations[0].activationId) {
// just a thought, but we could just return --last activation log when no id is present
this.error('Missing required arg: `activationID`')
this.error('Missing required arg: `activationId`')
}

try {
const result = await ow.activations.logs(id)
printLogs(result, flags.strip, this.log)
} catch (err) {
this.handleError('failed to retrieve the logs', err)
}
const logger = this.log
activations.forEach((ax) => {
ow.activations.logs(ax.activationId).then((result) => {
logger(chalk.dim('=== ') + chalk.bold('activation logs %s %s:%s'), ax.activationId, ax.name || '', ax.version || '')
printLogs(result, flags.strip, logger)
}, (err) => {
this.handleError('failed to retrieve logs for activation', err)
})
})
}
}

ActivationLogs.args = [
{
name: 'activationID'
name: 'activationId'
}
]

ActivationLogs.flags = {
...RuntimeBaseCommand.flags,
last: flags.boolean({
char: 'l',
description: 'retrieves the most recent activation log'
description: 'retrieves the most recent activation logs'
}),
strip: flags.boolean({
char: 'r',
description: 'strip timestamp information and output first line only'
}),
count: flags.integer({
char: 'c',
description: 'used with --last, return the last `count` activation logs. Max 5',
default: 1
})
}

Expand Down
3 changes: 3 additions & 0 deletions test/__fixtures__/logs/activation-logs.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
=== activation logs 12345 :
this is a log
so is this
41 changes: 26 additions & 15 deletions test/commands/runtime/activation/logs.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ test('aliases', async () => {
test('args', async () => {
const logName = TheCommand.args[0]
expect(logName.name).toBeDefined()
expect(logName.name).toEqual('activationID')
expect(logName.name).toEqual('activationId')
})

test('flags', async () => {
Expand Down Expand Up @@ -76,9 +76,9 @@ describe('instance methods', () => {
const cmd = ow.mockResolved(owAction, { logs: ['this is a log', 'so is this'] })
command.argv = ['12345']
return command.run()
.then(() => {
.then((res) => {
expect(cmd).toHaveBeenCalledWith('12345')
expect(stdout.output).toMatch('this is a log')
expect(stdout.output).toMatchFixture('logs/activation-logs.txt')
})
})

Expand All @@ -92,17 +92,15 @@ describe('instance methods', () => {
})
})

test('errors out on api error', () => {
return new Promise((resolve, reject) => {
ow.mockRejected(owAction, new Error('an error'))
command.argv = ['12345']
return command.run()
.then(() => reject(new Error('does not throw error')))
.catch(() => {
expect(handleError).toHaveBeenLastCalledWith('failed to retrieve the logs', new Error('an error'))
resolve()
})
})
test('throws error retrieve logs of an activation', () => {
ow.mockResolved('activations.list', [{ activationId: '12345' }])
const cmd = ow.mockRejected(owAction, new Error('Async error'))
command.argv = ['-l', '-c', '2']
return command.run()
.then(() => {
expect(cmd).toHaveBeenCalledWith('12345')
expect(handleError).toHaveBeenCalledWith('failed to retrieve logs for activation', expect.any(Error))
})
})

test('retrieve last log -l', () => {
Expand All @@ -129,14 +127,27 @@ describe('instance methods', () => {
})
})

test('retrieve last -c logs', () => {
const listCmd = ow.mockResolved('activations.list', [{ activationId: '12345' }, { activationId: '12346' }])
const logCmd = ow.mockResolved(owAction, { logs: ['line1', 'line2', 'line3'] })
command.argv = ['-l', '-c', '2']
return command.run()
.then(() => {
expect(listCmd).toHaveBeenCalledWith(expect.objectContaining({ limit: 2 }))
expect(logCmd).toHaveBeenCalledWith('12345')
expect(logCmd).toHaveBeenCalledWith('12346')
expect(stdout.output).toMatch('line3')
})
})

test('errors if np axId or --last flag', () => {
return new Promise((resolve, reject) => {
command.argv = []
const error = jest.spyOn(command, 'error')
return command.run()
.then(() => reject(new Error('does not throw error')))
.catch(() => {
expect(error).toHaveBeenLastCalledWith('Missing required arg: `activationID`')
expect(error).toHaveBeenLastCalledWith('Missing required arg: `activationId`')
resolve()
})
})
Expand Down
2 changes: 2 additions & 0 deletions test/jest.setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ delete process.env['WHISK_NAMESPACE']
delete process.env['WSK_CONFIG_FILE']

// trap console log
// if you want to see output, you can do this:
// beforeEach(() => { stdout.start(); stdout.print = true })
beforeEach(() => { stdout.start() })
afterEach(() => { stdout.stop() })

Expand Down

0 comments on commit d22673f

Please sign in to comment.