1 | 'use strict';
|
2 |
|
3 | const BbPromise = require('bluebird');
|
4 | const chalk = require('chalk');
|
5 |
|
6 | class OpenWhiskInfo {
|
7 | constructor(serverless, options) {
|
8 | this.serverless = serverless;
|
9 | this.options = options || {};
|
10 | this.provider = this.serverless.getProvider('openwhisk');
|
11 |
|
12 | this.hooks = {
|
13 | 'info:info': () => BbPromise.bind(this)
|
14 | .then(this.validate)
|
15 | .then(this.info),
|
16 | 'after:deploy:deploy': () => BbPromise.bind(this)
|
17 | .then(() => {
|
18 | if (this.options.noDeploy) {
|
19 | return BbPromise.resolve();
|
20 | }
|
21 | this.consoleLog('');
|
22 | this.failsafe = true;
|
23 | return BbPromise.bind(this)
|
24 | .then(this.validate)
|
25 | .then(this.info)
|
26 | })
|
27 | };
|
28 | }
|
29 |
|
30 | validate() {
|
31 | if (!this.serverless.config.servicePath) {
|
32 | throw new this.serverless.classes.Error('This command can only be run inside a service.');
|
33 | }
|
34 |
|
35 | return this.provider.props().then(props => {
|
36 | this.props = props;
|
37 | return this.provider.client();
|
38 | }).then(client => {
|
39 | this.client = client;
|
40 | })
|
41 | }
|
42 |
|
43 | info () {
|
44 | this.consoleLog(`${chalk.yellow.underline('Service Information')}`);
|
45 |
|
46 | return BbPromise.bind(this)
|
47 | .then(this.showServiceInfo)
|
48 | .then(this.showActionsInfo)
|
49 | .then(this.showTriggersInfo)
|
50 | .then(this.showRulesInfo)
|
51 | .then(this.showRoutesInfo)
|
52 | .then(this.showWebActionsInfo);
|
53 | }
|
54 |
|
55 | showServiceInfo () {
|
56 | this.consoleLog(`platform:\t${this.props.apihost}`);
|
57 | this.consoleLog(`namespace:\t${this.props.namespace || '_'}`);
|
58 | this.consoleLog(`service:\t${this.serverless.service.service}\n`);
|
59 | }
|
60 |
|
61 | showActionsInfo () {
|
62 | this.consoleLog(`${chalk.yellow('actions:')}`);
|
63 | return this.client.actions.list().then(actions => {
|
64 | this._actions = actions;
|
65 | if (!actions.length) return console.log('**no actions deployed**\n');
|
66 | const names = actions.map(action => action.name).join(' ');
|
67 | this.consoleLog(names + '\n')
|
68 | })
|
69 | }
|
70 |
|
71 | showWebActionsInfo () {
|
72 | this.consoleLog(`${chalk.yellow('endpoints (web actions):')}`);
|
73 | const web_actions = this._actions.filter(action => {
|
74 | const annotations = action.annotations || []
|
75 | return annotations.some(a => a.key === 'web-export' && a.value === true)
|
76 | })
|
77 | if (!web_actions.length) {
|
78 | this.consoleLog('**no web actions deployed**\n');
|
79 | return Promise.resolve();
|
80 | }
|
81 |
|
82 | return this.provider.props().then(props => {
|
83 | web_actions.forEach(action => {
|
84 | this.consoleLog(`https://${props.apihost}/api/v1/web/${action.namespace}/default/${action.name}`)
|
85 | })
|
86 | })
|
87 | }
|
88 |
|
89 | showTriggersInfo () {
|
90 | this.consoleLog(`${chalk.yellow('triggers:')}`);
|
91 | return this.client.triggers.list().then(triggers => {
|
92 | if (!triggers.length) return console.log('**no triggers deployed**\n');
|
93 | const names = triggers.map(trigger => trigger.name).join(' ');
|
94 | this.consoleLog(names + '\n')
|
95 | })
|
96 | }
|
97 |
|
98 | showRulesInfo () {
|
99 | this.consoleLog(`${chalk.yellow('rules:')}`);
|
100 | return this.client.rules.list().then(rules => {
|
101 | if (!rules.length) return console.log('**no rules deployed**\n');
|
102 | const names = rules.map(rule => rule.name).join(' ');
|
103 | this.consoleLog(names + '\n')
|
104 | })
|
105 | }
|
106 |
|
107 | showRoutesInfo () {
|
108 | this.consoleLog(`${chalk.yellow('endpoints (api-gw):')}`)
|
109 | let operation = this.client.routes.list().then(routes => {
|
110 | if (!routes.apis.length) return console.log('**no routes deployed**\n')
|
111 | routes.apis.forEach(api => this.logApiEndPoints(api.value))
|
112 | this.consoleLog('')
|
113 | })
|
114 |
|
115 | operation = operation.catch(err => {
|
116 | this.consoleLog(`${chalk.red('**failed to fetch routes**')}`)
|
117 | if(err.message.match(/status code 400/) && err.message.match(/expired/)) {
|
118 | this.consoleLog(`${chalk.red('**api gateway key is wrong or has expired! if it has expired, please refresh with wsk bluemix login**\n')}`)
|
119 | }
|
120 |
|
121 | if (!this.failsafe) throw err
|
122 | })
|
123 |
|
124 | return operation
|
125 | }
|
126 |
|
127 | logEndPoint (baseUrl, path, method, actionName) {
|
128 | if (!path.startsWith('/')) {
|
129 | path = `/${path}`
|
130 | }
|
131 | this.consoleLog(`${method.toUpperCase()} ${baseUrl}${path} --> ${actionName}`)
|
132 | }
|
133 |
|
134 | logApiEndPoints (api) {
|
135 | const paths = api.apidoc.paths
|
136 | Object.keys(paths).forEach(path => {
|
137 | const methods = Object.keys(paths[path])
|
138 | methods.forEach(method => {
|
139 | const operation = paths[path][method]
|
140 | let actionName = 'unknown'
|
141 | if (operation.hasOwnProperty('x-openwhisk')) {
|
142 | actionName = operation['x-openwhisk'].action;
|
143 | } else if (operation.hasOwnProperty('x-ibm-op-ext')) {
|
144 | actionName = operation['x-ibm-op-ext'].actionName;
|
145 | }
|
146 | this.logEndPoint(api.gwApiUrl, path, method, actionName)
|
147 | })
|
148 | })
|
149 | }
|
150 |
|
151 | consoleLog (message) {
|
152 | console.log(message)
|
153 | }
|
154 | }
|
155 |
|
156 | module.exports = OpenWhiskInfo;
|