Skip to main content

A Python wrapper for the Qlik Sense Enterprise SaaS APIs.

Project description

Status

Project Status: Active – The project has reached a stable, usable state and is being actively developed.

qsaas

A wrapper for the Qlik Sense Enterprise SaaS APIs.

Intended audience

Developers -- familiarity with the Qlik Sense Enterprise APIs is required.

High-level benefits:

  1. Automatic pagination on GETs, returning all results.
  2. Ability to asynchronously make POSTs, PUTs, and PATCHs, where one can input the amount of threads you'd like (default is 10), dramatically decreasing processing time.
  3. Ease of establishing and managing connections to multiple tenants.
  4. Ability to connect to any API endpoint.

Table of Contents

  1. Installation
  2. Configuration
  3. Basic Usage
  4. Advanced Usage
  5. Complete list of functions
  6. Additional Notes

Installation

pip install qsaas

Dependencies (auto-installed by pip):

requests
requests_toolbelt
aiohttp
asyncio

Configuration

To import qsaas, as qsaas only currently has one class, Tenant, the simplest way is:

from qsaas.qsaas import Tenant

From there, one can instantiate a new Tenant object by executing

q = Tenant(<args>)

Option A

If connecting locally, the simplest way can be to use a json file for each tenant, as these files can be securely stored locally. The file must be a valid json file with the following structure:

{
    "api_key": "<API_KEY>",
    "tenant_fqdn": "<TENANT>.<REGION>.qlikcloud.com",
    "tenant_id": "<TENANT_ID>"
}

When creating a new Tenant object then, the named param config can be used as follows (in this case, the file name is "config.json":

q = Tenant(config="config.json")

Option B

If it's preferred to feed in the api_key, tenant_fqdn, and tenant_id in a different manner, one can instead execute:

q = Tenant(api_key=<API_KEY>, tenant=<TENANT_FQDN>, tenant_id=<TENANT_ID>)

Basic Usage

Get all users from a tenant and print their IDs

users = q.get('users')
for user in users:
    print(user['id'])

Get a specific user from a tenant

user = q.get('users', params={"subject":"QLIK-POC\dpi"})

Get all apps from a tenant and print their names

apps = q.get('items', params={"resourceType":"app"})
for app in apps:
    print(app['name'])

Get all spaces from a tenant

spaces = q.get('spaces')

Create a new user

body = {
    "tenantId": q.tenant_id,
    "subject": 'WORKSHOP\\Qlik1',
    "name": 'Qlik1',
    "email": 'Qlik1@workshop.com',
    "status": "active"
}
q.post('users', body)

Reload an application

reload = q.post('reloads', json.dumps({"appId": "<APP_ID>"}))

Reload an application and wait

reload_id = q.post('reloads', json.dumps({"appId": "<APP_ID>"}))['id']
status = None
while status not in ['SUCCEEDED', 'FAILED']:
    time.sleep(1)
    status = q.get('reloads/' + reload_id)['status']

Publish an application

app_id = <APP_ID>
space_id = <SPACE_ID>
app = q.post('apps/' + app_id + '/publish', json.dumps({"spaceId": space_id}))
payload = {
    "name": app['attributes']['name'],
    "resourceId": app['attributes']['id'],
    "description": app['attributes']['description'],
    "resourceType": "app",
    "resourceAttributes": app['attributes'],
    "resourceCustomAttributes": {},
    "resourceCreatedAt": app['attributes']['createdDate'],
    "resourceCreatedBySubject": app['attributes']['owner'],
    "spaceId": space_id
}
q.post('items', json.dumps(payload))

Change the owner of an application

app_id = <APP_ID>
user_id = <USER_ID>
q.put('apps/' + app_id + '/owner', json.dumps({"ownerId": user_id}))

Import an application

with open('<APP-NAME>.qvf', 'rb') as f:
    data = f.read()
app = q.post('apps/import', data,
             params={"name": "<APP-NAME-NEW>"})
payload = {
    "name": app['attributes']['name'],
    "resourceId": app['attributes']['id'],
    "description": app['attributes']['description'],
    "resourceType": "app",
    "resourceAttributes": app['attributes'],
    "resourceCustomAttributes": {},
    "resourceCreatedAt": app['attributes']['createdDate'],
    "resourceCreatedBySubject": app['attributes']['owner']
}
q.post('items', json.dumps(payload))

Advanced Usage

Upload a file to DataFiles

file_path = directory_path + '\\' + file_name
body = open(file_path, 'rb')
q.post('qix-datafiles', body,
        params={"connectionId": conn_id, "name": file_name})

Asynchronously reload multiple applications

Note: The default threading is 10 at a time--to modify this, add the named param chunks=x, where x is an integer. Do not make this integer too high to avoid rate limiting.

app_ids = ['<APP_ID1>','<APP_ID2>','<APP_ID3>']
payloads = [json.dumps({"appId": app_id}) for app_id in app_ids]
q.async_post('reloads', payloads=payloads)

Asynchronously delete apps that have the name "delete_me"

Note: This process currently requires deleting both from the apps and items endpoints. The default threading is 10 at a time--to modify this, add the named param chunks=x, where x is an integer. Do not make this integer too high to avoid rate limiting.

items = q.get('items', params={"resourceType": "app", "name": "delete_me"})
delete_dict = {}
delete_dict['items'] = [item['id'] for item in items]
delete_dict['apps'] = [item['resourceId'] for item in items]
for e in delete_dict:
    q.async_delete(e, ids=delete_dict[e])

Asychronously add users

Note: The default threading is 10 at a time--to modify this, add the named param chunks=x, where x is an integer. Do not make this integer too high to avoid rate limiting.

payloads = []
for i in range(10):
    user_subject = 'WORKSHOP\\Qlik' + str(i+1)
    user_name = 'Qlik' + str(i+1)
    user_email = 'Qlik' + str(i+1) + '@workshop.com'
    body = {
        "tenantId": q.tenant_id,
        "subject": user_subject,
        "name": user_name,
        "email": user_email,
        "status": "active"
    }
    payloads.append(body)
q.async_post('users', payloads=payloads)

Asynchronously copy applications and assign them to new owners

Note: This is the only "custom" style function in all of qsaas, due to the fact that it has hardcoded endpoints and has an multi-step process--as it can copy applications and then assign those applications ot new owners in one go. The default threading is 10 at a time--to modify this, add the named param chunks=x, where x is an integer. Do not make this integer too high to avoid rate limiting. Copy app and assign ownership to new users

q.async_app_copy('<GUID>',users=['<UserId-1>','<UserId-2>'])

Simply copy an app 10 times, without assigning new ownership

q.async_app_copy('<GUID>',copies=10)

Customize Headers

Note: This is available for all functions, but should largely not be needed (most headers are automatically generated by the Python libraries used). If the need arises to pass in custom headers, or to overwrite the existing headers, one can leverage the keyword param headers as per below.

Upload an image to an application

data = open('your_image.png', 'rb').read()
q.put('apps/<GUID>/media/files/your_image.png',
      data, headers={"Content-Type": "image/png"})

Complete list of functions

  • q.get()
  • q.post()
  • q.put()
  • q.patch()
  • q.delete()
  • q.async_post()
  • q.async_put()
  • q.async_patch()
  • q.async_app_copy() *only custom function

For each function, one can always refer to the docstring for a helpful description, and most provide examples. For instance, help(q.get) will output:

    Description
    --------------------
    GETs and paginates all results. Takes optional params.

    Mandatory parameters
    --------------------
    endpoint (str), exclude api/{version}

    Optional parameters
    --------------------
    params (dict)

    Example Usage
    --------------------
    Example 1:
        get('users')

        This will return all users.

    Example 2:
        get('items', params={"resourceType":"app"})

        This will return all apps from items.

Additional Notes

API Documentation

It is highly encouraged to review the API documentation at the qlik.dev portal. As this wrapper does not have wrapped Qlik functions (aside from the async_app_copy function), it is integral to know the API appropriate endpoints to call.

Support

This project is built and maintained by Daniel Pilla, a Principal Analytics Platform Architect at Qlik. This project is however not supported by Qlik, and is only supported through Daniel.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

qsaas-1.2.0.tar.gz (12.8 kB view details)

Uploaded Source

File details

Details for the file qsaas-1.2.0.tar.gz.

File metadata

  • Download URL: qsaas-1.2.0.tar.gz
  • Upload date:
  • Size: 12.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.6.1 requests/2.21.0 setuptools/40.6.2 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.7.2

File hashes

Hashes for qsaas-1.2.0.tar.gz
Algorithm Hash digest
SHA256 e8cbb96b63392da12949ccaf2cfbe4d8d271fdfa3db92792cef1a9307390956b
MD5 29dcea00615e4023a6421a8982fba5a1
BLAKE2b-256 36d7b1fc223a38ca9c173be09bfd38fe4cf6f7de7ffb95b0ccecde4f2baa97c3

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page