User Tools

Site Tools


soft:server-apps-api

Api Application

This application provides support for building REST-style APIs in a pluggable way. It acts as a django-rest-framework proxy/adapter module, allowing us to base our development on this framework while being able to satisfy the most particular aspects of our API specifications.

In order to be automatically handled for this application, each app should provide its part of the API implementation in its own api.py module. More descriptive examples of how to register REST-style resources are provided on the following section.

Settings

  • CUSTOM_API_ROOT define a custom ApiBase class, i.e. CUSTOM_API_ROOT = 'controller.api.Base'

Resource registration pattern

api.options module provides support for pluggable resources on the REST API.

  1. It takes care of the url management:
    # controller/urls.py
    from api import api
    ...
    api.autodiscover()
     
    urlpatterns = patterns('',
        ...
        url(r'^api/', include(api.urls)),
    )
  2. Automatically find resources registred on app/api.py modules. An examples:
    # nodes/api.py
    from api import api
     
    class NodeList(generics.ListCreateAPIView):
        model = Node
        serializer_class = NodeSerializer
     
    class NodeDetail(generics.RetrieveUpdateDestroyAPIView):
        model = Node
        serializer_class = NodeSerializerapi.register(NodeResource)
     
    # for each resource you have to provide a ListView and a DetailView:
    api.register(NodeList, NodeDetail)
  3. Aggregate new fields to existing serializers (useful i.e. for Tinc pluggable app):
    # tinc/serializers.py
    from api import api
    class TincClientSerializer(serializers.ModelSerializer):
        connect_to = TincAddressSerializer()
        island = IslandSerializer()
        name = serializers.CharField()
     
        class Meta:
            model = TincClient
            exclude = ('object_id', 'content_type', 'id')
     
    api.aggregate(Server, TincClientSerializer, name='tinc')
  4. Automatically generates the Base resource which basically lists all the registered resources. Customization of the root api is enabled defining a new ApiRoot class and configuring the CUSTOM_API_ROOT setting value like: CUSTOM_API_ROOT = 'controller.api.Base'
    # controller/api.py
    class Base(ApiRoot):
        """ 
        **Media type:** [`application/vnd.confine.server.Base.v0+json`](http://
        wiki.confine-project.eu/arch:rest-api?&#base_at_server)
     
        This resource is located at the base URI of the server API. It 
        describes testbed-wide parameters and provides the API URIs to 
        navigate to other resources in the testbed.
     
        Note that you can also explore the API from the command line, for 
        instance using the curl command-line tool.
     
        For example: `curl -X GET https://controller.confine-project.eu/api/
        -H "Accept: application/json; indent=4"`
        """
        def get(self, *args, **kwargs):
            response = super(Base, self).get(*args, **kwargs)
            testbed_params = {
                "priv_ipv4_prefix_dflt": nodes_settings.PRIV_IPV4_PREFIX_DFLT,
                "sliver_mac_prefix_dflt": nodes_settings.SLIVER_MAC_PREFIX_DFLT, }
     
            if 'tinc' in settings.INSTALLED_APPS:
                from tinc.settings import MGMT_IPV6_PREFIX
                testbed_params.update({"mgmt_ipv6_prefix": MGMT_IPV6_PREFIX})
            response.data.update({"testbed_params": testbed_params})
            return response
  5. Provide specific serializer for resource creation (POST):
    # users/api.py
    class GroupList(generics.URIListCreateAPIView):
        model = Group
        add_serializer_class = GroupCreateSerializer
        serializer_class = GroupSerializer
        ...
     
    # users/serializers.py
    class GroupCreateSerializer(serializers.UriHyperlinkedModelSerializer):
        id = serializers.Field()
     
        class Meta:
            model = Group
            exclude = ('allow_nodes', 'allow_slices', 'user_roles')
     
    class GroupSerializer(GroupCreateSerializer):
        user_roles = UserRolesSerializer(source='roles', many=True, allow_add_remove=True)
        allow_nodes = serializers.BooleanField()
        allow_slices = serializers.BooleanField()
     
        class Meta:
            model = Group    
        ...

Using the API

  1. Get an auth token for your user username or email can be used indistinctly.
    curl -i -H "Accept: application/json" -X POST -d "username=pangea&password=pangea" \
        https://controller.confine-project.eu/api-token-auth/
     
    # OR use the email as user identifier
    curl -i -H "Accept: application/json" -X POST -d "username=pangea@example.com&password=pangea" \
        https://controller.confine-project.eu/api-token-auth/
     
  2. Authenticate requests using Tokens
    curl -i -H "Authorization: Token 755e6fd66dd9e74ca02c1e3f94ab9a4787351336" -X DELETE \
        https://controller.confine-project.eu/api/nodes/33
soft/server-apps-api.txt · Last modified: 2014/03/27 10:15 by santiago