CORD-762 extend core API to all django apps
Change-Id: Iab9aad98e078685c8e24a4474732115527a0263a
diff --git a/xos/grpc/apihelper.py b/xos/grpc/apihelper.py
index e6d3a40..04f22d2 100644
--- a/xos/grpc/apihelper.py
+++ b/xos/grpc/apihelper.py
@@ -12,6 +12,16 @@
SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
class XOSAPIHelperMixin(object):
+ def __init__(self):
+ import django.apps
+
+ self.models = {}
+ for model in django.apps.apps.get_models():
+ self.models[model.__name__] = model
+
+ def get_model(self, name):
+ return self.models[name]
+
def getProtoClass(self, djangoClass):
pClass = getattr(xos_pb2, djangoClass.__name__)
return pClass
diff --git a/xos/grpc/protos/Makefile b/xos/grpc/protos/Makefile
index df07cfd..aeee046 100644
--- a/xos/grpc/protos/Makefile
+++ b/xos/grpc/protos/Makefile
@@ -82,7 +82,7 @@
sudo make uninstall
rebuild-protos:
- cd ../../tools/apigen && python ./modelgen -a core protobuf.template.txt > /opt/xos/grpc/protos/xos.proto
- cd ../../tools/apigen && python ./modelgen -a core grpc_api.template.py > /opt/xos/grpc/xos_grpc_api.py
- cd ../../tools/apigen && python ./modelgen -a core grpc_list_test.template.py > /opt/xos/grpc/list_test.py
- cd ../../tools/apigen && python ./modelgen -a core chameleon_list_test.template.sh > /opt/xos/grpc/tests/chameleon_list_test.sh
+ cd ../../tools/apigen && python ./modelgen -a "*" protobuf.template.txt > /opt/xos/grpc/protos/xos.proto
+ cd ../../tools/apigen && python ./modelgen -a "*" grpc_api.template.py > /opt/xos/grpc/xos_grpc_api.py
+ cd ../../tools/apigen && python ./modelgen -a "*" grpc_list_test.template.py > /opt/xos/grpc/list_test.py
+ cd ../../tools/apigen && python ./modelgen -a "*" chameleon_list_test.template.sh > /opt/xos/grpc/tests/chameleon_list_test.sh
diff --git a/xos/tools/apigen/chameleon_list_test.template.sh b/xos/tools/apigen/chameleon_list_test.template.sh
index e46503d..c3297f3 100644
--- a/xos/tools/apigen/chameleon_list_test.template.sh
+++ b/xos/tools/apigen/chameleon_list_test.template.sh
@@ -7,7 +7,7 @@
fi
{% for object in generator.all() %}
-curl -f --silent http://$HOSTNAME:8080/xosapi/v1/{{ object.camel()|lower }}s > /dev/null
+curl -f --silent http://$HOSTNAME:8080/xosapi/v1/{{ object.app_name }}/{{ object.plural() }} > /dev/null
if [[ $? -ne 0 ]]; then
echo fail {{ object.camel() }}
fi
diff --git a/xos/tools/apigen/grpc_api.template.py b/xos/tools/apigen/grpc_api.template.py
index 9e23db5..fccec40 100644
--- a/xos/tools/apigen/grpc_api.template.py
+++ b/xos/tools/apigen/grpc_api.template.py
@@ -4,37 +4,42 @@
from google.protobuf.empty_pb2 import Empty
from django.contrib.auth import authenticate as django_authenticate
-from core.models import *
from xos.exceptions import *
from apihelper import XOSAPIHelperMixin
class XosService(xos_pb2.xosServicer, XOSAPIHelperMixin):
def __init__(self, thread_pool):
- self.thread_pool = thread_pool
-
- def stop(self):
+ self.thread_pool = thread_pool
+ XOSAPIHelperMixin.__init__(self)
+
+ def stop(self):
pass
{% for object in generator.all() %}
def List{{ object.camel() }}(self, request, context):
user=self.authenticate(context)
- return self.querysetToProto({{ object.camel() }}, {{ object.camel() }}.objects.all())
+ model=self.get_model("{{ object.camel() }}")
+ return self.querysetToProto(model, model.objects.all())
def Get{{ object.camel() }}(self, request, context):
user=self.authenticate(context)
- return self.get({{ object.camel() }}, request.id)
+ model=self.get_model("{{ object.camel() }}")
+ return self.get(model, request.id)
def Create{{ object.camel() }}(self, request, context):
user=self.authenticate(context)
- return self.create({{ object.camel() }}, user, request)
+ model=self.get_model("{{ object.camel() }}")
+ return self.create(model, user, request)
def Delete{{ object.camel() }}(self, request, context):
user=self.authenticate(context)
- return self.delete({{ object.camel() }}, user, request.id)
+ model=self.get_model("{{ object.camel() }}")
+ return self.delete(model, user, request.id)
def Update{{ object.camel() }}(self, request, context):
user=self.authenticate(context)
- return self.update({{ object.camel() }}, user, request.id, request)
+ model=self.get_model("{{ object.camel() }}")
+ return self.update(model, user, request.id, request)
{% endfor %}
diff --git a/xos/tools/apigen/modelgen b/xos/tools/apigen/modelgen
index 2beb508..44eaec4 100755
--- a/xos/tools/apigen/modelgen
+++ b/xos/tools/apigen/modelgen
@@ -16,6 +16,7 @@
sys.path.append('/opt/xos')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xos.settings")
from django.db.models.fields.related import ForeignKey, ManyToManyField
+from django.conf import settings
django.setup()
@@ -52,6 +53,13 @@
for classname in dir(models_module):
c = getattr(models_module, classname, None)
+
+ # For services, prevent loading of core models as it causes
+ # duplication.
+ if hasattr(c,"_meta") and hasattr(c._meta, "app_label"):
+ if (c._meta.app_label == "core") and (orig_app!="core"):
+ continue
+
if type(c)==type(PlCoreBase) and c.__name__ not in options.blacklist:
model_classes.append(c)
app_map[c.__name__]=orig_app
@@ -135,7 +143,8 @@
obj = GenObj(o)
fields = o._meta.fields
try:
- obj.app = app_map[o.__name__]
+ obj.app = app_map[o.__name__] # full name
+ obj.app_name = app_map[o.__name__].split(".")[-1] # only the last part
except KeyError:
print "KeyError: %r"%o.__name__
obj.class_name = o.class_name
@@ -231,8 +240,23 @@
obj.reverse_refs.append(cobj)
+def app_has_models(app):
+ """ check whether 'app' includes XOS models """
+ app = app + ".models"
+ try:
+ models_module = __import__(app)
+ except ImportError:
+ return False
+ for part in app.split(".")[1:]:
+ if hasattr(models_module, "PlCoreBase"):
+ return True
+ models_module = getattr(models_module,part)
+ if hasattr(models_module, "PlCoreBase"):
+ return True
+
+ return False
def main():
global options
@@ -250,13 +274,6 @@
(options, args) = parser.parse_args(sys.argv[1:])
- if not options.apps:
- options.apps = ["core"]
-
- if len(args)!=1:
- print 'Usage: modelgen [options] <template_fn>'
- exit(1)
-
template_name = os.path.abspath(args[0])
# try to make sure we're running from the right place
@@ -269,6 +286,16 @@
print >> sys.stderr, "Are you sure you're running modelgen from the root of an XOS installation"
sys.exit(-1)
+ if not options.apps:
+ options.apps = ["core"]
+
+ if options.apps == ["*"]:
+ options.apps = [x for x in settings.INSTALLED_APPS if app_has_models(x)]
+
+ if len(args)!=1:
+ print 'Usage: modelgen [options] <template_fn>'
+ exit(1)
+
generator = Generator()
models = enum_classes(options.apps)
diff --git a/xos/tools/apigen/protobuf.template.txt b/xos/tools/apigen/protobuf.template.txt
index 1c9ce4b..75d0b3c 100644
--- a/xos/tools/apigen/protobuf.template.txt
+++ b/xos/tools/apigen/protobuf.template.txt
@@ -72,29 +72,29 @@
{% for object in generator.all() %}
rpc List{{ object.camel() }}(google.protobuf.Empty) returns ({{ object.camel() }}s) {
option (google.api.http) = {
- get: "/xosapi/v1/{{ object.plural() }}"
+ get: "/xosapi/v1/{{ object.app_name }}/{{ object.plural() }}"
};
}
rpc Get{{ object.camel() }}(ID) returns ({{ object.camel() }}) {
option (google.api.http) = {
- get: "/xosapi/v1/{{ object.plural() }}/{id}"
+ get: "/xosapi/v1/{{ object.app_name }}/{{ object.plural() }}/{id}"
};
}
rpc Create{{ object.camel() }}({{ object.camel() }}) returns ({{ object.camel() }}) {
option (google.api.http) = {
- post: "/xosapi/v1/{{ object.plural() }}"
+ post: "/xosapi/v1/{{ object.app_name }}/{{ object.plural() }}"
body: "*"
};
}
rpc Update{{ object.camel() }}({{ object.camel() }}) returns ({{ object.camel() }}) {
option (google.api.http) = {
- put: "/xosapi/v1/{{ object.plural() }}/{id}"
+ put: "/xosapi/v1/{{ object.app_name }}/{{ object.plural() }}/{id}"
body: "*"
};
}
rpc Delete{{ object.camel() }}(ID) returns (google.protobuf.Empty) {
option (google.api.http) = {
- delete: "/xosapi/v1/{{ object.plural() }}/{id}"
+ delete: "/xosapi/v1/{{ object.app_name }}/{{ object.plural() }}/{id}"
};
}
{% endfor %}