You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

220 lines
6.5 KiB

10 years ago
10 years ago
10 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
9 years ago
9 years ago
6 years ago
6 years ago
9 years ago
9 years ago
6 years ago
9 years ago
9 years ago
6 years ago
9 years ago
6 years ago
6 years ago
  1. from django.contrib import admin
  2. from django.core.paginator import Paginator
  3. from django.db import connection
  4. from django.db.models import Count, F
  5. from django.utils.safestring import mark_safe
  6. from hc.api.models import Channel, Check, Flip, Notification, Ping
  7. from hc.lib.date import format_duration
  8. @admin.register(Check)
  9. class ChecksAdmin(admin.ModelAdmin):
  10. class Media:
  11. css = {
  12. 'all': ('css/admin/checks.css',)
  13. }
  14. search_fields = ["name", "code", "project__owner__email"]
  15. raw_id_fields = ("project", )
  16. list_display = ("id", "name_tags", "email", "created", "n_pings",
  17. "timeout_schedule", "status", "last_start", "last_ping")
  18. list_filter = ("status", "kind", "last_ping",
  19. "last_start")
  20. actions = ["send_alert"]
  21. def get_queryset(self, request):
  22. qs = super().get_queryset(request)
  23. qs = qs.annotate(email=F("project__owner__email"))
  24. return qs
  25. def email(self, obj):
  26. return obj.email
  27. def name_tags(self, obj):
  28. if not obj.tags:
  29. return obj.name
  30. return "%s [%s]" % (obj.name, obj.tags)
  31. def timeout_schedule(self, obj):
  32. if obj.kind == "simple":
  33. return format_duration(obj.timeout)
  34. elif obj.kind == "cron":
  35. return obj.schedule
  36. else:
  37. return "Unknown"
  38. timeout_schedule.short_description = "Schedule"
  39. def send_alert(self, request, qs):
  40. for check in qs:
  41. check.send_alert()
  42. self.message_user(request, "%d alert(s) sent" % qs.count())
  43. send_alert.short_description = "Send Alert"
  44. class SchemeListFilter(admin.SimpleListFilter):
  45. title = "Scheme"
  46. parameter_name = 'scheme'
  47. def lookups(self, request, model_admin):
  48. return (
  49. ('http', "HTTP"),
  50. ('https', "HTTPS"),
  51. ('email', "Email"),
  52. )
  53. def queryset(self, request, queryset):
  54. if self.value():
  55. queryset = queryset.filter(scheme=self.value())
  56. return queryset
  57. class MethodListFilter(admin.SimpleListFilter):
  58. title = "Method"
  59. parameter_name = 'method'
  60. methods = ["HEAD", "GET", "POST", "PUT", "DELETE"]
  61. def lookups(self, request, model_admin):
  62. return zip(self.methods, self.methods)
  63. def queryset(self, request, queryset):
  64. if self.value():
  65. queryset = queryset.filter(method=self.value())
  66. return queryset
  67. class KindListFilter(admin.SimpleListFilter):
  68. title = "Kind"
  69. parameter_name = 'kind'
  70. kinds = ["start", "fail"]
  71. def lookups(self, request, model_admin):
  72. return zip(self.kinds, self.kinds)
  73. def queryset(self, request, queryset):
  74. if self.value():
  75. queryset = queryset.filter(kind=self.value())
  76. return queryset
  77. # Adapted from: https://djangosnippets.org/snippets/2593/
  78. class LargeTablePaginator(Paginator):
  79. """ Overrides the count method to get an estimate instead of actual count
  80. when not filtered
  81. """
  82. def _get_estimate(self):
  83. try:
  84. cursor = connection.cursor()
  85. cursor.execute("SELECT reltuples FROM pg_class WHERE relname = %s",
  86. [self.object_list.query.model._meta.db_table])
  87. return int(cursor.fetchone()[0])
  88. except:
  89. return 0
  90. def _get_count(self):
  91. """
  92. Changed to use an estimate if the estimate is greater than 10,000
  93. Returns the total number of objects, across all pages.
  94. """
  95. if not hasattr(self, "_count") or self._count is None:
  96. try:
  97. estimate = 0
  98. if not self.object_list.query.where:
  99. estimate = self._get_estimate()
  100. if estimate < 10000:
  101. self._count = self.object_list.count()
  102. else:
  103. self._count = estimate
  104. except (AttributeError, TypeError):
  105. # AttributeError if object_list has no count() method.
  106. # TypeError if object_list.count() requires arguments
  107. # (i.e. is of type list).
  108. self._count = len(self.object_list)
  109. return self._count
  110. count = property(_get_count)
  111. @admin.register(Ping)
  112. class PingsAdmin(admin.ModelAdmin):
  113. search_fields = ("owner__name", "owner__code")
  114. readonly_fields = ("owner", )
  115. list_select_related = ("owner", )
  116. list_display = ("id", "created", "owner", "email", "scheme", "method",
  117. "ua")
  118. list_filter = ("created", SchemeListFilter, MethodListFilter,
  119. KindListFilter)
  120. paginator = LargeTablePaginator
  121. def get_queryset(self, request):
  122. qs = super().get_queryset(request)
  123. qs = qs.annotate(email=F("owner__project__owner__email"))
  124. return qs
  125. def email(self, obj):
  126. return obj.email
  127. @admin.register(Channel)
  128. class ChannelsAdmin(admin.ModelAdmin):
  129. class Media:
  130. css = {
  131. 'all': ('css/admin/channels.css',)
  132. }
  133. search_fields = ["value", "project__owner__email"]
  134. list_display = ("id", "name", "email", "formatted_kind", "value",
  135. "num_notifications")
  136. list_filter = ("kind", )
  137. raw_id_fields = ("project", "checks", )
  138. def get_queryset(self, request):
  139. qs = super().get_queryset(request)
  140. qs = qs.annotate(Count("notification", distinct=True))
  141. qs = qs.annotate(email=F("project__owner__email"))
  142. return qs
  143. def email(self, obj):
  144. return obj.email
  145. @mark_safe
  146. def formatted_kind(self, obj):
  147. if obj.kind == "email" and not obj.email_verified:
  148. return "Email <i>(unconfirmed)</i>"
  149. return obj.get_kind_display()
  150. formatted_kind.short_description = "Kind"
  151. def num_notifications(self, obj):
  152. return obj.notification__count
  153. num_notifications.short_description = "# Notifications"
  154. @admin.register(Notification)
  155. class NotificationsAdmin(admin.ModelAdmin):
  156. search_fields = ["owner__name", "owner__code", "channel__value"]
  157. list_select_related = ("owner", "channel")
  158. list_display = ("id", "created", "check_status", "owner",
  159. "channel_kind", "channel_value")
  160. list_filter = ("created", "check_status", "channel__kind")
  161. def channel_kind(self, obj):
  162. return obj.channel.kind
  163. def channel_value(self, obj):
  164. return obj.channel.value
  165. @admin.register(Flip)
  166. class FlipsAdmin(admin.ModelAdmin):
  167. list_display = ("id", "created", "processed", "owner", "old_status",
  168. "new_status")
  169. raw_id_fields = ("owner", )