-
Notifications
You must be signed in to change notification settings - Fork 48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding Azure REST samples support #178
Changes from 23 commits
ece25df
d36e077
a40b12a
4b64227
9f912e7
852d9a2
64a2fda
f5a6ab2
4667062
9e7db20
0d25849
944502b
925cd65
d3cf3ea
f361e7e
114bf33
e8c9f7c
913f4fb
6588f19
96aa6ba
41386b5
26601ab
4606950
4ebfea9
a640261
ae8dd93
52a8a94
9c7cabe
0621e92
d487980
80cf6c7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
'use strict'; | ||
|
||
import * as vscode from 'vscode'; | ||
import { Swagger } from './swagger'; | ||
import { PlaybookManager } from './playbookManager'; | ||
import * as utilities from './utilities'; | ||
var path = require("path"); | ||
var fs = require('fs'); | ||
var pm = new PlaybookManager(); | ||
|
||
export class RestSamples { | ||
protected _outputChannel: vscode.OutputChannel; | ||
|
||
constructor(outputChannel: vscode.OutputChannel) { | ||
this._outputChannel = outputChannel; | ||
} | ||
|
||
public async displayMenu() { | ||
let __this = this; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why need private __this?
zikalino marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
let specLocation = await this.getSpecificationLocation(); | ||
__this.queryDirectory(specLocation + '/specification', false, "", function (groups) { | ||
if (groups != null) { | ||
vscode.window.showQuickPick(groups).then(selection => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is async function already, pls use await vscode.window.showQuickPick() |
||
if (!selection) return; | ||
__this.selectOperation(specLocation + "/specification/" + selection); | ||
}); | ||
} | ||
}) | ||
} | ||
|
||
public selectOperation(path: string) { | ||
let operations = this.queryAll(path); | ||
let items = []; | ||
|
||
if (operations) { | ||
for (var key in operations) { | ||
items.push(operations[key]); | ||
} | ||
} | ||
|
||
|
||
if (items.length == 0) { | ||
vscode.window.showInformationMessage("No samples available"); | ||
return; | ||
} | ||
|
||
vscode.window.showQuickPick(items).then(selection => { | ||
// the user canceled the selection | ||
if (!selection) return; | ||
|
||
items = []; | ||
|
||
for (var f in selection['files']) { | ||
let swagger = require(selection['files'][f]); | ||
if (swagger != null) { | ||
let xpath = selection['files'][f].split('/').slice(0, -1).join('/'); | ||
let swaggerHandler = new Swagger(swagger); | ||
let examples: string[] = swaggerHandler.getExampleNames(selection['path'], selection['method']); | ||
let apiVersion = xpath.split('/').slice(-1)[0]; | ||
|
||
examples.forEach(function(s, i, a) { | ||
items.push({ | ||
'label': 'API Version: ' + apiVersion + ' - ' + s.split('/').pop().split('.json')[0], | ||
'file': selection['files'][f], | ||
'example': require(xpath + '/' + s), | ||
'path': selection['path'], | ||
'method': selection['method'] | ||
}); | ||
}) | ||
} | ||
} | ||
|
||
vscode.window.showQuickPick(items).then(selection => { | ||
// the user canceled the selection | ||
if (!selection) return; | ||
|
||
let swagger = require(selection['file']); | ||
let swaggerHandler = new Swagger(swagger); | ||
let playbook = swaggerHandler.generateRestApiTasks(selection['path'], selection['method'], selection['example']); | ||
pm.insertTask(playbook); | ||
}); | ||
}); | ||
} | ||
|
||
public async getSpecificationLocation(): Promise<string> { | ||
let spec = utilities.getCodeConfiguration('ansible', 'azureRestSpec'); | ||
if (spec != "") { | ||
return spec as string; | ||
} else { | ||
|
||
this._outputChannel.show(); | ||
const progress = utilities.delayedInterval(() => { this._outputChannel.append('.') }, 500); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. progress should at end of below log message, otherwise you'll ...............Getting Azurexxxxx |
||
|
||
this._outputChannel.append("Getting Azure REST API specifications."); | ||
let clone = require('git-clone'); | ||
let home: string = path.join(process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME'], 'azure-rest-api-specs'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. under .vscode to make it hide? |
||
clone("https://github.com/Azure/azure-rest-api-specs.git", home, null, (result) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. async function, pls use await instead of callback There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this library only supports callback There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. then pls remove async on function declaration |
||
progress.cancel(); | ||
if (!result) { | ||
utilities.updateCodeConfiguration('ansible', 'azureRestSpec', home, true); | ||
this._outputChannel.appendLine(""); | ||
this._outputChannel.appendLine("REST API feature ready"); | ||
} else { | ||
this._outputChannel.appendLine("Failed to acquire REST API specifications"); | ||
} | ||
return home; | ||
}) | ||
} | ||
} | ||
|
||
private queryAll(path: string) { | ||
let operations = {}; | ||
let __this = this; | ||
yungezz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
__this.queryApiGroup(path, function (dirs: string[]) { | ||
dirs.forEach(dir => { | ||
__this.queryDirectory(dir, true, ".json", function(files) { | ||
if (files != null) { | ||
files.forEach(file => { | ||
let swagger = require(dir + '/' + file); | ||
for (var path in swagger.paths) { | ||
for (var method in swagger.paths[path]) { | ||
// add only if there are examples | ||
if (swagger.paths[path][method]['x-ms-examples']) { | ||
let operationId: string = swagger.paths[path][method].operationId; | ||
let description: string = swagger.paths[path][method].description; | ||
|
||
if (!operations[operationId]) { | ||
operations[operationId] = { 'label': operationId, 'description': description, 'files': [], 'path': path, 'method': method } | ||
} | ||
|
||
operations[operationId]['files'].push(dir + '/' + file); | ||
} | ||
} | ||
} | ||
}); | ||
}; | ||
}); | ||
}); | ||
}); | ||
|
||
return operations; | ||
} | ||
|
||
private queryApiGroup(path, cb) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the 2 function names confusing.. why not use queryDirectory and queryApiGroup?
yungezz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
this.queryApiGroupInternal([ path ], [], cb); | ||
} | ||
|
||
private queryApiGroupInternal(dirsToQuery: string[], finalDirs: string[], cb) { | ||
|
||
let __this = this; | ||
// if no more dirs to query, just respond via callback | ||
if (dirsToQuery.length == 0) { | ||
cb(finalDirs); | ||
return; | ||
} | ||
|
||
// get first dir to query | ||
let nextDir: string = dirsToQuery.pop(); | ||
|
||
this.queryDirectory(nextDir, false, "", function(dir) { | ||
if (dir == null) { | ||
cb(null); | ||
vscode.window.showErrorMessage("Failed to query: " + nextDir); | ||
return; | ||
} else { | ||
let depth: number = nextDir.split('/specification/')[1].split('/').length; | ||
|
||
if (depth < 4) { | ||
for (var i = 0; i < dir.length; i++) dirsToQuery.push(nextDir + '/' + dir[i]) | ||
} else { | ||
for (var i = 0; i < dir.length; i++) finalDirs.push(nextDir + '/' + dir[i]) | ||
} | ||
|
||
__this.queryApiGroupInternal(dirsToQuery, finalDirs, cb); | ||
} | ||
}) | ||
} | ||
|
||
private queryDirectory(path: string, files: boolean, ext: string, cb) { | ||
// just use filesystem | ||
try { | ||
let dirEntries = fs.readdirSync(path); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. check path exists before read? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that's why try is here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. perhaps there should be a message and we could clear the configuration if not there? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so you'd like the caller handle when path not exists? |
||
let directories = []; | ||
|
||
for (var d in dirEntries) { | ||
if (ext != null && ext != "" && dirEntries[d].indexOf(ext) != (dirEntries[d].length - ext.length)) | ||
continue; | ||
|
||
if (!files) { | ||
if (fs.lstatSync(path + '/' + dirEntries[d]).isDirectory()) { | ||
directories.push(dirEntries[d]); | ||
} | ||
} else { | ||
if (!fs.lstatSync(path + '/' + dirEntries[d]).isDirectory()) { | ||
directories.push(dirEntries[d]); | ||
} | ||
} | ||
} | ||
cb(directories); | ||
} catch (e) { | ||
cb(null); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you meet error when using those samples, please file issues at xxxx/issues.