├── .gitignore ├── .npmignore ├── .travis.yml ├── README.md ├── credentials.json.enc ├── lib ├── logger.js └── pingdom.js ├── log4js.json ├── package.json └── test ├── test_pingdom_api.js └── vows_log4js.json /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.log 3 | node_modules/ 4 | credentials.json 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .git* 2 | .pdf 3 | credentials.json 4 | .log 5 | node_modules 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: false 3 | before_script: 4 | openssl aes-256-cbc -K $encrypted_c57309734bac_key -iv $encrypted_c57309734bac_iv -in credentials.json.enc -out credentials.json -d 5 | deploy: 6 | provider: npm 7 | on: 8 | tags: true 9 | all_branches: true 10 | email: ryan@ryanbreen.com 11 | api_key: 12 | secure: bwhZIXKniloMQz6+dJUMECUTLbG7j24wPwuG9G/H/YiMd6I7Z9P2roeeIC7TKu/NzXGLjySzqPYDxIZm9VGonx2lY4rOVC0vDkju2iEY3PIzAU8aO2FP9mFdaE03PN5bFwoB1BheHYypyOalPFZ6Zugq+RmM8SftyscdjhhFuRc= 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # node-pingdom 2 | 3 | Provides access to the Pingdom JSON API. 4 | 5 | ## Installation 6 | 7 | npm install pingdom 8 | 9 | ## Tests 10 | 11 | Tests use [vows](http://vowsjs.org) and can be run as `vows test/test_pingdom_api.js`. Note that to run the test suite, you must create a credentials.json file within the root directory of this repository. The file should be formatted like this: 12 | 13 | { 14 | "username" : "myusername@mydomain.com", 15 | "password" : "not_a_great_password", 16 | "app_key" : "111122223333444555aaabbbcccdddeeefff" 17 | } 18 | 19 | ## Usage 20 | 21 | Each method call of the Pingdom API expects your username and password. All optional parameters are passed in as a hash of name/value pairs which are composed into a query string. By default, the Pingdom API is assumed to be version 2.0, but this can be modified via the setAPIVersion method. If you're using Pingdom's [multi-user authentication](https://www.pingdom.com/features/api/documentation/#multi-user+authentication), then provide a username of the form 'master@example.com/subaccount@example.com'. 22 | 23 | ## Author 24 | 25 | Ryan Breen (ryan at ryanbreen.com) 26 | 27 | ## License 28 | 29 | Copyright (C) 2011 by Ryan Breen 30 | 31 | Permission is hereby granted, free of charge, to any person obtaining a copy 32 | of this software and associated documentation files (the "Software"), to deal 33 | in the Software without restriction, including without limitation the rights 34 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 35 | copies of the Software, and to permit persons to whom the Software is 36 | furnished to do so, subject to the following conditions: 37 | 38 | The above copyright notice and this permission notice shall be included in 39 | all copies or substantial portions of the Software. 40 | 41 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 42 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 43 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 44 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 45 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 46 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 47 | THE SOFTWARE. 48 | -------------------------------------------------------------------------------- /credentials.json.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanbreen/node-pingdom/09ed2c980bebf832c626bbdb472e9ba6fd554c78/credentials.json.enc -------------------------------------------------------------------------------- /lib/logger.js: -------------------------------------------------------------------------------- 1 | var log4js = require('log4js'); 2 | var sprintf = require('sprintf').sprintf; 3 | 4 | exports.getLogger = function(categoryName, config_file) { 5 | if (config_file !== undefined) { 6 | log4js.clearAppenders(); 7 | log4js.configure(config_file); 8 | } 9 | 10 | var _logger = log4js.getLogger(categoryName || '[default]'); 11 | 12 | return { 13 | trace: function() { 14 | if(_logger.isTraceEnabled()) _logger.trace(sprintf.apply(this, arguments)); 15 | }, 16 | 17 | debug: function() { 18 | if(_logger.isDebugEnabled()) _logger.debug(sprintf.apply(this, arguments)); 19 | }, 20 | 21 | info: function() { 22 | if(_logger.isInfoEnabled()) _logger.info(sprintf.apply(this, arguments)); 23 | }, 24 | 25 | warn: function() { 26 | if(_logger.isWarnEnabled()) _logger.warn(sprintf.apply(this, arguments)); 27 | }, 28 | 29 | error: function() { 30 | if(_logger.isErrorEnabled()) _logger.error(sprintf.apply(this, arguments)); 31 | }, 32 | 33 | fatal: function() { 34 | if(_logger.isFatalEnabled()) _logger.fatal(sprintf.apply(this, arguments)); 35 | } 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /lib/pingdom.js: -------------------------------------------------------------------------------- 1 | var sys = require('sys'); 2 | var request = require('request'); 3 | var url = require('url'); 4 | var querystring = require('querystring'); 5 | var Buffer = require('buffer').Buffer; 6 | var sprintf = require('sprintf').sprintf; 7 | var logger = require('./logger.js').getLogger('pingdom'); 8 | 9 | var DEFAULT_API_VERSION = '2.0'; 10 | var current_api_version = DEFAULT_API_VERSION; 11 | 12 | exports.setAPIVersion = function(ver) { 13 | current_api_version = ver; 14 | }; 15 | 16 | /** 17 | * Returns a list of actions (alerts) that has been generated for your account. 18 | */ 19 | exports.getActions = function(username, password, app_key, params, callback) { 20 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 5); 21 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/actions', current_api_version); 22 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'GET', paramsToQueryString(args.params), args.callback); 23 | }; 24 | 25 | /** 26 | * Returns a list of the latest error analysis results for a specified check. 27 | */ 28 | exports.getAnalysis = function(username, password, app_key, checkid, params, callback) { 29 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 6); 30 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/analysis/%s', current_api_version, checkid); 31 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'GET', paramsToQueryString(args.params), args.callback); 32 | }; 33 | 34 | /** 35 | * Returns the raw result for a specified error analysis. This data is primarily intended for internal use, 36 | * however, there is no real documentation for this data at the moment. In the future, we may add a new API 37 | * method that provides a more user-friendly format. 38 | */ 39 | exports.getRawAnalysis = function(username, password, app_key, checkid, analysisid, params, callback) { 40 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 7); 41 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/analysis/%s/%s', current_api_version, checkid, analysisid); 42 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'GET', paramsToQueryString(args.params), args.callback); 43 | }; 44 | 45 | /** 46 | * Returns a list overview of all checks. 47 | */ 48 | exports.getChecks = function(username, password, app_key, params, callback) { 49 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 5); 50 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/checks', current_api_version); 51 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'GET', paramsToQueryString(args.params), args.callback); 52 | }; 53 | 54 | /** 55 | * Returns a detailed description of a specified check. 56 | */ 57 | exports.getCheckDetails = function(username, password, app_key, checkid, params, callback) { 58 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 6); 59 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/checks/%s', current_api_version, checkid); 60 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'GET', paramsToQueryString(args.params), args.callback); 61 | }; 62 | 63 | /** 64 | * Creates a new check with settings specified by provided parameters. 65 | */ 66 | exports.createCheck = function(username, password, app_key, params, callback) { 67 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 5); 68 | var parameterized_url = sprintf('http://api.pingdom.com/api/%s/checks', current_api_version); 69 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'POST', paramsToQueryString(args.params), args.callback); 70 | }; 71 | 72 | /** 73 | * Modify settings for a check. The provided settings will overwrite previous values. Settings not provided 74 | * will stay the same as before the update. To clear an existing value, provide an empty value. Please note 75 | * that you cannot change the type of a check once it has been created. 76 | */ 77 | exports.modifyCheck = function(username, password, app_key, checkid, params, callback) { 78 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 6); 79 | var parameterized_url = sprintf('http://api.pingdom.com/api/%s/checks/%s', current_api_version, checkid); 80 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'PUT', paramsToQueryString(args.params), args.callback); 81 | }; 82 | 83 | /** 84 | * Deletes a check. THIS METHOD IS IRREVERSIBLE! You will lose all collected data. Be careful! 85 | */ 86 | exports.deleteCheck = function(username, password, app_key, checkid, params, callback) { 87 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 6); 88 | var parameterized_url = sprintf('http://api.pingdom.com/api/%s/checks/%s', current_api_version, checkid); 89 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'DELETE', paramsToQueryString(args.params), args.callback); 90 | }; 91 | 92 | /** 93 | * Returns a list of all contacts. 94 | */ 95 | exports.getContacts = function(username, password, app_key, params, callback) { 96 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 5); 97 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/notification_contacts', current_api_version); 98 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'GET', paramsToQueryString(args.params), args.callback); 99 | }; 100 | 101 | /** 102 | * Create a new contact. 103 | */ 104 | exports.createContact = function(username, password, app_key, params, callback) { 105 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 5); 106 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/notification_contacts', current_api_version); 107 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'POST', paramsToQueryString(args.params), args.callback); 108 | }; 109 | 110 | /** 111 | * Modify a contact. 112 | */ 113 | exports.modifyContact = function(username, password, app_key, contactid, params, callback) { 114 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 6); 115 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/notification_contacts/%s', current_api_version, contactid); 116 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'PUT', paramsToQueryString(args.params), args.callback); 117 | }; 118 | 119 | /** 120 | * Deletes a contact. 121 | */ 122 | exports.deleteContact = function(username, password, app_key, contactid, params, callback) { 123 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 6); 124 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/notification_contacts/%s', current_api_version, contactid); 125 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'DELETE', paramsToQueryString(args.params), args.callback); 126 | }; 127 | 128 | /** 129 | * Returns a list of all Pingdom probe servers. 130 | */ 131 | exports.getProbes = function(username, password, app_key, params, callback) { 132 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 5); 133 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/probes', current_api_version); 134 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'GET', paramsToQueryString(args.params), args.callback); 135 | }; 136 | 137 | /** 138 | * Get a reference of regions, timezones and date/time/number formats and their identifiers. 139 | */ 140 | exports.getReference = function(username, password, app_key, params, callback) { 141 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 5); 142 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/reference', current_api_version); 143 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'GET', paramsToQueryString(args.params), args.callback); 144 | }; 145 | 146 | /** 147 | * Returns a list of email report subscriptions. 148 | */ 149 | exports.getEmailReportList = function(username, password, app_key, params, callback) { 150 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 5); 151 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/reports.email', current_api_version); 152 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'GET', paramsToQueryString(args.params), args.callback); 153 | }; 154 | 155 | /** 156 | * Creates a new email report. 157 | */ 158 | exports.createEmailReport = function(username, password, app_key, params, callback) { 159 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 5); 160 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/reports.email', current_api_version); 161 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'POST', paramsToQueryString(args.params), args.callback); 162 | }; 163 | 164 | /** 165 | * Modify an email report. 166 | */ 167 | exports.modifyEmailReport = function(username, password, app_key, reportid, params, callback) { 168 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 6); 169 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/reports.email/%s', current_api_version, reportid); 170 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'PUT', paramsToQueryString(args.params), args.callback); 171 | }; 172 | 173 | /** 174 | * Delete an email report. 175 | */ 176 | exports.deleteEmailReport = function(username, password, app_key, reportid, params, callback) { 177 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 6); 178 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/reports.email/%s', current_api_version, reportid); 179 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'DELETE', paramsToQueryString(args.params), args.callback); 180 | }; 181 | 182 | /** 183 | * Returns a list of public (web-based) reports. 184 | */ 185 | exports.getPublicReportList = function(username, password, app_key, params, callback) { 186 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 5); 187 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/reports.public', current_api_version); 188 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'GET', paramsToQueryString(args.params), args.callback); 189 | }; 190 | 191 | /** 192 | * Activate public report for a specified check. 193 | */ 194 | exports.publishPublicReport = function(username, password, app_key, reportid, params, callback) { 195 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 6); 196 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/reports.public/%s', current_api_version, reportid); 197 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'PUT', paramsToQueryString(args.params), args.callback); 198 | }; 199 | 200 | /** 201 | * Deactivate public report for a specified check. 202 | */ 203 | exports.withdrawPublicReport = function(username, password, app_key, reportid, params, callback) { 204 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 6); 205 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/reports.public/%s', current_api_version, reportid); 206 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'DELETE', paramsToQueryString(args.params), args.callback); 207 | }; 208 | 209 | /** 210 | * Returns a list of shared reports (banners). 211 | */ 212 | exports.getSharedReportList = function(username, password, app_key, params, callback) { 213 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 5); 214 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/reports.shared', current_api_version); 215 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'GET', paramsToQueryString(args.params), args.callback); 216 | }; 217 | 218 | /** 219 | * Create a shared report (banner). 220 | */ 221 | exports.createSharedReport = function(username, password, app_key, params, callback) { 222 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 5); 223 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/reports.shared', current_api_version); 224 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'POST', paramsToQueryString(args.params), args.callback); 225 | }; 226 | 227 | /** 228 | * Delete a shared report (banner). 229 | */ 230 | exports.deleteSharedReport = function(username, password, app_key, reportid, params, callback) { 231 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 6); 232 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/reports.shared/%s', current_api_version, reportid); 233 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'DELETE', paramsToQueryString(args.params), args.callback); 234 | }; 235 | 236 | /** 237 | * Get the current time of the API server. 238 | */ 239 | exports.getCurrentServerTime = function(username, password, app_key, params, callback) { 240 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 5); 241 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/servertime', current_api_version); 242 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'GET', paramsToQueryString(args.params), args.callback); 243 | }; 244 | 245 | /** 246 | * Returns all account-specific settings. 247 | */ 248 | exports.getSettings = function(username, password, app_key, params, callback) { 249 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 5); 250 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/settings', current_api_version); 251 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'GET', paramsToQueryString(args.params), args.callback); 252 | }; 253 | 254 | /** 255 | * Modify account-specific settings. 256 | */ 257 | exports.modifySettings = function(username, password, app_key, params, callback) { 258 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 5); 259 | var parameterized_url = sprintf('https://api.pingdom.com/api/%s/settings', current_api_version); 260 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'PUT', paramsToQueryString(args.params), args.callback); 261 | }; 262 | 263 | /** 264 | * Return a list of raw test results for a specified check 265 | */ 266 | exports.getRawCheckResults = function(username, password, app_key, checkid, params, callback) { 267 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 6); 268 | var parameterized_url = sprintf('http://api.pingdom.com/api/%s/results/%s', current_api_version, checkid); 269 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'GET', paramsToQueryString(args.params), args.callback); 270 | }; 271 | 272 | /** 273 | * Get a summarized response time / uptime value for a specified check and time period. 274 | */ 275 | exports.getSummaryAverage = function(username, password, app_key, checkid, params, callback) { 276 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 6); 277 | var parameterized_url = sprintf('http://api.pingdom.com/api/%s/summary.average/%s', current_api_version, checkid); 278 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'GET', paramsToQueryString(args.params), args.callback); 279 | }; 280 | 281 | /** 282 | * Get a list of status changes for a specified check and time period. 283 | */ 284 | exports.getSummaryOutage = function(username, password, app_key, checkid, params, callback) { 285 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 6); 286 | var parameterized_url = sprintf('http://api.pingdom.com/api/%s/summary.outage/%s', current_api_version, checkid); 287 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'GET', paramsToQueryString(args.params), args.callback); 288 | }; 289 | 290 | /** 291 | * Get a list of intervals of average response time and uptime. Useful for generating graphs. 292 | */ 293 | exports.getSummaryPerformance = function(username, password, app_key, checkid, params, callback) { 294 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 6); 295 | var parameterized_url = sprintf('http://api.pingdom.com/api/%s/summary.performance/%s', current_api_version, checkid); 296 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'GET', paramsToQueryString(args.params), args.callback); 297 | }; 298 | 299 | /** 300 | * RGet a list of probes that performed tests for a specified check during a specified period. 301 | */ 302 | exports.getSummaryProbes = function(username, password, app_key, checkid, params, callback) { 303 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 6); 304 | var parameterized_url = sprintf('http://api.pingdom.com/api/%s/summary.probes/%s', current_api_version, checkid); 305 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'GET', paramsToQueryString(args.params), args.callback); 306 | }; 307 | 308 | /** 309 | * Performs a single test using a specified Pingdom probe against a specified target. 310 | */ 311 | exports.makeOneShotTest = function(username, password, app_key, params, callback) { 312 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 5); 313 | var parameterized_url = sprintf('http://api.pingdom.com/api/%s/single', current_api_version); 314 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'GET', paramsToQueryString(args.params), args.callback); 315 | }; 316 | 317 | /** 318 | * Perform a traceroute to a specified target from a specified Pingdom probe. 319 | */ 320 | exports.makeOneShotTraceroute = function(username, password, app_key, params, callback) { 321 | var args = reconcileArgs(Array.prototype.slice.call(arguments), 5); 322 | var parameterized_url = sprintf('http://api.pingdom.com/api/%s/traceroute', current_api_version); 323 | sendMessage(args.username, args.password, args.app_key, parameterized_url, 'GET', paramsToQueryString(args.params), args.callback); 324 | }; 325 | 326 | /** 327 | * Call the JSON API with the provided method and query parameters. Call the callback function once the 328 | * request is completed, passing in the JSON object returned from the server or null in case of error. 329 | */ 330 | function sendMessage(username, password, app_key, api, method, query, callback) { 331 | 332 | logger.trace('api: %s %s %s', method, api, query); 333 | 334 | var identifiers = username.split("/"); 335 | var usingSuperAccount = false; 336 | if (identifiers.length === 2) { 337 | username = identifiers[0]; 338 | usingSuperAccount = true; 339 | } 340 | var b = new Buffer([username, password].join(':')); 341 | var headers = { 342 | 'Connection': 'keep-alive', 343 | 'App-Key': app_key 344 | }; 345 | if ( usingSuperAccount ) { 346 | headers['Account-Email'] = identifiers[1]; 347 | } 348 | var parsedUrl = url.parse(api); 349 | var host = parsedUrl.host; 350 | var port = parsedUrl.port === undefined ? 443 : parsedUrl.port; 351 | var path = (parsedUrl.pathname + ((query === undefined) ? '' : ('?' + query))); 352 | var details = { 353 | 'url': 'https://' + host + path, 354 | 'method': method, 355 | 'headers': headers, 356 | 'auth': {'user': username, 'pass': password}, 357 | 'body': query 358 | } 359 | var req = request(details, function(error, response, body) { 360 | logger.trace('STATUS: %s', response.statusCode); 361 | 362 | if (!! error) { 363 | logger.error('Failed to send pingdom request:\n%s', sys.inspect(err)); 364 | callback(err); 365 | return; 366 | } 367 | if (response.statusCode > 399) { 368 | var msg = require('util').format('Got error response code %s, request failed.\nBody: %s', response.statusCode, body); 369 | logger.error(msg); 370 | callback(new Error(msg)); 371 | return; 372 | } 373 | 374 | try { 375 | var result = JSON.parse(body); 376 | callback(null, result); 377 | } catch(e) { 378 | logger.error('Failed to parse JSON response:\n%s', e.stack); 379 | callback(e); 380 | } 381 | }); 382 | } 383 | 384 | /** 385 | * Turn a hash of parameters into a query string 386 | */ 387 | function paramsToQueryString(params, post_style) { 388 | if (params === null) return ''; 389 | return querystring.stringify(params); 390 | } 391 | 392 | /* 393 | * Given an arguments array with an expected length, build a hash of arguments which provides all the 394 | * information needed for each method. 395 | */ 396 | function reconcileArgs(argsArr, expected) { 397 | return { 398 | 'username' : argsArr[0], 399 | 'password' : argsArr[1], 400 | 'app_key' : argsArr[2], 401 | 'params' : ( argsArr.length === expected ? argsArr[argsArr.length-2] : null), 402 | 'callback' : argsArr[argsArr.length-1] 403 | }; 404 | } 405 | -------------------------------------------------------------------------------- /log4js.json: -------------------------------------------------------------------------------- 1 | { 2 | "appenders": [ 3 | { 4 | "type": "logLevelFilter", 5 | "level": "trace", 6 | "appender": { 7 | "type": "console" 8 | } 9 | }] 10 | } 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pingdom", 3 | "version": "1.2.1", 4 | "main": "./lib/pingdom.js", 5 | "description": "Pingdom JSON API library", 6 | "author": "Ryan Breen ", 7 | "directories": {"lib": "./lib", "test": "./test"}, 8 | "dependencies": { 9 | "log4js": ">=0.3.0", 10 | "sprintf": ">=0.1.1", 11 | "request": "^2.49.0" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/ryanbreen/node-pingdom.git" 16 | }, 17 | "devDependencies": { 18 | "vows": ">=0.5.6" 19 | }, 20 | "engines": {"node": ">=0.4.0"}, 21 | "scripts": { 22 | "test": "vows test/*.js --spec" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/test_pingdom_api.js: -------------------------------------------------------------------------------- 1 | var sys = require('sys'); 2 | var fs = require('fs'); 3 | var vows = require('vows'); 4 | var assert = require('assert'); 5 | var logger = require('../lib/logger.js').getLogger('pingdom_test', './test/vows_log4js.json'); 6 | 7 | var pingdom = require('../lib/pingdom.js'); 8 | 9 | var happy = false; 10 | try { 11 | var credsJSON = fs.readFileSync('credentials.json', 'utf-8'); 12 | var creds = JSON.parse(credsJSON); 13 | happy = (creds !== undefined && creds.username !== undefined && creds.password !== undefined && creds.app_key !== undefined); 14 | } catch(e) { 15 | sys.puts(e.stack); 16 | } 17 | 18 | if (!happy) { 19 | sys.puts('To run vows, you must have a file called "credentials.json" in your working directory.'); 20 | sys.puts('That file must contain a JSON object like this { "username" : "ryan@ryanbreen.com", "password" : "12345678"}'); 21 | process.exit(1); 22 | } 23 | 24 | /** 25 | * Macro to validate that an array of results was properly composed. 26 | */ 27 | function assertValidResponseCollection(collectionName, equals, length) { 28 | return function (err, response) { 29 | assert.notEqual(null, response); 30 | assert.notEqual(undefined, response[collectionName]); 31 | assert[(equals ? 'equal' : 'notEqual')](length, response[collectionName].length); 32 | }; 33 | } 34 | 35 | function assertValidResponseObject(name, parameter, value) { 36 | logger.trace('%s', sys.inspect(value)); 37 | 38 | return function (err, response) { 39 | logger.trace('%s', sys.inspect(response)); 40 | logger.trace('%s', response[name][parameter]); 41 | logger.trace('%s', value); 42 | assert.notEqual(null, response); 43 | assert.notEqual(undefined, response[name]); 44 | assert.equal(value, response[name][parameter]); 45 | }; 46 | } 47 | 48 | var api = { 49 | call: function (command, params, args) { 50 | return function () { 51 | var arguments = [ creds.username, creds.password, creds.app_key ]; 52 | if (args !== undefined) arguments.push(args); 53 | if (params != undefined) arguments.push(params); 54 | arguments.push(this.callback); 55 | 56 | logger.trace('Arguments:\n%s', sys.inspect(arguments)); 57 | 58 | pingdom[command].apply(this, arguments); 59 | }; 60 | } 61 | }; 62 | 63 | vows.describe('pingdom API').addBatch({ 64 | 65 | 'Actions --' : { 66 | 'getActions' : { 67 | topic: api.call('getActions', {'limit' : 4 }), 68 | 'returns a valid response': function(err, response) { 69 | assert.equal(null, err); 70 | assert.notEqual(null, response); 71 | assert.notEqual(undefined, response.actions); 72 | assert.notEqual(undefined, response.actions.alerts); 73 | assert.ok(response.actions.alerts.length <= 4); 74 | } 75 | } 76 | }, 77 | 78 | 'Reference --' : { 79 | 'getReference' : { 80 | topic: api.call('getReference'), 81 | 'returns region data': assertValidResponseCollection('regions', false, 0), 82 | 'returns timezone data': assertValidResponseCollection('timezones', false, 0), 83 | 'returns datetime formats': assertValidResponseCollection('datetimeformats', false, 0), 84 | 'returns number formats': assertValidResponseCollection('numberformats', false, 0) 85 | } 86 | }, 87 | 88 | 'Probes --' : { 89 | 'getProbes' : { 90 | topic: api.call('getProbes', {'limit' : 10, 'onlyactive' : true}), 91 | 'returns probe server list': assertValidResponseCollection('probes', true, 10), 92 | 'which contains valid entries': function(err, response) { 93 | assert.notEqual(undefined, response.probes[9]); 94 | assert.equal(true, response.probes[9].active); 95 | } 96 | } 97 | }, 98 | 99 | 'Instant Tests --' : { 100 | 'makeOneShotTest HTTP' : { 101 | topic: api.call('makeOneShotTest', { 'host' : 'www.google.com', 'type' : 'http' }), 102 | 'returns valid data' : function(err, response) { 103 | assert.notEqual(undefined, response.result); 104 | assert.notEqual(undefined, response.result.status); 105 | assert.notEqual(undefined, response.result.probeid); 106 | assert.notEqual(undefined, response.result.probedesc); 107 | } 108 | }, 109 | 110 | 'makeOneShotTraceroute' : { 111 | topic: api.call('makeOneShotTraceroute', { 'host' : 'www.google.com' }), 112 | 'returns valid data' : function(err, response) { 113 | assert.notEqual(undefined, response.traceroute); 114 | assert.notEqual(undefined, response.traceroute.result); 115 | assert.notEqual(undefined, response.traceroute.probeid); 116 | assert.notEqual(undefined, response.traceroute.probedescription); 117 | } 118 | } 119 | }, 120 | 121 | 'Checks --' : { 122 | 123 | 'getChecks' : { 124 | topic: api.call('getChecks', {'limit' : 10}), 125 | 'returns a valid response' : assertValidResponseCollection('checks', false, undefined), 126 | 127 | '-> getCheckDetails' : { 128 | topic: function(err, getChecksResponse) { 129 | var parent = this; 130 | pingdom.getCheckDetails(creds.username, creds.password, creds.app_key, getChecksResponse.checks[0].id, function(err, response) { 131 | parent.callback(err, getChecksResponse, response); 132 | }); 133 | }, 134 | 135 | 'returns a valid response' : function(err, getChecksResponse, response) { 136 | assert.equal(getChecksResponse.checks[0].id, response['check']['id']); 137 | } 138 | } 139 | /** 140 | }, 141 | 142 | 'createCheck' : { 143 | topic: api.call('createCheck', {'name' : 'new_test', 'host' : 'www.google.com', 'type' : 'http', 'url' : '/'}), 144 | 'returns a valid response' : function(err, response) { 145 | assert.equal(null, err); 146 | assert.notEqual(undefined, response.check); 147 | assert.notEqual(undefined, response.check.id); 148 | assert.notEqual(0, response.check.id); 149 | }, 150 | 151 | '-> modifyCheck' : { 152 | 153 | topic: function(err, createCheck) { 154 | pingdom.modifyCheck(creds.username, creds.password, creds.app_key, createCheck.check.id, { 'name' : 'newer_check' }, this.callback); 155 | }, 156 | 157 | 'returns a valid response' : function(err, response) { 158 | assert.notEqual(undefined, response.message); 159 | assert.equal("Modification of check was successful!", response.message); 160 | }, 161 | 162 | '-> deleteCheck' : { 163 | 164 | topic: function(err1, modifyCheck, err2, createCheck) { 165 | pingdom.deleteCheck(creds.username, creds.password, creds.app_key, createCheck.check.id, this.callback); 166 | }, 167 | 168 | 'returns a valid response' : function(err, response) { 169 | assert.notEqual(undefined, response.message); 170 | assert.equal("Deletion of check was successful!", response.message); 171 | } 172 | } 173 | } 174 | **/ 175 | } 176 | } 177 | }).export(module, {error: false}); 178 | 179 | 180 | 181 | 182 | 183 | -------------------------------------------------------------------------------- /test/vows_log4js.json: -------------------------------------------------------------------------------- 1 | { 2 | "appenders": [{ 3 | "type": "logLevelFilter", 4 | "level": "trace", 5 | "appender": { 6 | "type": "file", 7 | "filename": "vows.log", 8 | "maxLogSize": 10485760, 9 | "backups": 10, 10 | "pollInterval": 15 11 | } 12 | }] 13 | } 14 | --------------------------------------------------------------------------------