netbox-docker-plugin 2.5.0__tar.gz → 2.7.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 (128) hide show
  1. {netbox_docker_plugin-2.5.0/netbox_docker_plugin.egg-info → netbox_docker_plugin-2.7.0}/PKG-INFO +1 -1
  2. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/__init__.py +1 -1
  3. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/api/serializers.py +36 -0
  4. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/api/views.py +1 -0
  5. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/filtersets.py +17 -0
  6. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/forms/container.py +7 -1
  7. netbox_docker_plugin-2.7.0/netbox_docker_plugin/forms/device.py +45 -0
  8. netbox_docker_plugin-2.7.0/netbox_docker_plugin/migrations/0031_container_cap_add.py +29 -0
  9. netbox_docker_plugin-2.7.0/netbox_docker_plugin/migrations/0032_device_and_more.py +66 -0
  10. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/models/container.py +68 -10
  11. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tables.py +31 -0
  12. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/templates/netbox_docker_plugin/container.html +24 -0
  13. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/container/test_container_api.py +6 -0
  14. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/container/test_container_views.py +1 -0
  15. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/urls.py +22 -0
  16. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/views/container.py +3 -0
  17. netbox_docker_plugin-2.7.0/netbox_docker_plugin/views/device.py +28 -0
  18. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0/netbox_docker_plugin.egg-info}/PKG-INFO +1 -1
  19. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin.egg-info/SOURCES.txt +4 -0
  20. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/pyproject.toml +1 -1
  21. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/LICENSE +0 -0
  22. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/MANIFEST.in +0 -0
  23. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/README.md +0 -0
  24. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/api/__init__.py +0 -0
  25. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/api/renderers.py +0 -0
  26. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/api/urls.py +0 -0
  27. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/forms/__init__.py +0 -0
  28. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/forms/bind.py +0 -0
  29. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/forms/env.py +0 -0
  30. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/forms/host.py +0 -0
  31. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/forms/image.py +0 -0
  32. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/forms/label.py +0 -0
  33. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/forms/mount.py +0 -0
  34. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/forms/network.py +0 -0
  35. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/forms/network_setting.py +0 -0
  36. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/forms/port.py +0 -0
  37. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/forms/registry.py +0 -0
  38. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/forms/volume.py +0 -0
  39. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0001_initial.py +0 -0
  40. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0002_image.py +0 -0
  41. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0003_image_size.py +0 -0
  42. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0004_volume.py +0 -0
  43. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0005_network.py +0 -0
  44. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0006_container_port_mount_label_env_and_more.py +0 -0
  45. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0007_remove_container_netbox_docker_plugin_container_unique_name_host__and_more.py +0 -0
  46. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0008_alter_network_unique_together_network_networkid_and_more.py +0 -0
  47. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0009_remove_container_network_networksettings_and_more.py +0 -0
  48. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0010_container_containerid_and_more.py +0 -0
  49. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0011_host_token.py +0 -0
  50. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0012_host_state.py +0 -0
  51. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0013_host_netbox_url.py +0 -0
  52. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0014_container_operation.py +0 -0
  53. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0015_remove_mount_netbox_docker_plugin_mount_unique_volume_and_more.py +0 -0
  54. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0016_alter_env_value.py +0 -0
  55. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0017_network_state.py +0 -0
  56. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0018_alter_mount_volume_alter_networksetting_network.py +0 -0
  57. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0019_host_agent_version_host_docker_api_version.py +0 -0
  58. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0020_container_hostname.py +0 -0
  59. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0021_registry_and_more.py +0 -0
  60. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0022_bind_bind_netbox_docker_plugin_bind_unique_bind.py +0 -0
  61. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0023_delete_hosts.py +0 -0
  62. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0024_registry_host_alter_registry_name_and_more.py +0 -0
  63. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0025_alter_image_version.py +0 -0
  64. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0026_image_digest.py +0 -0
  65. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0027_container_restart_policy.py +0 -0
  66. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0028_mount_and_bind_read_only.py +0 -0
  67. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0029_alter_container_state.py +0 -0
  68. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/0030_alter_container_containerid_alter_container_hostname_and_more.py +0 -0
  69. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/migrations/__init__.py +0 -0
  70. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/models/__init__.py +0 -0
  71. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/models/host.py +0 -0
  72. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/models/image.py +0 -0
  73. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/models/network.py +0 -0
  74. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/models/registry.py +0 -0
  75. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/models/volume.py +0 -0
  76. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/navigation.py +0 -0
  77. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/signals.py +0 -0
  78. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/templates/netbox_docker_plugin/container-exec.html +0 -0
  79. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/templates/netbox_docker_plugin/container-layout.html +0 -0
  80. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/templates/netbox_docker_plugin/container-logs.html +0 -0
  81. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/templates/netbox_docker_plugin/host-graph.html +0 -0
  82. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/templates/netbox_docker_plugin/host.html +0 -0
  83. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/templates/netbox_docker_plugin/image.html +0 -0
  84. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/templates/netbox_docker_plugin/network.html +0 -0
  85. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/templates/netbox_docker_plugin/registry.html +0 -0
  86. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/templates/netbox_docker_plugin/volume.html +0 -0
  87. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/templatetags/__init__.py +0 -0
  88. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/templatetags/host.py +0 -0
  89. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/__init__.py +0 -0
  90. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/base.py +0 -0
  91. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/container/__init__.py +0 -0
  92. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/container/test_container_actions.py +0 -0
  93. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/container/test_container_api_exec.py +0 -0
  94. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/container/test_container_operation_view.py +0 -0
  95. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/container/test_container_validation.py +0 -0
  96. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/host/__init__.py +0 -0
  97. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/host/test_host_api.py +0 -0
  98. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/host/test_host_views.py +0 -0
  99. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/host/test_replace_password.py +0 -0
  100. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/image/__init__.py +0 -0
  101. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/image/test_image_api.py +0 -0
  102. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/image/test_image_views.py +0 -0
  103. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/network/__init__.py +0 -0
  104. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/network/test_network_api.py +0 -0
  105. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/network/test_network_views.py +0 -0
  106. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/registry/__init__.py +0 -0
  107. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/registry/test_registry_api.py +0 -0
  108. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/registry/test_registry_views.py +0 -0
  109. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/test_init.py +0 -0
  110. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/volume/__init__.py +0 -0
  111. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/volume/test_volume_api.py +0 -0
  112. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/tests/volume/test_volume_views.py +0 -0
  113. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/utilities/__init__.py +0 -0
  114. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/views/__init__.py +0 -0
  115. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/views/bind.py +0 -0
  116. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/views/env.py +0 -0
  117. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/views/host.py +0 -0
  118. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/views/image.py +0 -0
  119. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/views/label.py +0 -0
  120. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/views/mount.py +0 -0
  121. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/views/network.py +0 -0
  122. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/views/network_setting.py +0 -0
  123. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/views/port.py +0 -0
  124. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/views/registry.py +0 -0
  125. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin/views/volume.py +0 -0
  126. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin.egg-info/dependency_links.txt +0 -0
  127. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/netbox_docker_plugin.egg-info/top_level.txt +0 -0
  128. {netbox_docker_plugin-2.5.0 → netbox_docker_plugin-2.7.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: netbox-docker-plugin
3
- Version: 2.5.0
3
+ Version: 2.7.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.5.0"
13
+ version = "2.7.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>"
@@ -18,6 +18,7 @@ from ..models.container import (
18
18
  Mount,
19
19
  Bind,
20
20
  NetworkSetting,
21
+ Device,
21
22
  )
22
23
  from ..models.registry import Registry
23
24
 
@@ -146,6 +147,7 @@ class NestedContainerSerializer(WritableNestedSerializer):
146
147
  "restart_policy",
147
148
  "operation",
148
149
  "hostname",
150
+ "cap_add",
149
151
  )
150
152
 
151
153
 
@@ -374,6 +376,19 @@ class NetworkSettingSerializer(serializers.ModelSerializer):
374
376
  fields = ("network",)
375
377
 
376
378
 
379
+ class DeviceSerializer(serializers.ModelSerializer):
380
+ """Container Device Serializer class"""
381
+
382
+ class Meta:
383
+ """Container Device Serializer Meta class"""
384
+
385
+ model = Device
386
+ fields = (
387
+ "host_path",
388
+ "container_path",
389
+ )
390
+
391
+
377
392
  class ContainerSerializer(NetBoxModelSerializer):
378
393
  """Container Serializer class"""
379
394
 
@@ -388,6 +403,7 @@ class ContainerSerializer(NetBoxModelSerializer):
388
403
  mounts = MountSerializer(many=True, required=False)
389
404
  binds = BindSerializer(many=True, required=False)
390
405
  network_settings = NetworkSettingSerializer(many=True, required=False)
406
+ devices = DeviceSerializer(many=True, required=False)
391
407
 
392
408
  class Meta:
393
409
  """Container Serializer Meta class"""
@@ -406,12 +422,14 @@ class ContainerSerializer(NetBoxModelSerializer):
406
422
  "ContainerID",
407
423
  "hostname",
408
424
  "restart_policy",
425
+ "cap_add",
409
426
  "ports",
410
427
  "env",
411
428
  "labels",
412
429
  "mounts",
413
430
  "binds",
414
431
  "network_settings",
432
+ "devices",
415
433
  "custom_fields",
416
434
  "created",
417
435
  "last_updated",
@@ -427,11 +445,13 @@ class ContainerSerializer(NetBoxModelSerializer):
427
445
  attrs.pop("mounts", None)
428
446
  attrs.pop("binds", None)
429
447
  attrs.pop("network_settings", None)
448
+ attrs.pop("devices", None)
430
449
 
431
450
  super().validate(attrs)
432
451
 
433
452
  return data
434
453
 
454
+ # pylint: disable=R0912
435
455
  def create(self, validated_data):
436
456
  ports_data = validated_data.pop("ports", None)
437
457
  env_data = validated_data.pop("env", None)
@@ -439,6 +459,7 @@ class ContainerSerializer(NetBoxModelSerializer):
439
459
  mounts_data = validated_data.pop("mounts", None)
440
460
  binds_data = validated_data.pop("binds", None)
441
461
  network_settings_data = validated_data.pop("network_settings", None)
462
+ devices_data = validated_data.pop("devices", None)
442
463
 
443
464
  container = super().create(validated_data)
444
465
 
@@ -472,8 +493,15 @@ class ContainerSerializer(NetBoxModelSerializer):
472
493
  obj.full_clean()
473
494
  obj.save()
474
495
 
496
+ if devices_data is not None:
497
+ for device in devices_data:
498
+ obj = Device(container=container, **device)
499
+ obj.full_clean()
500
+ obj.save()
501
+
475
502
  return container
476
503
 
504
+ # pylint: disable=R0912
477
505
  def update(self, instance, validated_data):
478
506
  ports_data = validated_data.pop("ports", None)
479
507
  env_data = validated_data.pop("env", None)
@@ -481,6 +509,7 @@ class ContainerSerializer(NetBoxModelSerializer):
481
509
  mounts_data = validated_data.pop("mounts", None)
482
510
  binds_data = validated_data.pop("binds", None)
483
511
  network_settings_data = validated_data.pop("network_settings", None)
512
+ devices_data = validated_data.pop("devices", None)
484
513
 
485
514
  container = super().update(instance, validated_data)
486
515
 
@@ -520,6 +549,13 @@ class ContainerSerializer(NetBoxModelSerializer):
520
549
  obj.full_clean()
521
550
  obj.save()
522
551
 
552
+ if devices_data is not None:
553
+ Device.objects.filter(container=container).delete()
554
+ for device in devices_data:
555
+ obj = Device(container=container, **device)
556
+ obj.full_clean()
557
+ obj.save()
558
+
523
559
  return container
524
560
 
525
561
 
@@ -136,6 +136,7 @@ class ContainerViewSet(NetBoxModelViewSet):
136
136
  """Container view set class"""
137
137
 
138
138
  queryset = Container.objects.prefetch_related(
139
+ "devices",
139
140
  "network_settings",
140
141
  "mounts",
141
142
  "binds",
@@ -15,6 +15,7 @@ from .models.container import (
15
15
  Mount,
16
16
  Bind,
17
17
  NetworkSetting,
18
+ Device,
18
19
  )
19
20
  from .models.registry import Registry
20
21
 
@@ -288,3 +289,19 @@ class NetworkSettingFilterSet(BaseFilterSet):
288
289
 
289
290
  model = NetworkSetting
290
291
  fields = ("id",)
292
+
293
+
294
+ class DeviceFilterSet(BaseFilterSet):
295
+ """Device filterset definition class"""
296
+
297
+ container_id = ModelMultipleChoiceFilter(
298
+ field_name="container_id",
299
+ queryset=Container.objects.all(),
300
+ label="Container (ID)",
301
+ )
302
+
303
+ class Meta:
304
+ """Device filterset definition meta class"""
305
+
306
+ model = Device
307
+ fields = ("id",)
@@ -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,45 @@
1
+ """Device Form definition"""
2
+
3
+ from django import forms
4
+ from utilities.forms.fields import (
5
+ DynamicModelMultipleChoiceField,
6
+ DynamicModelChoiceField,
7
+ )
8
+ from netbox.forms import (
9
+ NetBoxModelFilterSetForm,
10
+ )
11
+ from ..models.container import Device, Container
12
+
13
+
14
+ class DeviceForm(forms.ModelForm):
15
+ """Device form definition class"""
16
+
17
+ container = DynamicModelChoiceField(
18
+ label="Container", queryset=Container.objects.all(), required=True
19
+ )
20
+
21
+ class Meta:
22
+ """Device form definition Meta class"""
23
+
24
+ model = Device
25
+ fields = (
26
+ "container",
27
+ "host_path",
28
+ "container_path",
29
+ )
30
+ labels = {
31
+ "container": "Container",
32
+ "host_path": "Path to the device on host",
33
+ "container_path": "Path to the device in container",
34
+ }
35
+
36
+
37
+ class DeviceFilterForm(NetBoxModelFilterSetForm):
38
+ """Device filter form definition class"""
39
+
40
+ model = Device
41
+ container_id = DynamicModelMultipleChoiceField(
42
+ queryset=Container.objects.all(),
43
+ required=False,
44
+ label="Container",
45
+ )
@@ -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
+ ]
@@ -0,0 +1,66 @@
1
+ # pylint: disable=C0103
2
+ """Migration file"""
3
+
4
+ import django.core.validators
5
+ import django.db.models.deletion
6
+ from django.db import migrations, models
7
+
8
+
9
+ class Migration(migrations.Migration):
10
+ """Migration file"""
11
+
12
+ dependencies = [
13
+ ("netbox_docker_plugin", "0031_container_cap_add"),
14
+ ]
15
+
16
+ operations = [
17
+ migrations.CreateModel(
18
+ name="Device",
19
+ fields=[
20
+ (
21
+ "id",
22
+ models.BigAutoField(
23
+ auto_created=True, primary_key=True, serialize=False
24
+ ),
25
+ ),
26
+ (
27
+ "host_path",
28
+ models.CharField(
29
+ max_length=1024,
30
+ validators=[
31
+ django.core.validators.MinLengthValidator(limit_value=1),
32
+ django.core.validators.MaxLengthValidator(limit_value=1024),
33
+ ],
34
+ ),
35
+ ),
36
+ (
37
+ "container_path",
38
+ models.CharField(
39
+ max_length=1024,
40
+ validators=[
41
+ django.core.validators.MinLengthValidator(limit_value=1),
42
+ django.core.validators.MaxLengthValidator(limit_value=1024),
43
+ ],
44
+ ),
45
+ ),
46
+ (
47
+ "container",
48
+ models.ForeignKey(
49
+ on_delete=django.db.models.deletion.CASCADE,
50
+ related_name="devices",
51
+ to="netbox_docker_plugin.container",
52
+ ),
53
+ ),
54
+ ],
55
+ options={
56
+ "ordering": ("container", "container_path", "host_path"),
57
+ },
58
+ ),
59
+ migrations.AddConstraint(
60
+ model_name="device",
61
+ constraint=models.UniqueConstraint(
62
+ fields=("container", "container_path", "host_path"),
63
+ name="netbox_docker_plugin_device_unique_device",
64
+ ),
65
+ ),
66
+ ]
@@ -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"""
@@ -441,3 +461,41 @@ class NetworkSetting(models.Model):
441
461
  + f"{self.container.host}."
442
462
  }
443
463
  )
464
+
465
+
466
+ class Device(models.Model):
467
+ """Device definition class"""
468
+
469
+ objects = RestrictedQuerySet.as_manager()
470
+
471
+ container = models.ForeignKey(
472
+ Container, on_delete=models.CASCADE, related_name="devices"
473
+ )
474
+ host_path = models.CharField(
475
+ max_length=1024,
476
+ validators=[
477
+ MinLengthValidator(limit_value=1),
478
+ MaxLengthValidator(limit_value=1024),
479
+ ],
480
+ )
481
+ container_path = models.CharField(
482
+ max_length=1024,
483
+ validators=[
484
+ MinLengthValidator(limit_value=1),
485
+ MaxLengthValidator(limit_value=1024),
486
+ ],
487
+ )
488
+
489
+ class Meta:
490
+ """Device Model Meta Class"""
491
+
492
+ ordering = ("container", "container_path", "host_path")
493
+ constraints = (
494
+ models.UniqueConstraint(
495
+ fields=["container", "container_path", "host_path"],
496
+ name="%(app_label)s_%(class)s_unique_device",
497
+ ),
498
+ )
499
+
500
+ def __str__(self):
501
+ return f"{self.host_path}:{self.container_path}"
@@ -14,6 +14,7 @@ from .models.container import (
14
14
  Mount,
15
15
  Bind,
16
16
  NetworkSetting,
17
+ Device,
17
18
  )
18
19
  from .models.registry import Registry
19
20
  from .templatetags.host import remove_password
@@ -239,6 +240,11 @@ class ContainerTable(NetBoxTable):
239
240
  url_params={"container_id": "pk"},
240
241
  verbose_name="Labels count",
241
242
  )
243
+ device_count = columns.LinkedCountColumn(
244
+ viewname="plugins:netbox_docker_plugin:device_list",
245
+ url_params={"container_id": "pk"},
246
+ verbose_name="Devices count",
247
+ )
242
248
  tags = columns.TagColumn()
243
249
 
244
250
  class Meta(NetBoxTable.Meta):
@@ -256,12 +262,14 @@ class ContainerTable(NetBoxTable):
256
262
  "ContainerID",
257
263
  "hostname",
258
264
  "restart_policy",
265
+ "cap_add",
259
266
  "port_count",
260
267
  "mount_count",
261
268
  "bind_count",
262
269
  "networksetting_count",
263
270
  "env_count",
264
271
  "label_count",
272
+ "device_count",
265
273
  "tags",
266
274
  )
267
275
  default_columns = (
@@ -394,3 +402,26 @@ class NetworkSettingTable(NetBoxTable):
394
402
  "container",
395
403
  "network",
396
404
  )
405
+
406
+
407
+ class DeviceTable(NetBoxTable):
408
+ """Device Table definition class"""
409
+
410
+ container = tables.Column(linkify=True)
411
+
412
+ actions = columns.ActionsColumn(actions=("edit", "delete"))
413
+
414
+ class Meta(NetBoxTable.Meta):
415
+ """Device Table definition Meta class"""
416
+
417
+ model = Device
418
+ fields = (
419
+ "container",
420
+ "host_path",
421
+ "container_path",
422
+ )
423
+ default_columns = (
424
+ "container",
425
+ "host_path",
426
+ "container_path",
427
+ )
@@ -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>
@@ -161,4 +165,24 @@
161
165
  </div>
162
166
  </div>
163
167
  </div>
168
+
169
+ <h2>Host capabilities</h2>
170
+ <div class="row mb-3">
171
+ <div class="col col-md-6">
172
+ <div class="card">
173
+ <h5 class="card-header">DEVICES</h5>
174
+ <div class="card-body htmx-container table-responsive"
175
+ hx-get="{% url 'plugins:netbox_docker_plugin:device_list' %}?container_id={{ object.pk }}"
176
+ hx-trigger="load"
177
+ ></div>
178
+ {% if perms.netbox_docker_plugin.add_device %}
179
+ <div class="card-footer text-end noprint">
180
+ <a href="{% url 'plugins:netbox_docker_plugin:device_add' %}?container={{ object.pk }}&return_url={{ object.get_absolute_url }}" class="btn btn-primary">
181
+ <i class="mdi mdi-plus-thick" aria-hidden="true"></i> New Device
182
+ </a>
183
+ </div>
184
+ {% endif %}
185
+ </div>
186
+ </div>
187
+ </div>
164
188
  {% endblock content %}
@@ -29,6 +29,7 @@ class ContainerApiTestCase(
29
29
  model = Container
30
30
  brief_fields = [
31
31
  "ContainerID",
32
+ "cap_add",
32
33
  "display",
33
34
  "hostname",
34
35
  "id",
@@ -46,6 +47,7 @@ class ContainerApiTestCase(
46
47
  "mounts",
47
48
  "binds",
48
49
  "network_settings",
50
+ "devices",
49
51
  ]
50
52
 
51
53
  @classmethod
@@ -120,6 +122,9 @@ class ContainerApiTestCase(
120
122
  "network_settings": [
121
123
  {"network": network1.pk},
122
124
  ],
125
+ "devices": [
126
+ {"host_path": "/dev/sda", "container_path": "/dev/xvdc"},
127
+ ]
123
128
  },
124
129
  {
125
130
  "host": host2.pk,
@@ -168,6 +173,7 @@ class ContainerApiTestCase(
168
173
  "ports": [],
169
174
  "env": [{"var_name": "ENV", "value": ""}],
170
175
  "labels": [],
176
+ "cap_add": ["NET_ADMIN"],
171
177
  },
172
178
  ]
173
179
 
@@ -66,6 +66,7 @@ class ContainerViewsTestCase(
66
66
  "host": host1.pk,
67
67
  "image": image1.pk,
68
68
  "restart_policy": "unless-stopped",
69
+ "cap_add": "NET_ADMIN",
69
70
  }
70
71
 
71
72
  cls.csv_data = (
@@ -21,6 +21,7 @@ from .views import (
21
21
  bind as bind_views,
22
22
  network_setting as network_setting_views,
23
23
  registry as registry_views,
24
+ device as device_views,
24
25
  )
25
26
 
26
27
  urlpatterns = (
@@ -405,4 +406,25 @@ urlpatterns = (
405
406
  name="registry_journal",
406
407
  kwargs={"model": Registry},
407
408
  ),
409
+ # Device
410
+ path(
411
+ "devices/",
412
+ device_views.DeviceListView.as_view(),
413
+ name="device_list",
414
+ ),
415
+ path(
416
+ "devices/add/",
417
+ device_views.DeviceEditView.as_view(),
418
+ name="device_add",
419
+ ),
420
+ path(
421
+ "devices/<int:pk>/edit/",
422
+ device_views.DeviceEditView.as_view(),
423
+ name="device_edit",
424
+ ),
425
+ path(
426
+ "devices/<int:pk>/delete/",
427
+ device_views.DeviceDeleteView.as_view(),
428
+ name="device_delete",
429
+ ),
408
430
  )
@@ -13,6 +13,7 @@ from ..models.container import (
13
13
  NetworkSetting,
14
14
  Env,
15
15
  Label,
16
+ Device,
16
17
  )
17
18
 
18
19
 
@@ -29,6 +30,7 @@ class ContainerView(generic.ObjectView):
29
30
  "binds",
30
31
  "ports",
31
32
  "network_settings",
33
+ "devices",
32
34
  )
33
35
 
34
36
 
@@ -74,6 +76,7 @@ class ContainerListView(generic.ObjectListView):
74
76
  networksetting_count=count_related(NetworkSetting, "container"),
75
77
  env_count=count_related(Env, "container"),
76
78
  label_count=count_related(Label, "container"),
79
+ device_count=count_related(Device, "container"),
77
80
  )
78
81
 
79
82
  table = tables.ContainerTable
@@ -0,0 +1,28 @@
1
+ """Container views definitions"""
2
+
3
+ from netbox.views import generic
4
+ from .. import tables, filtersets
5
+ from ..forms.device import DeviceForm, DeviceFilterForm
6
+ from ..models.container import Device
7
+
8
+
9
+ class DeviceListView(generic.ObjectListView):
10
+ """Device list view definition"""
11
+
12
+ queryset = Device.objects.prefetch_related("container")
13
+ table = tables.DeviceTable
14
+ filterset = filtersets.DeviceFilterSet
15
+ filterset_form = DeviceFilterForm
16
+
17
+
18
+ class DeviceEditView(generic.ObjectEditView):
19
+ """Device edition view definition"""
20
+
21
+ queryset = Device.objects.all()
22
+ form = DeviceForm
23
+
24
+
25
+ class DeviceDeleteView(generic.ObjectDeleteView):
26
+ """Device delete view definition"""
27
+
28
+ queryset = Device.objects.all()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: netbox-docker-plugin
3
- Version: 2.5.0
3
+ Version: 2.7.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
@@ -20,6 +20,7 @@ netbox_docker_plugin/api/views.py
20
20
  netbox_docker_plugin/forms/__init__.py
21
21
  netbox_docker_plugin/forms/bind.py
22
22
  netbox_docker_plugin/forms/container.py
23
+ netbox_docker_plugin/forms/device.py
23
24
  netbox_docker_plugin/forms/env.py
24
25
  netbox_docker_plugin/forms/host.py
25
26
  netbox_docker_plugin/forms/image.py
@@ -60,6 +61,8 @@ netbox_docker_plugin/migrations/0027_container_restart_policy.py
60
61
  netbox_docker_plugin/migrations/0028_mount_and_bind_read_only.py
61
62
  netbox_docker_plugin/migrations/0029_alter_container_state.py
62
63
  netbox_docker_plugin/migrations/0030_alter_container_containerid_alter_container_hostname_and_more.py
64
+ netbox_docker_plugin/migrations/0031_container_cap_add.py
65
+ netbox_docker_plugin/migrations/0032_device_and_more.py
63
66
  netbox_docker_plugin/migrations/__init__.py
64
67
  netbox_docker_plugin/models/__init__.py
65
68
  netbox_docker_plugin/models/container.py
@@ -110,6 +113,7 @@ netbox_docker_plugin/utilities/__init__.py
110
113
  netbox_docker_plugin/views/__init__.py
111
114
  netbox_docker_plugin/views/bind.py
112
115
  netbox_docker_plugin/views/container.py
116
+ netbox_docker_plugin/views/device.py
113
117
  netbox_docker_plugin/views/env.py
114
118
  netbox_docker_plugin/views/host.py
115
119
  netbox_docker_plugin/views/image.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "netbox-docker-plugin"
7
- version = "2.5.0"
7
+ version = "2.7.0"
8
8
  authors = [
9
9
  { name="Vincent Simonin", email="vincent@saashup.com" },
10
10
  { name="David Delassus", email="david.jose.delassus@gmail.com" }