-
-
Notifications
You must be signed in to change notification settings - Fork 306
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
19 changed files
with
1,343 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
from base import Provider as BaseProvider | ||
import requests | ||
import json | ||
|
||
class Provider(BaseProvider): | ||
|
||
def __init__(self, options, provider_options={}): | ||
super(Provider, self).__init__(options) | ||
self.domain_id = None | ||
self.api_endpoint = provider_options.get('api_endpoint') or 'https://rage4.com/rapi' | ||
|
||
def authenticate(self): | ||
|
||
payload = self._get('/getdomainbyname/', {'name': self.options['domain']}) | ||
|
||
if not payload['id']: | ||
raise StandardError('No domain found') | ||
|
||
self.domain_id = payload['id'] | ||
|
||
# Create record. If record already exists with the same content, do nothing' | ||
def create_record(self, type, name, content): | ||
record = { | ||
'id': self.domain_id, | ||
'name': self._clean_name(name), | ||
'content': content, | ||
'type': type | ||
} | ||
payload = {} | ||
try: | ||
payload = self._post('/createrecord/',{},record) | ||
except requests.exceptions.HTTPError, e: | ||
if e.response.status_code == 400: | ||
payload = {} | ||
|
||
# http 400 is ok here, because the record probably already exists | ||
print 'create_record: {0}'.format(payload['status']) | ||
return payload['status'] | ||
|
||
# List all records. Return an empty list if no records found | ||
# type, name and content are used to filter records. | ||
# If possible filter during the query, otherwise filter after response is received. | ||
def list_records(self, type=None, name=None, content=None): | ||
filter = { | ||
'id': self.domain_id | ||
} | ||
if name: | ||
filter['name'] = self._clean_name(name) | ||
payload = self._get('/getrecords/', filter) | ||
|
||
records = [] | ||
for record in payload: | ||
processed_record = { | ||
'type': record['type'], | ||
'name': record['name'], | ||
'ttl': record['ttl'], | ||
'content': record['content'], | ||
'id': record['id'] | ||
} | ||
records.append(processed_record) | ||
|
||
|
||
print 'list_records: {0}'.format(records) | ||
return records | ||
|
||
# Create or update a record. | ||
def update_record(self, identifier, type=None, name=None, content=None): | ||
|
||
data = { | ||
'id': identifier | ||
} | ||
|
||
if name: | ||
data['name'] = self._clean_name(name) | ||
if content: | ||
data['content'] = content | ||
# if type: | ||
# raise 'Type updating is not supported by this provider.' | ||
|
||
payload = self._put('/updaterecord/', {}, data) | ||
|
||
print 'update_record: {0}'.format(payload['status']) | ||
return payload['status'] | ||
|
||
# Delete an existing record. | ||
# If record does not exist, do nothing. | ||
def delete_record(self, identifier=None, type=None, name=None, content=None): | ||
if not identifier: | ||
records = self.list_records(type, name, content) | ||
print records | ||
if len(records) == 1: | ||
identifier = records[0]['id'] | ||
else: | ||
raise StandardError('Record identifier could not be found.') | ||
payload = self._post('/deleterecord/', {'id': identifier}) | ||
|
||
# is always True at this point, if a non 200 response is returned an error is raised. | ||
print 'delete_record: {0}'.format(payload['status']) | ||
return payload['status'] | ||
|
||
|
||
# Helpers | ||
|
||
# record names can be in a variety of formats: relative (sub), full (sub.example.com), and fqdn (sub.example.com.) | ||
# Rage4 handles full record names, so we need to make sure we clean up all user specified record_names before | ||
# submitting them | ||
def _clean_name(self, record_name): | ||
record_name = record_name.rstrip('.') # strip trailing period from fqdn if present | ||
#check if the record_name is fully specified | ||
if not record_name.endswith(self.options['domain']): | ||
record_name = "{0}.{1}".format(record_name, self.options['domain']) | ||
return record_name | ||
|
||
def _get(self, url='/', query_params={}): | ||
return self._request('GET', url, query_params=query_params) | ||
|
||
def _post(self, url='/', data={}, query_params={}): | ||
return self._request('POST', url, data=data, query_params=query_params) | ||
|
||
def _put(self, url='/', data={}, query_params={}): | ||
return self._request('PUT', url, data=data, query_params=query_params) | ||
|
||
def _delete(self, url='/', query_params={}): | ||
return self._request('DELETE', url, query_params=query_params) | ||
|
||
def _request(self, action='GET', url='/', data={}, query_params={}): | ||
|
||
default_headers = { | ||
'Accept': 'application/json', | ||
'Content-Type': 'application/json', | ||
} | ||
default_auth = requests.auth.HTTPBasicAuth(self.options['auth_username'], self.options['auth_token']) | ||
|
||
r = requests.request(action, self.api_endpoint + url, params=query_params, | ||
data=json.dumps(data), | ||
headers=default_headers, | ||
auth=default_auth) | ||
r.raise_for_status() # if the request fails for any reason, throw an error. | ||
return r.json() |
27 changes: 27 additions & 0 deletions
27
tests/fixtures/cassettes/rage4/IntegrationTests/test_Provider_authenticate.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
interactions: | ||
- request: | ||
body: '{}' | ||
headers: | ||
Accept: [application/json] | ||
Accept-Encoding: ['gzip, deflate'] | ||
Connection: [keep-alive] | ||
Content-Length: ['2'] | ||
Content-Type: [application/json] | ||
User-Agent: [python-requests/2.9.1] | ||
method: GET | ||
uri: https://rage4.com/rapi/getdomainbyname/?name=capsulecd.com | ||
response: | ||
body: {string: !!python/unicode '{"id":57039,"name":"capsulecd.com","owner_email":"[email protected]","type":0,"subnet_mask":0,"default_ns1":"ns1.r4ns.com","default_ns2":"ns2.r4ns.net"}'} | ||
headers: | ||
access-control-allow-origin: ['*'] | ||
cache-control: ['private, s-maxage=0'] | ||
content-length: ['157'] | ||
content-type: [text/plain; charset=utf-8] | ||
date: ['Wed, 30 Mar 2016 06:39:15 GMT'] | ||
server: [GBSHouse/2.0] | ||
strict-transport-security: [max-age=31536000; includeSubDomains; preload;] | ||
transfer-encoding: [chunked] | ||
x-frame-options: ['ALLOW-FROM https://www.google.com/maps/d/embed?mid=zuJ4aNyO7vT4.kxxuYpgxSxwo'] | ||
x-powered-by: [Rage4] | ||
status: {code: 200, message: OK} | ||
version: 1 |
28 changes: 28 additions & 0 deletions
28
.../rage4/IntegrationTests/test_Provider_authenticate_with_unmanaged_domain_should_fail.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
interactions: | ||
- request: | ||
body: '{}' | ||
headers: | ||
Accept: [application/json] | ||
Accept-Encoding: ['gzip, deflate'] | ||
Connection: [keep-alive] | ||
Content-Length: ['2'] | ||
Content-Type: [application/json] | ||
User-Agent: [python-requests/2.9.1] | ||
method: GET | ||
uri: https://rage4.com/rapi/getdomainbyname/?name=thisisadomainidonotown.com | ||
response: | ||
body: {string: !!python/unicode '{"status":false,"id":0,"error":"Unable to fetch | ||
the item or API access not allowed"}'} | ||
headers: | ||
access-control-allow-origin: ['*'] | ||
cache-control: ['private, s-maxage=0'] | ||
content-length: ['84'] | ||
content-type: [text/plain; charset=utf-8] | ||
date: ['Wed, 30 Mar 2016 06:39:16 GMT'] | ||
server: [GBSHouse/2.0] | ||
strict-transport-security: [max-age=31536000; includeSubDomains; preload;] | ||
transfer-encoding: [chunked] | ||
x-frame-options: ['ALLOW-FROM https://www.google.com/maps/d/embed?mid=zuJ4aNyO7vT4.kxxuYpgxSxwo'] | ||
x-powered-by: [Rage4] | ||
status: {code: 200, message: OK} | ||
version: 1 |
51 changes: 51 additions & 0 deletions
51
...tionTests/test_Provider_when_calling_create_record_for_A_with_valid_name_and_content.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
interactions: | ||
- request: | ||
body: '{}' | ||
headers: | ||
Accept: [application/json] | ||
Accept-Encoding: ['gzip, deflate'] | ||
Connection: [keep-alive] | ||
Content-Length: ['2'] | ||
Content-Type: [application/json] | ||
User-Agent: [python-requests/2.9.1] | ||
method: GET | ||
uri: https://rage4.com/rapi/getdomainbyname/?name=capsulecd.com | ||
response: | ||
body: {string: !!python/unicode '{"id":57039,"name":"capsulecd.com","owner_email":"[email protected]","type":0,"subnet_mask":0,"default_ns1":"ns1.r4ns.com","default_ns2":"ns2.r4ns.net"}'} | ||
headers: | ||
access-control-allow-origin: ['*'] | ||
cache-control: ['private, s-maxage=0'] | ||
content-length: ['157'] | ||
content-type: [text/plain; charset=utf-8] | ||
date: ['Wed, 30 Mar 2016 06:39:23 GMT'] | ||
server: [GBSHouse/2.0] | ||
strict-transport-security: [max-age=31536000; includeSubDomains; preload;] | ||
x-frame-options: ['ALLOW-FROM https://www.google.com/maps/d/embed?mid=zuJ4aNyO7vT4.kxxuYpgxSxwo'] | ||
x-powered-by: [Rage4] | ||
status: {code: 200, message: OK} | ||
- request: | ||
body: '{}' | ||
headers: | ||
Accept: [application/json] | ||
Accept-Encoding: ['gzip, deflate'] | ||
Connection: [keep-alive] | ||
Content-Length: ['2'] | ||
Content-Type: [application/json] | ||
User-Agent: [python-requests/2.9.1] | ||
method: POST | ||
uri: https://rage4.com/rapi/createrecord/?content=127.0.0.1&type=A&id=57039&name=localhost.capsulecd.com | ||
response: | ||
body: {string: !!python/unicode '{"status":true,"id":1954621,"error":""}'} | ||
headers: | ||
access-control-allow-origin: ['*'] | ||
cache-control: ['private, s-maxage=0'] | ||
content-length: ['39'] | ||
content-type: [text/plain; charset=utf-8] | ||
date: ['Wed, 30 Mar 2016 06:39:43 GMT'] | ||
server: [GBSHouse/2.0] | ||
strict-transport-security: [max-age=31536000; includeSubDomains; preload;] | ||
transfer-encoding: [chunked] | ||
x-frame-options: ['ALLOW-FROM https://www.google.com/maps/d/embed?mid=zuJ4aNyO7vT4.kxxuYpgxSxwo'] | ||
x-powered-by: [Rage4] | ||
status: {code: 200, message: OK} | ||
version: 1 |
51 changes: 51 additions & 0 deletions
51
...Tests/test_Provider_when_calling_create_record_for_CNAME_with_valid_name_and_content.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
interactions: | ||
- request: | ||
body: '{}' | ||
headers: | ||
Accept: [application/json] | ||
Accept-Encoding: ['gzip, deflate'] | ||
Connection: [keep-alive] | ||
Content-Length: ['2'] | ||
Content-Type: [application/json] | ||
User-Agent: [python-requests/2.9.1] | ||
method: GET | ||
uri: https://rage4.com/rapi/getdomainbyname/?name=capsulecd.com | ||
response: | ||
body: {string: !!python/unicode '{"id":57039,"name":"capsulecd.com","owner_email":"[email protected]","type":0,"subnet_mask":0,"default_ns1":"ns1.r4ns.com","default_ns2":"ns2.r4ns.net"}'} | ||
headers: | ||
access-control-allow-origin: ['*'] | ||
cache-control: ['private, s-maxage=0'] | ||
content-length: ['157'] | ||
content-type: [text/plain; charset=utf-8] | ||
date: ['Wed, 30 Mar 2016 06:39:24 GMT'] | ||
server: [GBSHouse/2.0] | ||
strict-transport-security: [max-age=31536000; includeSubDomains; preload;] | ||
x-frame-options: ['ALLOW-FROM https://www.google.com/maps/d/embed?mid=zuJ4aNyO7vT4.kxxuYpgxSxwo'] | ||
x-powered-by: [Rage4] | ||
status: {code: 200, message: OK} | ||
- request: | ||
body: '{}' | ||
headers: | ||
Accept: [application/json] | ||
Accept-Encoding: ['gzip, deflate'] | ||
Connection: [keep-alive] | ||
Content-Length: ['2'] | ||
Content-Type: [application/json] | ||
User-Agent: [python-requests/2.9.1] | ||
method: POST | ||
uri: https://rage4.com/rapi/createrecord/?content=docs.example.com&type=CNAME&id=57039&name=docs.capsulecd.com | ||
response: | ||
body: {string: !!python/unicode '{"status":true,"id":1954623,"error":""}'} | ||
headers: | ||
access-control-allow-origin: ['*'] | ||
cache-control: ['private, s-maxage=0'] | ||
content-length: ['39'] | ||
content-type: [text/plain; charset=utf-8] | ||
date: ['Wed, 30 Mar 2016 06:39:38 GMT'] | ||
server: [GBSHouse/2.0] | ||
strict-transport-security: [max-age=31536000; includeSubDomains; preload;] | ||
transfer-encoding: [chunked] | ||
x-frame-options: ['ALLOW-FROM https://www.google.com/maps/d/embed?mid=zuJ4aNyO7vT4.kxxuYpgxSxwo'] | ||
x-powered-by: [Rage4] | ||
status: {code: 200, message: OK} | ||
version: 1 |
51 changes: 51 additions & 0 deletions
51
...ionTests/test_Provider_when_calling_create_record_for_TXT_with_fqdn_name_and_content.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
interactions: | ||
- request: | ||
body: '{}' | ||
headers: | ||
Accept: [application/json] | ||
Accept-Encoding: ['gzip, deflate'] | ||
Connection: [keep-alive] | ||
Content-Length: ['2'] | ||
Content-Type: [application/json] | ||
User-Agent: [python-requests/2.9.1] | ||
method: GET | ||
uri: https://rage4.com/rapi/getdomainbyname/?name=capsulecd.com | ||
response: | ||
body: {string: !!python/unicode '{"id":57039,"name":"capsulecd.com","owner_email":"[email protected]","type":0,"subnet_mask":0,"default_ns1":"ns1.r4ns.com","default_ns2":"ns2.r4ns.net"}'} | ||
headers: | ||
access-control-allow-origin: ['*'] | ||
cache-control: ['private, s-maxage=0'] | ||
content-length: ['157'] | ||
content-type: [text/plain; charset=utf-8] | ||
date: ['Wed, 30 Mar 2016 06:39:18 GMT'] | ||
server: [GBSHouse/2.0] | ||
strict-transport-security: [max-age=31536000; includeSubDomains; preload;] | ||
x-frame-options: ['ALLOW-FROM https://www.google.com/maps/d/embed?mid=zuJ4aNyO7vT4.kxxuYpgxSxwo'] | ||
x-powered-by: [Rage4] | ||
status: {code: 200, message: OK} | ||
- request: | ||
body: '{}' | ||
headers: | ||
Accept: [application/json] | ||
Accept-Encoding: ['gzip, deflate'] | ||
Connection: [keep-alive] | ||
Content-Length: ['2'] | ||
Content-Type: [application/json] | ||
User-Agent: [python-requests/2.9.1] | ||
method: POST | ||
uri: https://rage4.com/rapi/createrecord/?content=challengetoken&type=TXT&id=57039&name=_acme-challenge.fqdn.capsulecd.com | ||
response: | ||
body: {string: !!python/unicode '{"status":true,"id":1954625,"error":""}'} | ||
headers: | ||
access-control-allow-origin: ['*'] | ||
cache-control: ['private, s-maxage=0'] | ||
content-length: ['39'] | ||
content-type: [text/plain; charset=utf-8] | ||
date: ['Wed, 30 Mar 2016 06:39:45 GMT'] | ||
server: [GBSHouse/2.0] | ||
strict-transport-security: [max-age=31536000; includeSubDomains; preload;] | ||
transfer-encoding: [chunked] | ||
x-frame-options: ['ALLOW-FROM https://www.google.com/maps/d/embed?mid=zuJ4aNyO7vT4.kxxuYpgxSxwo'] | ||
x-powered-by: [Rage4] | ||
status: {code: 200, message: OK} | ||
version: 1 |
Oops, something went wrong.