in core/routemgmt/createApi/createApi.js [58:236]
function main(message) {
//console.log('message: '+JSON.stringify(message)); // ONLY FOR TEMPORARY/LOCAL DEBUG; DON'T ENABLE PERMANENTLY
var badArgMsg = validateArgs(message);
if (badArgMsg) {
return Promise.reject(utils2.makeErrorResponseObject(badArgMsg, (message.__ow_method !== undefined)));
}
var gwInfo = {
gwUrl: message.gwUrl,
};
// Replace the CLI provided namespace values with the controller provided namespace value
// If __ow_user is not set, the namespace values are left alone
if (message.accesstoken) {
utils2.updateNamespace(message.apidoc, message.__ow_user);
} else {
utils.updateNamespace(message.apidoc, message.__ow_user);
}
// Set the User-Agent header value
if (message.__ow_headers && message.__ow_headers['user-agent']) {
utils2.setSubUserAgent(message.__ow_headers['user-agent']);
}
// message.apidoc already validated; creating shortcut to it
var doc;
if (typeof message.apidoc === 'object') {
doc = message.apidoc;
} else if (typeof message.apidoc === 'string') {
doc = JSON.parse(message.apidoc);
}
// message.swagger already validated; creating object
var swaggerObj;
if (typeof doc.swagger === 'object') {
swaggerObj = doc.swagger;
} else if (typeof doc.swagger === 'string') {
swaggerObj = JSON.parse(doc.swagger);
}
doc.swagger = swaggerObj;
var basepath = getBasePath(doc);
var tenantInstance = message.tenantInstance || 'openwhisk';
// This can be invoked as either a standard web action or as a normal action
var calledAsWebAction = message.__ow_method !== undefined;
// Log parameter values
console.log('GW URL : '+message.gwUrl);
console.log('GW URL V2 : '+message.gwUrlV2);
console.log('GW Auth : '+utils.confidentialPrint(message.gwPwd));
console.log('__ow_user : '+message.__ow_user);
console.log('namespace : '+doc.namespace);
console.log('tenantInstance: '+message.tenantInstance+' / '+tenantInstance);
console.log('accesstoken : '+message.accesstoken);
console.log('spaceguid : '+message.spaceguid);
console.log('responsetype : '+message.responsetype);
console.log('API name : '+doc.apiName);
console.log('basepath : '+basepath);
console.log('relpath : '+doc.gatewayPath);
console.log('GW method : '+doc.gatewayMethod);
if (doc.action) {
console.log('action name: '+doc.action.name);
console.log('action namespace: '+doc.action.namespace);
console.log('action backendUrl: '+doc.action.backendUrl);
console.log('action backendMethod: '+doc.action.backendMethod);
console.log('action authkey: '+utils.confidentialPrint(doc.action.authkey));
console.log('action secureKey: '+utils.confidentialPrint(doc.action.secureKey));
}
console.log('calledAsWebAction: '+calledAsWebAction);
console.log('apidoc :\n'+JSON.stringify(doc));
// If an API GW access token is provided, use the API GW V2 URL and use this token to auth with the API GW
// Otherwise, use the API GW "V1" URL and use the supplied GW auth credentials to auth with the API GW
if (message.accesstoken) {
var apiDocId;
gwInfo.gwUrl = message.gwUrlV2;
gwInfo.gwAuth = message.accesstoken;
// 1. If an existing API exists for this namespace/basepath combination, retrieve it and update it
// 2. If not, create a new API
return utils2.getApis(gwInfo, message.spaceguid, basepath)
.then(function(endpointDocs) {
console.log('Got '+endpointDocs.length+' APIs');
if (endpointDocs.length === 0) {
console.log('No API found for namespace '+doc.namespace + ' with basePath '+ basepath);
return Promise.resolve(utils2.generateBaseSwaggerApi(basepath, doc.apiName));
} else {
apiDocId = endpointDocs[0].artifact_id;
return Promise.resolve(endpointDocs[0].open_api_doc);
}
})
.then(function(endpointDoc) {
if (doc.swagger) {
console.log('Use provided swagger as the entire API; override any existing API');
return Promise.resolve(doc.swagger);
} else {
console.log('Add the provided API endpoint');
return Promise.resolve(utils2.addEndpointToSwaggerApi(endpointDoc, doc, message.responsetype));
}
})
.then(function(apiSwagger){
console.log("Validating Swagger doc before sending it to API GW.")
return utils2.validateFinalSwagger(apiSwagger);
})
.then(function(apiSwagger) {
console.log('Final swagger API config: '+ JSON.stringify(apiSwagger));
return utils2.addApiToGateway(gwInfo, message.spaceguid, apiSwagger, apiDocId);
})
.then(function(gwApi) {
console.log('API GW configured with API');
var cliApi = utils2.generateCliApiFromGwApi(gwApi).value;
console.log('createApi success');
return Promise.resolve(utils2.makeResponseObject(cliApi, calledAsWebAction));
})
.catch(function(reason) {
var rejmsg = 'API creation failure: ' + JSON.parse(utils2.makeJsonString(reason)); // Avoid unnecessary JSON escapes
console.error(rejmsg);
return Promise.reject(utils2.makeErrorResponseObject(rejmsg, calledAsWebAction));
});
} else {
// Create and activate a new API path
// 1. Create tenant id this namespace. If id exists, create is a noop
// 2. Obtain any existing configuration for the target API. If none, this is a new API
// 3. Create the API document to send to the API GW. If API exists, update it
// 4. Configure API GW with the new/updated API
var tenantId;
var gwApiId;
if (message.gwUser && message.gwPwd) {
gwInfo.gwAuth = Buffer.from(message.gwUser+':'+message.gwPwd,'ascii').toString('base64');
}
return utils.createTenant(gwInfo, doc.namespace, tenantInstance)
.then(function(tenant) {
console.log('Got the API GW tenant: '+JSON.stringify(tenant));
tenantId = tenant.id;
return Promise.resolve(utils.getApis(gwInfo, tenant.id, basepath));
})
.then(function(apis) {
console.log('Got '+apis.length+' APIs');
if (apis.length === 0) {
console.log('No APIs found for namespace '+doc.namespace+' with basepath '+basepath);
return Promise.resolve(utils.generateBaseSwaggerApi(basepath, doc.apiName));
} else if (apis.length > 1) {
console.error('Multiple APIs found for namespace '+doc.namespace+' with basepath '+basepath);
return Promise.reject('Internal error. Multiple APIs found for namespace '+doc.namespace+' with basepath '+basepath);
}
gwApiId = apis[0].id;
return Promise.resolve(utils.generateSwaggerApiFromGwApi(apis[0]));
})
.then(function(swaggerApi) {
if (doc.swagger) {
console.log('Use provided swagger as the entire API; override any existing API');
return Promise.resolve(doc.swagger);
} else {
console.log('Add the provided API endpoint');
return Promise.resolve(utils.addEndpointToSwaggerApi(swaggerApi, doc));
}
})
.then(function(apiSwagger){
console.log("Validating Swagger doc before sending it to API GW.")
return utils2.validateFinalSwagger(apiSwagger);
})
.then(function(swaggerApi) {
console.log('Final swagger API config: '+ JSON.stringify(swaggerApi));
return utils.addApiToGateway(gwInfo, tenantId, swaggerApi, gwApiId);
})
.then(function(gwApi) {
console.log('API GW configured with API');
var cliApi = utils.generateCliApiFromGwApi(gwApi).value;
console.log('createApi success');
return Promise.resolve(utils2.makeResponseObject(cliApi, calledAsWebAction));
})
.catch(function(reason) {
var rejmsg = 'API creation failure: ' + JSON.parse(utils2.makeJsonString(reason)); // Avoid unnecessary JSON escapes
console.error(rejmsg);
return Promise.reject(utils2.makeErrorResponseObject(rejmsg, calledAsWebAction));
});
}
}