Skip to content

Commit 2a49324

Browse files
author
Bojan Jovanovic
committed
Adds update_or_create function, and also adapts some views to kong 1.1 api
Signed-off-by: Bojan Jovanovic <bojan@kortechs.io>
1 parent dc131dc commit 2a49324

7 files changed

Lines changed: 55 additions & 18 deletions

File tree

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ python:
77
- "3.7-dev" # 3.7 development branch
88
# command to install dependencies
99
install:
10-
- pip install -r requirements.txt
10+
- pip install .[testing]
1111
- npm install
1212
script:
1313
- ./scripts/tests.sh

kong/exceptions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
class SchemaViolation(Exception):
22
pass
3+
4+
5+
class ObjectNotFound(Exception):
6+
pass

kong/kong_clients.py

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1+
import logging
12
from abc import abstractmethod
3+
4+
import dictdiffer
25
from urllib3.util.url import Url, parse_url
36
from requests import session
47
from kong.structures import ApiData, ServiceData, ConsumerData, \
58
PluginData, RouteData, TargetData, UpstreamData
6-
from kong.exceptions import SchemaViolation
9+
from kong.exceptions import SchemaViolation, ObjectNotFound
10+
11+
logger = logging.getLogger(__name__)
712

813

914
class RestClient: # pylint:disable=too-few-public-methods
@@ -68,6 +73,17 @@ def _to_object_data(self, data_dict):
6873
def _to_list_object_data(self, list_data_dict):
6974
return map(self._to_object_data, list_data_dict)
7075

76+
def update_or_create(self, **kwargs):
77+
pk_or_id = kwargs.get(self._object_data_class.pk_identifier)
78+
try:
79+
data_dict = self._perform_retrieve(pk_or_id)
80+
except ObjectNotFound:
81+
return self.create(**kwargs)
82+
83+
self.update(pk_or_id, **kwargs)
84+
85+
return self._to_object_data(data_dict)
86+
7187
def create(self, **kwargs):
7288
data_dict = self._perform_create(**kwargs)
7389
return self._to_object_data(data_dict)
@@ -177,6 +193,9 @@ def _send_retrieve(self, name_or_id, endpoint=None):
177193
response = self.session.get(url)
178194

179195
if response.status_code == 404:
196+
if response.json().get('message') == "Not found":
197+
raise ObjectNotFound(response.content)
198+
180199
raise NameError(response.content)
181200

182201
if response.status_code != 200:
@@ -188,7 +207,7 @@ def _validate_params(self, query_params, allowed_params):
188207
validated_params = {}
189208
for k, val in query_params.items():
190209
if k in allowed_params:
191-
validated_params[k] = self._stringify_if_list(val)
210+
validated_params[k] = val # self._stringify_if_list(val)
192211
else:
193212
raise KeyError('invalid query parameter: %s' % k)
194213
return validated_params
@@ -409,11 +428,11 @@ def _object_data_class(self):
409428
def _allowed_update_params(self):
410429
return 'name', 'protocol', 'host', 'port', 'path', \
411430
'retries', 'connect_timeout', 'send_timeout', \
412-
'read_timeout', 'url'
431+
'read_timeout', 'url', "tags"
413432

414433
@property
415434
def _allowed_query_params(self):
416-
return []
435+
return ["tags"]
417436

418437
@property
419438
def _path(self):
@@ -432,9 +451,9 @@ def _object_data_class(self):
432451

433452
@property
434453
def _allowed_update_params(self):
435-
return 'protocols', 'methods', 'hosts',\
454+
return 'name', 'protocols', 'methods', 'hosts',\
436455
'paths', 'strip_path', 'preserve_host',\
437-
'service',
456+
'service', 'tags'
438457

439458
@property
440459
def _allowed_query_params(self):
@@ -444,6 +463,13 @@ def _allowed_query_params(self):
444463
def _path(self):
445464
return 'routes/'
446465

466+
# pylint: disable=arguments-differ
467+
def _perform_update(self, pk_or_id, **kwargs):
468+
if 'service' in kwargs.keys():
469+
kwargs['service'] = {"id": self.get_service_id(kwargs['service'])}
470+
471+
return super(RouteAdminClient, self)._perform_update(pk_or_id, **kwargs)
472+
447473
# pylint: disable=arguments-differ
448474
def _perform_create(self, service, **kwargs):
449475

kong/structures.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ def __normalize_uri(uri):
8989

9090

9191
class ServiceData(ObjectData):
92+
pk_identifier = 'name'
9293

9394
def validate_semi_optional_parameters(self, **kwargs):
9495
pass
@@ -128,7 +129,7 @@ def allowed_parameters(self):
128129
return 'name', 'protocol', 'host', 'port', 'path',\
129130
'retries', 'connect_timeout', 'send_timeout',\
130131
'read_timeout', 'url', 'id', \
131-
'created_at', 'updated_at', 'write_timeout'
132+
'created_at', 'updated_at', 'write_timeout', 'tags'
132133

133134
@property
134135
def url(self):
@@ -156,7 +157,7 @@ def validate_obligatory_parameters(self, **kwargs):
156157

157158
@property
158159
def allowed_parameters(self):
159-
return "id", "username", "custom_id", "created_at"
160+
return "id", "username", "custom_id", "created_at", "tags"
160161

161162
def validate_semi_optional_parameters(self, **kwargs):
162163
if ("username" not in kwargs) and ("custom_id" not in kwargs):
@@ -166,6 +167,7 @@ def validate_semi_optional_parameters(self, **kwargs):
166167

167168

168169
class RouteData(ObjectData):
170+
pk_identifier = 'name'
169171

170172
def validate_semi_optional_parameters(self, **kwargs):
171173
if not ('hosts' in kwargs
@@ -178,10 +180,11 @@ def validate_obligatory_parameters(self, **kwargs):
178180

179181
@property
180182
def allowed_parameters(self):
181-
return "id", "created_at", "updated_at", \
183+
return "name", "id", "created_at", "updated_at", \
182184
"protocols", "methods", "hosts", \
183185
"paths", "regex_priority", "strip_path", \
184-
"preserve_host", "service"
186+
"preserve_host", "service", "snis", "sources", \
187+
"destinations", "tags"
185188

186189

187190
class TargetData(ObjectData):

readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Supported Information Routes
1212
- node_information
1313

1414
Supported operations for Services, Routes, Apis, Consumers, Plugins and Upstreams
15+
- update_or_create
1516
- create
1617
- delete
1718
- retrieve
@@ -33,7 +34,6 @@ Additional supported operations for Targets
3334
- set_healthy
3435

3536
Not supported
36-
- update_or_create
3737
- count (dropped in 0.16/kong 0.13.0)
3838
- Certificates object routes (yet)
3939
- SNI object routes (yet)

requirements/testing.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
-r base.txt
21
flake8==3.5.0 # This covers pycodestyle
32
pylint==1.8.2
43
pytest==3.4.0

setup.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from os.path import dirname
44
from os.path import join
55

6-
6+
from pip._internal.req import parse_requirements
77
from setuptools import setup
88

99
__version__ = '0.1.7'
@@ -18,9 +18,12 @@ def read(*names, **kwargs):
1818
).read()
1919

2020

21-
# parse_requirements() returns generator of pip.req.InstallRequirement objects
22-
requirements = []
23-
# requirements_test = [str(ir.req) for ir in parse_requirements('./requirements-test.txt', session=False)]
21+
with open(os.path.join(BASE_DIR, 'requirements', 'base.txt')) as f:
22+
requirements = f.read().splitlines()
23+
24+
with open(os.path.join(BASE_DIR, 'requirements', 'testing.txt')) as f:
25+
requirements_test = f.read().splitlines()
26+
2427

2528
setup(
2629
name='python-kong-client',
@@ -42,5 +45,7 @@ def read(*names, **kwargs):
4245
],
4346
keywords=[],
4447
install_requires=requirements,
45-
extras_require={},
48+
extras_require={
49+
"tests": requirements_test
50+
},
4651
)

0 commit comments

Comments
 (0)