Question

Generating Clients/SDKs Using Swagger Codegen

  • 18 November 2015
  • 44 replies
  • 1236 views

  • Anonymous
  • 0 replies

The Looker API v3.0 has a custom authentication scheme which requires a SHA-1 hash of the query parameters. Does the generated code know how to do this or I need to modify the generated code.


44 replies

OK. I’m using API 3.0 and creating a .NET SDK. I thought I could gen it from Swagger Code Gen. That looks like it will work. I’ll test it out.


Thanks

So that means that I don’t have to worry about adding the SHA-1 signature and nonce, etc to the HTTP request, right?

Thanks for the help. Swagger Gen does support C# and .NET. I’ve generated the classes. I’ll test them this weekend and update this discussion on my progress.


Thanks for your help.


Sonny

Can I get a sample of a valid HTTP request for a request (not Login). I’ll need the HTTP headers, Body, and Parameters. A simple example would be Logout and GetUser.


I have login in working. I suspect that is because it only requires ClientId and Secret. However, on subsequent calls like logout or get user I will get HTTP 401 - Requires Authentication. I suspect I’m NOT sending the HTTP headers over properly (Authorization, etc)


Thanks,

I found what I was looking for at Ruby SDK Authentication Implementation. As the Looker documentation is out of date, this serves to resolve my issues.

I was able to get the Swagger Codegen to generate the C# .Net implementation of the client. It’s important to note that I had to add the authorization token to the Authorization header parameter. And add it to the default header (see below).


`    class Program
{
static void Main(string[] args)
{
string clientId = "client id";
string clientSecret = "secret";

IO.Swagger.Api.ApiAuthApi authApi = new IO.Swagger.Api.ApiAuthApi();
AccessToken token = authApi.Login( clientId, clientSecret);

// set the default authorization header to 'token <your token>'
// this will add as a default header and be sent on all API calls
ApiClient client = authApi.ApiClient;
client.AddDefaultHeader("Authorization", "token " + token.Token);

UserApi userApi = new UserApi(client);
User meUser = userApi.Me("first_name,last_name, email");

string output = authApi.Logout();
}
}
`

Not being familiar with using OAuth 2.0 and curl, the setup steps to get swagger.json took a bit of figuring out.

In case anyone else is experiencing similar difficulties:



  1. Get the access token:

    curl -X POST -d ‘client_id=Pxg…&client_secret=sdfo…’ https://mycompany.looker.com:19999/login

    -> returns {“access_token”:“bhg5…”,“token_type”:“Bearer”,“expires_in”:3600}

  2. Use the access token to get the resource of interest

    curl -H ‘Authorization: Bearer bhg5…https://mycompany.looker.com:19999/api/3.0/swagger.json

    -> returns swagger.json


(Possibly optional Step 0: some fiddling with ca-cert location on Ubuntu to get curl https working:

sudo ln -s /etc/ssl/certs/ca-certificates.crt /etc/pki/tls/certs/ca-bundle.crt

but that could be machine-specific)

Thanks for the excellent article! I was able to generate and install the python client library using your directions. I modified your sample code to call looks.all_looks(), but it returns a 404 error. The user who’s API 3 client id/secret I’m using has Admin role. See below for the stack trace.


Not sure if I need to supply some parameter to the call or what, any help would be appreciated.


Traceback (most recent call last):

File “simpleTest.py”, line 25, in

lookList = looks.all_looks()

File “/Users/scottdavidson/looker_python_client/swagger_client/apis/look_api.py”, line 121, in all_looks

callback=params.get(‘callback’))

File “/Users/scottdavidson/looker_python_client/swagger_client/api_client.py”, line 322, in call_api

response_type, auth_settings, callback)

File “/Users/scottdavidson/looker_python_client/swagger_client/api_client.py”, line 149, in __call_api

post_params=post_params, body=body)

File “/Users/scottdavidson/looker_python_client/swagger_client/api_client.py”, line 342, in request

headers=headers)

File “/Users/scottdavidson/looker_python_client/swagger_client/rest.py”, line 184, in GET

query_params=query_params)

File “/Users/scottdavidson/looker_python_client/swagger_client/rest.py”, line 177, in request

raise ApiException(http_resp=r)

swagger_client.rest.ApiException: (404)

Reason: Not Found

HTTP response headers: HTTPHeaderDict({‘Vary’: ‘Accept-Encoding’, ‘Content-Type’: ‘application/json;charset=utf-8’, ‘Content-Length’: ‘69’, ‘X-Cascade’: ‘pass’, ‘X-Content-Type-Options’: ‘nosniff’})

HTTP response body: {“message”:“Not found”,“documentation_url”:“http://docs.looker.com/”}

Didn’t try other looks methods…need a look ID for the other and all_looks() appeared to be the most basic. Any others you suggest I try?


When I change the port in the python script from 19999 to 9999 the call to login fails with a 403 error. Not sure what you mean by “put that port in your api endpoint”.


From what I’ve gathered from your article API communication is over 19999, but typical Looker traffic is over 9999. Or am I misunderstanding?

login can’t even connect when I drop the port:


2016-02-23 12:59:28,969 WARNING Retrying (Retry(total=2, connect=None, read=None, redirect=None)) after connection broken by ‘NewConnectionError(’<urllib3.connection.VerifiedHTTPSConnection object at 0x10b38ed50>: Failed to establish a new connection: [Errno 61] Connection refused’,)’: /login?client_secret=hidden&client_id=hidden


Did I miss some configuration step?

Fixed it by appending /api/3.0 to base_url e.g. base_url = https://looker.customer.com:19999/api/3.0.


Sorry for any confusion I may have created.

So excited to start working with the API.


I followed these instructions and got the python client to work. My question is that no matter which format i pass to run_look, I always get the same format back.


I had


myresult = looks.run_look(1012,'json')
print myresult

and i get


[{u'user.id': u'71'}, {u'user.id': u'88'}, {u'user.id': u'89'}, {u'user.id': u'92'}, {u'user.id': u'97'}, {u'user.id': u'102'}, {u'user.id': u'108'}, {u'user.id': u'109'}, {u'user.id': u'114'}, {u'user.id': u'119'}, {u'user.id': u'121'}, {u'user.id': u'126'}, {u'user.id': u'133'}, {u'user.id': u'151'}, {u'user.id': u'152'}, {u'user.id': u'169'}]


and if i change the format to csv, or sql or whatever, I still get that same result.


It looks like json, but when I try to call json.loads(myresult) it errors causing me to believe its not json.


Any thoughts?


Thanks

Thanks sdhoover

Hi,


I’m running into the same issue as Scott had above, but appending /api/3.0 to my base_url didn’t work and I’m still getting the 404 errors. Any ideas?


Thanks!


-Grayson

Grayson-Williamss-Macbook-Pro:rsdw.old grayson$ python looker_test.py

Traceback (most recent call last):

File “looker_test.py”, line 17, in

token = unauthenticated_authApi.login(client_id=client_id, client_secret=client_secret)

File “build/bdist.macosx-10.11-intel/egg/swagger_client/apis/api_auth_api.py”, line 122, in login

File “build/bdist.macosx-10.11-intel/egg/swagger_client/api_client.py”, line 322, in call_api

File “build/bdist.macosx-10.11-intel/egg/swagger_client/api_client.py”, line 149, in __call_api

File “build/bdist.macosx-10.11-intel/egg/swagger_client/api_client.py”, line 358, in request

File “build/bdist.macosx-10.11-intel/egg/swagger_client/rest.py”, line 208, in POST

File “build/bdist.macosx-10.11-intel/egg/swagger_client/rest.py”, line 177, in request

swagger_client.rest.ApiException: (404)

Reason: Not Found

HTTP response headers: HTTPHeaderDict({‘Content-Type’: ‘application/json;charset=utf-8’, ‘Content-Length’: ‘69’, ‘Vary’: ‘Accept-Encoding’, ‘X-Content-Type-Options’: ‘nosniff’})

HTTP response body: {“message”:“Not found”,“documentation_url”:“http://docs.looker.com/”}


Grayson-Williamss-Macbook-Pro:rsdw.old grayson$

Here you go. I am using the API keys from my user page in Admin.


preliminaries


import swagger_client as looker

import os


dir(looker) # to see available methods

base_url = “https://looker.mycompany.com:19999

#base_url = “https://looker.mycompany.com:19999/api/3.0

client_id = os.environ.get(‘LOOKER3_KEY’)

client_secret = os.environ.get(‘LOOKER3_SECRET’)


instantiate Auth API


unauthenticated_client = looker.ApiClient(base_url)

unauthenticated_authApi = looker.ApiAuthApi(unauthenticated_client)


authenticate client


token = unauthenticated_authApi.login(client_id=client_id, client_secret=client_secret)

client = looker.ApiClient(base_url, ‘Authorization’, 'token ’ + token.access_token)


instantiate Look API


looks = looker.LookApi(client)

I tried hardcoding them and that got me farther, but now when I try to run a look I get:


Grayson-Williamss-Macbook-Pro:rsdw.old grayson$ python looker_test.py 
Traceback (most recent call last):
File "looker_test.py", line 23, in <module>
my_1235 = looks.run_look(1235, 'json')
File "build/bdist.macosx-10.11-intel/egg/swagger_client/apis/look_api.py", line 439, in run_look
File "build/bdist.macosx-10.11-intel/egg/swagger_client/api_client.py", line 322, in call_api
File "build/bdist.macosx-10.11-intel/egg/swagger_client/api_client.py", line 149, in __call_api
File "build/bdist.macosx-10.11-intel/egg/swagger_client/api_client.py", line 342, in request
File "build/bdist.macosx-10.11-intel/egg/swagger_client/rest.py", line 184, in GET
File "build/bdist.macosx-10.11-intel/egg/swagger_client/rest.py", line 177, in request
swagger_client.rest.ApiException: (404)
Reason: Not Found
HTTP response headers: HTTPHeaderDict({'Vary': 'Accept-Encoding', 'Content-Type': 'application/json;charset=utf-8', 'Content-Length': '69', 'X-Cascade': 'pass', 'X-Content-Type-Options': 'nosniff'})
HTTP response body: {"message":"Not found","documentation_url":"http://docs.looker.com/"}

Grayson-Williamss-Macbook-Pro:rsdw.old grayson$

I was able to generate the classes for c#.net application successfully and was able to successfully login using the Client ID and secret key and receive a token successfully but facing an issue when executing “ApiClient Client = authApi.ApiClient;”. When i try to troubleshoot using breakpoints, i receive a NULL value due to which i receive a NULL pointer exception while calling Client.AddDefaultHeader. Any help is greatly appreciated.

Can you shoot me a code sample? I’ll take a quick look.

Hello,


I’m having similar issues to scottmdavidson and I am unable to run a look as I get a 404 error. See code below:


import swagger_client as looker
import os


client_id = os.environ.get('LOOKER_CLIENT_ID')
client_secret = os.environ.get('LOOKER_SECRET_KEY')
#base_url = 'https://looker.mycompany.com:9999/api/3.0/'
base_url = 'https://looker.mycompany.com:19999/api/3.0/'


unauthenticated_client = looker.ApiClient(base_url)
unauthenticated_authApi = looker.ApiAuthApi(unauthenticated_client)


token = unauthenticated_authApi.login(client_id=client_id, client_secret=client_secret)
client = looker.ApiClient(base_url, 'Authorization', 'token ' + token.access_token)

looks = looker.LookApi(client)
looks.run_look(9669,'json')

The error I receive:


ApiException: (404)
Reason: Not Found
HTTP response headers: HTTPHeaderDict({'Server': 'nginx', 'Date': 'Thu, 29 Jun 2017 19:14:36 GMT', 'Content-Type': 'application/json;charset=utf-8', 'Content-Length': '69', 'Connection': 'keep-alive', 'Vary': 'Accept-Encoding', 'X-Content-Type-Options': 'nosniff'})
HTTP response body: {"message":"Not found","documentation_url":"http://docs.looker.com/"}

I can authenticate successfully and receive a token. I tested that access_token in curl and it retrieves my user info successfully. Any help here to run a look would be great!

Userlevel 3
Badge

Hey there @cross!


I normally see this error when I’ve made a mistake in the permissions and groups that I’ve given to the user that I am authenticating as. This can also come up when the optional arguments provided to the function are not as expected.


I’d try these two steps first:



  1. Sudo as the API user and make sure you can see and run the Look in the front-end application. If you can’t, then you must adjust their permissions or access so that they can find and run the Look.

  2. EDIT: Nevermind, data format argument is only optional for other endpoints, required for this one.


If you still can’t run the Look from the API, try authenticating and running the Look via curl. If you can, this implies that maybe authentication is not working as expected in your Python script.

Ok thanks for the advice.



  1. I can see the look in the front end (I created it).


Can you point me in the direction to run the look via curl or tell me the syntax. Below is what I have:


curl https://looker.mycompany:19999/api/3.0/looks/15133/run/csv -H "Authorization: Bearer access_token here"
Userlevel 3
Badge

That basic syntax works for me, this worked on looker.learn.com:


curl -i -H "Authorization: token <BIG_TOKEN_HERE>" https://learn.looker.com:19999/api/3.0/looks/2938/run/json

HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8
Vary: Accept-Encoding
X-Content-Type-Options: nosniff
Transfer-Encoding: chunked

[{"users.age_tier":"80 or Above","order_items.count":1984,"order_items.percent_total_gm":4.8631375010242754},
. . .

Are you still getting a 404?

Hey,


I still received the 404 error but the issue is resolved. You were correct it was a permission issue.


I re-looked (no pun intended) at the info from my original curl query and found the space id from the curl query was different than the space id from the front end application. I contacted the admin and the admin setup new api keys for the “right” account. Thanks for the help!

Userlevel 3
Badge

@cross no problem! Glad to hear it’s working now 😃

Reply