function main()

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));
    });
  }
}