netbox-docker-plugin 1.4.0__tar.gz → 1.5.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 (111) hide show
  1. {netbox-docker-plugin-1.4.0/netbox_docker_plugin.egg-info → netbox-docker-plugin-1.5.0}/PKG-INFO +1 -1
  2. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/__init__.py +1 -1
  3. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/api/serializers.py +4 -0
  4. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/api/views.py +4 -2
  5. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/filtersets.py +5 -0
  6. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/forms/image.py +15 -1
  7. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/forms/registry.py +8 -1
  8. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/0021_registry_and_more.py +0 -2
  9. netbox-docker-plugin-1.5.0/netbox_docker_plugin/migrations/0023_delete_hosts.py +33 -0
  10. netbox-docker-plugin-1.5.0/netbox_docker_plugin/migrations/0024_registry_host_alter_registry_name_and_more.py +47 -0
  11. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/models/image.py +0 -1
  12. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/models/registry.py +23 -11
  13. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/templates/netbox_docker_plugin/host.html +17 -0
  14. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/templates/netbox_docker_plugin/registry.html +4 -0
  15. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/container/test_container_api.py +10 -2
  16. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/container/test_container_operation_view.py +10 -2
  17. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/container/test_container_validation.py +14 -2
  18. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/container/test_container_views.py +10 -2
  19. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/host/test_host_api.py +41 -0
  20. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/registry/test_registry_api.py +21 -7
  21. netbox-docker-plugin-1.5.0/netbox_docker_plugin/tests/registry/test_registry_views.py +39 -0
  22. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/views/host.py +7 -1
  23. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0/netbox_docker_plugin.egg-info}/PKG-INFO +1 -1
  24. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin.egg-info/SOURCES.txt +2 -0
  25. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/pyproject.toml +1 -1
  26. netbox-docker-plugin-1.4.0/netbox_docker_plugin/tests/registry/test_registry_views.py +0 -33
  27. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/LICENSE +0 -0
  28. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/MANIFEST.in +0 -0
  29. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/README.md +0 -0
  30. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/api/__init__.py +0 -0
  31. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/api/urls.py +0 -0
  32. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/forms/__init__.py +0 -0
  33. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/forms/bind.py +0 -0
  34. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/forms/container.py +0 -0
  35. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/forms/env.py +0 -0
  36. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/forms/host.py +0 -0
  37. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/forms/label.py +0 -0
  38. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/forms/mount.py +0 -0
  39. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/forms/network.py +0 -0
  40. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/forms/network_setting.py +0 -0
  41. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/forms/port.py +0 -0
  42. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/forms/volume.py +0 -0
  43. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/0001_initial.py +0 -0
  44. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/0002_image.py +0 -0
  45. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/0003_image_size.py +0 -0
  46. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/0004_volume.py +0 -0
  47. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/0005_network.py +0 -0
  48. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/0006_container_port_mount_label_env_and_more.py +0 -0
  49. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/0007_remove_container_netbox_docker_plugin_container_unique_name_host__and_more.py +0 -0
  50. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/0008_alter_network_unique_together_network_networkid_and_more.py +0 -0
  51. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/0009_remove_container_network_networksettings_and_more.py +0 -0
  52. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/0010_container_containerid_and_more.py +0 -0
  53. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/0011_host_token.py +0 -0
  54. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/0012_host_state.py +0 -0
  55. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/0013_host_netbox_url.py +0 -0
  56. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/0014_container_operation.py +0 -0
  57. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/0015_remove_mount_netbox_docker_plugin_mount_unique_volume_and_more.py +0 -0
  58. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/0016_alter_env_value.py +0 -0
  59. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/0017_network_state.py +0 -0
  60. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/0018_alter_mount_volume_alter_networksetting_network.py +0 -0
  61. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/0019_host_agent_version_host_docker_api_version.py +0 -0
  62. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/0020_container_hostname.py +0 -0
  63. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/0022_bind_bind_netbox_docker_plugin_bind_unique_bind.py +0 -0
  64. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/migrations/__init__.py +0 -0
  65. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/models/__init__.py +0 -0
  66. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/models/container.py +0 -0
  67. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/models/host.py +0 -0
  68. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/models/network.py +0 -0
  69. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/models/volume.py +0 -0
  70. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/navigation.py +0 -0
  71. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tables.py +0 -0
  72. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/templates/netbox_docker_plugin/container.html +0 -0
  73. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/templates/netbox_docker_plugin/image.html +0 -0
  74. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/templates/netbox_docker_plugin/network.html +0 -0
  75. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/templates/netbox_docker_plugin/volume.html +0 -0
  76. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/templatetags/__init__.py +0 -0
  77. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/templatetags/host.py +0 -0
  78. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/__init__.py +0 -0
  79. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/base.py +0 -0
  80. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/container/__init__.py +0 -0
  81. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/host/__init__.py +0 -0
  82. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/host/test_host_views.py +0 -0
  83. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/host/test_replace_password.py +0 -0
  84. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/image/__init__.py +0 -0
  85. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/image/test_image_api.py +0 -0
  86. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/image/test_image_views.py +0 -0
  87. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/network/__init__.py +0 -0
  88. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/network/test_network_api.py +0 -0
  89. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/network/test_network_views.py +0 -0
  90. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/registry/__init__.py +0 -0
  91. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/test_init.py +0 -0
  92. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/volume/__init__.py +0 -0
  93. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/volume/test_volume_api.py +0 -0
  94. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/tests/volume/test_volume_views.py +0 -0
  95. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/urls.py +0 -0
  96. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/utilities/__init__.py +0 -0
  97. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/views/__init__.py +0 -0
  98. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/views/bind.py +0 -0
  99. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/views/container.py +0 -0
  100. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/views/env.py +0 -0
  101. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/views/image.py +0 -0
  102. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/views/label.py +0 -0
  103. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/views/mount.py +0 -0
  104. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/views/network.py +0 -0
  105. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/views/network_setting.py +0 -0
  106. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/views/port.py +0 -0
  107. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/views/registry.py +0 -0
  108. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin/views/volume.py +0 -0
  109. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin.egg-info/dependency_links.txt +0 -0
  110. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/netbox_docker_plugin.egg-info/top_level.txt +0 -0
  111. {netbox-docker-plugin-1.4.0 → netbox-docker-plugin-1.5.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: netbox-docker-plugin
3
- Version: 1.4.0
3
+ Version: 1.5.0
4
4
  Summary: Manage Docker with Netbox & style.
5
5
  Author-email: Vincent Simonin <vincent@saashup.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 = "1.4.0"
13
+ version = "1.5.0"
14
14
  base_url = "docker"
15
15
  author= "Vincent Simonin"
16
16
  author_email= "vincent@saashup.com"
@@ -501,6 +501,7 @@ class RegistrySerializer(NetBoxModelSerializer):
501
501
  url = serializers.HyperlinkedIdentityField(
502
502
  view_name="plugins-api:netbox_docker_plugin-api:registry-detail"
503
503
  )
504
+ host = NestedHostSerializer()
504
505
  images = NestedImageSerializer(many=True, read_only=True)
505
506
 
506
507
  class Meta:
@@ -511,6 +512,7 @@ class RegistrySerializer(NetBoxModelSerializer):
511
512
  "id",
512
513
  "name",
513
514
  "url",
515
+ "host",
514
516
  "display",
515
517
  "serveraddress",
516
518
  "username",
@@ -530,6 +532,7 @@ class HostSerializer(NetBoxModelSerializer):
530
532
  volumes = NestedVolumeSerializer(many=True, read_only=True)
531
533
  networks = NestedNetworkSerializer(many=True, read_only=True)
532
534
  containers = NestedContainerSerializer(many=True, read_only=True)
535
+ registries = NestedRegistrySerializer(many=True, read_only=True)
533
536
  token = NestedTokenSerializer(read_only=True)
534
537
 
535
538
  class Meta:
@@ -555,4 +558,5 @@ class HostSerializer(NetBoxModelSerializer):
555
558
  "volumes",
556
559
  "networks",
557
560
  "containers",
561
+ "registries",
558
562
  )
@@ -23,7 +23,9 @@ from ..models.registry import Registry
23
23
  class HostViewSet(NetBoxModelViewSet):
24
24
  """Host view set class"""
25
25
 
26
- queryset = Host.objects.prefetch_related("images", "volumes", "tags")
26
+ queryset = Host.objects.prefetch_related(
27
+ "images", "volumes", "networks", "containers", "registries", "tags"
28
+ )
27
29
  filterset_class = filtersets.HostFilterSet
28
30
  serializer_class = HostSerializer
29
31
  http_method_names = ["get", "post", "patch", "delete", "options"]
@@ -97,7 +99,7 @@ class ContainerViewSet(NetBoxModelViewSet):
97
99
  class RegistryViewSet(NetBoxModelViewSet):
98
100
  """Registry view set class"""
99
101
 
100
- queryset = Registry.objects.prefetch_related("images", "tags")
102
+ queryset = Registry.objects.prefetch_related("host", "images", "tags")
101
103
  filterset_class = filtersets.RegistryFilterSet
102
104
  serializer_class = RegistrySerializer
103
105
  http_method_names = ["get", "post", "patch", "delete", "options"]
@@ -49,6 +49,11 @@ class RegistryFilterSet(NetBoxModelFilterSet):
49
49
  """Registry filterset definition class"""
50
50
 
51
51
  name = filters.CharFilter(lookup_expr="icontains")
52
+ host_id = ModelMultipleChoiceFilter(
53
+ field_name="host_id",
54
+ queryset=Host.objects.all(),
55
+ label="Host (ID)",
56
+ )
52
57
 
53
58
  class Meta:
54
59
  """Registry filterset definition meta class"""
@@ -1,7 +1,11 @@
1
1
  """Image Forms definitions"""
2
2
 
3
3
  from django import forms
4
- from utilities.forms.fields import TagFilterField, DynamicModelMultipleChoiceField
4
+ from utilities.forms.fields import (
5
+ TagFilterField,
6
+ DynamicModelMultipleChoiceField,
7
+ DynamicModelChoiceField,
8
+ )
5
9
  from netbox.forms import (
6
10
  NetBoxModelForm,
7
11
  NetBoxModelImportForm,
@@ -16,6 +20,16 @@ from ..models.registry import Registry
16
20
  class ImageForm(NetBoxModelForm):
17
21
  """Image form definition class"""
18
22
 
23
+ host = DynamicModelChoiceField(
24
+ label="Host", queryset=Host.objects.all(), required=True
25
+ )
26
+ registry = DynamicModelChoiceField(
27
+ label="Registry",
28
+ queryset=Registry.objects.all(),
29
+ required=True,
30
+ query_params={"host_id": "$host"},
31
+ )
32
+
19
33
  class Meta:
20
34
  """Image form definition Meta class"""
21
35
 
@@ -1,12 +1,13 @@
1
1
  """Registry Forms definitions"""
2
2
 
3
3
  from django import forms
4
- from utilities.forms.fields import TagFilterField
4
+ from utilities.forms.fields import TagFilterField, DynamicModelMultipleChoiceField
5
5
  from netbox.forms import (
6
6
  NetBoxModelForm,
7
7
  NetBoxModelFilterSetForm,
8
8
  )
9
9
  from ..models.registry import Registry
10
+ from ..models.host import Host
10
11
 
11
12
 
12
13
  class RegistryForm(NetBoxModelForm):
@@ -24,6 +25,7 @@ class RegistryForm(NetBoxModelForm):
24
25
 
25
26
  model = Registry
26
27
  fields = (
28
+ "host",
27
29
  "name",
28
30
  "serveraddress",
29
31
  "username",
@@ -39,5 +41,10 @@ class RegistryFilterForm(NetBoxModelFilterSetForm):
39
41
  """Registry filter form definition class"""
40
42
 
41
43
  model = Registry
44
+ host_id = DynamicModelMultipleChoiceField(
45
+ queryset=Host.objects.all(),
46
+ required=False,
47
+ label="Host",
48
+ )
42
49
  name = forms.CharField(label="Name", required=False)
43
50
  tag = TagFilterField(model)
@@ -6,7 +6,6 @@ import utilities.json
6
6
  import django.core.validators
7
7
  from django.db import migrations, models
8
8
  import django.db.models.deletion
9
- import netbox_docker_plugin.models.registry
10
9
 
11
10
 
12
11
  class Migration(migrations.Migration):
@@ -60,7 +59,6 @@ class Migration(migrations.Migration):
60
59
  model_name="image",
61
60
  name="registry",
62
61
  field=models.ForeignKey(
63
- default=netbox_docker_plugin.models.registry.Registry.get_default_registry,
64
62
  on_delete=django.db.models.deletion.CASCADE,
65
63
  related_name="images",
66
64
  to="netbox_docker_plugin.registry",
@@ -0,0 +1,33 @@
1
+ # pylint: disable=C0103
2
+ """Migration file"""
3
+
4
+ from django.db import migrations
5
+
6
+
7
+ def delete_hosts(apps, schema_editor):
8
+ """Delete all Hosts and Registries"""
9
+ Host = apps.get_model("netbox_docker_plugin", "Host")
10
+ Host.objects.using(schema_editor.connection.alias).all().delete()
11
+
12
+ Registry = Host = apps.get_model("netbox_docker_plugin", "Registry")
13
+ Registry.objects.using(schema_editor.connection.alias).all().delete()
14
+
15
+
16
+ def do_nothing(apps, schema_editor): # pylint: disable=W0613
17
+ """Nothing to do"""
18
+ return None
19
+
20
+
21
+ class Migration(migrations.Migration):
22
+ """Migration file"""
23
+
24
+ dependencies = [
25
+ (
26
+ "netbox_docker_plugin",
27
+ "0022_bind_bind_netbox_docker_plugin_bind_unique_bind",
28
+ ),
29
+ ]
30
+
31
+ operations = [
32
+ migrations.RunPython(delete_hosts, do_nothing),
33
+ ]
@@ -0,0 +1,47 @@
1
+ # pylint: disable=C0103
2
+ """Migration file"""
3
+
4
+ import django.core.validators
5
+ from django.db import migrations, models
6
+ import django.db.models.deletion
7
+
8
+ class Migration(migrations.Migration):
9
+ """Migration file"""
10
+
11
+ dependencies = [
12
+ (
13
+ "netbox_docker_plugin",
14
+ "0023_delete_hosts",
15
+ ),
16
+ ]
17
+
18
+ operations = [
19
+ migrations.AddField(
20
+ model_name="registry",
21
+ name="host",
22
+ field=models.ForeignKey(
23
+ default=None,
24
+ on_delete=django.db.models.deletion.CASCADE,
25
+ related_name="registries",
26
+ to="netbox_docker_plugin.host",
27
+ ),
28
+ preserve_default=False,
29
+ ),
30
+ migrations.AlterField(
31
+ model_name="registry",
32
+ name="name",
33
+ field=models.CharField(
34
+ max_length=255,
35
+ validators=[
36
+ django.core.validators.MinLengthValidator(limit_value=1),
37
+ django.core.validators.MaxLengthValidator(limit_value=255),
38
+ ],
39
+ ),
40
+ ),
41
+ migrations.AddConstraint(
42
+ model_name="registry",
43
+ constraint=models.UniqueConstraint(
44
+ fields=("host", "name"), name="netbox_docker_plugin_registry_name_host"
45
+ ),
46
+ ),
47
+ ]
@@ -19,7 +19,6 @@ class Image(NetBoxModel):
19
19
  host = models.ForeignKey(Host, on_delete=models.CASCADE, related_name="images")
20
20
  registry = models.ForeignKey(
21
21
  Registry,
22
- default=Registry.get_default_registry, # type: ignore
23
22
  on_delete=models.CASCADE,
24
23
  related_name="images",
25
24
  )
@@ -1,19 +1,35 @@
1
1
  """Registry Model definition"""
2
2
 
3
3
  from django.db import models
4
+ from django.db.models.signals import post_save
5
+ from django.dispatch import receiver
4
6
  from django.core.validators import (
5
7
  MinLengthValidator,
6
8
  MaxLengthValidator,
7
9
  )
8
10
  from django.urls import reverse
9
11
  from netbox.models import NetBoxModel
12
+ from .host import Host
13
+
14
+
15
+ @receiver(post_save, sender=Host)
16
+ def create_default_registry(sender, **kwargs): # pylint: disable=W0613
17
+ """Create default registry on Host creation"""
18
+
19
+ if kwargs.get("created") is True:
20
+ registry = Registry(
21
+ host=kwargs.get("instance"),
22
+ name="dockerhub",
23
+ serveraddress="https://registry.hub.docker.com/v2/",
24
+ )
25
+ registry.save()
10
26
 
11
27
 
12
28
  class Registry(NetBoxModel):
13
29
  """Registry definition class"""
14
30
 
31
+ host = models.ForeignKey(Host, on_delete=models.CASCADE, related_name="registries")
15
32
  name = models.CharField(
16
- unique=True,
17
33
  max_length=255,
18
34
  validators=[
19
35
  MinLengthValidator(limit_value=1),
@@ -25,20 +41,16 @@ class Registry(NetBoxModel):
25
41
  password = models.CharField(blank=True, null=True, max_length=512)
26
42
  email = models.EmailField(blank=True, null=True, max_length=512)
27
43
 
28
- @classmethod
29
- def get_default_registry(cls):
30
- """Return the default Registry"""
31
- # pylint: disable=W0612
32
- registry, created = cls.objects.get_or_create(
33
- name="dockerhub",
34
- serveraddress="https://registry.hub.docker.com/v2/",
35
- )
36
- return registry.pk
37
-
38
44
  class Meta:
39
45
  """Registry Model Meta Class"""
40
46
 
41
47
  ordering = ("name",)
48
+ constraints = (
49
+ models.UniqueConstraint(
50
+ fields=["host", "name"],
51
+ name="%(app_label)s_%(class)s_name_host",
52
+ ),
53
+ )
42
54
 
43
55
  def __str__(self):
44
56
  return f"{self.name}"
@@ -43,6 +43,23 @@
43
43
  </div>
44
44
  </div>
45
45
  <div class="row">
46
+ <div class="col col-md-12">
47
+ <div class="card">
48
+ <h5 class="card-header">Registry</h5>
49
+ <div class="card-body htmx-container table-responsive"
50
+ hx-get="{% url 'plugins:netbox_docker_plugin:registry_list' %}?host_id={{ object.pk }}"
51
+ hx-trigger="load"
52
+ ></div>
53
+ {% if perms.netbox_docker_plugin.add_container %}
54
+ <div class="card-footer text-end noprint">
55
+ <a href="{% url 'plugins:netbox_docker_plugin:registry_add' %}?host={{ object.pk }}&return_url={{ object.get_absolute_url }}" class="btn btn-primary btn-sm">
56
+ <i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add a Registry
57
+ </a>
58
+ </div>
59
+ {% endif %}
60
+ </div>
61
+ {% plugin_full_width_page object %}
62
+ </div>
46
63
  <div class="col col-md-12">
47
64
  <div class="card">
48
65
  <h5 class="card-header">Container</h5>
@@ -10,6 +10,10 @@
10
10
  <h5 class="card-header">REGISTRY</h5>
11
11
  <div class="card-body">
12
12
  <table class="table table-hover attr-table">
13
+ <tr>
14
+ <th scope="row">Host</th>
15
+ <td><a href="{{ object.host.get_absolute_url }}">{{ object.host }}</a></td>
16
+ </tr>
13
17
  <tr>
14
18
  <th scope="row">Name</th>
15
19
  <td>{{ object.name }}</td>
@@ -6,6 +6,7 @@ from netbox_docker_plugin.models.host import Host
6
6
  from netbox_docker_plugin.models.network import Network
7
7
  from netbox_docker_plugin.models.image import Image
8
8
  from netbox_docker_plugin.models.volume import Volume
9
+ from netbox_docker_plugin.models.registry import Registry
9
10
  from netbox_docker_plugin.tests.base import BaseAPITestCase
10
11
 
11
12
 
@@ -44,8 +45,15 @@ class ContainerApiTestCase(
44
45
  host1 = Host.objects.create(endpoint="http://localhost:8080", name="host1")
45
46
  host2 = Host.objects.create(endpoint="http://localhost:8080", name="host2")
46
47
 
47
- image1 = Image.objects.create(host=host1, name="image1")
48
- image2 = Image.objects.create(host=host2, name="image2")
48
+ registry1 = Registry.objects.create(
49
+ host=host1, name="registry1", serveraddress="http://localhost:8080"
50
+ )
51
+ registry2 = Registry.objects.create(
52
+ host=host2, name="registry2", serveraddress="http://localhost:8082"
53
+ )
54
+
55
+ image1 = Image.objects.create(host=host1, name="image1", registry=registry1)
56
+ image2 = Image.objects.create(host=host2, name="image2", registry=registry2)
49
57
 
50
58
  network1 = Network.objects.create(host=host1, name="network1")
51
59
  network2 = Network.objects.create(host=host2, name="network2")
@@ -11,6 +11,7 @@ from extras.models import ObjectChange
11
11
  from netbox_docker_plugin.models.host import Host
12
12
  from netbox_docker_plugin.models.container import Container
13
13
  from netbox_docker_plugin.models.image import Image
14
+ from netbox_docker_plugin.models.registry import Registry
14
15
  from netbox_docker_plugin.tests.base import BaseModelViewTestCase
15
16
 
16
17
 
@@ -248,8 +249,15 @@ class ContainerViewsTestCase(BaseModelViewTestCase, ModelViewTestCase):
248
249
  host1 = Host.objects.create(endpoint="http://localhost:8080", name="host1")
249
250
  host2 = Host.objects.create(endpoint="http://localhost:8081", name="host2")
250
251
 
251
- image1 = Image.objects.create(host=host1, name="image1")
252
- image2 = Image.objects.create(host=host2, name="image2")
252
+ registry1 = Registry.objects.create(
253
+ host=host1, name="registry1", serveraddress="http://localhost:8080"
254
+ )
255
+ registry2 = Registry.objects.create(
256
+ host=host2, name="registry2", serveraddress="http://localhost:8082"
257
+ )
258
+
259
+ image1 = Image.objects.create(host=host1, name="image1", registry=registry1)
260
+ image2 = Image.objects.create(host=host2, name="image2", registry=registry2)
253
261
 
254
262
  Container.objects.create(host=host1, image=image1, name="container1")
255
263
  Container.objects.create(host=host1, image=image1, name="container2")
@@ -7,6 +7,7 @@ from netbox_docker_plugin.models.host import Host
7
7
  from netbox_docker_plugin.models.image import Image
8
8
  from netbox_docker_plugin.models.volume import Volume
9
9
  from netbox_docker_plugin.models.network import Network
10
+ from netbox_docker_plugin.models.registry import Registry
10
11
  from netbox_docker_plugin.models.container import Mount, NetworkSetting
11
12
 
12
13
 
@@ -113,11 +114,22 @@ class ContainerValidationTestCase(TestCase):
113
114
  endpoint="http://localhost:8081", name="host2"
114
115
  )
115
116
 
117
+ cls.objects["registry1"] = Registry.objects.create(
118
+ host=cls.objects["host1"],
119
+ name="registry1",
120
+ serveraddress="http://localhost:8080",
121
+ )
122
+ cls.objects["registry2"] = Registry.objects.create(
123
+ host=cls.objects["host2"],
124
+ name="registry2",
125
+ serveraddress="http://localhost:8082",
126
+ )
127
+
116
128
  cls.objects["image1"] = Image.objects.create(
117
- host=cls.objects["host1"], name="image1"
129
+ host=cls.objects["host1"], name="image1", registry=cls.objects["registry1"]
118
130
  )
119
131
  cls.objects["image2"] = Image.objects.create(
120
- host=cls.objects["host2"], name="image2"
132
+ host=cls.objects["host2"], name="image2", registry=cls.objects["registry2"]
121
133
  )
122
134
 
123
135
  cls.objects["volume1"] = Volume.objects.create(
@@ -5,6 +5,7 @@ from netbox_docker_plugin.tests.base import BaseModelViewTestCase
5
5
  from netbox_docker_plugin.models.host import Host
6
6
  from netbox_docker_plugin.models.container import Container
7
7
  from netbox_docker_plugin.models.image import Image
8
+ from netbox_docker_plugin.models.registry import Registry
8
9
 
9
10
 
10
11
  class ContainerViewsTestCase(
@@ -19,8 +20,15 @@ class ContainerViewsTestCase(
19
20
  host1 = Host.objects.create(endpoint="http://localhost:8080", name="host1")
20
21
  host2 = Host.objects.create(endpoint="http://localhost:8081", name="host2")
21
22
 
22
- image1 = Image.objects.create(host=host1, name="image1")
23
- image2 = Image.objects.create(host=host2, name="image2")
23
+ registry1 = Registry.objects.create(
24
+ host=host1, name="registry1", serveraddress="http://localhost:8080"
25
+ )
26
+ registry2 = Registry.objects.create(
27
+ host=host2, name="registry2", serveraddress="http://localhost:8082"
28
+ )
29
+
30
+ image1 = Image.objects.create(host=host1, name="image1", registry=registry1)
31
+ image2 = Image.objects.create(host=host2, name="image2", registry=registry2)
24
32
 
25
33
  container1 = Container.objects.create(
26
34
  host=host1, image=image1, name="container1"
@@ -7,6 +7,7 @@ from users.models import ObjectPermission
7
7
  from rest_framework import status
8
8
  from utilities.testing import APIViewTestCases
9
9
  from netbox_docker_plugin.models.host import Host
10
+ from netbox_docker_plugin.models.registry import Registry
10
11
  from ..base import BaseAPITestCase
11
12
 
12
13
 
@@ -50,6 +51,46 @@ class HostApiTestCase(
50
51
  super().setUp()
51
52
  self.header["HTTP_ORIGIN"] = "http://localhost:8080"
52
53
 
54
+ def test_create_object(self):
55
+ """
56
+ POST a single object with permission.
57
+ """
58
+ # Add object-level permission
59
+ obj_perm = ObjectPermission(name="Test permission", actions=["add"])
60
+ obj_perm.save()
61
+ # pylint: disable=E1101
62
+ obj_perm.users.add(self.user)
63
+ # pylint: disable=E1101
64
+ obj_perm.object_types.add(ContentType.objects.get_for_model(self.model))
65
+
66
+ initial_count = self._get_queryset().count()
67
+ response = self.client.post(
68
+ self._get_list_url(), self.create_data[0], format="json", **self.header
69
+ )
70
+ self.assertHttpStatus(response, status.HTTP_201_CREATED)
71
+ self.assertEqual(self._get_queryset().count(), initial_count + 1)
72
+ instance = self._get_queryset().get(pk=response.data["id"])
73
+ self.assertInstanceEqual(
74
+ instance,
75
+ self.create_data[0],
76
+ exclude=self.validation_excluded_fields,
77
+ api=True,
78
+ )
79
+
80
+ # Verify ObjectChange creation
81
+ if hasattr(self.model, "to_objectchange"):
82
+ objectchanges = ObjectChange.objects.filter(
83
+ changed_object_type=ContentType.objects.get_for_model(instance),
84
+ changed_object_id=instance.pk,
85
+ )
86
+ self.assertEqual(len(objectchanges), 1)
87
+ self.assertEqual(
88
+ objectchanges[0].action, ObjectChangeActionChoices.ACTION_CREATE
89
+ )
90
+
91
+ registries = Registry.objects.filter(host=instance.pk)
92
+ self.assertEqual(len(registries), 1)
93
+
53
94
  def test_delete_object(self):
54
95
  """
55
96
  DELETE a single object identified by its numeric ID.
@@ -2,6 +2,7 @@
2
2
 
3
3
  from utilities.testing import APIViewTestCases
4
4
  from netbox_docker_plugin.models.registry import Registry
5
+ from netbox_docker_plugin.models.host import Host
5
6
  from ..base import BaseAPITestCase
6
7
 
7
8
 
@@ -26,12 +27,30 @@ class RegistryApiTestCase(
26
27
  "url",
27
28
  "username",
28
29
  ]
29
- create_data = [
30
+
31
+ @classmethod
32
+ def setUpTestData(cls) -> None:
33
+ host1 = Host.objects.create(endpoint="http://localhost:8080", name="host1")
34
+ host2 = Host.objects.create(endpoint="http://localhost:8080", name="host2")
35
+
36
+ Registry.objects.create(
37
+ host=host1, serveraddress="http://localhost:8080", name="registry0"
38
+ )
39
+ Registry.objects.create(
40
+ host=host1, serveraddress="http://localhost:8081", name="registry1"
41
+ )
42
+ Registry.objects.create(
43
+ host=host2, serveraddress="http://localhost:8082", name="registry2"
44
+ )
45
+
46
+ cls.create_data = [
30
47
  {
48
+ "host": host1.pk,
31
49
  "name": "github",
32
50
  "serveraddress": "https://ghcr.io",
33
51
  },
34
52
  {
53
+ "host": host2.pk,
35
54
  "name": "gitlab",
36
55
  "serveraddress": "http://registry.example.com",
37
56
  "username": "test",
@@ -39,13 +58,8 @@ class RegistryApiTestCase(
39
58
  "email": "test@example.com",
40
59
  },
41
60
  {
61
+ "host": host1.pk,
42
62
  "name": "registry",
43
63
  "serveraddress": "http://localhost:1010",
44
64
  },
45
65
  ]
46
-
47
- @classmethod
48
- def setUpTestData(cls) -> None:
49
- Registry.objects.create(serveraddress="http://localhost:8080", name="registry0")
50
- Registry.objects.create(serveraddress="http://localhost:8081", name="registry1")
51
- Registry.objects.create(serveraddress="http://localhost:8082", name="registry2")
@@ -0,0 +1,39 @@
1
+ """Registry Views Test Case"""
2
+
3
+ from utilities.testing import ViewTestCases
4
+ from netbox_docker_plugin.models.registry import Registry
5
+ from netbox_docker_plugin.models.host import Host
6
+ from ..base import BaseModelViewTestCase
7
+
8
+
9
+ class RegistryTestCase(
10
+ BaseModelViewTestCase,
11
+ ViewTestCases.GetObjectViewTestCase,
12
+ ViewTestCases.GetObjectChangelogViewTestCase,
13
+ ViewTestCases.CreateObjectViewTestCase,
14
+ ViewTestCases.EditObjectViewTestCase,
15
+ ViewTestCases.DeleteObjectViewTestCase,
16
+ ViewTestCases.ListObjectsViewTestCase,
17
+ ViewTestCases.BulkDeleteObjectsViewTestCase,
18
+ ):
19
+ """Registry Views Test Case Class"""
20
+
21
+ model = Registry
22
+
23
+ @classmethod
24
+ def setUpTestData(cls):
25
+ host1 = Host.objects.create(endpoint="http://localhost:8080", name="host1")
26
+ host2 = Host.objects.create(endpoint="http://localhost:8081", name="host2")
27
+
28
+ Registry.objects.create(host=host1, serveraddress="http://localhost:8080", name="registry0")
29
+ Registry.objects.create(host=host1, serveraddress="http://localhost:8081", name="registry1")
30
+ Registry.objects.create(host=host2, serveraddress="http://localhost:8082", name="registry2")
31
+
32
+ cls.form_data = {
33
+ "host": host1.pk,
34
+ "name": "github",
35
+ "serveraddress": "https://ghcr.io",
36
+ "username": "test",
37
+ "password": "thisisapassword",
38
+ "email": "test@example.com",
39
+ }
@@ -10,13 +10,14 @@ from ..models.image import Image
10
10
  from ..models.volume import Volume
11
11
  from ..models.network import Network
12
12
  from ..models.container import Container
13
+ from ..models.registry import Registry
13
14
 
14
15
 
15
16
  class HostView(generic.ObjectView):
16
17
  """Host view definition"""
17
18
 
18
19
  queryset = Host.objects.prefetch_related(
19
- "images", "volumes", "networks", "containers"
20
+ "images", "volumes", "networks", "containers", "registries"
20
21
  )
21
22
 
22
23
  def get_extra_context(self, request, instance):
@@ -37,6 +38,10 @@ class HostView(generic.ObjectView):
37
38
  Container.objects.filter(host=instance),
38
39
  "host_id",
39
40
  ),
41
+ (
42
+ Registry.objects.filter(host=instance),
43
+ "host_id",
44
+ ),
40
45
  )
41
46
 
42
47
  return {
@@ -52,6 +57,7 @@ class HostListView(generic.ObjectListView):
52
57
  volume_count=count_related(Volume, "host"),
53
58
  network_count=count_related(Network, "host"),
54
59
  container_count=count_related(Container, "host"),
60
+ registry_count=count_related(Registry, "host"),
55
61
  )
56
62
  table = tables.HostTable
57
63
  filterset = filtersets.HostFilterSet
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: netbox-docker-plugin
3
- Version: 1.4.0
3
+ Version: 1.5.0
4
4
  Summary: Manage Docker with Netbox & style.
5
5
  Author-email: Vincent Simonin <vincent@saashup.com>
6
6
  Project-URL: Homepage, https://github.com/SaaShup/netbox-docker-plugin
@@ -50,6 +50,8 @@ netbox_docker_plugin/migrations/0019_host_agent_version_host_docker_api_version.
50
50
  netbox_docker_plugin/migrations/0020_container_hostname.py
51
51
  netbox_docker_plugin/migrations/0021_registry_and_more.py
52
52
  netbox_docker_plugin/migrations/0022_bind_bind_netbox_docker_plugin_bind_unique_bind.py
53
+ netbox_docker_plugin/migrations/0023_delete_hosts.py
54
+ netbox_docker_plugin/migrations/0024_registry_host_alter_registry_name_and_more.py
53
55
  netbox_docker_plugin/migrations/__init__.py
54
56
  netbox_docker_plugin/models/__init__.py
55
57
  netbox_docker_plugin/models/container.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "netbox-docker-plugin"
7
- version = "1.4.0"
7
+ version = "1.5.0"
8
8
  authors = [
9
9
  { name="Vincent Simonin", email="vincent@saashup.com" },
10
10
  ]
@@ -1,33 +0,0 @@
1
- """Registry Views Test Case"""
2
-
3
- from utilities.testing import ViewTestCases
4
- from netbox_docker_plugin.models.registry import Registry
5
- from ..base import BaseModelViewTestCase
6
-
7
-
8
- class RegistryTestCase(
9
- BaseModelViewTestCase,
10
- ViewTestCases.GetObjectViewTestCase,
11
- ViewTestCases.GetObjectChangelogViewTestCase,
12
- ViewTestCases.CreateObjectViewTestCase,
13
- ViewTestCases.EditObjectViewTestCase,
14
- ViewTestCases.DeleteObjectViewTestCase,
15
- ViewTestCases.ListObjectsViewTestCase,
16
- ViewTestCases.BulkDeleteObjectsViewTestCase,
17
- ):
18
- """Registry Views Test Case Class"""
19
-
20
- model = Registry
21
- form_data = {
22
- "name": "github",
23
- "serveraddress": "https://ghcr.io",
24
- "username": "test",
25
- "password": "thisisapassword",
26
- "email": "test@example.com",
27
- }
28
-
29
- @classmethod
30
- def setUpTestData(cls):
31
- Registry.objects.create(serveraddress="http://localhost:8080", name="registry0")
32
- Registry.objects.create(serveraddress="http://localhost:8081", name="registry1")
33
- Registry.objects.create(serveraddress="http://localhost:8082", name="registry2")