3232
3333from vinyldns .batch_change import BatchChange , ListBatchChangeSummaries , to_review_json
3434from vinyldns .membership import Group , ListGroupsResponse , ListGroupChangesResponse , ListMembersResponse , \
35- ListAdminsResponse
35+ ListAdminsResponse , GroupChange , UserInfo
3636from vinyldns .serdes import to_json_string
37- from vinyldns .zone import ListZonesResponse , ListZoneChangesResponse , Zone , ZoneChange
38- from vinyldns .record import ListRecordSetsResponse , ListRecordSetChangesResponse , RecordSet , RecordSetChange
37+ from vinyldns .zone import ListZonesResponse , ListZoneChangesResponse , Zone , ZoneChange , ZoneDetails , \
38+ ZoneChangeFailuresResponse , DeletedZonesResponse
39+ from vinyldns .record import ListRecordSetsResponse , ListRecordSetChangesResponse , RecordSet , RecordSetChange , \
40+ RecordSetCount , RecordSetChangeFailuresResponse , OwnershipTransfer , OwnershipTransferStatus
41+ from vinyldns .status import SystemStatus
3942
4043try :
4144 basestring
@@ -161,6 +164,24 @@ def __make_request(self, url, method=u'GET', headers=None, body_string=None, **k
161164
162165 return self .__check_response (response , method )
163166
167+ def __make_request_raw (self , url , method = u'GET' , headers = None , body_string = None , ** kwargs ):
168+
169+ # remove retries arg if provided
170+ kwargs .pop (u'retries' , None )
171+
172+ path = urlparse (url ).path
173+ query = parse_qs (urlsplit (url ).query )
174+ if query :
175+ query = dict ((k , v if len (v ) > 1 else v [0 ])
176+ for k , v in query .items ())
177+
178+ signed_headers , signed_body = self .__build_vinyldns_request (method , path , body_string , query ,
179+ with_headers = headers or {}, ** kwargs )
180+
181+ response = self .session .request (method , url , data = signed_body , headers = signed_headers , ** kwargs )
182+
183+ return self .__check_response_raw (response , method )
184+
164185 def __check_response (self , response , method ):
165186 status = response .status_code
166187 if status == 200 or status == 202 :
@@ -183,6 +204,28 @@ def __check_response(self, response, method):
183204 else :
184205 raise ClientError (response .text )
185206
207+ def __check_response_raw (self , response , method ):
208+ status = response .status_code
209+ if status == 200 or status == 202 :
210+ return response .status_code , response .text
211+ elif status == 404 :
212+ if method == 'GET' :
213+ return 404 , None
214+ else :
215+ raise NotFoundError (response .text )
216+ elif status == 400 :
217+ raise BadRequestError (response .text )
218+ elif status == 401 :
219+ raise UnauthorizedError (response .text )
220+ elif status == 403 :
221+ raise ForbiddenError (response .text )
222+ elif status == 409 :
223+ raise ConflictError (response .text )
224+ elif status == 422 :
225+ raise UnprocessableError (response .text )
226+ else :
227+ raise ClientError (response .text )
228+
186229 def __build_vinyldns_request (self , method , path , body_data , params = None , ** kwargs ):
187230
188231 if isinstance (body_data , basestring ):
@@ -379,6 +422,28 @@ def list_group_changes(self, group_id, start_from=None, max_items=None, **kwargs
379422
380423 return ListGroupChangesResponse .from_dict (data )
381424
425+ def get_group_change (self , group_change_id , ** kwargs ):
426+ """
427+ Get a group change by ID.
428+
429+ :param group_change_id: the group change ID
430+ :return: the group change details
431+ """
432+ url = urljoin (self .index_url , u'/groups/change/{0}' .format (group_change_id ))
433+ response , data = self .__make_request (url , u'GET' , self .headers , ** kwargs )
434+
435+ return GroupChange .from_dict (data ) if data is not None else None
436+
437+ def list_group_valid_domains (self , ** kwargs ):
438+ """
439+ List valid email domains for groups.
440+
441+ :return: list of valid domains
442+ """
443+ url = urljoin (self .index_url , u'/groups/valid/domains' )
444+ response , data = self .__make_request (url , u'GET' , self .headers , ** kwargs )
445+ return data if data is not None else []
446+
382447 def connect_zone (self , zone , ** kwargs ):
383448 """
384449 Create a new zone with the given name and email.
@@ -447,6 +512,71 @@ def get_zone_by_name(self, name, **kwargs):
447512 response , data = self .__make_request (url , u'GET' , self .headers , ** kwargs )
448513 return Zone .from_dict (data ['zone' ]) if data is not None else None
449514
515+ def get_zone_details (self , zone_id , ** kwargs ):
516+ """
517+ Get detailed zone info for the given zone id.
518+
519+ :param zone_id: the id of the zone to retrieve
520+ :return: the zone details, or will 404 if not found
521+ """
522+ url = urljoin (self .index_url , u'/zones/{0}/details' .format (zone_id ))
523+ response , data = self .__make_request (url , u'GET' , self .headers , ** kwargs )
524+
525+ return ZoneDetails .from_dict (data ['zone' ]) if data is not None else None
526+
527+ def list_zone_backend_ids (self , ** kwargs ):
528+ """
529+ List configured backend IDs.
530+ """
531+ url = urljoin (self .index_url , u'/zones/backendids' )
532+ response , data = self .__make_request (url , u'GET' , self .headers , ** kwargs )
533+
534+ if data is None :
535+ return []
536+ if isinstance (data , dict ):
537+ return data .get ('backendIds' , [])
538+ return data
539+
540+ def list_zone_changes_failure (self , name_filter = None , start_from = None , max_items = None , ** kwargs ):
541+ """
542+ List failed zone changes.
543+ """
544+ args = []
545+ if name_filter :
546+ args .append (u'nameFilter={0}' .format (name_filter ))
547+ if start_from :
548+ args .append (u'startFrom={0}' .format (start_from ))
549+ if max_items is not None :
550+ args .append (u'maxItems={0}' .format (max_items ))
551+
552+ url = urljoin (self .index_url , u'/metrics/health/zonechangesfailure' )
553+ if args :
554+ url = url + u'?' + u'&' .join (args )
555+
556+ response , data = self .__make_request (url , u'GET' , self .headers , ** kwargs )
557+ return ZoneChangeFailuresResponse .from_dict (data )
558+
559+ def list_deleted_zones (self , name_filter = None , start_from = None , max_items = None , ignore_access = None , ** kwargs ):
560+ """
561+ List deleted zone changes.
562+ """
563+ args = []
564+ if name_filter :
565+ args .append (u'nameFilter={0}' .format (name_filter ))
566+ if start_from :
567+ args .append (u'startFrom={0}' .format (start_from ))
568+ if max_items is not None :
569+ args .append (u'maxItems={0}' .format (max_items ))
570+ if ignore_access is not None :
571+ args .append (u'ignoreAccess={0}' .format (ignore_access ))
572+
573+ url = urljoin (self .index_url , u'/zones/deleted/changes' )
574+ if args :
575+ url = url + u'?' + u'&' .join (args )
576+
577+ response , data = self .__make_request (url , u'GET' , self .headers , ** kwargs )
578+ return DeletedZonesResponse .from_dict (data )
579+
450580 def list_zone_changes (self , zone_id , start_from = None , max_items = None , ** kwargs ):
451581 """
452582 Get the zone changes for the given zone id.
@@ -564,6 +694,84 @@ def list_record_sets(self, zone_id, start_from=None, max_items=None, record_name
564694 response , data = self .__make_request (url , u'GET' , self .headers , ** kwargs )
565695 return ListRecordSetsResponse .from_dict (data )
566696
697+ def get_record_set_count (self , zone_id , ** kwargs ):
698+ """
699+ Get record set count for a zone.
700+ """
701+ url = urljoin (self .index_url , u'/zones/{0}/recordsetcount' .format (zone_id ))
702+ response , data = self .__make_request (url , u'GET' , self .headers , ** kwargs )
703+ return RecordSetCount .from_dict (data )
704+
705+ def list_record_set_change_history (self , zone_id , fqdn , record_type , start_from = None , max_items = None , ** kwargs ):
706+ """
707+ Retrieve record set change history for a FQDN and type.
708+ """
709+ args = [u'zoneId={0}' .format (zone_id ), u'fqdn={0}' .format (fqdn ), u'recordType={0}' .format (record_type )]
710+ if start_from :
711+ args .append (u'startFrom={0}' .format (start_from ))
712+ if max_items is not None :
713+ args .append (u'maxItems={0}' .format (max_items ))
714+
715+ url = urljoin (self .index_url , u'/recordsetchange/history' ) + u'?' + u'&' .join (args )
716+ response , data = self .__make_request (url , u'GET' , self .headers , ** kwargs )
717+ return ListRecordSetChangesResponse .from_dict (data )
718+
719+ def list_record_set_changes_failure (self , zone_id , start_from = None , max_items = None , ** kwargs ):
720+ """
721+ List failed record set changes for a zone.
722+ """
723+ args = []
724+ if start_from :
725+ args .append (u'startFrom={0}' .format (start_from ))
726+ if max_items is not None :
727+ args .append (u'maxItems={0}' .format (max_items ))
728+
729+ url = urljoin (self .index_url , u'/metrics/health/zones/{0}/recordsetchangesfailure' .format (zone_id ))
730+ if args :
731+ url = url + u'?' + u'&' .join (args )
732+
733+ response , data = self .__make_request (url , u'GET' , self .headers , ** kwargs )
734+ return RecordSetChangeFailuresResponse .from_dict (data )
735+
736+ def request_record_set_ownership (self , record_set , requested_owner_group_id , ** kwargs ):
737+ """
738+ Request record set ownership transfer.
739+ """
740+ return self .__record_set_ownership_transfer (record_set , OwnershipTransferStatus .Requested ,
741+ requested_owner_group_id , ** kwargs )
742+
743+ def approve_record_set_ownership (self , record_set , requested_owner_group_id , ** kwargs ):
744+ """
745+ Approve record set ownership transfer.
746+ """
747+ return self .__record_set_ownership_transfer (record_set , OwnershipTransferStatus .ManuallyApproved ,
748+ requested_owner_group_id , update_owner_group = True , ** kwargs )
749+
750+ def reject_record_set_ownership (self , record_set , requested_owner_group_id , ** kwargs ):
751+ """
752+ Reject record set ownership transfer.
753+ """
754+ return self .__record_set_ownership_transfer (record_set , OwnershipTransferStatus .ManuallyRejected ,
755+ requested_owner_group_id , ** kwargs )
756+
757+ def cancel_record_set_ownership (self , record_set , requested_owner_group_id , ** kwargs ):
758+ """
759+ Cancel record set ownership transfer.
760+ """
761+ return self .__record_set_ownership_transfer (record_set , OwnershipTransferStatus .Cancelled ,
762+ requested_owner_group_id , ** kwargs )
763+
764+ def __record_set_ownership_transfer (self , record_set , status , requested_owner_group_id ,
765+ update_owner_group = False , ** kwargs ):
766+ record_set .record_set_group_change = OwnershipTransfer (
767+ ownership_transfer_status = status ,
768+ requested_owner_group_id = requested_owner_group_id
769+ )
770+ if update_owner_group :
771+ record_set .owner_group_id = requested_owner_group_id
772+
773+ return self .update_record_set (record_set , ** kwargs )
774+
567775 def search_record_sets (self , start_from = None , max_items = None , record_name_filter = None ,
568776 record_type_filter = None , record_owner_group_filter = None , name_sort = None , ** kwargs ):
569777 """
@@ -745,3 +953,83 @@ def delete_zone_acl_rule(self, zone_id, acl_rule, **kwargs):
745953 to_json_string (acl_rule ), ** kwargs )
746954
747955 return ZoneChange .from_dict (data )
956+
957+ def ping (self , ** kwargs ):
958+ """
959+ Simple health check.
960+ """
961+ url = urljoin (self .index_url , u'/ping' )
962+ response , data = self .__make_request_raw (url , u'GET' , self .headers , ** kwargs )
963+ return data
964+
965+ def health (self , ** kwargs ):
966+ """
967+ Comprehensive health check.
968+ """
969+ url = urljoin (self .index_url , u'/health' )
970+ response , data = self .__make_request_raw (url , u'GET' , self .headers , ** kwargs )
971+ return data
972+
973+ def color (self , ** kwargs ):
974+ """
975+ Blue/green deployment status.
976+ """
977+ url = urljoin (self .index_url , u'/color' )
978+ response , data = self .__make_request_raw (url , u'GET' , self .headers , ** kwargs )
979+ return data
980+
981+ def metrics_prometheus (self , names = None , ** kwargs ):
982+ """
983+ Prometheus metrics export.
984+ """
985+ args = []
986+ if names :
987+ for name in names :
988+ args .append (u'name={0}' .format (name ))
989+
990+ url = urljoin (self .index_url , u'/metrics/prometheus' )
991+ if args :
992+ url = url + u'?' + u'&' .join (args )
993+
994+ response , data = self .__make_request_raw (url , u'GET' , self .headers , ** kwargs )
995+ return data
996+
997+ def get_status (self , ** kwargs ):
998+ """
999+ Get system processing status.
1000+ """
1001+ url = urljoin (self .index_url , u'/status' )
1002+ response , data = self .__make_request (url , u'GET' , self .headers , ** kwargs )
1003+ return SystemStatus .from_dict (data )
1004+
1005+ def update_status (self , processing_disabled , ** kwargs ):
1006+ """
1007+ Enable/disable processing (admin).
1008+ """
1009+ url = urljoin (self .index_url , u'/status?processingDisabled={0}' .format (str (processing_disabled ).lower ()))
1010+ response , data = self .__make_request (url , u'POST' , self .headers , ** kwargs )
1011+ return SystemStatus .from_dict (data )
1012+
1013+ def get_user (self , user_id , ** kwargs ):
1014+ """
1015+ Get user by ID.
1016+ """
1017+ url = urljoin (self .index_url , u'/users/{0}' .format (user_id ))
1018+ response , data = self .__make_request (url , u'GET' , self .headers , ** kwargs )
1019+ return UserInfo .from_dict (data ) if data is not None else None
1020+
1021+ def lock_user (self , user_id , ** kwargs ):
1022+ """
1023+ Lock a user (admin).
1024+ """
1025+ url = urljoin (self .index_url , u'/users/{0}/lock' .format (user_id ))
1026+ response , data = self .__make_request (url , u'PUT' , self .headers , ** kwargs )
1027+ return UserInfo .from_dict (data )
1028+
1029+ def unlock_user (self , user_id , ** kwargs ):
1030+ """
1031+ Unlock a user (admin).
1032+ """
1033+ url = urljoin (self .index_url , u'/users/{0}/unlock' .format (user_id ))
1034+ response , data = self .__make_request (url , u'PUT' , self .headers , ** kwargs )
1035+ return UserInfo .from_dict (data )
0 commit comments