Skip to content

Commit ec55a53

Browse files
committed
feat(controller): add resource services api
1 parent 11546a0 commit ec55a53

6 files changed

Lines changed: 81 additions & 4 deletions

File tree

charts/controller/templates/controller-clusterrole.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ rules:
6868
resources: ["persistentvolumeclaims"]
6969
verbs: ["get", "list", "watch", "create", "delete", "patch", "update"]
7070
- apiGroups: ["servicecatalog.k8s.io"]
71-
resources: ["serviceinstances"]
72-
verbs: ["get", "list", "watch", "create", "delete", "patch", "update"]
71+
resources: ["clusterserviceclasses", "serviceclasses", "clusterserviceplans", "serviceplans"]
72+
verbs: ["get", "list", "watch"]
7373
- apiGroups: ["servicecatalog.k8s.io"]
74-
resources: ["servicebindings"]
74+
resources: ["serviceinstances", "servicebindings"]
7575
verbs: ["get", "list", "watch", "create", "delete", "patch", "update"]
7676
{{- end -}}

rootfs/api/models/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,9 @@ class Meta:
6565
"""Mark :class:`AuditedModel` as abstract."""
6666
abstract = True
6767

68+
@classmethod
6869
@property
69-
def _scheduler(self):
70+
def _scheduler(cls):
7071
mod = importlib.import_module(settings.SCHEDULER_MODULE)
7172
return mod.SchedulerClient(settings.SCHEDULER_URL, settings.K8S_API_VERIFY_TLS)
7273

rootfs/api/models/resource.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,37 @@ def save(self, *args, **kwargs):
3535
# Save to DB
3636
return super(Resource, self).save(*args, **kwargs)
3737

38+
@classmethod
39+
@property
40+
def services(cls):
41+
services = []
42+
for serviceclass in cls._scheduler.svcat.get_serviceclasses().json()["items"]:
43+
services.append({
44+
"id": serviceclass["spec"]["externalID"],
45+
"name": serviceclass["spec"]["externalName"],
46+
"updateable": serviceclass["spec"]["planUpdatable"],
47+
})
48+
return services
49+
50+
@classmethod
51+
def plans(cls, serviceclass_name):
52+
serviceclass_id = None
53+
for service in cls.services:
54+
if service["name"] == serviceclass_name:
55+
serviceclass_id = service["id"]
56+
break
57+
58+
plans = []
59+
if serviceclass_id is not None:
60+
for serviceplan in cls._scheduler.svcat.get_serviceplans().json()["items"]:
61+
if serviceplan["spec"]["clusterServiceClassRef"]["name"] == serviceclass_id:
62+
plans.append({
63+
"id": serviceplan["spec"]["externalID"],
64+
"name": serviceplan["spec"]["externalName"],
65+
"description": serviceplan["spec"]["description"],
66+
})
67+
return plans
68+
3869
def attach(self, *args, **kwargs):
3970
try:
4071
self._scheduler.svcat.get_instance(self.app.id, self.name)

rootfs/api/urls.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@
8888
url(r"^apps/(?P<id>{})/volumes/(?P<name>[-_\w]+)/path/?$".format(settings.APP_URL_REGEX),
8989
views.AppVolumeMountPathViewSet.as_view({'patch': 'path'})),
9090
# application resources
91+
url(r"^resources/services/?$".format(settings.APP_URL_REGEX),
92+
views.AppResourcesViewSet.as_view({'get': 'services'})),
93+
url(r"^resources/services/(?P<id>[-_\w]+)/plans/?$".format(settings.APP_URL_REGEX),
94+
views.AppResourcesViewSet.as_view({'get': 'plans'})),
9195
url(r"^apps/(?P<id>{})/resources/?$".format(settings.APP_URL_REGEX),
9296
views.AppResourcesViewSet.as_view({'get': 'list', 'post': 'create'})),
9397
url(r"^apps/(?P<id>{})/resources/(?P<name>[-_\w]+)/?$".format(settings.APP_URL_REGEX),

rootfs/api/views.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,23 @@ class AppResourcesViewSet(AppResourceViewSet):
777777
model = models.Resource
778778
serializer_class = serializers.ResourceSerializer
779779

780+
def services(self, request, *args, **kwargs):
781+
results = self.model.services
782+
# fake out pagination for now
783+
pagination = {'results': results, 'count': len(results)}
784+
return Response(data=cache.get_or_set(
785+
"resources:services", pagination
786+
))
787+
788+
def plans(self, request, *args, **kwargs):
789+
serviceclass_name = kwargs["id"]
790+
results = self.model.plans(serviceclass_name)
791+
# fake out pagination for now
792+
pagination = {'results': results, 'count': len(results)}
793+
return Response(data=cache.get_or_set(
794+
"resources:services:%s:plan" % serviceclass_name, pagination
795+
))
796+
780797

781798
class AppSingleResourceViewSet(AppResourceViewSet):
782799
"""RESTful views for resource apps with collaborators."""

rootfs/scheduler/resources/svcat.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,30 @@ def service_instance_manifest(namespace, name, version=None, **kwargs):
3333
data["spec"]["externalID"] = kwargs.get('external_id')
3434
return data
3535

36+
def get_serviceclasses(self, namespace=None):
37+
if namespace is None:
38+
url = self.api('/clusterserviceclasses')
39+
message = 'get clusterserviceclasses'
40+
else:
41+
url = self.api('/namespaces/{}/serviceclasses', namespace)
42+
message = 'get serviceclasses ' + namespace
43+
response = self.http_get(url)
44+
if self.unhealthy(response.status_code):
45+
raise KubeHTTPException(response, message)
46+
return response
47+
48+
def get_serviceplans(self, namespace=None):
49+
if namespace is None:
50+
url = self.api('/clusterserviceplans')
51+
message = 'get clusterserviceplans'
52+
else:
53+
url = self.api('/namespaces/{}/serviceplans', namespace)
54+
message = 'get serviceplans ' + namespace
55+
response = self.http_get(url)
56+
if self.unhealthy(response.status_code):
57+
raise KubeHTTPException(response, message)
58+
return response
59+
3660
def get_instance(self, namespace, name=None):
3761
"""
3862
Fetch a single serviceinstance or a list of serviceinstances

0 commit comments

Comments
 (0)