connect to a running Juttle program by job_id

def connect_job(job_id,
                deployment_name,
                token_manager=None,
                app_url=defaults.APP_URL,
                persist=False,
                websocket=None,
                data_url=None):
    """
    connect to a running Juttle program by job_id

    """

    if data_url == None:
        data_url = get_data_url_for_job(job_id,
                                        deployment_name,
                                        token_manager=token_manager,
                                        app_url=app_url)

    if websocket == None:
        websocket = __wss_connect(data_url,
                                  token_manager,
                                  job_id=job_id)

    pong = json.dumps({
        'pong': True
    })

    if not persist:
        job_finished = False

        while not job_finished:
            try:
                data = websocket.recv()

                if data:
                    payload = json.loads(data)

                    if is_debug_enabled():
                        printable_payload = dict(payload)
                        if 'points' in payload:
                            # don't want to print out all the outputs when in
                            # debug mode
                            del printable_payload['points']
                            printable_payload['points'] = 'NOT SHOWN'

                        debug('received %s' % json.dumps(printable_payload))

                    if 'ping' in payload.keys():
                        # ping/pong (ie heartbeat) mechanism
                        websocket.send(pong)

                        if is_debug_enabled():
                            debug('sent %s' % json.dumps(pong))

                    if 'job_end' in payload.keys() and payload['job_end'] == True:
                        job_finished = True

                    if token_manager.is_access_token_expired():
                        debug('refreshing access token')
                        token_obj = {
                            "accessToken": token_manager.get_access_token()
                        }
                        # refresh authentication token
                        websocket.send(json.dumps(token_obj))

                    if 'error' in payload:
                        if payload['error'] == 'NONEXISTENT-JOB':
                            raise JutException('Job "%s" no longer running' % job_id)

                    # return all channel messages
                    yield payload

                else:
                    debug('payload was "%s", forcing websocket reconnect' % data)
                    raise IOError()

            except IOError:
                if is_debug_enabled():
                    traceback.print_exc()
                #
                # We'll retry for just under 30s since internally we stop
                # running non persistent programs after 30s of not heartbeating
                # with the client
                #
                retry = 1
                while retry <= 5:
                    try:
                        debug('network error reconnecting to job %s, '
                              'try %s of 5' % (job_id, retry))
                        websocket = __wss_connect(data_url, token_manager, job_id=job_id)
                        break

                    except socket.error:

                        if is_debug_enabled():
                            traceback.print_exc()

                        retry += 1
                        time.sleep(5)

                debug('network error reconnecting to job %s, '
                      'try %s of 5' % (job_id, retry))
                websocket = __wss_connect(data_url, token_manager, job_id=job_id)

    websocket.close()