Exemplo n.º 1
0
def delete_main(path):
    valid_keys = ['containers', 'keyvals']
    try:
        container = ccget.get_container(path)
    except ce.noResult:
        return(error(
               404,
               "Container you want to delete from is not found",
               requested_container_tree=" -> ".join(path.split("/"))))

    # Check the validity of request
    if len(flask.request.args) > 0:
        return(error(
               400,
               "DELETE requests should not have querystring params",
               querystring_params=flask.request.args))

    # Load the JSON data, and validate it
    try:
        request_data = json.loads(flask.request.get_data())
    except json.JSONDecodeError as e:
        return(error(
               400,
               "JSON Data is invalid",
               escaped_data_submitted=flask.request.get_data(),
               parsing_error=e.message))

    # Check for invalid keys
    for key in sorted(request_data.keys()):
        if key not in valid_keys:
            return(error(
                   400,
                   "JSON contained bad key",
                   errored_on_key=key))

    return_data = list()
    for key in valid_keys:
        try:
            local_data = request_data[key]
        except (KeyError) as e:
            continue
        return_data = globals()["delete_process_" + key](
            local_data,
            container_id=container.id,
            processed_so_far=return_data,
            path=path)

        # Return data will become a TUPLE if there was a processing error, in
        # which case we need to return this back up the stack
        if type(return_data) is tuple:
            return return_data

    # Time to clean up the caches...
    # post_invalidate_cache(path, request_data)
    purge(path, request_data)
    return json.dumps({"results": return_data})
Exemplo n.º 2
0
def put_main(path):
    # A function that matches post_process_{valid_key} must exist
    valid_keys = ['containers', 'keyvals']
    try:
        container = ccget.get_container(path)
    except ce.noResult:
        return(error(
               404,
               "Container you want to PUT into is not found",
               requested_container_tree=" -> ".join(path.split("/"))))

    # Check the validity of request
    if len(flask.request.args) > 0:
        return(error(
               400,
               "PUT requests should not have querystring params",
               querystring_params=flask.request.args))

    # Load the JSON data, and validate it
    try:
        request_data = json.loads(flask.request.get_data())
    except json.JSONDecodeError as e:
        return(error(
               400,
               "JSON Data is invalid",
               escaped_data_submitted=flask.request.get_data(),
               parsing_error=e.message))

    # Check for invalid keys
    for key in sorted(request_data.keys()):
        if key not in valid_keys:
            return(error(
                   400,
                   "JSON contained bad key",
                   errored_on_key=key))

    return_data = list()
    for key in valid_keys:
        try:
            local_data = request_data[key]
        except (KeyError) as e:
            continue
        return_data = globals()["put_process_" + key](
            local_data,
            path=path,
            container_id=container.id,
            processed_so_far=return_data)

        # Return data will become a TUPLE if there was a processing error, in
        # which case we need to return this back up the stack
        if type(return_data) is tuple:
            return return_data

    # Time to clean up the caches...
    purge(path, request_data)
    return json.dumps({"results": return_data})
Exemplo n.º 3
0
def before_request():
    try:
        auth = ("APIKEY", flask.request.headers['X-API-Auth'], flask.request)
    except KeyError as e:
        try:
            auth = ("LDAP", flask.request.headers['X-SSO-Auth'], flask.request)
        except KeyError as e:
            return (error(403,
                          "authentication headers not provided",
                          validheaders=['X-API-Auth', 'X-SSO-Auth']))
    if util.checkAuth(auth) is not True:
        return (error(403, "invalid authentication informationed provided"))
Exemplo n.º 4
0
def before_request():
    try:
        auth = ("APIKEY", flask.request.headers['X-API-Auth'], flask.request)
    except KeyError as e:
        try:
            auth = ("LDAP", flask.request.headers['X-SSO-Auth'], flask.request)
        except KeyError as e:
            return(error(
                   403,
                   "authentication headers not provided",
                   validheaders=['X-API-Auth', 'X-SSO-Auth']))
    if util.checkAuth(auth) is not True:
        return(error(403, "invalid authentication informationed provided"))
Exemplo n.º 5
0
def post_process_containers(data, **kwargs):
    cid = kwargs['container_id']
    return_data = kwargs['processed_so_far']
    try:
        for container in data:
            try:
                name = container['name']
            except TypeError as e:
                return(error(
                       400,
                       "containers JSON should be a list of JSON"
                       " dictionaries, and yours is not",
                       processed_so_far=return_data))
            except KeyError as e:
                return(error(
                       400,
                       "unable to add container, forgot to specify name!",
                       processed_so_far=return_data))
            try:
                desc = container['description']
            except KeyError:
                desc = None

            try:
                return_data.append("Created:" +
                                   str(ccpost.add_container(
                                       cid,
                                       name,
                                       desc)))
            except ce.notUnique:
                return_data.append("Container Not Added, Already Exists: %s" %
                                   (name))

    except TypeError as e:
        return(error(
               400,
               "containers JSON should be a list of JSON dictionaries",
               processed_so_far=return_data),
               True)

    return return_data
Exemplo n.º 6
0
def post_process_keyvals(data, **kwargs):
    cid = kwargs['container_id']
    return_data = kwargs['processed_so_far']
    try:
        for keyval in data:
            try:
                key = keyval['key'].lower()
            except TypeError as e:
                return(error(
                       400,
                       "containers JSON should be a list of JSON dictionaries",
                       processed_so_far=return_data))
            except KeyError as e:
                return(error(
                       400,
                       "must specify key name for all keyvals",
                       processed_so_far=return_data))

            try:
                value = keyval['value']
            except KeyError as e:
                return(error(
                       400,
                       "must specify value for all keyvals",
                       processed_so_far=return_data))

            try:
                tag = keyval['tag']
            except KeyError as e:
                tag = None

            return_data.append("Created:" + str(
                               ccpost.add_keyval(cid, key, value, tag)))

    except TypeError as e:
        raise
        return(error(
               400,
               "keyvals JSON should be a list of JSON dictionaries",
               processed_so_far=return_data))
    return return_data
Exemplo n.º 7
0
def put_process_keyvals(data, **kwargs):
    return_data = kwargs['processed_so_far']
    for item in data:
        try:
            k = item['key'].lower()
            v = item['value']
        except KeyError as e:
            return(error(
                   400,
                   "Key Val items must contain both a key and a value",
                   processed_so_far=kwargs['processed_so_far']))
        try:
            t = item['tag']
        except KeyError as e:
            t = app.config['DEFAULT_TAG']
        try:
            ccput.update_keyval(kwargs['path'], k, v, tag=t)
            return_data.append("set /%s :%s=%s?TAG=%s" %
                               (kwargs['path'], k, v, t))
        except ce.noResult as e:
            return(error(400,
                   "key '%s' not found at /%s" % (k, kwargs['path']),
                   processed_so_far=kwargs['processed_so_far']))
    return return_data
Exemplo n.º 8
0
def get_content(path):
    """
    This will return a dict of the content in containers matching key or key and value provided
    in arguments.

    """
    cache_key = "/operations/container/content/" + path + "?" + "&".join(
        ["%s=%s" % (k.upper(), v.upper()) for k, v in sorted(
         flask.request.args.iteritems())])
    app.logger.debug("Using Cache Key: %s" % (cache_key))
    loadkey = "loading-" + cache_key
    cache_result = cache.get(cache_key)
    loops = 0
    while cache_result is None:
        loops += 1
        if loops > 70:
            return error(500,
                         message="item never became available in cache",
                         debug="%d: %s" % (loops, cache_key))
        app.logger.debug("%s is not cached, checked %d times" %
                         (cache_key, loops))
        sleeptime = random() / 10
        sleep(sleeptime)
        if ((cache.get("loading-" + cache_key) is None and
            cache.get(cache_key) is None)):

            cache.set("loading-" + cache_key, "True",
                      timeout=app.config['CACHE_LOCKING_SECONDS'])
            max_recursion = int(app.config['TREE_MAX_RECURSION'])

            request_key = None
            request_val = None
            for (k, v) in flask.request.args.iteritems():
                if k.upper() == "KEY":
                    request_key = v.lower()

                elif k.upper() == "VALUE":
                    request_val = v.lower()

                else:
                    return error(400,
                                 "client error",
                                 "invalid query string",
                                 key=k,
                                 value=v,
                                 path=cache_key
                                 )
            app.logger.debug("loading %s after %f seconds wait" % (cache_key, sleeptime))
            # Check that key is provided
            if request_key == None:
                return error(400,
                             "client error",
                             "No key provided"
                            )
            try:
                container = ccget.get_container(path)
            except ce.noResult as e:
                return error(404,
                             "container not found",
                             container=path)

            if request_key is not None and request_val is None:
                #app.logger.debug("Content with no key")
                return_hash = dict()
                a = container.dumptree_with_key(max_recursion=max_recursion, key=request_key, container_id=True)
                for container in a:
                    c = ccget.get_container(container)
                    all_values = dict()
                    for key in c.keys:
                        all_values[key.name] = list()

                        for value in key.values:
                            all_values[key.name].append(value.value)

                    return_hash[c.name]= all_values

                cache.set(cache_key,
                          json.dumps(return_hash),
                          timeout=app.config['CACHE_DEFAULT_AGE_SECONDS'])

            elif request_key is not None and request_val is not None:
                #app.logger.debug("Content with given key")
                return_hash = dict()
                a = container.dumptree_with_key_val(max_recursion=max_recursion, key=request_key, r_val=request_val, container_id=True)
                for container in a:
                    c = ccget.get_container(container)
                    all_values = dict()
                    for key in c.keys:
                        all_values[key.name] = list()

                        for value in key.values:
                            all_values[key.name].append(value.value)

                    return_hash[c.name]=all_values

                cache.set(cache_key,
                          json.dumps(return_hash),
                          timeout=app.config['CACHE_DEFAULT_AGE_SECONDS'])

            ## Shouldn't get here TODO fix or error
            else:
                app.logger.debug("Should not get here!")
                cache.set(cache_key,
                          json.dumps([x for x in container.children.keys()]),
                          timeout=app.config['CACHE_DEFAULT_AGE_SECONDS'])

        cache.delete("loading-" + cache_key)
        cache_result = cache.get(cache_key)
    return cache_result
Exemplo n.º 9
0
def get_main(path):
    # This will handle all gets that are not otherwise defined.
    cache_key = "/" + path + "?" + "&".join(
        ["%s=%s" % (k.upper(), v.upper()) for k, v in sorted(
         flask.request.args.iteritems())])
    app.logger.debug("Using Cache Key: %s" % (cache_key))
    loadkey = "loading-" + cache_key
    cache_result = cache.get(cache_key)
    loops = 0
    # All get's are served up from the cache.
    while cache_result is None:
        # Keep track of loops, abort if it get's to be excessive, this may
        # need tuned later depending on how long DB operations take, right now
        # the number of wait loops is excessive
        loops += 1
        if loops > 50:
            return(error(
                   500,
                   message="item never became available in cache",
                   debug="%d: %s" % (loops, cache_key)))
        app.logger.debug("%s is not cached, checked %d times" %
                         (cache_key, loops))
        sleeptime = random() / 100
        sleep(sleeptime)
        # For other threads that might be requesting the same thing, announce
        # to the cache that we're processing this page, help to eliminate
        # overloading during bursts for the same key.
        if ((cache.get("loading-" + cache_key) is None and
             cache.get(cache_key) is None)):

            # Announce we're loading to the cache
            cache.set("loading-" + cache_key, "True",
                      timeout=app.config['CACHE_LOCKING_SECONDS'])
            # Set values for the request
            request_tag = app.config['DEFAULT_TAG']
            request_return = "VALUES"
            request_key = None
            for (k, v) in flask.request.args.iteritems():
                if k.upper() == "TAG":
                    request_tag = v.upper()
                elif k.upper() == "KEY":
                    request_key = v.lower()
                elif k.upper() == "RETURN":
                    request_return = v.upper()
                else:
                    # Clean up known query string params, avoid cachebusting
                    # and make clearing the cache possible for posts/puts
                    return(error(
                           400,
                           "client error",
                           "invalid query string parameters",
                           key=k,
                           value=v,
                           path=cache_key))

            app.logger.debug(
                "I'm doing the loading after a sleep of %f seconds" %
                (sleeptime))

            # Can't request a key in conjuction with some request_return types
            if request_key is not None and request_return is not "VALUES":
                return(error(
                       400,
                       "client error",
                       "paramater conflict",
                       message="%s can't be return value when requesting a single key" %(request_return),
                       ))

            if request_key is not None:
                # A single Key is requested
                try:
                    key = ccget.get_key(path, request_key, tag=request_tag)
                except ce.noResult:
                    return error(404, "key not found", requested_key=request_key, requested_container=path, applied_tag=request_tag)

                return_key = {key.name: {"values": list()}}
                return_key[key.name]['tag'] = key.tag
                # @TODO: Fix date added/date updated
                # return_key['added'] = key.added
                # return_key['updated'] = key.updated

                for v in key.values:
                    return_key[key.name]['values'].append(
                            {'id': v.id, 'value': v.value } )

                cache.set(cache_key,
                          json.dumps(return_key),
                          timeout=app.config['CACHE_DEFAULT_AGE_SECONDS'])

            else:
                try:
                    container = ccget.get_container(path)
                except ce.noResult:
                    return error(404, "container not found", requested_container=path)

                # Process a container list
                if request_return == "ALL" or request_return == "CONTAINERS":
                    child_containers = list()
                    all_child_containers = dict()
                    app.logger.debug(request_return)
                    for child_container in container.children:
                        child_containers.append(path + "/" + child_container)
                        app.logger.debug(all_child_containers)
                    for child_container in child_containers:
                        c = ccget.get_container(child_container)
                        all_child_containers[c.name] = { "description": c.description,
                                                         "id": c.id }

                # Process a value list
                if request_return == "ALL" or request_return =="VALUES":
                    all_containers = [container.id]
                    all_values = dict()
                    while container.parent is not None:
                        container = container.parent
                        if container is not None:
                            all_containers.append(container.id)

                    for container in reversed(all_containers):
                        c = ccget.get_container(container)
                        for key in c.keys:
                            if ((key.tag != request_tag and
                                 key.tag != app.config['DEFAULT_TAG'])):
                                continue
                            try:
                                if ((all_values[key.name]['tag'] !=
                                     app.config['DEFAULT_TAG'])):
                                    continue
                            except KeyError:
                                pass
                            all_values[key.name] = {'values': list(),
                                                    'tag': key.tag,
                                                    'id': key.id}
                            for value in key.values:
                                all_values[key.name]['values'].append(
                                    {'id': value.id, 'value': value.value })
                if request_return == "ALL":
                    return_hash = { "containers": all_child_containers, 
                                    "key_values": all_values }

                elif request_return == "CONTAINERS":
                    return_hash = all_child_containers

                elif request_return == "VALUES":
                    return_hash = all_values

                else:
                    return(error(400,
                                 "client_error",
                                 "invalid paramater value",
                                 key=k,
                                 value=v,
                                 path=cache_key))


                cache.set(cache_key,
                          json.dumps(return_hash),
                          timeout=app.config['CACHE_DEFAULT_AGE_SECONDS'])

        cache.delete("loading-" + cache_key)
        cache_result = cache.get(cache_key)
    return cache_result
Exemplo n.º 10
0
def get_list(path):
    """
    This will return a list of all containers inside of another 
    container

    Setting ?recursive=true will get all the child containers,
    until there are no more children and provide a full container
    tree
    """
    cache_key = "/operations/container/list/" + path + "?" + "&".join(
        ["%s=%s" % (k.upper(), v.upper()) for k, v in sorted(
         flask.request.args.iteritems())])
    app.logger.debug("Using Cache Key: %s" % (cache_key))
    loadkey = "loading-" + cache_key
    cache_result = cache.get(cache_key)
    loops = 0
    while cache_result is None:
        loops += 1
        if loops > 50:
            return error(500,
                         message="item never became available in cache",
                         debug="%d: %s" % (loops, cache_key))
        app.logger.debug("%s is not cached, checked %d times" %
                         (cache_key, loops))
        sleeptime = random() / 10
        sleep(sleeptime)
        if ((cache.get("loading-" + cache_key) is None and
            cache.get(cache_key) is None)):

            cache.set("loading-" + cache_key, "True",
                      timeout=app.config['CACHE_LOCKING_SECONDS'])
            request_recursive = False
            max_recursion = int(app.config['TREE_MAX_RECURSION'])

            request_key = None
            request_val = None
            for (k, v) in flask.request.args.iteritems():
                if k.upper() == "DEPTH":
                    try:
                        max_recursion = int(v)
                    except ValueError as e:
                        return error(400,
                                     "client_error",
                                     "invalid querystring",
                                     recursion_depth="%s does not appear to be" +
                                      " an integer" % (v))

                elif k.upper() == "RECURSIVE":
                    try:
                        request_recursive = crud_config.util.toBool(v)
                    except ValueError as e:
                        return error(400,
                                     "client error",
                                     "invalid querystring",
                                     recursion_request_value=v)

                elif k.upper() == "KEY":
                    request_key = v.lower()

                elif k.upper() == "VALUE":
                    request_val = v.lower()

                else:
                    return error(400,
                                 "client error",
                                 "invalid query string",
                                 key=k,
                                 value=v,
                                 path=cache_key
                                 )
            app.logger.debug("loading %s after %f seconds wait" % (cache_key, sleeptime))
            try:
                container = ccget.get_container(path)
            except ce.noResult as e:
                return error(404,
                             "container not found",
                             container=path)

            if request_recursive is True and request_key is None:
                #app.logger.debug("recursive with NO key")
                cache.set(cache_key,
                          json.dumps(container.dumptree(max_recursion=max_recursion)),
                          timeout=app.config['CACHE_DEFAULT_AGE_SECONDS'])

            elif request_recursive is True and request_key is not None and request_val is None:
                #app.logger.debug("recursive with key")
                cache.set(cache_key,
                          json.dumps(container.dumptree_with_key(max_recursion=max_recursion, key=request_key)),
                          timeout=app.config['CACHE_DEFAULT_AGE_SECONDS'])

            elif request_recursive is True and request_key is not None and request_val is not None:
                #app.logger.debug("recursive with key and val")
                cache.set(cache_key,
                         json.dumps(container.dumptree_with_key_val(max_recursion=max_recursion, key=request_key, r_val=request_val)),
                         timeout=app.config['CACHE_DEFAULT_AGE_SECONDS'])


            else:
                cache.set(cache_key,
                          json.dumps([x for x in container.children.keys()]),
                          timeout=app.config['CACHE_DEFAULT_AGE_SECONDS'])

        cache.delete("loading-" + cache_key)
        cache_result = cache.get(cache_key)
    return cache_result