Skip to content

Commit

Permalink
Allowed more flexible config.
Browse files Browse the repository at this point in the history
  • Loading branch information
serban-petrescu committed Apr 2, 2018
1 parent 7380566 commit f2fd645
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 28 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "sapim",
"version": "0.0.6",
"version": "0.0.7",
"description": "SAP API Manager Tools",
"main": "dst/index.js",
"files": [
Expand Down Expand Up @@ -40,6 +40,7 @@
"base64-stream": "^0.1.3",
"caw": "^2.0.1",
"commander": "^2.13.0",
"dotenv": "^5.0.1",
"fs-extra": "^5.0.0",
"glob": "^7.1.2",
"glob-promise": "^3.3.0",
Expand Down
3 changes: 2 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ maps:
To use the commands that imply communicating with the API Manager, you need to provide a user, password and host for the library to use. You have two options for specifying them:
- Using the environment variables `SAPIM_USERNAME`, `SAPIM_PASSWORD` and `SAPIM_HOST`.
- Using a [.env](https://github.com/motdotla/dotenv) file for loading the environment variables mentioned above.
- Using a [.sapim](https://github.com/serban-petrescu/sapim/wiki/Configuration#using-a-sapim-file) file.

For more details, check out the [configuration](https://github.com/serban-petrescu/sapim/wiki/Configuration) wiki page.
Expand All @@ -65,7 +66,7 @@ The following commands are available:
- [get virtual host info](https://github.com/serban-petrescu/sapim/wiki/Command-Line-Interface#get-virtual-host-info)

### Programmatic usage
All the above commands have a corresponding method exposed as part of the library's public API. You can read more about using it [in the corresponding wiki page](https://github.com/serban-petrescu/sapim/wiki/Programmatic-Usage) and you can find the reference documentation [on GitHub Pages](https://serban-petrescu.github.io/sapim/sapim/0.0.6/).
All the above commands have a corresponding method exposed as part of the library's public API. You can read more about using it [in the corresponding wiki page](https://github.com/serban-petrescu/sapim/wiki/Programmatic-Usage) and you can find the reference documentation [on GitHub Pages](https://serban-petrescu.github.io/sapim/sapim/0.0.7/).

Example usage:
```js
Expand Down
6 changes: 6 additions & 0 deletions src/ApiClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ export default class ApiClient {
auth: {
username: config.username,
password: config.password
},
callback: function(error, response) {
if (!error) {
logger.debug("Got response status " + response.statusCode + " " + response.statusMessage +
" from: '" + response.request.uri.path + "'.");
}
}
});
this.client = base.head({ uri: "/Management.svc", headers: { [CSRF_HEADER]: "fetch" } })
Expand Down
53 changes: 34 additions & 19 deletions src/cli.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#!/usr/bin/env node

import sapim, { createConfigFile } from "./index";
import sapim, { createConfigFile, loadConfigFile } from "./index";
import program from "commander";
import prompt from "prompt";
import { version, name, description } from "../package.json";
import dotenv from "dotenv";

import logger, { LOG_LEVEL } from "./logger";

Expand Down Expand Up @@ -37,91 +38,105 @@ function extractPlaceholders(ph) {
return placeholders;
}

function build() {
if (program.config) {
return sapim(loadConfigFile(program.config));
} else if (program.env) {
dotenv.config({ path: program.env });
return sapim();
} else {
dotenv.config();
return sapim();
}
}

program.name(name)
.version(version, "-v, --version")
.description(description)
.option("-s, --silent", "suppress console output")
.option("-e, --env <path>", "load environment variables from the given file")
.option("-c, --config <path>", "load the given configuration file")
.option("-d, --debug", "show debug messages");

program.command("apply-template <source_directory> <target_directory> [placeholders...]")
.description("applies a template by replacing the given placeholders")
.option("-c, --clean", "clean the target directory first")
.action(wrapAction((source, target, ph, options) =>
sapim().applyTemplate(source, target, extractPlaceholders(ph), options.clean)));
build().applyTemplate(source, target, extractPlaceholders(ph), options.clean)));

program.command("deploy <manifest>")
.description("deploy API manager artifacts described by the given manifest")
.action(wrapAction(manifest => sapim().deployManifest(manifest)));
.action(wrapAction(manifest => build().deployManifest(manifest)));

program.command("deploy-all <pattern>")
.description("deploy all the manifests matching the given glob pattern")
.option("-f, --force", "continues execution even if one manifest deployment fails")
.action(wrapAction((pattern, options) => sapim().deployManifestsMatching(pattern, options.force)));
.action(wrapAction((pattern, options) => build().deployManifestsMatching(pattern, options.force)));

program.command("deploy-proxy <directory> [placeholders...]")
.description("deploy the API proxy located in the given directory")
.action(wrapAction((path, ph) => ph.length > 0 ?
sapim().deployProxy(path, true, extractPlaceholders(ph)) : sapim().deployProxy(path)));
build().deployProxy(path, true, extractPlaceholders(ph)) : build().deployProxy(path)));

program.command("download-proxy <proxy_name> <target_directory>")
.description("download an already existing API proxy from the API Portal")
.option("-c, --clean", "clean the target directory first")
.action(wrapAction((name, target, options) => sapim().downloadProxy(name, target, options.clean)));
.action(wrapAction((name, target, options) => build().downloadProxy(name, target, options.clean)));

program.command("extract-template-proxy <source> <target> [placeholders...]")
.description("extract a template from an existing API proxy")
.option("-c, --clean", "clean the target directory first")
.action(wrapAction((source, target, ph, options) =>
sapim().extractTemplate(source, target, extractPlaceholders(ph), options.clean)));
build().extractTemplate(source, target, extractPlaceholders(ph), options.clean)));

program.command("extract-template <manifest> [target_directory]")
.description("extract a template from an already deployed proxy (described by the given manifest)")
.option("-c, --clean", "clean the target directory first")
.action(wrapAction((manifest, target, options) =>
sapim().extractTemplateFromManifest(manifest, target, options.clean)));
build().extractTemplateFromManifest(manifest, target, options.clean)));

program.command("get-proxy-url <name>")
.description("retrieves the base URL for the given proxy")
.action(wrapAction(name => sapim().getProxyUrl(name).then(s => console.log(s))));
.action(wrapAction(name => build().getProxyUrl(name).then(s => console.log(s))));

program.command("get-manifest-url <path>")
.description("retrieves the base URL for the proxy described by the given manifest")
.action(wrapAction(path => sapim().getManifestUrl(path).then(s => console.log(s))));
.action(wrapAction(path => build().getManifestUrl(path).then(s => console.log(s))));

program.command("get-vhost-info")
.description("retrieves the information pertaining virtual host(s); without any options, retrieves the default vhost")
.option("-i, --id <id>", "uses the given id to select the vhost")
.option("-a, --all", "retrieves all the virtual host available")
.option("-a, --all", "retrieves all the virtual hosts available")
.action(wrapAction(command => {
let result;
if (command.id) {
result = sapim().getVirtualHostInfoById(command.id);
result = build().getVirtualHostInfoById(command.id);
} else if (command.all) {
result = sapim().getAllVirtualHostInfo();
result = build().getAllVirtualHostInfo();
} else {
result = sapim().getDefaultVirtualHostInfo();
result = build().getDefaultVirtualHostInfo();
}
return result.then(info => console.log(JSON.stringify(info, null, 4)));
}));

program.command("package <manifest> [target_archive]")
.description("package the API proxy described by the given manifest into an archive")
.action(wrapAction((path, target) => sapim().packageManifest(path, target)));
.action(wrapAction((path, target) => build().packageManifest(path, target)));

program.command("package-all <pattern>")
.description("package all the API proxies described by the manifests matched by the given pattern")
.option("-f, --force", "continues execution even if one operation fails")
.action(wrapAction((path, options) => sapim().packageManifestsMatching(path, options.force)));
.action(wrapAction((path, options) => build().packageManifestsMatching(path, options.force)));

program.command("package-proxy <directory> <target_archive> [placeholders...]")
.description("package the proxy located in the given directory")
.action(wrapAction((path, target, ph) => ph.length > 0 ?
sapim().packageProxyToFile(path, target, true, extractPlaceholders(ph)) :
sapim().packageProxyToFile(path, target)));
build().packageProxyToFile(path, target, true, extractPlaceholders(ph)) :
build().packageProxyToFile(path, target)));

program.command("upload-proxy <archive>")
.description("upload an API proxy as an archive to the API Portal")
.action(wrapAction(path => sapim().uploadProxy(path)));
.action(wrapAction(path => build().uploadProxy(path)));

program.command("config")
.description("configure the sapim library (create a .sapim file)")
Expand Down
30 changes: 23 additions & 7 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,18 @@ import logger from "./logger";

tmp.setGracefulCleanup();

function loadConfig(path) {
/**
* Utility function for loading a configuration file.
* @param {string} path The path to the config file.
* @returns {Configuration} The resulting configuration or null if not found.
*/
export function loadConfigFile(path) {
try {
if (existsSync(path)) {
logger.debug("Loading configuration file: " + path);
return JSON.parse(readFileSync(path, "utf8"));
} else {
logger.debug("No configuration file found at: " + path + ". Skipping.");
return null;
}
} catch (e) {
Expand All @@ -26,15 +33,25 @@ function loadConfig(path) {
}
}

function getProperty(field, envVar, config) {
if (process.env[envVar]) {
logger.debug("Using " + field + " from the environment.");
return process.env[envVar];
} else {
logger.debug("Using " + field + " from the configuration.");
return config[field];
}
}

let defaultConfigCache = null;
function defaultConfig() {
if (!defaultConfigCache) {
let fileConfig = loadConfig(resolve(".sapim")) || loadConfig(join(homedir(), ".sapim")) || {};
let fileConfig = loadConfigFile(resolve(".sapim")) || loadConfigFile(join(homedir(), ".sapim")) || {};
defaultConfigCache = {
username: process.env.SAPIM_USERNAME || fileConfig.username,
password: process.env.SAPIM_PASSWORD || fileConfig.password,
host: process.env.SAPIM_HOST || fileConfig.host,
proxy: process.env.HTTPS_PROXY || fileConfig.proxy
username: getProperty("username", "SAPIM_USERNAME", fileConfig),
password: getProperty("password", "SAPIM_PASSWORD", fileConfig),
host: getProperty("host", "SAPIM_HOST", fileConfig),
proxy: getProperty("proxy", "HTTPS_PROXY", fileConfig)
};
}
return defaultConfigCache;
Expand Down Expand Up @@ -67,6 +84,5 @@ export default function(config = defaultConfig()) {

export {
ApiManager,

logger
};

0 comments on commit f2fd645

Please sign in to comment.