Esempio n. 1
0
class TestClass(object):
    __metaclass__ = RestClientMetaClass
    some_resource = RestResource(
        "some_resource",
        "/{resource_one_id}/subresources/{resource_two_id}")
    extra_views_resource = RestResource(
        "books",
        "/{resource_one_id}/books/{bookid}",
        extra_views=["unavailable",
                     {"name": "get_all_books_status", "path": "status"}])
    detail_only_resource = RestResource(
        "auction",
        "/users/{user_id}/auctions/{auction_id}",
        methods=["detail"])
    extra_object_view_resource = RestResource(
        "tools",
        "/sheds/{shed_id}/tools/{tool_id}",
        extra_views=[
            {"name": "get_tool_users", "path": "users", "scope": "object"}]
    )
    custom_names_resource = RestResource(
        "stupidname",
        "/place/{objid}",
        method_names={
            "list": "get_birds",
            "object": "get_bird",
            "create": "create_bird",
            "update": "update_bird",
            "delete": "delete_bird"
        })
Esempio n. 2
0
 def test_resource_path_calculated_correctly(self):
     # Catch a bug where the url /accounts/{account_id}/phone_numbers/{phone_number}
     # was parsing incorrectly
     resource = RestResource("phone_numbers",
                             "/accounts/{account_id}/phone_numbers/{phone_number}")
     self.assertEqual(resource.path,
                      "/accounts/{account_id}/phone_numbers")
Esempio n. 3
0
 def test_custom_resource_names(self):
     method_names={"list":"get_books",
                   "object": "get_book",
                   "update": "update_book",
                   "create": "create_book",
                   "delete": "delete_book"}
     resource = RestResource("someresource", "/someplace/{resource_id}",
                             method_names=method_names)
     self.assertEqual(resource.method_names, method_names)
Esempio n. 4
0
 def test_resource_names_for_default_method_names(self):
     resource = RestResource("someresource", "/someplace/{resource_id}")
     method_names = resource.method_names
     expected_names = {"list": "get_someresources",
                       "object": "get_someresource",
                       "update": "update_someresource",
                       "create": "create_someresource",
                       "delete": "delete_someresource"}
     self.assertEqual(expected_names, method_names)
Esempio n. 5
0
 def test_custom_resource_names_merged_with_default(self):
     method_names = {"list": "get_books", "create": "create_book"}
     resource = RestResource("someresource", "/someplace/{resource_id}",
                             method_names=method_names)
     expected_names = dict(method_names)
     expected_names.update({
         "object": "get_someresource",
         "update": "update_someresource",
         "delete": "delete_someresource"
     })
     self.assertEqual(expected_names, resource.method_names)
Esempio n. 6
0
 def setUp(self):
     self.resource = RestResource(
         "somresource",
         "/{id1}/somesubresource/{id2}",
         extra_views=[
             {"path": "status", "name":  "all_devices_status"},
             "missing",
             {"path": "children", "name": "subresource_children",
              "scope": "object"},
             {"path": "ingredients", "name": "ingredients",
              "scope": "object", "method": "put"}]
     )
Esempio n. 7
0
class Client(object):
    """The interface to the Kazoo API

    This class should be initialized either with a username, password and
    account name combination, or with an API key. Once you have initialized
    the client you will need to call :meth:`authenticate()` before you can
    begin making API calls. ::

        >>>import kazoo
        >>>client = kazoo.Client(api_key="sdfasdfas")
        >>>client.authenticate()

    You can also initialize with a username and password combination: ::

        >>>client = kazoo.Client(username="******", password="******", account_name="my_account_name")
        >>>client.authenticate()

    API calls which require data take it in the form of a required argument
    called 'data' which is the last argument to the method. For example ::

        >>>client.update_account(acct_id, {"name": "somename", "realm":"superfunrealm"})

    Dictionaries and lists will automatically be converted to their appropriate
    representation so you can do things like: ::

        >>>client.update_callflow(acct_id, callflow_id, {"flow":{"module":"somemodule"}})

    Invalid data will result in an exception explaining the problem.

    The server response is returned from each method as a python dictionary of
    the returned JSON object, for example: ::

        >>>client.get_account(acct_id)
        {u'auth_token': u'abc437d000007d0454cc984f6f09daf3',
         u'data': {u'billing_mode': u'normal',
          u'caller_id': {},
          u'caller_id_options': {},
          u'id': u'c4f64412ad0057222c0009a3e7da011',
          u'media': {u'bypass_media': u'auto'},
          u'music_on_hold': {},
          u'name': u'test3',
          u'notifications': {},
          u'realm': u'4c8050.sip.2600hz.com',
          u'superduper_admin': False,
          u'timezone': u'America/Los_Angeles',
          u'wnm_allow_additions': False},
         u'request_id': u'ea6441422fb85000ad21db4f1e2326c1',
         u'revision': u'3-c16dd0a629fe1da0000e1e7b3e5fb35a',
         u'status': u'success'}

    For each resource exposed by the kazoo api there are corresponding methods
    on the client. For example, for the 'callflows' resource the
    correspondence is as follows. ::

        GET /accounts/{account_id}/callflows -> client.get_callflows(acct_id)
        GET /accounts/{account_id}/callflows/{callflow_id} -> client.get_callflow(acct_id, callflow_id)
        PUT /accounts/{account_id}/callflows/ -> client.create_callflow(acct_id, data)
        POST /account/{account_id}/callflows/{callflow_id} -> client.update_callflow(acct_id, data)
        DELETE /account/{account_id}/callflows/{callflow_id} -> client.delete_callflow(acct_id, callflow_id)

    Some resources do not have all methods available, in which case they are
    not present on the client.

    There are also some resources which don't quite fit this paradigm, they are: ::

        GET /accounts/{account_id}/media -> client.get_all_media(acct_id)
        GET /accounts/{account_id}/children -> client.get_account_children(acct_id)
        GET /accounts/{account_id}/descendants -> client.get_account_descendants(acct_id)
        GET /accounts/{account_id}/devices/status -> client.get_all_devices_status(acct_id)
        GET /accounts/{account_id}/servers/{server_id}/deployment -> client.get_deployment(acct_id, server_id)
        GET /accounts/{account_id}/users/hotdesk -> client.get_hotdesk(acct_id)

    """
    __metaclass__ = RestClientMetaClass
    BASE_URL = "http://api.2600hz.com:8000/v1"

    _accounts_resource = RestResource(
        "account",
        "/accounts/{account_id}",
        exclude_methods=["list", "delete", "create"],
        extra_views=[{
            "name": "get_account_children",
            "path": "children",
            "scope": "object"
        }, {
            "name": "get_account_descendants",
            "path": "descendants",
            "scope": "object"
        }])
    _callflow_resource = RestResource(
        "callflow", "/accounts/{account_id}/callflows/{callflow_id}")
    _conference_resource = RestResource(
        "conference", "/accounts/{account_id}/conferences/{conference_id}")
    _device_resource = RestResource(
        "device",
        "/accounts/{account_id}/devices/{device_id}",
        extra_views=[{
            "name": "get_all_devices_status",
            "path": "status"
        }])
    _directories_resource = RestResource(
        "directory",
        "/accounts/{account_id}/directories/{directory_id}",
        plural_name="directories")
    _global_resources = RestResource(
        "global_resource",
        "/accounts/{account_id}/global_resources/{resource_id}")
    _limits_resource = RestResource("limit",
                                    "/accounts/{account_id}/limits/{ignored}",
                                    methods=["list"])
    _local_resources_resource = RestResource(
        "local_resource",
        "/accounts/{account_id}/local_resources/{resource_id}")
    _media_resource = RestResource("media",
                                   "/accounts/{account_id}/media/{media_id}",
                                   plural_name="media",
                                   method_names={"list": "get_all_media"})
    _menus_resource = RestResource("menu",
                                   "/accounts/{account_id}/menus/{menu_id}")
    _phone_number_resource = RestResource(
        "phone_number",
        "/accounts/{account_id}/phone_numbers/{phone_number}",
        methods=["list", "update", "delete"],
        extra_views=[{
            "name": "activate_phone_number",
            "path": "activate",
            "scope": "object",
            "method": "put"
        }, {
            "name": "reserve_phone_number",
            "path": "reserve",
            "scope": "object",
            "method": "put"
        }, {
            "name": "add_port_in_number",
            "path": "port",
            "scope": "object",
            "method": "put"
        }])
    _queues_resource = RestResource(
        "queue", "/accounts/{account_id}/queues/{queue_id}")
    _server_resource = RestResource(
        "server",
        "/accounts/{account_id}/servers/{server_id}",
        methods=["list"],
        extra_views=[{
            "name": "get_deployment",
            "path": "deployment",
            "scope": "object"
        }, {
            "name": "create_deployment",
            "path": "deployment",
            "scope": "object",
            "method": "put"
        }, {
            "name": "get_server_log",
            "path": "log"
        }])
    _temporal_rules_resource = RestResource(
        "temporal_rule", "/accounts/{account_id}/temporal_rules/{rule_id}")
    _users_resource = RestResource("user",
                                   "/accounts/{account_id}/users/{user_id}",
                                   extra_views=[{
                                       "name": "get_hotdesk",
                                       "path": "hotdesks"
                                   }])
    _vmbox_resource = RestResource("voicemail_box",
                                   "/accounts/{account_id}/vmboxes/{vmbox_id}",
                                   plural_name="voicemail_boxes")
    _phone_number_docs_resource = RestResource(
        "phone_number_doc",
        "/accounts/{account_id}/phone_numbers/{phone_number}/docs/{filename}",
        methods=["delete"],
    )

    def __init__(self,
                 api_key=None,
                 password=None,
                 account_name=None,
                 username=None):
        if not api_key and not password:
            raise RuntimeError("You must pass either an api_key or an "
                               "account name/password pair")

        if password or account_name or username:
            if not (password and account_name and username):
                raise RuntimeError("If using account name/password "
                                   "authentication then you must specify "
                                   "password, userame and account_name "
                                   "arguments")
            self.auth_request = UsernamePasswordAuthRequest(
                username, password, account_name)
        else:
            self.auth_request = ApiKeyAuthRequest(api_key)

        self.api_key = api_key
        self._authenticated = False
        self.auth_token = None

    def authenticate(self):
        """Call this before making other api calls to fetch an auth token
        which will be automatically used for all further requests
        """
        if not self._authenticated:
            self.auth_data = self.auth_request.execute(self.BASE_URL)
            self.auth_token = self.auth_data["auth_token"]
            self._authenticated = True
        return self.auth_token

    def _execute_request(self, request, **kwargs):
        if request.auth_required:
            kwargs["token"] = self.auth_token
        return request.execute(self.BASE_URL, **kwargs)

    def search_phone_numbers(self, prefix, quantity=10):
        request = KazooRequest("/phone_numbers",
                               get_params={
                                   "prefix": prefix,
                                   "quantity": quantity
                               })
        return self._execute_request(request)

    def create_phone_number(self, acct_id, phone_number):
        request = KazooRequest(
            "/accounts/{account_id}/phone_numbers/{phone_number}",
            method="put")
        return self._execute_request(request,
                                     account_id=acct_id,
                                     phone_number=phone_number)

    def upload_phone_number_file(self, acct_id, phone_number, filename,
                                 file_obj):
        """Uploads a file like object as part of a phone numbers documents"""
        request = KazooRequest(
            "/accounts/{account_id}/phone_numbers/{phone_number}",
            method="post")
        return self._execute_request(request, files={filename: file_obj})
Esempio n. 8
0
 def setUp(self):
     self.path = "/{argument1}/subresource/{argument2}"
     self.resource = RestResource(
         "subresource", "/{argument1}/subresource/{argument2}")
Esempio n. 9
0
 def test_resource_with_no_required_args_correct(self):
     resource = RestResource("somename", "/sompath/{someobj_id}")
     self.assertEqual(resource.required_args, [])
     self.assertEqual(resource.object_arg, "someobj_id")
Esempio n. 10
0
 def test_resource_with_no_args_generates_error(self):
     with self.assertRaises(ValueError):
         resource = RestResource("somename", "/blahblah/blah")
Esempio n. 11
0
 def test_excludes_resource(self):
     resource = RestResource("subresource", "/{oneid}/someplace",
                             exclude_methods=["list", "detail"])
     self.assertEqual(resource.methods, ["create", "update", "delete"])
Esempio n. 12
0
 def test_if_plural_name_set_in_constructor_then_use_that(self):
     resource = RestResource("subresource", "/{oneid}/someotherplace",
                             plural_name="subresourcae")
     self.assertEqual(resource.plural_name, "subresourcae")
Esempio n. 13
0
 def test_resource_plural_name(self):
     resource = RestResource("subresource", "/{oneid}/someotherplace")
     self.assertEqual(resource.plural_name, "subresources")