netbox-docker-plugin 2.1.0__tar.gz → 2.6.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. {netbox_docker_plugin-2.1.0/netbox_docker_plugin.egg-info → netbox_docker_plugin-2.6.0}/PKG-INFO +1 -1
  2. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/__init__.py +1 -1
  3. netbox_docker_plugin-2.6.0/netbox_docker_plugin/api/renderers.py +19 -0
  4. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/api/serializers.py +2 -0
  5. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/api/views.py +57 -15
  6. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/forms/container.py +7 -1
  7. netbox_docker_plugin-2.6.0/netbox_docker_plugin/migrations/0031_container_cap_add.py +29 -0
  8. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/models/container.py +30 -10
  9. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tables.py +1 -0
  10. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/templates/netbox_docker_plugin/container.html +46 -20
  11. netbox_docker_plugin-2.6.0/netbox_docker_plugin/templates/netbox_docker_plugin/host-graph.html +211 -0
  12. netbox_docker_plugin-2.6.0/netbox_docker_plugin/templates/netbox_docker_plugin/image.html +122 -0
  13. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/container/test_container_api.py +4 -2
  14. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/container/test_container_views.py +1 -0
  15. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/image/test_image_api.py +37 -0
  16. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/urls.py +5 -0
  17. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/views/host.py +11 -0
  18. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0/netbox_docker_plugin.egg-info}/PKG-INFO +1 -1
  19. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin.egg-info/SOURCES.txt +2 -0
  20. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/pyproject.toml +1 -1
  21. netbox_docker_plugin-2.1.0/netbox_docker_plugin/api/renderers.py +0 -14
  22. netbox_docker_plugin-2.1.0/netbox_docker_plugin/templates/netbox_docker_plugin/image.html +0 -59
  23. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/LICENSE +0 -0
  24. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/MANIFEST.in +0 -0
  25. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/README.md +0 -0
  26. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/api/__init__.py +0 -0
  27. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/api/urls.py +0 -0
  28. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/filtersets.py +0 -0
  29. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/forms/__init__.py +0 -0
  30. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/forms/bind.py +0 -0
  31. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/forms/env.py +0 -0
  32. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/forms/host.py +0 -0
  33. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/forms/image.py +0 -0
  34. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/forms/label.py +0 -0
  35. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/forms/mount.py +0 -0
  36. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/forms/network.py +0 -0
  37. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/forms/network_setting.py +0 -0
  38. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/forms/port.py +0 -0
  39. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/forms/registry.py +0 -0
  40. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/forms/volume.py +0 -0
  41. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0001_initial.py +0 -0
  42. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0002_image.py +0 -0
  43. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0003_image_size.py +0 -0
  44. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0004_volume.py +0 -0
  45. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0005_network.py +0 -0
  46. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0006_container_port_mount_label_env_and_more.py +0 -0
  47. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0007_remove_container_netbox_docker_plugin_container_unique_name_host__and_more.py +0 -0
  48. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0008_alter_network_unique_together_network_networkid_and_more.py +0 -0
  49. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0009_remove_container_network_networksettings_and_more.py +0 -0
  50. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0010_container_containerid_and_more.py +0 -0
  51. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0011_host_token.py +0 -0
  52. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0012_host_state.py +0 -0
  53. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0013_host_netbox_url.py +0 -0
  54. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0014_container_operation.py +0 -0
  55. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0015_remove_mount_netbox_docker_plugin_mount_unique_volume_and_more.py +0 -0
  56. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0016_alter_env_value.py +0 -0
  57. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0017_network_state.py +0 -0
  58. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0018_alter_mount_volume_alter_networksetting_network.py +0 -0
  59. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0019_host_agent_version_host_docker_api_version.py +0 -0
  60. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0020_container_hostname.py +0 -0
  61. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0021_registry_and_more.py +0 -0
  62. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0022_bind_bind_netbox_docker_plugin_bind_unique_bind.py +0 -0
  63. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0023_delete_hosts.py +0 -0
  64. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0024_registry_host_alter_registry_name_and_more.py +0 -0
  65. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0025_alter_image_version.py +0 -0
  66. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0026_image_digest.py +0 -0
  67. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0027_container_restart_policy.py +0 -0
  68. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0028_mount_and_bind_read_only.py +0 -0
  69. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0029_alter_container_state.py +0 -0
  70. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/0030_alter_container_containerid_alter_container_hostname_and_more.py +0 -0
  71. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/migrations/__init__.py +0 -0
  72. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/models/__init__.py +0 -0
  73. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/models/host.py +0 -0
  74. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/models/image.py +0 -0
  75. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/models/network.py +0 -0
  76. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/models/registry.py +0 -0
  77. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/models/volume.py +0 -0
  78. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/navigation.py +0 -0
  79. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/signals.py +0 -0
  80. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/templates/netbox_docker_plugin/container-exec.html +0 -0
  81. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/templates/netbox_docker_plugin/container-layout.html +0 -0
  82. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/templates/netbox_docker_plugin/container-logs.html +0 -0
  83. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/templates/netbox_docker_plugin/host.html +0 -0
  84. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/templates/netbox_docker_plugin/network.html +0 -0
  85. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/templates/netbox_docker_plugin/registry.html +0 -0
  86. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/templates/netbox_docker_plugin/volume.html +0 -0
  87. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/templatetags/__init__.py +0 -0
  88. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/templatetags/host.py +0 -0
  89. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/__init__.py +0 -0
  90. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/base.py +0 -0
  91. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/container/__init__.py +0 -0
  92. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/container/test_container_actions.py +0 -0
  93. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/container/test_container_api_exec.py +0 -0
  94. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/container/test_container_operation_view.py +0 -0
  95. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/container/test_container_validation.py +0 -0
  96. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/host/__init__.py +0 -0
  97. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/host/test_host_api.py +0 -0
  98. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/host/test_host_views.py +0 -0
  99. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/host/test_replace_password.py +0 -0
  100. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/image/__init__.py +0 -0
  101. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/image/test_image_views.py +0 -0
  102. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/network/__init__.py +0 -0
  103. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/network/test_network_api.py +0 -0
  104. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/network/test_network_views.py +0 -0
  105. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/registry/__init__.py +0 -0
  106. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/registry/test_registry_api.py +0 -0
  107. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/registry/test_registry_views.py +0 -0
  108. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/test_init.py +0 -0
  109. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/volume/__init__.py +0 -0
  110. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/volume/test_volume_api.py +0 -0
  111. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/tests/volume/test_volume_views.py +0 -0
  112. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/utilities/__init__.py +0 -0
  113. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/views/__init__.py +0 -0
  114. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/views/bind.py +0 -0
  115. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/views/container.py +0 -0
  116. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/views/env.py +0 -0
  117. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/views/image.py +0 -0
  118. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/views/label.py +0 -0
  119. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/views/mount.py +0 -0
  120. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/views/network.py +0 -0
  121. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/views/network_setting.py +0 -0
  122. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/views/port.py +0 -0
  123. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/views/registry.py +0 -0
  124. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin/views/volume.py +0 -0
  125. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin.egg-info/dependency_links.txt +0 -0
  126. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/netbox_docker_plugin.egg-info/top_level.txt +0 -0
  127. {netbox_docker_plugin-2.1.0 → netbox_docker_plugin-2.6.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: netbox-docker-plugin
3
- Version: 2.1.0
3
+ Version: 2.6.0
4
4
  Summary: Manage Docker with Netbox & style.
5
5
  Author-email: Vincent Simonin <vincent@saashup.com>, David Delassus <david.jose.delassus@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/SaaShup/netbox-docker-plugin
@@ -10,7 +10,7 @@ class NetBoxDockerConfig(PluginConfig):
10
10
  name = "netbox_docker_plugin"
11
11
  verbose_name = " NetBox Docker Plugin"
12
12
  description = "Manage Docker"
13
- version = "2.1.0"
13
+ version = "2.6.0"
14
14
  base_url = "docker"
15
15
  min_version = "4.0.0"
16
16
  author= "Vincent Simonin <vincent@saashup.com>, David Delassus <david.jose.delassus@gmail.com>"
@@ -0,0 +1,19 @@
1
+ """ Response renderers for Django Rest Framework """
2
+
3
+ from django.utils.encoding import smart_str
4
+ from rest_framework import renderers
5
+
6
+
7
+ def make_content_type_renderer(content_type: str, api_format: str):
8
+ """ Create a response renderer for the specific content type """
9
+
10
+ class ContentTypeRenderer(renderers.BaseRenderer):
11
+ """ content type renderer """
12
+
13
+ media_type = content_type
14
+ format = api_format
15
+
16
+ def render(self, data, accepted_media_type=None, renderer_context=None):
17
+ return smart_str(data, encoding=self.charset)
18
+
19
+ return ContentTypeRenderer
@@ -146,6 +146,7 @@ class NestedContainerSerializer(WritableNestedSerializer):
146
146
  "restart_policy",
147
147
  "operation",
148
148
  "hostname",
149
+ "cap_add",
149
150
  )
150
151
 
151
152
 
@@ -406,6 +407,7 @@ class ContainerSerializer(NetBoxModelSerializer):
406
407
  "ContainerID",
407
408
  "hostname",
408
409
  "restart_policy",
410
+ "cap_add",
409
411
  "ports",
410
412
  "env",
411
413
  "labels",
@@ -3,6 +3,7 @@
3
3
  from collections.abc import Sequence
4
4
  import json
5
5
  import requests
6
+ from django.utils.html import escape
6
7
  from rest_framework import status
7
8
  from rest_framework.renderers import JSONRenderer
8
9
  from rest_framework.decorators import action
@@ -15,7 +16,7 @@ from drf_spectacular.utils import (
15
16
  from users.models import Token
16
17
  from netbox.api.viewsets import NetBoxModelViewSet
17
18
  from .. import filtersets
18
- from .renderers import PlainTextRenderer
19
+ from .renderers import make_content_type_renderer
19
20
  from .serializers import (
20
21
  HostSerializer,
21
22
  ImageSerializer,
@@ -71,6 +72,47 @@ class ImageViewSet(NetBoxModelViewSet):
71
72
  serializer_class = ImageSerializer
72
73
  http_method_names = ["get", "post", "patch", "delete", "options"]
73
74
 
75
+ @extend_schema(
76
+ operation_id="plugins_docker_image_force_pull",
77
+ responses={
78
+ (200, "application/json"): OpenApiResponse(response=str),
79
+ (502, "application/json"): OpenApiResponse(response=str),
80
+ },
81
+ )
82
+ @action(
83
+ detail=True,
84
+ methods=["post"],
85
+ renderer_classes=[JSONRenderer],
86
+ )
87
+ def force_pull(self, _request, **_kwargs):
88
+ """ Force pull an existing image """
89
+
90
+ image: Image = self.get_object()
91
+ agent_url = image.host.endpoint
92
+
93
+ url = f"{agent_url}/api/engine/images"
94
+
95
+ try:
96
+ serializer = self.get_serializer(image)
97
+ data = serializer.data
98
+ data["force"] = True
99
+
100
+ resp = requests.post(url, timeout=10, json={"data": data})
101
+ resp.raise_for_status()
102
+
103
+ except requests.HTTPError:
104
+ return Response(
105
+ {"success": False, "payload": resp.text},
106
+ status=status.HTTP_502_BAD_GATEWAY,
107
+ content_type="application/json",
108
+ )
109
+
110
+ return Response(
111
+ {"success": True, "payload": resp.json()},
112
+ status=status.HTTP_200_OK,
113
+ content_type="application/json",
114
+ )
115
+
74
116
 
75
117
  class VolumeViewSet(NetBoxModelViewSet):
76
118
  """Volume view set class"""
@@ -111,23 +153,23 @@ class ContainerViewSet(NetBoxModelViewSet):
111
153
  @extend_schema(
112
154
  operation_id="plugins_docker_container_logs",
113
155
  responses={
114
- (200, "text/plain"): OpenApiResponse(
156
+ (200, "text/html"): OpenApiResponse(
115
157
  response=str,
116
158
  examples=[
117
159
  OpenApiExample(
118
160
  "Container's logs",
119
161
  value="Hello World",
120
- media_type="text/plain",
162
+ media_type="text/html",
121
163
  ),
122
164
  ],
123
165
  ),
124
- (502, "text/plain"): OpenApiResponse(
166
+ (502, "text/html"): OpenApiResponse(
125
167
  response=str,
126
168
  examples=[
127
169
  OpenApiExample(
128
170
  "Engine error",
129
171
  value="Error as returned by Agent",
130
- media_type="text/plain",
172
+ media_type="text/html",
131
173
  ),
132
174
  ],
133
175
  ),
@@ -136,7 +178,7 @@ class ContainerViewSet(NetBoxModelViewSet):
136
178
  @action(
137
179
  detail=True,
138
180
  methods=["get"],
139
- renderer_classes=[PlainTextRenderer],
181
+ renderer_classes=[make_content_type_renderer("text/html", "txt")],
140
182
  )
141
183
  def logs(self, _request, **_kwargs):
142
184
  """Fetch container's logs"""
@@ -153,22 +195,22 @@ class ContainerViewSet(NetBoxModelViewSet):
153
195
 
154
196
  except requests.HTTPError:
155
197
  return Response(
156
- resp.text,
198
+ escape(resp.text),
157
199
  status=status.HTTP_502_BAD_GATEWAY,
158
- content_type="text/plain",
200
+ content_type="text/html",
159
201
  )
160
202
 
161
203
  return Response(
162
- resp.text,
204
+ escape(resp.text),
163
205
  status=status.HTTP_200_OK,
164
- content_type="text/plain",
206
+ content_type="text/html",
165
207
  )
166
208
 
167
209
  @extend_schema(
168
210
  operation_id="plugins_docker_container_exec",
169
211
  request=ContainerCommandSerializer,
170
212
  responses={
171
- (200, "text/plain"): OpenApiResponse(
213
+ (200, "application/json"): OpenApiResponse(
172
214
  response=str,
173
215
  examples=[
174
216
  OpenApiExample(
@@ -178,13 +220,13 @@ class ContainerViewSet(NetBoxModelViewSet):
178
220
  ),
179
221
  ],
180
222
  ),
181
- (502, "text/plain"): OpenApiResponse(
223
+ (502, "text/html"): OpenApiResponse(
182
224
  response=str,
183
225
  examples=[
184
226
  OpenApiExample(
185
227
  "Engine error",
186
228
  value="Error as returned by Agent",
187
- media_type="text/plain",
229
+ media_type="text/html",
188
230
  ),
189
231
  ],
190
232
  ),
@@ -215,9 +257,9 @@ class ContainerViewSet(NetBoxModelViewSet):
215
257
 
216
258
  except requests.HTTPError:
217
259
  return Response(
218
- resp.text,
260
+ escape(resp.text),
219
261
  status=status.HTTP_502_BAD_GATEWAY,
220
- content_type="text/plain",
262
+ content_type="text/html",
221
263
  )
222
264
 
223
265
  return Response(data=json.loads(resp.text))
@@ -15,7 +15,7 @@ from netbox.forms import (
15
15
  )
16
16
  from ..models.volume import Volume
17
17
  from ..models.host import Host
18
- from ..models.container import Container, ContainerRestartPolicyChoices
18
+ from ..models.container import Container, ContainerRestartPolicyChoices, ContainerCapAddChoices
19
19
  from ..models.image import Image
20
20
 
21
21
 
@@ -31,6 +31,7 @@ class ContainerForm(NetBoxModelForm):
31
31
  required=True,
32
32
  query_params={"host_id": "$host"},
33
33
  )
34
+ cap_add = forms.MultipleChoiceField(choices=ContainerCapAddChoices, required=False)
34
35
 
35
36
  class Meta:
36
37
  """Container form definition Meta class"""
@@ -42,6 +43,7 @@ class ContainerForm(NetBoxModelForm):
42
43
  "name",
43
44
  "hostname",
44
45
  "restart_policy",
46
+ "cap_add",
45
47
  "tags",
46
48
  )
47
49
  labels = {
@@ -50,6 +52,7 @@ class ContainerForm(NetBoxModelForm):
50
52
  "image": "Image",
51
53
  "hostname": "Hostname",
52
54
  "restart_policy": "Restart Policy",
55
+ "cap_add": "Add Host capabilities",
53
56
  }
54
57
 
55
58
 
@@ -62,6 +65,7 @@ class ContainerEditForm(NetBoxModelForm):
62
65
  required=True,
63
66
  query_params={"host_id": "$host"},
64
67
  )
68
+ cap_add = forms.MultipleChoiceField(choices=ContainerCapAddChoices, required=False)
65
69
 
66
70
  class Meta:
67
71
  """Container form definition Meta class"""
@@ -72,6 +76,7 @@ class ContainerEditForm(NetBoxModelForm):
72
76
  "name",
73
77
  "hostname",
74
78
  "restart_policy",
79
+ "cap_add",
75
80
  "tags",
76
81
  )
77
82
  labels = {
@@ -79,6 +84,7 @@ class ContainerEditForm(NetBoxModelForm):
79
84
  "image": "Image",
80
85
  "hostname": "Hostname",
81
86
  "restart_policy": "Restart Policy",
87
+ "cap_add": "Add Host capabilities",
82
88
  }
83
89
 
84
90
 
@@ -0,0 +1,29 @@
1
+ # pylint: disable=C0103
2
+ """Migration file"""
3
+
4
+ import django.contrib.postgres.fields
5
+ from django.db import migrations, models
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+ """Migration file"""
10
+
11
+ dependencies = [
12
+ (
13
+ "netbox_docker_plugin",
14
+ "0030_alter_container_containerid_alter_container_hostname_and_more",
15
+ ),
16
+ ]
17
+
18
+ operations = [
19
+ migrations.AddField(
20
+ model_name="container",
21
+ name="cap_add",
22
+ field=django.contrib.postgres.fields.ArrayField(
23
+ base_field=models.CharField(blank=True, max_length=32, null=True),
24
+ blank=True,
25
+ null=True,
26
+ size=None,
27
+ ),
28
+ ),
29
+ ]
@@ -2,6 +2,7 @@
2
2
 
3
3
  # pylint: disable=E1101
4
4
 
5
+ from django.contrib.postgres.fields import ArrayField
5
6
  from django.core.exceptions import ValidationError
6
7
  from django.db import models
7
8
  from django.db.models.functions import Lower
@@ -84,6 +85,16 @@ class PortTypeChoices(ChoiceSet):
84
85
  ]
85
86
 
86
87
 
88
+ class ContainerCapAddChoices(ChoiceSet):
89
+ """cap-add choices definition class"""
90
+
91
+ key = "Container.cap_add"
92
+
93
+ CHOICES = [
94
+ ("NET_ADMIN", "NET_ADMIN"),
95
+ ]
96
+
97
+
87
98
  class Container(NetBoxModel):
88
99
  """Container definition class"""
89
100
 
@@ -134,39 +145,48 @@ class Container(NetBoxModel):
134
145
  choices=ContainerRestartPolicyChoices,
135
146
  default=ContainerRestartPolicyChoices.DEFAULT_VALUE,
136
147
  )
148
+ cap_add = ArrayField(
149
+ models.CharField(
150
+ max_length=32, blank=True, null=True, choices=ContainerCapAddChoices
151
+ ),
152
+ null=True,
153
+ blank=True,
154
+ )
137
155
 
138
156
  @property
139
157
  def can_create(self) -> bool:
140
- """ Check if the container can be created """
158
+ """Check if the container can be created"""
141
159
  return self.state == "none"
142
160
 
143
161
  @property
144
162
  def can_start(self) -> bool:
145
- """ Check if the container can be started """
163
+ """Check if the container can be started"""
146
164
  return self.state in ["created", "exited", "dead"]
147
165
 
148
166
  @property
149
167
  def can_stop(self) -> bool:
150
- """ Check if the container can be stopped """
168
+ """Check if the container can be stopped"""
151
169
  return self.state in ["running"]
152
170
 
153
171
  @property
154
172
  def can_restart(self) -> bool:
155
- """ Check if the container can be restarted """
173
+ """Check if the container can be restarted"""
156
174
  return self.state in ["running"]
157
175
 
158
176
  @property
159
177
  def can_recreate(self) -> bool:
160
- """ Check if the container can be recreated """
178
+ """Check if the container can be recreated"""
161
179
  return self.state in ["created", "running", "exited", "dead"]
162
180
 
163
181
  @property
164
182
  def can_delete(self) -> bool:
165
- """ Check if the container can be deleted """
166
- return (
167
- self.host.state == HostStateChoices.STATE_DELETED
168
- or self.state in ["created", "paused", "exited", "dead"]
169
- )
183
+ """Check if the container can be deleted"""
184
+ return self.host.state == HostStateChoices.STATE_DELETED or self.state in [
185
+ "created",
186
+ "paused",
187
+ "exited",
188
+ "dead",
189
+ ]
170
190
 
171
191
  class Meta:
172
192
  """Image Model Meta Class"""
@@ -256,6 +256,7 @@ class ContainerTable(NetBoxTable):
256
256
  "ContainerID",
257
257
  "hostname",
258
258
  "restart_policy",
259
+ "cap_add",
259
260
  "port_count",
260
261
  "mount_count",
261
262
  "bind_count",
@@ -37,6 +37,10 @@
37
37
  <th scope="row">Restart Policy</th>
38
38
  <td>{{ object.get_restart_policy_display }}</td>
39
39
  </tr>
40
+ <tr>
41
+ <th scope="row">Host Capacities added</th>
42
+ <td>{{ object.cap_add }}</td>
43
+ </tr>
40
44
  <tr>
41
45
  <th scope="row">Status</th>
42
46
  <td>{{ object.status|placeholder }}</td>
@@ -54,47 +58,61 @@
54
58
  </div>
55
59
  <div class="col col-md-6">
56
60
  <div class="card">
57
- <h5 class="card-header">PORT MAPPINGS</h5>
61
+ <h5 class="card-header">LABELS</h5>
58
62
  <div class="card-body htmx-container table-responsive"
59
- hx-get="{% url 'plugins:netbox_docker_plugin:port_list' %}?container_id={{ object.pk }}"
63
+ hx-get="{% url 'plugins:netbox_docker_plugin:label_list' %}?container_id={{ object.pk }}"
60
64
  hx-trigger="load"
61
65
  ></div>
62
66
  {% if perms.netbox_docker_plugin.add_env %}
63
67
  <div class="card-footer text-end noprint">
64
- <a href="{% url 'plugins:netbox_docker_plugin:port_add' %}?container={{ object.pk }}&return_url={{ object.get_absolute_url }}" class="btn btn-primary">
65
- <i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add a Port Mapping
68
+ <a href="{% url 'plugins:netbox_docker_plugin:label_add' %}?container={{ object.pk }}&return_url={{ object.get_absolute_url }}" class="btn btn-primary">
69
+ <i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add a Label
66
70
  </a>
67
71
  </div>
68
72
  {% endif %}
69
73
  </div>
74
+ </div>
75
+ </div>
76
+
77
+ <h2>Runtime</h2>
78
+ <div class="row mb-3">
79
+ <div class="col col-md-6">
70
80
  <div class="card">
71
- <h5 class="card-header">MOUNTS</h5>
81
+ <h5 class="card-header">ENVIRONMENT VARIABLES</h5>
72
82
  <div class="card-body htmx-container table-responsive"
73
- hx-get="{% url 'plugins:netbox_docker_plugin:mount_list' %}?container_id={{ object.pk }}"
83
+ hx-get="{% url 'plugins:netbox_docker_plugin:env_list' %}?container_id={{ object.pk }}"
74
84
  hx-trigger="load"
75
85
  ></div>
76
86
  {% if perms.netbox_docker_plugin.add_env %}
77
87
  <div class="card-footer text-end noprint">
78
- <a href="{% url 'plugins:netbox_docker_plugin:mount_add' %}?container={{ object.pk }}&return_url={{ object.get_absolute_url }}" class="btn btn-primary">
79
- <i class="mdi mdi-plus-thick" aria-hidden="true"></i> New Mount
88
+ <a href="{% url 'plugins:netbox_docker_plugin:env_add' %}?container={{ object.pk }}&return_url={{ object.get_absolute_url }}" class="btn btn-primary">
89
+ <i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add an Env Variable
80
90
  </a>
81
91
  </div>
82
92
  {% endif %}
83
93
  </div>
94
+ </div>
95
+ </div>
96
+
97
+ <h2>Networking</h2>
98
+ <div class="row mb-3">
99
+ <div class="col col-md-6">
84
100
  <div class="card">
85
- <h5 class="card-header">BINDS</h5>
101
+ <h5 class="card-header">PORT MAPPINGS</h5>
86
102
  <div class="card-body htmx-container table-responsive"
87
- hx-get="{% url 'plugins:netbox_docker_plugin:bind_list' %}?container_id={{ object.pk }}"
103
+ hx-get="{% url 'plugins:netbox_docker_plugin:port_list' %}?container_id={{ object.pk }}"
88
104
  hx-trigger="load"
89
105
  ></div>
90
106
  {% if perms.netbox_docker_plugin.add_env %}
91
107
  <div class="card-footer text-end noprint">
92
- <a href="{% url 'plugins:netbox_docker_plugin:bind_add' %}?container={{ object.pk }}&return_url={{ object.get_absolute_url }}" class="btn btn-primary">
93
- <i class="mdi mdi-plus-thick" aria-hidden="true"></i> New Bind
108
+ <a href="{% url 'plugins:netbox_docker_plugin:port_add' %}?container={{ object.pk }}&return_url={{ object.get_absolute_url }}" class="btn btn-primary">
109
+ <i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add a Port Mapping
94
110
  </a>
95
111
  </div>
96
112
  {% endif %}
97
113
  </div>
114
+ </div>
115
+ <div class="col col-md-6">
98
116
  <div class="card">
99
117
  <h5 class="card-header">NETWORK SETTINGS</h5>
100
118
  <div class="card-body htmx-container table-responsive"
@@ -109,30 +127,38 @@
109
127
  </div>
110
128
  {% endif %}
111
129
  </div>
130
+ </div>
131
+ </div>
132
+
133
+ <h2>Storage</h2>
134
+ <div class="row mb-3">
135
+ <div class="col col-md-6">
112
136
  <div class="card">
113
- <h5 class="card-header">ENV VARIABLE</h5>
137
+ <h5 class="card-header">MOUNTS</h5>
114
138
  <div class="card-body htmx-container table-responsive"
115
- hx-get="{% url 'plugins:netbox_docker_plugin:env_list' %}?container_id={{ object.pk }}"
139
+ hx-get="{% url 'plugins:netbox_docker_plugin:mount_list' %}?container_id={{ object.pk }}"
116
140
  hx-trigger="load"
117
141
  ></div>
118
142
  {% if perms.netbox_docker_plugin.add_env %}
119
143
  <div class="card-footer text-end noprint">
120
- <a href="{% url 'plugins:netbox_docker_plugin:env_add' %}?container={{ object.pk }}&return_url={{ object.get_absolute_url }}" class="btn btn-primary">
121
- <i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add an Env Variable
144
+ <a href="{% url 'plugins:netbox_docker_plugin:mount_add' %}?container={{ object.pk }}&return_url={{ object.get_absolute_url }}" class="btn btn-primary">
145
+ <i class="mdi mdi-plus-thick" aria-hidden="true"></i> New Mount
122
146
  </a>
123
147
  </div>
124
148
  {% endif %}
125
149
  </div>
150
+ </div>
151
+ <div class="col col-md-6">
126
152
  <div class="card">
127
- <h5 class="card-header">LABELS</h5>
153
+ <h5 class="card-header">BINDS</h5>
128
154
  <div class="card-body htmx-container table-responsive"
129
- hx-get="{% url 'plugins:netbox_docker_plugin:label_list' %}?container_id={{ object.pk }}"
155
+ hx-get="{% url 'plugins:netbox_docker_plugin:bind_list' %}?container_id={{ object.pk }}"
130
156
  hx-trigger="load"
131
157
  ></div>
132
158
  {% if perms.netbox_docker_plugin.add_env %}
133
159
  <div class="card-footer text-end noprint">
134
- <a href="{% url 'plugins:netbox_docker_plugin:label_add' %}?container={{ object.pk }}&return_url={{ object.get_absolute_url }}" class="btn btn-primary">
135
- <i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add a Label
160
+ <a href="{% url 'plugins:netbox_docker_plugin:bind_add' %}?container={{ object.pk }}&return_url={{ object.get_absolute_url }}" class="btn btn-primary">
161
+ <i class="mdi mdi-plus-thick" aria-hidden="true"></i> New Bind
136
162
  </a>
137
163
  </div>
138
164
  {% endif %}