def test_call_HEAD(self): fluiddb.login(USERNAME, PASSWORD) # Grab an object ID for a user for us to use in the HEAD path result = fluiddb.call("GET", "/users/test") obj_id = result[1]["id"] path = "/objects/%s/fluiddb/users/username" % obj_id result = fluiddb.call("HEAD", path) self.assertEqual("200", result[0]["status"]) self.assertFalse(result[1]) # no response body with HEAD call
def test_call_POST(self): fluiddb.login(USERNAME, PASSWORD) new_namespace = str(uuid.uuid4()) ns_body = {"description": "a test namespace", "name": new_namespace} # Make sure that if the body is a dict it gets translated to json result = fluiddb.call("POST", "/namespaces/test", ns_body) self.assertEqual("201", result[0]["status"]) self.assertTrue(result[1].has_key("id")) # Housekeeping fluiddb.call("DELETE", "/namespaces/test/" + new_namespace)
def test_call_DELETE(self): fluiddb.login(USERNAME, PASSWORD) # Simply create a new namespace and then delete it new_namespace = str(uuid.uuid4()) body = {"description": "a test namespace", "name": new_namespace} result = fluiddb.call("POST", "/namespaces/test", body) self.assertEqual("201", result[0]["status"]) self.assertTrue(result[1].has_key("id")) result = fluiddb.call("DELETE", "/namespaces/test/" + new_namespace) self.assertEqual("204", result[0]["status"])
def test_call_GET(self): fluiddb.login(USERNAME, PASSWORD) # No query string args to append result = fluiddb.call("GET", "/namespaces/test") self.assertEqual("200", result[0]["status"]) # make sure the resulting json is turned into a Python dictionary self.assertTrue(isinstance(result[1], dict)) # ...and we have the expected id self.assertTrue(result[1].has_key("id")) # The same call WITH query string args to append to the URL # eg we'll get /namespaces/test?returnDescription=True as the path result = fluiddb.call("GET", "/namespaces/test", None, None, returnDescription=True) self.assertEqual("200", result[0]["status"]) # make sure the result has the expected description field self.assertTrue(result[1].has_key("description")) # finally we need to make sure that primitive values returned from # fluidDB are turned from their json representation to their # Pythonic form new_namespace = str(uuid.uuid4()) new_tag = str(uuid.uuid4()) ns_body = {"description": "a test namespace", "name": new_namespace} tag_body = {"description": "a test tag", "name": new_tag, "indexed": False} # create a namespace and tag to use in a bit result = fluiddb.call("POST", "/namespaces/test", ns_body) self.assertEqual("201", result[0]["status"]) self.assertTrue(result[1].has_key("id")) ns_id = result[1]["id"] # for later use result = fluiddb.call("POST", "/tags/test/" + new_namespace, tag_body) self.assertEqual("201", result[0]["status"]) self.assertTrue(result[1].has_key("id")) path = "/" + "/".join(["objects", ns_id, "test", new_namespace, new_tag]) primitives = [1, 1.1, u"foo", ["a", "b", u"c"], True, None] for primitive in primitives: result = fluiddb.call("PUT", path, primitive) self.assertEqual("204", result[0]["status"]) # GET the new tag value and check it gets translated back to # the correct type result = fluiddb.call("GET", path) self.assertEqual("application/vnd.fluiddb.value+json", result[0]["content-type"]) self.assertTrue(isinstance(result[1], type(primitive))) # check the new /values GET works result = fluiddb.call( "GET", "/values", tags=["fluiddb/about", "test/%s/%s" % (new_namespace, new_tag)], query="has test/%s/%s" % (new_namespace, new_tag), ) self.assertEqual("200", result[0]["status"]) self.assertTrue(result[1].has_key("results")) # Housekeeping fluiddb.call("DELETE", "/tags/test/" + new_namespace + "/" + new_tag) fluiddb.call("DELETE", "/namespaces/test/" + new_namespace)
def test_logout(self): # Lets first log in and check we're good to go fluiddb.login(USERNAME, PASSWORD) result = fluiddb.call("GET", "/users/test") self.assertEqual("200", result[0]["status"]) # Log out (this should clear the Authorization header) fluiddb.logout() # We should still be able to do anonymous calls result = fluiddb.call("GET", "/users/test") self.assertEqual("200", result[0]["status"]) # but we can't do anything that requires us to be authenticated new_namespace = str(uuid.uuid4()) result = fluiddb.call("POST", "/namespaces/test", {"description": "will fail", "name": new_namespace}) self.assertEqual("401", result[0]["status"])
def test_call_PUT(self): fluiddb.login(USERNAME, PASSWORD) new_namespace = str(uuid.uuid4()) new_tag = str(uuid.uuid4()) ns_body = {"description": "a test namespace", "name": new_namespace} tag_body = {"description": "a test tag", "name": new_tag, "indexed": False} # create a namespace and tag to use in a bit result = fluiddb.call("POST", "/namespaces/test", ns_body) self.assertEqual("201", result[0]["status"]) self.assertTrue(result[1].has_key("id")) ns_id = result[1]["id"] # for later use result = fluiddb.call("POST", "/tags/test/" + new_namespace, tag_body) self.assertEqual("201", result[0]["status"]) self.assertTrue(result[1].has_key("id")) path = "/" + "/".join(["objects", ns_id, "test", new_namespace, new_tag]) # Make sure that primitive types are json encoded properly with # the correct mime-type, dicts are translated to json, the # mime-type argument for opaque types is used properly and if # no mime-type is supplied and the previous checks are not met # an appropriate exception is raised. primitives = [1, 1.1, "foo", u"foo", True, None, ["a", "b", u"c"]] for primitive in primitives: result = fluiddb.call("PUT", path, primitive) self.assertEqual("204", result[0]["status"]) # call HEAD verb on that tag value to get the mime-type from # FluidDB result = fluiddb.call("HEAD", path) self.assertEqual("application/vnd.fluiddb.value+json", result[0]["content-type"]) # dicts are json encoded result = fluiddb.call("PUT", path, {"foo": "bar"}) # check again with HEAD verb result = fluiddb.call("HEAD", path) self.assertEqual("application/json", result[0]["content-type"]) # Make sure that the body and mime args work as expected (mime # overrides the primitive string type making the value opaque) result = fluiddb.call("PUT", path, "<html><body><h1>Hello," "World!</h1></body></html>", "text/html") result = fluiddb.call("HEAD", path) self.assertEqual("text/html", result[0]["content-type"]) # unspecified mime-type on a non-primitive value results in an # exception self.assertRaises(TypeError, fluiddb.call, "PUT", path, object()) # make sure it's possible to PUT a tag value using a list based path pathAsList = ["objects", ns_id, "test", new_namespace, new_tag] result = fluiddb.call("PUT", pathAsList, "foo") self.assertEqual("204", result[0]["status"]) # Housekeeping fluiddb.call("DELETE", "/tags/test/" + new_namespace + "/" + new_tag) fluiddb.call("DELETE", "/namespaces/test/" + new_namespace)
def test_login(self): # we're not logged in but able to do anonymous calls result = fluiddb.call("GET", "/users/test") self.assertEqual("200", result[0]["status"]) new_namespace = str(uuid.uuid4()) # and we can't do anything that requires us to be authenticated result = fluiddb.call("POST", "/namespaces/test", {"description": "will fail", "name": new_namespace}) self.assertEqual("401", result[0]["status"]) # Now lets log in with *bad* credentials fluiddb.login(USERNAME, PASSWORD + "bad_password") result = fluiddb.call("GET", "/users/test") # Unauthorised due to bad credentials self.assertEqual("401", result[0]["status"]) # Try again with the good case fluiddb.login(USERNAME, PASSWORD) result = fluiddb.call("GET", "/users/test") self.assertEqual("200", result[0]["status"])
def main(args): """ Set stuff up, read credentials, start the ball rolling """ logging.info("++++++++++++++++++++++++++++++++++++++++++++++") logging.info("++++++++++++++++++++++++++++++++++++++++++++++") logging.info("Starting push at %s"%datetime.datetime.today().ctime()) try: homedir = os.path.expanduser('~') logging.info("Attempting to load credentials.json from %s"%homedir) credentials_file = open(homedir+'/credentials.json', 'r') credentials = json.loads(credentials_file.read()) except Exception as e: logging.error("Could not process credentials...") logging.error(e) sys.exit() finally: credentials_file.close() if 'main' in args: fd.prefix = fd.MAIN else: fd.prefix = fd.SANDBOX logging.info("FluidDB instance: %s"%fd.prefix) fd.login(credentials['username'], credentials['password']) object = '/objects/'+credentials['object_id'] logging.info("Object id: %s"%object) os.chdir('..') try: timestamp_file = open('.timestamp', 'r') last_update = float(timestamp_file.read()) timestamp_file.close() except: last_update = 1.0 # Update the timestamp to now try: timestamp_file = open('.timestamp', 'w') timestamp_file.write(str(time.mktime(datetime.datetime.today().timetuple()))) finally: timestamp_file.close() # navigate the directory tree and work out what are the new/updated files # and namespaces that need pushing to FluidDB for directory in os.walk('.'): processDirectoryIntoNamespace(directory, last_update, credentials, object)
def test_put_about_type_header(self): """ There was a bug where the fluiddb.py wasn't creating the correct content-type header when PUTting to an about tag value, this test re-creates it. """ # ensures we have an object about foo headers, response = fluiddb.call("GET", "/about/foo") # create a one off tag to use for the purposes of testing fluiddb.login(USERNAME, PASSWORD) new_tag = str(uuid.uuid4()) tag_body = {"description": "a test tag", "name": new_tag, "indexed": False} # create a tag to use in a bit result = fluiddb.call("POST", "/tags/test", tag_body) self.assertEqual("201", result[0]["status"]) self.assertTrue(result[1].has_key("id")) # make sure we can PUT using the about API try: header, content = fluiddb.call("PUT", "/about/foo/test/" + new_tag, "this is a test") # check that it worked self.assertEqual("204", header["status"]) finally: # Housekeeping fluiddb.call("DELETE", "/tags/test/" + new_tag)
def main(args): """ Set stuff up, read credentials, start the ball rolling """ logging.info("++++++++++++++++++++++++++++++++++++++++++++++") logging.info("++++++++++++++++++++++++++++++++++++++++++++++") logging.info("Starting push at %s"%datetime.datetime.today().ctime()) try: credentials_file = open('credentials.json', 'r') credentials = json.loads(credentials_file.read()) except Exception as e: logging.error("Could not process credentials...") logging.error(e) sys.exit() finally: credentials_file.close() if 'sandbox' in args: fd.prefix = fd.SANDBOX else: fd.prefix = fd.MAIN logging.info("FluidDB instance: %s"%fd.prefix) fd.login(credentials['username'], credentials['password']) new_object_flag = False last_update = False if credentials.has_key('object_id'): object = '/objects/'+credentials['object_id'] # lets just check we've got the expected object (in case of Sandbox reset) logging.info('Checking object in FluidDB: %s'%object) check_response = fd.call('GET', object) logging.info(check_response) if check_response[0]['status'] == '200': new_object_flag = not check_response[1]['tagPaths'] else: new_object_flag = True else: new_object_flag = True if new_object_flag: # ok, so the expected object doesn't exist so create a new one and store # back in the credentials file... new_about = raw_input("Please describe your new FluidDB application: ") new_object_response = fd.call('POST', '/objects', {"about": new_about}) if new_object_response[0]['status'] == '201': new_id = new_object_response[1]['id'] credentials['object_id'] = new_id object = '/objects/'+credentials['object_id'] try: credentials_out = open('credentials.json', 'w') credentials_out.write(json.dumps(credentials, indent=2)) finally: credentials_out.close() logging.warning('New object created: %s'%object) print 'New object created: %s'%object last_update = 1.0 logging.info("Object id: %s"%object) # Change out of the python directory to the root of the project os.chdir('..') # timestamp allows us to check for updated files if not last_update: try: timestamp_file = open('.timestamp', 'r') last_update = float(timestamp_file.read()) timestamp_file.close() except: last_update = 1.0 # Update the timestamp to now try: timestamp_file = open('.timestamp', 'w') timestamp_file.write(str(time.mktime(datetime.datetime.today().timetuple()))) finally: timestamp_file.close() # lets check we have a fluidApp namespace # Lets build the path as it would appear in FluidDB fluid_namespace_path = '/'.join(( '/namespaces', # namespaces root credentials['username'], # user's root namespace 'fluidapp', # the namespace underneath which we store fluid applications )) state_of_fluidapp_namespace = fd.call('GET', fluid_namespace_path) logging.info(state_of_fluidapp_namespace) if state_of_fluidapp_namespace[0]['status'] == '404': # The namespace that represents the fluidapp namespace logging.info('Creating new namespace for fluidapps') parent_namespace = '/'.join(fluid_namespace_path.split('/')[:-1]) logging.info('Parent namespace: %s'%parent_namespace) new_namespace_name = fluid_namespace_path.split('/')[-1:][0] logging.info('New namespace name: %s'%new_namespace_name) logging.info(fd.call('POST', parent_namespace, {'description': u'A namespace for storing fluidapps created by %s'%credentials['username'], 'name': new_namespace_name})) # navigate the directory tree and work out what are the new/updated files # and namespaces that need pushing to FluidDB for directory in os.walk('.'): processDirectoryIntoNamespace(directory, last_update, credentials, object)
def main(args): """ Set stuff up, read credentials, start the ball rolling """ logging.info("++++++++++++++++++++++++++++++++++++++++++++++") logging.info("++++++++++++++++++++++++++++++++++++++++++++++") logging.info("Starting push at %s"%datetime.datetime.today().ctime()) try: homedir = os.path.expanduser('~') logging.info("Attempting to load credentials.json from %s"%homedir) credentials_file = open('credentials.json', 'r') credentials = json.loads(credentials_file.read()) except Exception as e: logging.error("Could not process credentials...") logging.error(e) sys.exit() finally: credentials_file.close() if 'sandbox' in args: fd.prefix = fd.SANDBOX else: fd.prefix = fd.MAIN logging.info("FluidDB instance: %s"%fd.prefix) fd.login(credentials['username'], credentials['password']) new_object_flag = False last_update = False if credentials.has_key('object_id'): object = '/objects/'+credentials['object_id'] # lets just check we've got the expected object (in case of Sandbox reset) check_response = fd.call('GET', object) if check_response[0]['status'] == '200': new_object_flag = not check_response[1]['tagPaths'] else: new_object_flag = True else: new_object_flag = True if new_object_flag: # ok, so the expected object doesn't exist so create a new one and store # back in the credentials file... new_about = raw_input("Please describe your new FluidDB application: ") new_object_response = fd.call('POST', '/objects', {"about": new_about}) if new_object_response[0]['status'] == '201': new_id = new_object_response[1]['id'] credentials['object_id'] = new_id object = '/objects/'+credentials['object_id'] try: credentials_out = open('credentials.json', 'w') credentials_out.write(json.dumps(credentials, indent=2)) finally: credentials_out.close() logging.warning('New object created: %s'%object) print 'New object created: %s'%object last_update = 1.0 logging.info("Object id: %s"%object) os.chdir('..') if not last_update: try: timestamp_file = open('.timestamp', 'r') last_update = float(timestamp_file.read()) timestamp_file.close() except: last_update = 1.0 # Update the timestamp to now try: timestamp_file = open('.timestamp', 'w') timestamp_file.write(str(time.mktime(datetime.datetime.today().timetuple()))) finally: timestamp_file.close() # lets check we have a fluidApp namespace # Lets build the path as it would appear in FluidDB fluid_namespace_path = '/'.join(( '/namespaces', # namespaces root credentials['username'], # user's root namespace 'fluidapp', # the namespace underneath which we store fluid applications )) state_of_fluidapp_namespace = fd.call('GET', fluid_namespace_path) logging.info(state_of_fluidapp_namespace) if state_of_fluidapp_namespace[0]['status'] == '404': # The namespace that represents the fluidapp namespace logging.info('Creating new namespace for fluidapps') parent_namespace = '/'.join(fluid_namespace_path.split('/')[:-1]) logging.info('Parent namespace: %s'%parent_namespace) new_namespace_name = fluid_namespace_path.split('/')[-1:][0] logging.info('New namespace name: %s'%new_namespace_name) logging.info(fd.call('POST', parent_namespace, {'description': u'A namespace for storing fluidapps created by %s'%credentials['username'], 'name': new_namespace_name})) # navigate the directory tree and work out what are the new/updated files # and namespaces that need pushing to FluidDB for directory in os.walk('.'): processDirectoryIntoNamespace(directory, last_update, credentials, object)