forked from GithubBackups/healthchecks
Merge branch 'jameskirsop-api-single-check'
This commit is contained in:
commit
ffc7ccddf2
@ -224,7 +224,7 @@ class Check(models.Model):
|
||||
if readonly:
|
||||
result["unique_key"] = self.unique_key
|
||||
else:
|
||||
update_rel_url = reverse("hc-api-update", args=[self.code])
|
||||
update_rel_url = reverse("hc-api-single", args=[self.code])
|
||||
pause_rel_url = reverse("hc-api-pause", args=[self.code])
|
||||
|
||||
result["ping_url"] = self.url()
|
||||
|
55
hc/api/tests/test_get_check.py
Normal file
55
hc/api/tests/test_get_check.py
Normal file
@ -0,0 +1,55 @@
|
||||
from datetime import timedelta as td
|
||||
import uuid
|
||||
|
||||
from django.utils.timezone import now
|
||||
from hc.api.models import Channel, Check
|
||||
from hc.test import BaseTestCase
|
||||
|
||||
|
||||
class GetCheckTestCase(BaseTestCase):
|
||||
def setUp(self):
|
||||
super(GetCheckTestCase, self).setUp()
|
||||
|
||||
self.now = now().replace(microsecond=0)
|
||||
|
||||
self.a1 = Check(project=self.project, name="Alice 1")
|
||||
self.a1.timeout = td(seconds=3600)
|
||||
self.a1.grace = td(seconds=900)
|
||||
self.a1.n_pings = 0
|
||||
self.a1.status = "new"
|
||||
self.a1.tags = "a1-tag a1-additional-tag"
|
||||
self.a1.desc = "This is description"
|
||||
self.a1.save()
|
||||
|
||||
self.c1 = Channel.objects.create(project=self.project)
|
||||
self.a1.channel_set.add(self.c1)
|
||||
|
||||
def get(self, code):
|
||||
url = "/api/v1/checks/%s" % code
|
||||
return self.client.get(url, HTTP_X_API_KEY="X" * 32)
|
||||
|
||||
def test_it_works(self):
|
||||
r = self.get(self.a1.code)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
self.assertEqual(r["Access-Control-Allow-Origin"], "*")
|
||||
|
||||
doc = r.json()
|
||||
self.assertEqual(len(doc), 13)
|
||||
|
||||
self.assertEqual(doc["timeout"], 3600)
|
||||
self.assertEqual(doc["grace"], 900)
|
||||
self.assertEqual(doc["ping_url"], self.a1.url())
|
||||
self.assertEqual(doc["last_ping"], None)
|
||||
self.assertEqual(doc["n_pings"], 0)
|
||||
self.assertEqual(doc["status"], "new")
|
||||
self.assertEqual(doc["channels"], str(self.c1.code))
|
||||
self.assertEqual(doc["desc"], "This is description")
|
||||
|
||||
def test_it_handles_invalid_uuid(self):
|
||||
r = self.get("not-an-uuid")
|
||||
self.assertEqual(r.status_code, 404)
|
||||
|
||||
def test_it_handles_missing_check(self):
|
||||
made_up_code = "07c2f548-9850-4b27-af5d-6c9dc157ec02"
|
||||
r = self.get(made_up_code)
|
||||
self.assertEqual(r.status_code, 404)
|
@ -72,11 +72,6 @@ class UpdateCheckTestCase(BaseTestCase):
|
||||
check = Check.objects.get()
|
||||
self.assertEqual(check.channel_set.count(), 0)
|
||||
|
||||
def test_it_requires_post(self):
|
||||
url = "/api/v1/checks/%s" % self.check.code
|
||||
r = self.client.get(url, HTTP_X_API_KEY="X" * 32)
|
||||
self.assertEqual(r.status_code, 405)
|
||||
|
||||
def test_it_handles_invalid_uuid(self):
|
||||
r = self.post("not-an-uuid", {"api_key": "X" * 32})
|
||||
self.assertEqual(r.status_code, 404)
|
||||
|
@ -22,7 +22,7 @@ urlpatterns = [
|
||||
path("ping/<uuid:code>/fail", views.ping, {"action": "fail"}, name="hc-fail"),
|
||||
path("ping/<uuid:code>/start", views.ping, {"action": "start"}, name="hc-start"),
|
||||
path("api/v1/checks/", views.checks),
|
||||
path("api/v1/checks/<uuid:code>", views.update, name="hc-api-update"),
|
||||
path("api/v1/checks/<uuid:code>", views.single, name="hc-api-single"),
|
||||
path("api/v1/checks/<uuid:code>/pause", views.pause, name="hc-api-pause"),
|
||||
path("api/v1/notifications/<uuid:code>/bounce", views.bounce, name="hc-api-bounce"),
|
||||
path("api/v1/channels/", views.channels),
|
||||
|
@ -19,6 +19,7 @@ from hc.api import schemas
|
||||
from hc.api.decorators import authorize, authorize_read, cors, validate_json
|
||||
from hc.api.models import Check, Notification, Channel
|
||||
from hc.lib.badges import check_signature, get_badge_svg
|
||||
from hc.lib.jsonschema import ValidationError, validate
|
||||
|
||||
|
||||
class BadChannelException(Exception):
|
||||
@ -178,18 +179,19 @@ def channels(request):
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
@cors("POST", "DELETE")
|
||||
@validate_json(schemas.check)
|
||||
@cors("POST", "DELETE", "GET")
|
||||
@validate_json()
|
||||
@authorize
|
||||
def update(request, code):
|
||||
def single(request, code):
|
||||
check = get_object_or_404(Check, code=code)
|
||||
if check.project != request.project:
|
||||
return HttpResponseForbidden()
|
||||
|
||||
if request.method == "POST":
|
||||
try:
|
||||
validate(request.json, schemas.check)
|
||||
_update(check, request.json)
|
||||
except BadChannelException as e:
|
||||
except (BadChannelException,ValidationError) as e:
|
||||
return JsonResponse({"error": str(e)}, status=400)
|
||||
|
||||
return JsonResponse(check.to_dict())
|
||||
@ -199,10 +201,21 @@ def update(request, code):
|
||||
check.delete()
|
||||
return JsonResponse(response)
|
||||
|
||||
elif request.method == "GET":
|
||||
return JsonResponse(check.to_dict())
|
||||
|
||||
# Otherwise, method not allowed
|
||||
return HttpResponse(status=405)
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
@cors("POST", "DELETE")
|
||||
@validate_json(schemas.check)
|
||||
@authorize
|
||||
def update(request, code):
|
||||
single(request, code)
|
||||
|
||||
|
||||
@cors("POST")
|
||||
@csrf_exempt
|
||||
@validate_json()
|
||||
|
@ -15,6 +15,10 @@ checks in user's account.</p>
|
||||
<td><code>GET SITE_ROOT/api/v1/checks/</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#get-check">Create a single check</a></td>
|
||||
<td><code>GET SITE_ROOT/api/v1/checks/<uuid></code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#create-check">Create a new check</a></td>
|
||||
<td><code>POST SITE_ROOT/api/v1/checks/</code></td>
|
||||
</tr>
|
||||
@ -174,6 +178,40 @@ is added. This identifier is stable across API calls. Example:</p>
|
||||
</code></pre></div>
|
||||
|
||||
|
||||
<h2 class="rule" id="get-check">Get a single Check</h2>
|
||||
<p><code>GET SITE_ROOT/api/v1/checks/<uuid></code></p>
|
||||
<p>Returns a JSON object containing information information from a single check.</p>
|
||||
<h3>Response Codes</h3>
|
||||
<dl>
|
||||
<dt>200 OK</dt>
|
||||
<dd>The request succeeded.</dd>
|
||||
<dt>401 Unauthorized</dt>
|
||||
<dd>The API key is either missing or invalid.</dd>
|
||||
</dl>
|
||||
<h3>Example Request</h3>
|
||||
<div class="highlight"><pre><span></span><code>curl --header <span class="s2">"X-Api-Key: your-api-key"</span> SITE_ROOT/api/v1/checks/<uuid>
|
||||
</code></pre></div>
|
||||
|
||||
|
||||
<h3>Example Response</h3>
|
||||
<div class="highlight"><pre><span></span><code><span class="p">{</span>
|
||||
<span class="nt">"channels"</span><span class="p">:</span> <span class="s2">"4ec5a071-2d08-4baa-898a-eb4eb3cd6941,746a083e-f542-4554-be1a-707ce16d3acc"</span><span class="p">,</span>
|
||||
<span class="nt">"desc"</span><span class="p">:</span> <span class="s2">"Longer free-form description goes here"</span><span class="p">,</span>
|
||||
<span class="nt">"grace"</span><span class="p">:</span> <span class="mi">900</span><span class="p">,</span>
|
||||
<span class="nt">"last_ping"</span><span class="p">:</span> <span class="s2">"2017-01-04T13:24:39.903464+00:00"</span><span class="p">,</span>
|
||||
<span class="nt">"n_pings"</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
|
||||
<span class="nt">"name"</span><span class="p">:</span> <span class="s2">"Api test 1"</span><span class="p">,</span>
|
||||
<span class="nt">"next_ping"</span><span class="p">:</span> <span class="s2">"2017-01-04T14:24:39.903464+00:00"</span><span class="p">,</span>
|
||||
<span class="nt">"pause_url"</span><span class="p">:</span> <span class="s2">"SITE_ROOT/api/v1/checks/662ebe36-ecab-48db-afe3-e20029cb71e6/pause"</span><span class="p">,</span>
|
||||
<span class="nt">"ping_url"</span><span class="p">:</span> <span class="s2">"PING_ENDPOINT662ebe36-ecab-48db-afe3-e20029cb71e6"</span><span class="p">,</span>
|
||||
<span class="nt">"status"</span><span class="p">:</span> <span class="s2">"up"</span><span class="p">,</span>
|
||||
<span class="nt">"tags"</span><span class="p">:</span> <span class="s2">"foo"</span><span class="p">,</span>
|
||||
<span class="nt">"timeout"</span><span class="p">:</span> <span class="mi">3600</span><span class="p">,</span>
|
||||
<span class="nt">"update_url"</span><span class="p">:</span> <span class="s2">"SITE_ROOT/api/v1/checks/662ebe36-ecab-48db-afe3-e20029cb71e6"</span>
|
||||
<span class="p">}</span>
|
||||
</code></pre></div>
|
||||
|
||||
|
||||
<h2 class="rule" id="create-check">Create a Check</h2>
|
||||
<p><code>POST SITE_ROOT/api/v1/checks/</code></p>
|
||||
<p>Creates a new check and returns its ping URL.
|
||||
|
@ -8,6 +8,7 @@ checks in user's account.
|
||||
Endpoint Name | Endpoint Address
|
||||
------------------------------------------------------|-------
|
||||
[Get a list of existing checks](#list-checks) | `GET SITE_ROOT/api/v1/checks/`
|
||||
[Create a single check](#get-check) | `GET SITE_ROOT/api/v1/checks/<uuid>`
|
||||
[Create a new check](#create-check) | `POST SITE_ROOT/api/v1/checks/`
|
||||
[Update an existing check](#update-check) | `POST SITE_ROOT/api/v1/checks/<uuid>`
|
||||
[Pause monitoring of a check](#pause-check) | `POST SITE_ROOT/api/v1/checks/<uuid>/pause`
|
||||
@ -157,6 +158,45 @@ is added. This identifier is stable across API calls. Example:
|
||||
}
|
||||
```
|
||||
|
||||
## Get a single Check {: #get-check .rule }
|
||||
`GET SITE_ROOT/api/v1/checks/<uuid>`
|
||||
|
||||
Returns a JSON object containing information information from a single check.
|
||||
|
||||
### Response Codes
|
||||
|
||||
200 OK
|
||||
: The request succeeded.
|
||||
|
||||
401 Unauthorized
|
||||
: The API key is either missing or invalid.
|
||||
|
||||
### Example Request
|
||||
|
||||
```bash
|
||||
curl --header "X-Api-Key: your-api-key" SITE_ROOT/api/v1/checks/<uuid>
|
||||
```
|
||||
|
||||
### Example Response
|
||||
|
||||
```json
|
||||
{
|
||||
"channels": "4ec5a071-2d08-4baa-898a-eb4eb3cd6941,746a083e-f542-4554-be1a-707ce16d3acc",
|
||||
"desc": "Longer free-form description goes here",
|
||||
"grace": 900,
|
||||
"last_ping": "2017-01-04T13:24:39.903464+00:00",
|
||||
"n_pings": 1,
|
||||
"name": "Api test 1",
|
||||
"next_ping": "2017-01-04T14:24:39.903464+00:00",
|
||||
"pause_url": "SITE_ROOT/api/v1/checks/662ebe36-ecab-48db-afe3-e20029cb71e6/pause",
|
||||
"ping_url": "PING_ENDPOINT662ebe36-ecab-48db-afe3-e20029cb71e6",
|
||||
"status": "up",
|
||||
"tags": "foo",
|
||||
"timeout": 3600,
|
||||
"update_url": "SITE_ROOT/api/v1/checks/662ebe36-ecab-48db-afe3-e20029cb71e6"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Create a Check {: #create-check .rule }
|
||||
`POST SITE_ROOT/api/v1/checks/`
|
||||
|
Loading…
x
Reference in New Issue
Block a user