7

I use the following lib to connect to the cloud controller

https://github.com/prosociallearnEU/cf-nodejs-client

const endpoint = "https://api.mycompany.com/";
const username = "myuser";
const password = "mypass";

const CloudController = new (require("cf-client")).CloudController(endpoint);
const UsersUAA = new (require("cf-client")).UsersUAA;
const Apps = new (require("cf-client")).Apps(endpoint);

CloudController.getInfo().then((result) => {
    UsersUAA.setEndPoint(result.authorization_endpoint);
    return UsersUAA.login(username, password);
}).then((result) => {
    Apps.setToken(result);
    return Apps.getApps();
}).then((result) => {
    console.log(result);
}).catch((reason) => {
    console.error("Error: " + reason);
});
  1. I try to run it against our API and its not working and Im not getting no error message in the console, what it can be ?

  2. where does the space/org is handled here ? since when I connect from the cli it ask me to which space/org I want to connect...

Im able to login via the CLI, just from the code I cant, any idea what is missing here?

The issue it when I run it I dont get any error that can help to understand what is the root cause

Chris Snow
  • 23,813
  • 35
  • 144
  • 309
John Jerrby
  • 1,683
  • 7
  • 31
  • 68
  • what is the endpoint you are using? I just tried your code with https://api.ng.bluemix.net (Bluemix endpoint) and it worked fine. – Alex da Silva Jan 09 '17 at 23:01
  • @AlexdaSilva - The API is my company API but before im able to connect in the CLI i use proxy ...like https_proxy=mycompany.corp:8080 , i think that this lib is not supporting this... – John Jerrby Jan 10 '17 at 13:35
  • The API does not support proxy. I looked at the code and it uses request module, but no option to set the proxy. You would have to add proxy support or open an issue in github asking for it. – Alex da Silva Jan 10 '17 at 21:10

2 Answers2

4

I cloned the original git repository and modified some methods to support proxy. Please note that I modified just some methods to get the sample code working, but a complete refactor of the package is needed.

Basically what you have to do is to add a proxy parameter before calling the request method (this is done throughout the package, so several modifications are needed), for example this is for one of the methods in the Organization.js file:

getSummary (guid) {

        const url = `${this.API_URL}/v2/organizations/${guid}/summary`;
        const proxy = `${this.API_PROXY}`;
        const options = {
            method: "GET",
            url: url,
            proxy: proxy,
            headers: {
                Authorization: `${this.UAA_TOKEN.token_type} ${this.UAA_TOKEN.access_token}`
            }
        };

        return this.REST.request(options, this.HttpStatus.OK, true);
    }

You can find my changes in the git repository below:

https://github.com/adasilva70/cf-nodejs-client.git

I have also created a new sample below. This sample lists all organizations for a user, gets the first organization returned and lists its spaces. You can modify the code to provide a similar functionality that cf login provides (allow you to select an organization then a space).

const endpoint = "https://api.mycompany.com/";
const username = "youruser";
const password = "yourpassword";
const proxy = "http://proxy.mycompany.com:8080";

const CloudController = new (require("cf-nodejs-client")).CloudController(endpoint, proxy);
const UsersUAA = new (require("cf-nodejs-client")).UsersUAA;
const Apps = new (require("cf-nodejs-client")).Apps(endpoint, proxy);
const Orgs = new (require("cf-nodejs-client")).Organizations(endpoint, proxy);

CloudController.getInfo().then((result) => {
    console.log(result);
    UsersUAA.setEndPoint(result.authorization_endpoint, proxy);
    return UsersUAA.login(username, password);
}).then((result) => {
    //Apps.setToken(result);
    //return Apps.getApps();
    Orgs.setToken(result);
    return Orgs.getOrganizations();
}).then((result) => {
    console.log(result);
    org_guid = result.resources[1].metadata.guid;
    return Orgs.getSummary(org_guid);
}).then((result) => {
    console.log(result);
}).catch((reason) => {
    console.error("Error: " + reason);
});

I have done just minor tests to make sure the sample works, so use carefully. Also, the changes will only work for a case where proxy is needed now.

Alex da Silva
  • 4,552
  • 2
  • 17
  • 25
  • Hi Alex thanks I provided the bounty :) my question is if there is cleaner way to do it ? instead override all the needed files (org apps space etc) constructors with the proxy ? – John Jerrby Jan 15 '17 at 09:30
  • Unfortunately I don't know of another way to do that. Ideally the request should be contained in the CloudControllerBase class, but since each method to each class explicit calls request with its own `options` variable I don't know another way to do that. – Alex da Silva Jan 16 '17 at 18:42
2

The first thing that strikes me on the library's github site is the warning:

Note: This package is not ready for a production App yet.

It also seems that the project is not being maintained as there are a number of tickets ooened that are quite a few months old that don't have a response.

Anyway, to figure out why the library is not working and producing no error message, I would check out the library source code and add some console logging statements, probably starting with the HttpUtils. For example:

requestWithDefaults(options, function (error, response, body) {
    console.log("requestWithDefaults error: ", error)
    console.log("requestWithDefaults response: ", response)
    console.log("requestWithDefaults body: ", body)
    ...
}

Alternatively, you could try debugging the code by adding breakpoints to the requestWithDefaults and other key places in the library, using the nodejs debugger.

You could also try debugging the network calls similar to this how to monitor the network on node.js similar to chrome/firefox developer tools?

To understand how to use the library, I would take a look into the tests folder and look for a test that is similar to your use case. There are a reasonable amount if tests that look useful in the test/lib/model/cloudcontroller folder.

As for the question about spaces, I have found an example where you can pass in a space guid to return apps for that space guid.

CloudFoundrySpaces.getSpaceApps(space_guid, filter).then( ... )

I'm assuming the call you are using App.getApps() will return Apps for all spaces/organizations.

Community
  • 1
  • 1
Chris Snow
  • 23,813
  • 35
  • 144
  • 309
  • Hi Chris Thanks!, I've tested it also with https://github.com/IBM-Bluemix/cf-nodejs-client and it doesnt work..., I put a BP & and the console logs in requestWithDefaults as you mentioned and it doesnt stops or print logs, any idea why? does this works for you ? – John Jerrby Jan 10 '17 at 08:38
  • after a while I got this error requestWithDefaults error: { Error: connect ETIMEDOUT 35.156.96.41:443 at Object.exports._errnoException (util.js:1022:11) at exports._exceptionWithHostPort (util.js:1045:20) at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1087:14) – John Jerrby Jan 10 '17 at 08:40
  • one thing that I do in the command line when I login I enter the proxy of my company like export https_proxy=http://mycompany.corp:8080 , should I put it also in the code , if so how ?Thanks! – John Jerrby Jan 10 '17 at 08:41
  • It looks like the restler and request libraries are used for http calls. See here for a possible workaround for restler https://github.com/danwrong/restler/issues/9 and here for the proxy option for request https://github.com/request/request#requestoptions-callback. You may have to change the cf-nodejs-client source to implement proxy support. – Chris Snow Jan 10 '17 at 12:12