From 6ab38472be13d8fe60320f4518a9753de41378e4 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Tue, 29 Dec 2020 16:24:16 -0500 Subject: [PATCH 01/32] circuits model startup_scripts --- initializers/circuit_types.yml | 6 ++++++ initializers/circuits.yml | 6 ++++++ initializers/providers.yml | 6 ++++++ startup_scripts/280_providers.py | 18 +++++++++++++++++ startup_scripts/290_circuit_types.py | 18 +++++++++++++++++ startup_scripts/300_circuits.py | 29 ++++++++++++++++++++++++++++ 6 files changed, 83 insertions(+) create mode 100644 initializers/circuit_types.yml create mode 100644 initializers/circuits.yml create mode 100644 initializers/providers.yml create mode 100644 startup_scripts/280_providers.py create mode 100644 startup_scripts/290_circuit_types.py create mode 100644 startup_scripts/300_circuits.py diff --git a/initializers/circuit_types.yml b/initializers/circuit_types.yml new file mode 100644 index 0000000..0e9c356 --- /dev/null +++ b/initializers/circuit_types.yml @@ -0,0 +1,6 @@ +# - name: VPLS +# slug: vpls +# - name: MPLS +# slug: mpls +# - name: Internet +# slug: internet diff --git a/initializers/circuits.yml b/initializers/circuits.yml new file mode 100644 index 0000000..44e0a3a --- /dev/null +++ b/initializers/circuits.yml @@ -0,0 +1,6 @@ +# - cid: Circuit_ID-1 +# provider: Provider1 +# type: Internet +# - name: Circuit_ID-2 +# provider: Provider2 +# type: MPLS diff --git a/initializers/providers.yml b/initializers/providers.yml new file mode 100644 index 0000000..ca2ca1a --- /dev/null +++ b/initializers/providers.yml @@ -0,0 +1,6 @@ +# - name: Provider1 +# slug: provider1 +# asn: 121 +# - name: Provider2 +# slug: provider2 +# asn: 122 diff --git a/startup_scripts/280_providers.py b/startup_scripts/280_providers.py new file mode 100644 index 0000000..393d5ed --- /dev/null +++ b/startup_scripts/280_providers.py @@ -0,0 +1,18 @@ +from circuits.models import Provider +from startup_script_utils import * +import sys + +providers = load_yaml('/opt/netbox/initializers/providers.yml') + +if providers is None: + sys.exit() + +for params in providers: + custom_field_data = pop_custom_fields(params) + + provider, created = Provider.objects.get_or_create(**params) + + if created: + set_custom_fields_values(name, custom_field_data) + + print("πŸ“‘ Created provider", provider.name) diff --git a/startup_scripts/290_circuit_types.py b/startup_scripts/290_circuit_types.py new file mode 100644 index 0000000..b6dca6c --- /dev/null +++ b/startup_scripts/290_circuit_types.py @@ -0,0 +1,18 @@ +from circuits.models import CircuitType +from startup_script_utils import * +import sys + +circuit_types = load_yaml('/opt/netbox/initializers/circuit_types.yml') + +if circuit_types is None: + sys.exit() + +for params in circuit_types: + custom_field_data = pop_custom_fields(params) + + circuit_type, created = CircuitType.objects.get_or_create(**params) + + if created: + set_custom_fields_values(name, custom_field_data) + + print("⚑ Created Circuit Type", circuit_type.name) diff --git a/startup_scripts/300_circuits.py b/startup_scripts/300_circuits.py new file mode 100644 index 0000000..3d2bf24 --- /dev/null +++ b/startup_scripts/300_circuits.py @@ -0,0 +1,29 @@ +from circuits.models import Circuit, Provider, CircuitType +from startup_script_utils import * +import sys + +circuits = load_yaml('/opt/netbox/initializers/circuits.yml') + +if circuits is None: + sys.exit() + +required_assocs = { + 'provider': (Provider, 'name'), + 'circuit_type': (CircuitType, 'name') +} + +for params in circuits: + custom_field_data = pop_custom_fields(params) + + for assoc, details in required_assocs.items(): + model, field = details + query = { field: params.pop(assoc) } + + params[assoc] = model.objects.get(**query) + + circuit, created = Circuit.objects.get_or_create(**params) + + if created: + set_custom_fields_values(cid, custom_field_data) + + print("⚑ Created Circuit", circuit.cid) From 31f52041f87e6f5cd412a06fdfeeb320197a3d86 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Tue, 29 Dec 2020 18:27:41 -0500 Subject: [PATCH 02/32] correct circuit model startup scripts --- initializers/circuit_types.yml | 12 ++++++------ initializers/circuits.yml | 2 +- initializers/providers.yml | 12 ++++++------ startup_scripts/280_providers.py | 2 +- startup_scripts/290_circuit_types.py | 2 +- startup_scripts/300_circuits.py | 4 ++-- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/initializers/circuit_types.yml b/initializers/circuit_types.yml index 0e9c356..95dee30 100644 --- a/initializers/circuit_types.yml +++ b/initializers/circuit_types.yml @@ -1,6 +1,6 @@ -# - name: VPLS -# slug: vpls -# - name: MPLS -# slug: mpls -# - name: Internet -# slug: internet +- name: VPLS + slug: vpls +- name: MPLS + slug: mpls +- name: Internet + slug: internet diff --git a/initializers/circuits.yml b/initializers/circuits.yml index 44e0a3a..93b4659 100644 --- a/initializers/circuits.yml +++ b/initializers/circuits.yml @@ -1,6 +1,6 @@ # - cid: Circuit_ID-1 # provider: Provider1 # type: Internet -# - name: Circuit_ID-2 +# - cid: Circuit_ID-2 # provider: Provider2 # type: MPLS diff --git a/initializers/providers.yml b/initializers/providers.yml index ca2ca1a..4d0e5b0 100644 --- a/initializers/providers.yml +++ b/initializers/providers.yml @@ -1,6 +1,6 @@ -# - name: Provider1 -# slug: provider1 -# asn: 121 -# - name: Provider2 -# slug: provider2 -# asn: 122 +- name: Provider1 + slug: provider1 + asn: 121 +- name: Provider2 + slug: provider2 + asn: 122 diff --git a/startup_scripts/280_providers.py b/startup_scripts/280_providers.py index 393d5ed..e927dda 100644 --- a/startup_scripts/280_providers.py +++ b/startup_scripts/280_providers.py @@ -13,6 +13,6 @@ for params in providers: provider, created = Provider.objects.get_or_create(**params) if created: - set_custom_fields_values(name, custom_field_data) + set_custom_fields_values(provider, custom_field_data) print("πŸ“‘ Created provider", provider.name) diff --git a/startup_scripts/290_circuit_types.py b/startup_scripts/290_circuit_types.py index b6dca6c..441f059 100644 --- a/startup_scripts/290_circuit_types.py +++ b/startup_scripts/290_circuit_types.py @@ -13,6 +13,6 @@ for params in circuit_types: circuit_type, created = CircuitType.objects.get_or_create(**params) if created: - set_custom_fields_values(name, custom_field_data) + set_custom_fields_values(circuit_type, custom_field_data) print("⚑ Created Circuit Type", circuit_type.name) diff --git a/startup_scripts/300_circuits.py b/startup_scripts/300_circuits.py index 3d2bf24..456c792 100644 --- a/startup_scripts/300_circuits.py +++ b/startup_scripts/300_circuits.py @@ -9,7 +9,7 @@ if circuits is None: required_assocs = { 'provider': (Provider, 'name'), - 'circuit_type': (CircuitType, 'name') + 'type': (CircuitType, 'name') } for params in circuits: @@ -24,6 +24,6 @@ for params in circuits: circuit, created = Circuit.objects.get_or_create(**params) if created: - set_custom_fields_values(cid, custom_field_data) + set_custom_fields_values(circuit, custom_field_data) print("⚑ Created Circuit", circuit.cid) From 3094665092155cc23cd0d05e2d0dc6349ebe9c0a Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Tue, 29 Dec 2020 19:36:58 -0500 Subject: [PATCH 03/32] add tags & secret roles --- initializers/secret_roles.yml | 4 ++++ initializers/tags.yml | 12 ++++++++++++ startup_scripts/020_tags.py | 23 +++++++++++++++++++++++ startup_scripts/310_secret_roles.py | 14 ++++++++++++++ 4 files changed, 53 insertions(+) create mode 100644 initializers/secret_roles.yml create mode 100644 initializers/tags.yml create mode 100644 startup_scripts/020_tags.py create mode 100644 startup_scripts/310_secret_roles.py diff --git a/initializers/secret_roles.yml b/initializers/secret_roles.yml new file mode 100644 index 0000000..d85e719 --- /dev/null +++ b/initializers/secret_roles.yml @@ -0,0 +1,4 @@ +# - name: Super Secret Passwords +# slug: super-secret +# - name: SNMP Communities +# slug: snmp \ No newline at end of file diff --git a/initializers/tags.yml b/initializers/tags.yml new file mode 100644 index 0000000..1cbe3be --- /dev/null +++ b/initializers/tags.yml @@ -0,0 +1,12 @@ +# - name: Tag 1 +# slug: tag-1 +# color: Pink +# - name: Tag 2 +# slug: tag-2 +# color: Cyan +# - name: Tag 3 +# slug: tag-3 +# color: Grey +# - name: Tag 4 +# slug: tag-4 +# color: Teal diff --git a/startup_scripts/020_tags.py b/startup_scripts/020_tags.py new file mode 100644 index 0000000..2939e75 --- /dev/null +++ b/startup_scripts/020_tags.py @@ -0,0 +1,23 @@ +from extras.models import Tag +from utilities.choices import ColorChoices + +from startup_script_utils import load_yaml +import sys + +tags = load_yaml('/opt/netbox/initializers/tags.yml') + +if tags is None: + sys.exit() + +for params in tags: + if 'color' in params: + color = params.pop('color') + + for color_tpl in ColorChoices: + if color in color_tpl: + params['color'] = color_tpl[0] + + tag, created = Tag.objects.get_or_create(**params) + + if created: + print("🎨 Created Tag", tag.name) diff --git a/startup_scripts/310_secret_roles.py b/startup_scripts/310_secret_roles.py new file mode 100644 index 0000000..9b0e816 --- /dev/null +++ b/startup_scripts/310_secret_roles.py @@ -0,0 +1,14 @@ +from secrets.models import SecretRole +from startup_script_utils import load_yaml +import sys + +secret_roles = load_yaml('/opt/netbox/initializers/secret_roles.yml') + +if secret_roles is None: + sys.exit() + +for params in secret_roles: + secret_role, created = SecretRole.objects.get_or_create(**params) + + if created: + print("πŸ”‘ Created Secret Role", secret_role.name) From 621fa1293411475db6564ff828b8bd4ea9ad8f1d Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Tue, 29 Dec 2020 22:09:31 -0500 Subject: [PATCH 04/32] comment out secret roles --- initializers/secret_roles.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/initializers/secret_roles.yml b/initializers/secret_roles.yml index d85e719..239906a 100644 --- a/initializers/secret_roles.yml +++ b/initializers/secret_roles.yml @@ -1,4 +1,4 @@ # - name: Super Secret Passwords # slug: super-secret # - name: SNMP Communities -# slug: snmp \ No newline at end of file +# slug: snmp From 90018fc6d7e0070367d6e1e90c03a03e571c73bc Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Tue, 29 Dec 2020 22:10:19 -0500 Subject: [PATCH 05/32] add cluster group startup script --- initializers/cluster_groups.yml | 4 ++++ initializers/clusters.yml | 1 + startup_scripts/165_cluster_groups.py | 14 ++++++++++++++ 3 files changed, 19 insertions(+) create mode 100644 initializers/cluster_groups.yml create mode 100644 startup_scripts/165_cluster_groups.py diff --git a/initializers/cluster_groups.yml b/initializers/cluster_groups.yml new file mode 100644 index 0000000..a611afa --- /dev/null +++ b/initializers/cluster_groups.yml @@ -0,0 +1,4 @@ +# - name: Group 1 +# slug: group-1 +# - name: Group 2 +# slug: group-2 diff --git a/initializers/clusters.yml b/initializers/clusters.yml index 1b1aca0..692be6c 100644 --- a/initializers/clusters.yml +++ b/initializers/clusters.yml @@ -1,5 +1,6 @@ # - name: cluster1 # type: Hyper-V +# group: Group 1 # - name: cluster2 # type: Hyper-V # site: SING 1 diff --git a/startup_scripts/165_cluster_groups.py b/startup_scripts/165_cluster_groups.py new file mode 100644 index 0000000..b52518a --- /dev/null +++ b/startup_scripts/165_cluster_groups.py @@ -0,0 +1,14 @@ +from virtualization.models import ClusterGroup +from startup_script_utils import load_yaml +import sys + +cluster_groups = load_yaml('/opt/netbox/initializers/cluster_groups.yml') + +if cluster_groups is None: + sys.exit() + +for params in cluster_groups: + cluster_group, created = ClusterGroup.objects.get_or_create(**params) + + if created: + print("πŸ—„οΈ Created Cluster Group", cluster_group.name) From 0f1cc9eea09235ab229602f906ad58bc9aca4ec0 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Wed, 30 Dec 2020 18:22:12 -0500 Subject: [PATCH 06/32] add tenant to aggregate startup_script --- startup_scripts/160_aggregates.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/startup_scripts/160_aggregates.py b/startup_scripts/160_aggregates.py index cc1d220..40aea1b 100644 --- a/startup_scripts/160_aggregates.py +++ b/startup_scripts/160_aggregates.py @@ -3,6 +3,7 @@ import sys from ipam.models import Aggregate, RIR from netaddr import IPNetwork from startup_script_utils import * +from tenancy.models import Tenant aggregates = load_yaml('/opt/netbox/initializers/aggregates.yml') @@ -13,6 +14,10 @@ required_assocs = { 'rir': (RIR, 'name') } +optional_assocs = { + 'tenant': (Tenant, 'name'), +} + for params in aggregates: custom_field_data = pop_custom_fields(params) @@ -24,6 +29,13 @@ for params in aggregates: params[assoc] = model.objects.get(**query) + for assoc, details in optional_assocs.items(): + if assoc in params: + model, field = details + query = { field: params.pop(assoc) } + + params[assoc] = model.objects.get(**query) + aggregate, created = Aggregate.objects.get_or_create(**params) if created: From cbaaffc58914da9de93d1f7abfc59ff90ac41f24 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Wed, 30 Dec 2020 18:23:12 -0500 Subject: [PATCH 07/32] =?UTF-8?q?add=20extra=20space=20after=20=E2=96=B6?= =?UTF-8?q?=EF=B8=8F=20to=20remove=20text=20overlap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- startup_scripts/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/startup_scripts/__main__.py b/startup_scripts/__main__.py index dc4cdc9..f85a1de 100644 --- a/startup_scripts/__main__.py +++ b/startup_scripts/__main__.py @@ -20,7 +20,7 @@ with scandir(this_dir) as it: if not f.name.endswith('.py'): continue - print(f"▢️ Running the startup script {f.path}") + print(f"▢️ Running the startup script {f.path}") try: runpy.run_path(f.path) except SystemExit as e: From 8d8c58df549e891d2923c0bab65ad636636942e8 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Wed, 30 Dec 2020 19:09:08 -0500 Subject: [PATCH 08/32] optional assoc to cluster & circuit startup_script --- initializers/circuits.yml | 1 + initializers/clusters.yml | 1 + startup_scripts/170_clusters.py | 4 +++- startup_scripts/300_circuits.py | 12 ++++++++++++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/initializers/circuits.yml b/initializers/circuits.yml index 93b4659..d47b06f 100644 --- a/initializers/circuits.yml +++ b/initializers/circuits.yml @@ -1,6 +1,7 @@ # - cid: Circuit_ID-1 # provider: Provider1 # type: Internet +# tenant: tenant1 # - cid: Circuit_ID-2 # provider: Provider2 # type: MPLS diff --git a/initializers/clusters.yml b/initializers/clusters.yml index 692be6c..4e15477 100644 --- a/initializers/clusters.yml +++ b/initializers/clusters.yml @@ -1,6 +1,7 @@ # - name: cluster1 # type: Hyper-V # group: Group 1 +# tenant: tenant1 # - name: cluster2 # type: Hyper-V # site: SING 1 diff --git a/startup_scripts/170_clusters.py b/startup_scripts/170_clusters.py index ffd965e..85e462f 100644 --- a/startup_scripts/170_clusters.py +++ b/startup_scripts/170_clusters.py @@ -3,6 +3,7 @@ import sys from dcim.models import Site from startup_script_utils import * from virtualization.models import Cluster, ClusterType, ClusterGroup +from tenancy.models import Tenant clusters = load_yaml('/opt/netbox/initializers/clusters.yml') @@ -15,7 +16,8 @@ required_assocs = { optional_assocs = { 'site': (Site, 'name'), - 'group': (ClusterGroup, 'name') + 'group': (ClusterGroup, 'name'), + 'tenant': (Tenant, 'name') } for params in clusters: diff --git a/startup_scripts/300_circuits.py b/startup_scripts/300_circuits.py index 456c792..d53272c 100644 --- a/startup_scripts/300_circuits.py +++ b/startup_scripts/300_circuits.py @@ -1,4 +1,5 @@ from circuits.models import Circuit, Provider, CircuitType +from tenancy.models import Tenant from startup_script_utils import * import sys @@ -12,6 +13,10 @@ required_assocs = { 'type': (CircuitType, 'name') } +optional_assocs = { + 'tenant': (Tenant, 'name') +} + for params in circuits: custom_field_data = pop_custom_fields(params) @@ -21,6 +26,13 @@ for params in circuits: params[assoc] = model.objects.get(**query) + for assoc, details in optional_assocs.items(): + if assoc in params: + model, field = details + query = { field: params.pop(assoc) } + + params[assoc] = model.objects.get(**query) + circuit, created = Circuit.objects.get_or_create(**params) if created: From e3946af27c08496eb12a049f97963a605bc5f05d Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Wed, 30 Dec 2020 19:09:27 -0500 Subject: [PATCH 09/32] added tenant to example aggregates.yml --- initializers/aggregates.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/initializers/aggregates.yml b/initializers/aggregates.yml index d923a04..1d89272 100644 --- a/initializers/aggregates.yml +++ b/initializers/aggregates.yml @@ -1,6 +1,7 @@ -# - prefix: 10.0.0.0/16 -# rir: RFC1918 -# - prefix: fd00:ccdd::/32 -# rir: RFC4193 ULA -# - prefix: 2001:db8::/32 -# rir: RFC3849 + # - prefix: 10.0.0.0/16 + # rir: RFC1918 + # tenant: tenant1 + # - prefix: fd00:ccdd::/32 + # rir: RFC4193 ULA + # - prefix: 2001:db8::/32 + # rir: RFC3849 From dfb0327340d370fd3ebece5d62e8cf5a61842b95 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Wed, 30 Dec 2020 19:10:30 -0500 Subject: [PATCH 10/32] Added power startup_scripts --- initializers/power_feeds.yml | 16 +++++++++++ initializers/power_panels.yml | 5 ++++ startup_scripts/330_power_panels.py | 41 +++++++++++++++++++++++++++++ startup_scripts/340_power_feeds.py | 41 +++++++++++++++++++++++++++++ 4 files changed, 103 insertions(+) create mode 100644 initializers/power_feeds.yml create mode 100644 initializers/power_panels.yml create mode 100644 startup_scripts/330_power_panels.py create mode 100644 startup_scripts/340_power_feeds.py diff --git a/initializers/power_feeds.yml b/initializers/power_feeds.yml new file mode 100644 index 0000000..1c7b222 --- /dev/null +++ b/initializers/power_feeds.yml @@ -0,0 +1,16 @@ +# - name: power feed 1 +# #site: AMS 1 +# power_panel: power panel AMS 1 +# voltage: 208 +# amperage: 50 +# max_utilization: 80 +# phase: Single phase +# rack: rack-01 +# - name: power feed 2 +# #site: SING 1 +# power_panel: power panel SING 1 +# voltage: 208 +# amperage: 50 +# max_utilization: 80 +# phase: Three-phase +# rack: rack-03 diff --git a/initializers/power_panels.yml b/initializers/power_panels.yml new file mode 100644 index 0000000..1205851 --- /dev/null +++ b/initializers/power_panels.yml @@ -0,0 +1,5 @@ +# - name: power panel AMS 1 +# site: AMS 1 +# - name: power panel SING 1 +# site: SING 1 +# rack_group: cage 101 diff --git a/startup_scripts/330_power_panels.py b/startup_scripts/330_power_panels.py new file mode 100644 index 0000000..3057a96 --- /dev/null +++ b/startup_scripts/330_power_panels.py @@ -0,0 +1,41 @@ +import sys + +from dcim.models import Site, RackGroup, PowerPanel +from startup_script_utils import * +from tenancy.models import Tenant + +power_panels = load_yaml('/opt/netbox/initializers/power_panels.yml') + +if power_panels is None: + sys.exit() + +required_assocs = { + 'site': (Site, 'name') +} + +optional_assocs = { + 'rack_group': (RackGroup, 'name') +} + +for params in power_panels: + custom_field_data = pop_custom_fields(params) + + for assoc, details in required_assocs.items(): + model, field = details + query = { field: params.pop(assoc) } + + params[assoc] = model.objects.get(**query) + + for assoc, details in optional_assocs.items(): + if assoc in params: + model, field = details + query = { field: params.pop(assoc) } + + params[assoc] = model.objects.get(**query) + + power_panel, created = PowerPanel.objects.get_or_create(**params) + + if created: + set_custom_fields_values(power_panel, custom_field_data) + + print("⚑ Created Power Panel", power_panel.site, power_panel.name) diff --git a/startup_scripts/340_power_feeds.py b/startup_scripts/340_power_feeds.py new file mode 100644 index 0000000..fc7ee38 --- /dev/null +++ b/startup_scripts/340_power_feeds.py @@ -0,0 +1,41 @@ +import sys + +from dcim.models import Rack, PowerPanel, PowerFeed +from startup_script_utils import * +from tenancy.models import Tenant + +power_feeds = load_yaml('/opt/netbox/initializers/power_feeds.yml') + +if power_feeds is None: + sys.exit() + +required_assocs = { + 'power_panel': (PowerPanel, 'name') +} + +optional_assocs = { + 'rack': (Rack, 'name') +} + +for params in power_feeds: + custom_field_data = pop_custom_fields(params) + + for assoc, details in required_assocs.items(): + model, field = details + query = { field: params.pop(assoc) } + + params[assoc] = model.objects.get(**query) + + for assoc, details in optional_assocs.items(): + if assoc in params: + model, field = details + query = { field: params.pop(assoc) } + + params[assoc] = model.objects.get(**query) + + power_feed, created = PowerFeed.objects.get_or_create(**params) + + if created: + set_custom_fields_values(power_feed, custom_field_data) + + print("⚑ Created Power Feed", power_feed.name) From 818266ace1449183aefd06377b8bbb7285b4a916 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Wed, 30 Dec 2020 19:10:46 -0500 Subject: [PATCH 11/32] added services startup_script --- initializers/services.yml | 10 ++++++++++ startup_scripts/320_services.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 initializers/services.yml create mode 100644 startup_scripts/320_services.py diff --git a/initializers/services.yml b/initializers/services.yml new file mode 100644 index 0000000..49b081c --- /dev/null +++ b/initializers/services.yml @@ -0,0 +1,10 @@ +# - name: SSH +# protocol: TCP +# ports: +# - 22 +# virtual_machine: virtual machine 1 +# - name: FTP +# protocol: TCP +# ports: +# - 21 +# device: server01 diff --git a/startup_scripts/320_services.py b/startup_scripts/320_services.py new file mode 100644 index 0000000..800f215 --- /dev/null +++ b/startup_scripts/320_services.py @@ -0,0 +1,29 @@ +from ipam.models import Service +from dcim.models import Device +from virtualization.models import VirtualMachine +from startup_script_utils import load_yaml +import sys + +services = load_yaml('/opt/netbox/initializers/services.yml') + +if services is None: + sys.exit() + +optional_assocs = { + 'device': (Device, 'name'), + 'virtual_machine': (VirtualMachine, 'name') +} + +for params in services: + + for assoc, details in optional_assocs.items(): + if assoc in params: + model, field = details + query = { field: params.pop(assoc) } + + params[assoc] = model.objects.get(**query) + + service, created = Service.objects.get_or_create(**params) + + if created: + print("🧰 Created Service", service.name) From 94509f86d799b718edc166a4369a7de2a9b1164e Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Wed, 30 Dec 2020 19:11:09 -0500 Subject: [PATCH 12/32] added route_targets startup_script --- initializers/route_targets.yml | 3 +++ startup_scripts/175_route_targets.py | 31 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 initializers/route_targets.yml create mode 100644 startup_scripts/175_route_targets.py diff --git a/initializers/route_targets.yml b/initializers/route_targets.yml new file mode 100644 index 0000000..2ef1406 --- /dev/null +++ b/initializers/route_targets.yml @@ -0,0 +1,3 @@ +# - name: 65000:1001 +# tenant: tenant1 +# - name: 65000:1002 diff --git a/startup_scripts/175_route_targets.py b/startup_scripts/175_route_targets.py new file mode 100644 index 0000000..efdaba6 --- /dev/null +++ b/startup_scripts/175_route_targets.py @@ -0,0 +1,31 @@ +import sys + +from ipam.models import RouteTarget +from startup_script_utils import * +from tenancy.models import Tenant + +route_targets = load_yaml('/opt/netbox/initializers/route_targets.yml') + +if route_targets is None: + sys.exit() + +optional_assocs = { + 'tenant': (Tenant, 'name') +} + +for params in route_targets: + custom_field_data = pop_custom_fields(params) + + for assoc, details in optional_assocs.items(): + if assoc in params: + model, field = details + query = { field: params.pop(assoc) } + + params[assoc] = model.objects.get(**query) + + route_target, created = RouteTarget.objects.get_or_create(**params) + + if created: + set_custom_fields_values(route_target, custom_field_data) + + print("🎯 Created Route Target", route_target.name) From 92b6608403cd4347a038fe74a4f97b26cda0451a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20M=C3=A4der?= Date: Thu, 7 Jan 2021 14:08:06 +0100 Subject: [PATCH 13/32] Create config.yml for ISSUE_TEMPLATE This commit adds links to the _New Issue_ section of Github. The intention is to provide more hints where to get help and further reduce the amount of Github issues that can not be acted upon. --- .github/ISSUE_TEMPLATE/config.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..3ca3f71 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,13 @@ +blank_issues_enabled: false +contact_links: + - name: The \#netbox-docker Slack channel + url: http://slack.networktocode.com/ + about: It's usually the quickest way to seek help when you're in trouble with regards to Netbox Docker. + + - name: Github Discussions + url: https://github.com/netbox-community/netbox-docker/discussions + about: This is the right place to ask questions about how to use or do certain things with Netbox Docker. + + - name: Have you had a look at our Wiki? + url: https://github.com/netbox-community/netbox-docker/wiki + about: Our wiki contains information for common problems and tips for operating Netbox Docker in production. From d2733917732fd8c73239f50407046604f03c838d Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Tue, 10 Nov 2020 15:23:07 +0100 Subject: [PATCH 14/32] Gunicorn is replaced with nginx-unit We now serve Netbox with an nginx-unit instance instead of Gunicorn. This allows us to get rid of the extra Nginx container because Unit is also serving the static files. The static files are now collected at container buildtime instead of every startup. --- .github/ISSUE_TEMPLATE/bug_report.md | 10 ------ .github/workflows/push.yml | 2 +- Dockerfile | 48 +++++++++++-------------- README.md | 2 +- build.sh | 14 ++++---- docker-compose.test.yml | 14 -------- docker-compose.yml | 23 +++--------- docker/configuration.docker.py | 1 + docker/docker-entrypoint.sh | 6 ++-- docker/gunicorn_config.py | 8 ----- docker/launch-netbox.sh | 53 ++++++++++++++++++++++++++++ docker/nginx-unit.json | 40 +++++++++++++++++++++ docker/nginx.conf | 44 ----------------------- requirements-container.txt | 4 +++ test.sh | 2 +- 15 files changed, 135 insertions(+), 136 deletions(-) delete mode 100644 docker/gunicorn_config.py create mode 100755 docker/launch-netbox.sh create mode 100644 docker/nginx-unit.json delete mode 100644 docker/nginx.conf create mode 100644 requirements-container.txt diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 82f22b1..7bf0632 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -65,13 +65,3 @@ If your log is very long, create a Gist instead (and post the link to it): https ```text LOG LOG LOG ``` - -The output of `docker-compose logs nginx`: - - -```text -LOG LOG LOG -``` diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index e1780b7..09bc661 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -19,7 +19,7 @@ jobs: - ./build.sh develop docker_from: - '' # use the default of the build script - # - python:3.10-rc-alpine # disable until dependencies work + - alpine:edge fail-fast: false runs-on: ubuntu-latest name: Builds new Netbox Docker Images diff --git a/Dockerfile b/Dockerfile index 8db4cac..272f882 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,27 +12,15 @@ RUN apk add --no-cache \ libffi-dev \ libxslt-dev \ openldap-dev \ - postgresql-dev - -WORKDIR /install - -RUN pip install --prefix="/install" --no-warn-script-location \ -# gunicorn is used for launching netbox - gunicorn \ - greenlet \ - eventlet \ -# napalm is used for gathering information from network devices - napalm \ -# ruamel is used in startup_scripts - 'ruamel.yaml>=0.15,<0.16' \ -# django_auth_ldap is required for ldap - django_auth_ldap \ -# django-storages was introduced in 2.7 and is optional - django-storages + postgresql-dev \ + py3-pip \ + python3-dev \ + && python3 -m venv /opt/netbox/venv \ + && /opt/netbox/venv/bin/python3 -m pip install --upgrade pip setuptools ARG NETBOX_PATH -COPY ${NETBOX_PATH}/requirements.txt / -RUN pip install --prefix="/install" --no-warn-script-location -r /requirements.txt +COPY ${NETBOX_PATH}/requirements.txt requirements-container.txt / +RUN /opt/netbox/venv/bin/pip install -r /requirements.txt -r /requirements-container.txt ### # Main stage @@ -44,6 +32,7 @@ FROM ${FROM} as main RUN apk add --no-cache \ bash \ ca-certificates \ + curl \ graphviz \ libevent \ libffi \ @@ -51,35 +40,38 @@ RUN apk add --no-cache \ libressl \ libxslt \ postgresql-libs \ - ttf-ubuntu-font-family + python3 \ + py3-pip \ + ttf-ubuntu-font-family \ + unit \ + unit-python3 WORKDIR /opt -COPY --from=builder /install /usr/local +COPY --from=builder /opt/netbox/venv /opt/netbox/venv ARG NETBOX_PATH COPY ${NETBOX_PATH} /opt/netbox COPY docker/configuration.docker.py /opt/netbox/netbox/netbox/configuration.py -COPY docker/gunicorn_config.py /etc/netbox/ -COPY docker/nginx.conf /etc/netbox-nginx/nginx.conf COPY docker/docker-entrypoint.sh /opt/netbox/docker-entrypoint.sh +COPY docker/launch-netbox.sh /opt/netbox/launch-netbox.sh COPY startup_scripts/ /opt/netbox/startup_scripts/ COPY initializers/ /opt/netbox/initializers/ COPY configuration/ /etc/netbox/config/ +COPY docker/nginx-unit.json /etc/unit/ WORKDIR /opt/netbox/netbox -# Must set permissions for '/opt/netbox/netbox/static' directory -# to g+w so that `./manage.py collectstatic` can be executed during -# container startup. # Must set permissions for '/opt/netbox/netbox/media' directory # to g+w so that pictures can be uploaded to netbox. -RUN mkdir static && chmod -R g+w static media +RUN mkdir -p static /opt/unit/state/ /opt/unit/tmp/ \ + && chmod -R g+w media /opt/unit/ \ + && SECRET_KEY="dummy" /opt/netbox/venv/bin/python /opt/netbox/netbox/manage.py collectstatic --no-input ENTRYPOINT [ "/opt/netbox/docker-entrypoint.sh" ] -CMD ["gunicorn", "-c /etc/netbox/gunicorn_config.py", "netbox.wsgi"] +CMD [ "/opt/netbox/launch-netbox.sh" ] LABEL ORIGINAL_TAG="" \ NETBOX_GIT_BRANCH="" \ diff --git a/README.md b/README.md index 11edf52..0125c29 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ cd netbox-docker tee docker-compose.override.yml <=0.15,<0.16 +django-auth-ldap==2.2.0 +django-storages==1.10.1 \ No newline at end of file diff --git a/test.sh b/test.sh index fa6fa38..2249316 100755 --- a/test.sh +++ b/test.sh @@ -35,7 +35,7 @@ if [ -z "${IMAGE}" ]; then fi # The docker compose command to use -doco="docker-compose -f docker-compose.test.yml" +doco="docker-compose --file docker-compose.test.yml --project-name netbox_docker_test_${1}" INITIALIZERS_DIR=".initializers" From 728a16c93d714a8835396f72972a3e7cff4334d2 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Fri, 15 Jan 2021 09:19:21 -0500 Subject: [PATCH 15/32] correct initializers commenting --- initializers/aggregates.yml | 14 +++++++------- initializers/circuit_types.yml | 12 ++++++------ initializers/power_feeds.yml | 2 +- initializers/providers.yml | 12 ++++++------ 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/initializers/aggregates.yml b/initializers/aggregates.yml index 1d89272..b04eb7e 100644 --- a/initializers/aggregates.yml +++ b/initializers/aggregates.yml @@ -1,7 +1,7 @@ - # - prefix: 10.0.0.0/16 - # rir: RFC1918 - # tenant: tenant1 - # - prefix: fd00:ccdd::/32 - # rir: RFC4193 ULA - # - prefix: 2001:db8::/32 - # rir: RFC3849 +# - prefix: 10.0.0.0/16 +# rir: RFC1918 +# tenant: tenant1 +# - prefix: fd00:ccdd::/32 +# rir: RFC4193 ULA +# - prefix: 2001:db8::/32 +# rir: RFC3849 diff --git a/initializers/circuit_types.yml b/initializers/circuit_types.yml index 95dee30..0e9c356 100644 --- a/initializers/circuit_types.yml +++ b/initializers/circuit_types.yml @@ -1,6 +1,6 @@ -- name: VPLS - slug: vpls -- name: MPLS - slug: mpls -- name: Internet - slug: internet +# - name: VPLS +# slug: vpls +# - name: MPLS +# slug: mpls +# - name: Internet +# slug: internet diff --git a/initializers/power_feeds.yml b/initializers/power_feeds.yml index 1c7b222..9e6a7af 100644 --- a/initializers/power_feeds.yml +++ b/initializers/power_feeds.yml @@ -7,7 +7,7 @@ # phase: Single phase # rack: rack-01 # - name: power feed 2 -# #site: SING 1 +# site: SING 1 # power_panel: power panel SING 1 # voltage: 208 # amperage: 50 diff --git a/initializers/providers.yml b/initializers/providers.yml index 4d0e5b0..ca2ca1a 100644 --- a/initializers/providers.yml +++ b/initializers/providers.yml @@ -1,6 +1,6 @@ -- name: Provider1 - slug: provider1 - asn: 121 -- name: Provider2 - slug: provider2 - asn: 122 +# - name: Provider1 +# slug: provider1 +# asn: 121 +# - name: Provider2 +# slug: provider2 +# asn: 122 From 02713e1465c67ff3f0b2d917fc45fd5cc6806ead Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Fri, 15 Jan 2021 09:23:21 -0500 Subject: [PATCH 16/32] showcase protcol options in services initializer --- initializers/services.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/initializers/services.yml b/initializers/services.yml index 49b081c..59647df 100644 --- a/initializers/services.yml +++ b/initializers/services.yml @@ -3,8 +3,8 @@ # ports: # - 22 # virtual_machine: virtual machine 1 -# - name: FTP -# protocol: TCP +# - name: MISC +# protocol: UDP # ports: -# - 21 +# - 4000 # device: server01 From 4260e9b864ec653c1e086195b8237b0cd88cd762 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Fri, 15 Jan 2021 09:26:09 -0500 Subject: [PATCH 17/32] more comment corrections --- initializers/power_feeds.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/initializers/power_feeds.yml b/initializers/power_feeds.yml index 9e6a7af..4b1338a 100644 --- a/initializers/power_feeds.yml +++ b/initializers/power_feeds.yml @@ -1,5 +1,5 @@ # - name: power feed 1 -# #site: AMS 1 +# site: AMS 1 # power_panel: power panel AMS 1 # voltage: 208 # amperage: 50 From 00fa1793d066554816e759a4b56c7657c5b205f1 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Fri, 15 Jan 2021 14:14:07 -0500 Subject: [PATCH 18/32] update services examples --- initializers/services.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/initializers/services.yml b/initializers/services.yml index 59647df..8d4441c 100644 --- a/initializers/services.yml +++ b/initializers/services.yml @@ -1,7 +1,12 @@ -# - name: SSH +# - name: DNS # protocol: TCP # ports: -# - 22 +# - 53 +# virtual_machine: virtual machine 1 +# - name: DNS +# protocol: UDP +# ports: +# - 53 # virtual_machine: virtual machine 1 # - name: MISC # protocol: UDP From 788aeacd9b4377fac4f751efeaacf4ea02c646c7 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Fri, 15 Jan 2021 14:25:42 -0500 Subject: [PATCH 19/32] correct missing required sites in power_feeds --- startup_scripts/340_power_feeds.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/startup_scripts/340_power_feeds.py b/startup_scripts/340_power_feeds.py index fc7ee38..8660da5 100644 --- a/startup_scripts/340_power_feeds.py +++ b/startup_scripts/340_power_feeds.py @@ -1,6 +1,6 @@ import sys -from dcim.models import Rack, PowerPanel, PowerFeed +from dcim.models import Rack, PowerPanel, PowerFeed, Site from startup_script_utils import * from tenancy.models import Tenant @@ -10,7 +10,8 @@ if power_feeds is None: sys.exit() required_assocs = { - 'power_panel': (PowerPanel, 'name') + 'power_panel': (PowerPanel, 'name'), + 'site': (Site, 'name') } optional_assocs = { From 2372c1eeff14e6a511acf7c9ce880bdc4f865720 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Fri, 15 Jan 2021 15:02:01 -0500 Subject: [PATCH 20/32] remove site from power_feeds --- initializers/power_feeds.yml | 2 -- startup_scripts/340_power_feeds.py | 5 ++--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/initializers/power_feeds.yml b/initializers/power_feeds.yml index 4b1338a..7ef5891 100644 --- a/initializers/power_feeds.yml +++ b/initializers/power_feeds.yml @@ -1,5 +1,4 @@ # - name: power feed 1 -# site: AMS 1 # power_panel: power panel AMS 1 # voltage: 208 # amperage: 50 @@ -7,7 +6,6 @@ # phase: Single phase # rack: rack-01 # - name: power feed 2 -# site: SING 1 # power_panel: power panel SING 1 # voltage: 208 # amperage: 50 diff --git a/startup_scripts/340_power_feeds.py b/startup_scripts/340_power_feeds.py index 8660da5..fc7ee38 100644 --- a/startup_scripts/340_power_feeds.py +++ b/startup_scripts/340_power_feeds.py @@ -1,6 +1,6 @@ import sys -from dcim.models import Rack, PowerPanel, PowerFeed, Site +from dcim.models import Rack, PowerPanel, PowerFeed from startup_script_utils import * from tenancy.models import Tenant @@ -10,8 +10,7 @@ if power_feeds is None: sys.exit() required_assocs = { - 'power_panel': (PowerPanel, 'name'), - 'site': (Site, 'name') + 'power_panel': (PowerPanel, 'name') } optional_assocs = { From 5399f8c890dd0f2566d29b0f9617a229af0eaef2 Mon Sep 17 00:00:00 2001 From: Schylar Utley Date: Fri, 18 Dec 2020 15:06:08 -0600 Subject: [PATCH 21/32] Update 270_primary_ips.py fix issue where user has no virtual machines defined, but startup script still tries to iterate over empty file. --- startup_scripts/270_primary_ips.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/startup_scripts/270_primary_ips.py b/startup_scripts/270_primary_ips.py index 74acece..b5a3d84 100644 --- a/startup_scripts/270_primary_ips.py +++ b/startup_scripts/270_primary_ips.py @@ -31,13 +31,14 @@ def link_primary_ip(assets, asset_model): devices = load_yaml('/opt/netbox/initializers/devices.yml') virtual_machines = load_yaml('/opt/netbox/initializers/virtual_machines.yml') -if devices is None and virtual_machines is None: - sys.exit() - optional_assocs = { 'primary_ip4': (IPAddress, 'address'), 'primary_ip6': (IPAddress, 'address') } -link_primary_ip(devices, Device) -link_primary_ip(virtual_machines, VirtualMachine) +if devices is None and virtual_machines is None: + sys.exit() +elif devices is not None: + link_primary_ip(devices, Device) +elif virtual_machines is not None: + link_primary_ip(virtual_machines, VirtualMachine) From 584566b0f0df53d82c2441255373a067104ec616 Mon Sep 17 00:00:00 2001 From: Schylar Utley Date: Fri, 15 Jan 2021 23:44:10 -0600 Subject: [PATCH 22/32] allow simultaneous virtual machine and device primary ip initialization --- startup_scripts/270_primary_ips.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/startup_scripts/270_primary_ips.py b/startup_scripts/270_primary_ips.py index b5a3d84..33af3b7 100644 --- a/startup_scripts/270_primary_ips.py +++ b/startup_scripts/270_primary_ips.py @@ -42,3 +42,6 @@ elif devices is not None: link_primary_ip(devices, Device) elif virtual_machines is not None: link_primary_ip(virtual_machines, VirtualMachine) +else: + link_primary_ip(devices, Device) + link_primary_ip(virtual_machines, VirtualMachine) From 426adb233397a727c30193f9a9e94be1724278dd Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Mon, 18 Jan 2021 08:38:44 +0100 Subject: [PATCH 23/32] Preparation for 0.28.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 1b58cc1..697f087 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.27.0 +0.28.0 From 385c66e30ded889ce240b2d68e48cc80e9f9f821 Mon Sep 17 00:00:00 2001 From: Schylar Utley Date: Tue, 19 Jan 2021 12:54:52 -0600 Subject: [PATCH 24/32] Update startup_scripts/270_primary_ips.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ah, of course.. I would agree. :) Co-authored-by: Christian MΓ€der --- startup_scripts/270_primary_ips.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/startup_scripts/270_primary_ips.py b/startup_scripts/270_primary_ips.py index 33af3b7..7a7400e 100644 --- a/startup_scripts/270_primary_ips.py +++ b/startup_scripts/270_primary_ips.py @@ -38,10 +38,7 @@ optional_assocs = { if devices is None and virtual_machines is None: sys.exit() -elif devices is not None: - link_primary_ip(devices, Device) -elif virtual_machines is not None: - link_primary_ip(virtual_machines, VirtualMachine) -else: +if devices is not None: link_primary_ip(devices, Device) +if virtual_machines is not None: link_primary_ip(virtual_machines, VirtualMachine) From 0022392f031e43400f34f645c46cb2f5c1744c66 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Tue, 19 Jan 2021 17:11:45 +0000 Subject: [PATCH 25/32] Add renovate.json --- renovate.json | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 renovate.json diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..f45d8f1 --- /dev/null +++ b/renovate.json @@ -0,0 +1,5 @@ +{ + "extends": [ + "config:base" + ] +} From 72859ca71a4b9716ec8190f5b57172926b0ff5c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20M=C3=A4der?= Date: Tue, 19 Jan 2021 19:45:01 +0100 Subject: [PATCH 26/32] Configure Renovate --- renovate.json | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/renovate.json b/renovate.json index f45d8f1..b98598c 100644 --- a/renovate.json +++ b/renovate.json @@ -1,5 +1,13 @@ { "extends": [ "config:base" - ] + ], + "enabled": true, + "labels": ["maintenance"], + "baseBranches": ["develop"], + "pip_requirements": { + "fileMatch": [ + "requirements-container.txt" + ] + } } From 7f8cc76af6aafd9dabcae1a428b5883ec84a41ba Mon Sep 17 00:00:00 2001 From: Schylar Utley Date: Fri, 15 Jan 2021 23:33:19 -0600 Subject: [PATCH 27/32] address issue #365 --- startup_scripts/{140_cluster_types.py => 130_cluster_types.py} | 0 startup_scripts/{170_clusters.py => 135_clusters.py} | 0 startup_scripts/{130_devices.py => 140_devices.py} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename startup_scripts/{140_cluster_types.py => 130_cluster_types.py} (100%) rename startup_scripts/{170_clusters.py => 135_clusters.py} (100%) rename startup_scripts/{130_devices.py => 140_devices.py} (100%) diff --git a/startup_scripts/140_cluster_types.py b/startup_scripts/130_cluster_types.py similarity index 100% rename from startup_scripts/140_cluster_types.py rename to startup_scripts/130_cluster_types.py diff --git a/startup_scripts/170_clusters.py b/startup_scripts/135_clusters.py similarity index 100% rename from startup_scripts/170_clusters.py rename to startup_scripts/135_clusters.py diff --git a/startup_scripts/130_devices.py b/startup_scripts/140_devices.py similarity index 100% rename from startup_scripts/130_devices.py rename to startup_scripts/140_devices.py From a0f7737916d54933969dff05e0fed7074b4a3e89 Mon Sep 17 00:00:00 2001 From: Schylar Utley Date: Tue, 19 Jan 2021 23:19:09 -0600 Subject: [PATCH 28/32] rebase and fix script order --- startup_scripts/135_cluster_groups.py | 14 ++++++++ startup_scripts/140_clusters.py | 44 +++++++++++++++++++++++ startup_scripts/145_devices.py | 51 +++++++++++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 startup_scripts/135_cluster_groups.py create mode 100644 startup_scripts/140_clusters.py create mode 100644 startup_scripts/145_devices.py diff --git a/startup_scripts/135_cluster_groups.py b/startup_scripts/135_cluster_groups.py new file mode 100644 index 0000000..b52518a --- /dev/null +++ b/startup_scripts/135_cluster_groups.py @@ -0,0 +1,14 @@ +from virtualization.models import ClusterGroup +from startup_script_utils import load_yaml +import sys + +cluster_groups = load_yaml('/opt/netbox/initializers/cluster_groups.yml') + +if cluster_groups is None: + sys.exit() + +for params in cluster_groups: + cluster_group, created = ClusterGroup.objects.get_or_create(**params) + + if created: + print("πŸ—„οΈ Created Cluster Group", cluster_group.name) diff --git a/startup_scripts/140_clusters.py b/startup_scripts/140_clusters.py new file mode 100644 index 0000000..85e462f --- /dev/null +++ b/startup_scripts/140_clusters.py @@ -0,0 +1,44 @@ +import sys + +from dcim.models import Site +from startup_script_utils import * +from virtualization.models import Cluster, ClusterType, ClusterGroup +from tenancy.models import Tenant + +clusters = load_yaml('/opt/netbox/initializers/clusters.yml') + +if clusters is None: + sys.exit() + +required_assocs = { + 'type': (ClusterType, 'name') +} + +optional_assocs = { + 'site': (Site, 'name'), + 'group': (ClusterGroup, 'name'), + 'tenant': (Tenant, 'name') +} + +for params in clusters: + custom_field_data = pop_custom_fields(params) + + for assoc, details in required_assocs.items(): + model, field = details + query = { field: params.pop(assoc) } + + params[assoc] = model.objects.get(**query) + + for assoc, details in optional_assocs.items(): + if assoc in params: + model, field = details + query = { field: params.pop(assoc) } + + params[assoc] = model.objects.get(**query) + + cluster, created = Cluster.objects.get_or_create(**params) + + if created: + set_custom_fields_values(cluster, custom_field_data) + + print("πŸ—„οΈ Created cluster", cluster.name) diff --git a/startup_scripts/145_devices.py b/startup_scripts/145_devices.py new file mode 100644 index 0000000..d73fd07 --- /dev/null +++ b/startup_scripts/145_devices.py @@ -0,0 +1,51 @@ +import sys + +from dcim.models import Site, Rack, DeviceRole, DeviceType, Device, Platform +from startup_script_utils import * +from tenancy.models import Tenant +from virtualization.models import Cluster + +devices = load_yaml('/opt/netbox/initializers/devices.yml') + +if devices is None: + sys.exit() + +required_assocs = { + 'device_role': (DeviceRole, 'name'), + 'device_type': (DeviceType, 'model'), + 'site': (Site, 'name') +} + +optional_assocs = { + 'tenant': (Tenant, 'name'), + 'platform': (Platform, 'name'), + 'rack': (Rack, 'name'), + 'cluster': (Cluster, 'name') +} + +for params in devices: + custom_field_data = pop_custom_fields(params) + + # primary ips are handled later in `270_primary_ips.py` + params.pop('primary_ip4', None) + params.pop('primary_ip6', None) + + for assoc, details in required_assocs.items(): + model, field = details + query = { field: params.pop(assoc) } + + params[assoc] = model.objects.get(**query) + + for assoc, details in optional_assocs.items(): + if assoc in params: + model, field = details + query = { field: params.pop(assoc) } + + params[assoc] = model.objects.get(**query) + + device, created = Device.objects.get_or_create(**params) + + if created: + set_custom_fields_values(device, custom_field_data) + + print("πŸ–₯️ Created device", device.name) From f810d0342dea4669056cba9d2e6fa06b3cb739ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Ma=CC=88der?= Date: Wed, 20 Jan 2021 09:36:13 +0100 Subject: [PATCH 29/32] Skip Startup Scripts in Unit Tests --- docker-compose.test.yml | 2 ++ test.sh | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docker-compose.test.yml b/docker-compose.test.yml index a7fa7a3..8233bf6 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -7,6 +7,8 @@ services: - redis - redis-cache env_file: env/netbox.env + environment: + SKIP_STARTUP_SCRIPTS: ${SKIP_STARTUP_SCRIPTS-false} user: '101' volumes: - ./startup_scripts:/opt/netbox/startup_scripts:z,ro diff --git a/test.sh b/test.sh index 2249316..cc033b0 100755 --- a/test.sh +++ b/test.sh @@ -56,7 +56,7 @@ test_setup() { test_netbox_unit_tests() { echo "⏱ Running Netbox Unit Tests" - $doco run --rm netbox ./manage.py test + SKIP_STARTUP_SCRIPTS=true $doco run --rm netbox ./manage.py test } test_initializers() { From 896651ed97d486c4f32429c326d2a2b398a172a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Ma=CC=88der?= Date: Wed, 20 Jan 2021 09:50:00 +0100 Subject: [PATCH 30/32] Update of ruamel.yaml --- requirements-container.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements-container.txt b/requirements-container.txt index e011042..4b33cd7 100644 --- a/requirements-container.txt +++ b/requirements-container.txt @@ -1,4 +1,4 @@ napalm==3.2.0 -ruamel.yaml>=0.15,<0.16 +ruamel.yaml==0.16.12 django-auth-ldap==2.2.0 -django-storages==1.10.1 \ No newline at end of file +django-storages==1.10.1 From 96132e1dcca89adc97cf212dd39b8084a0739aa6 Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Wed, 20 Jan 2021 09:57:30 +0100 Subject: [PATCH 31/32] Prevent "alpine:edge" from failling the workflow Alpine is releases a new version once a year. Therefore our workflow runs don't need to be marked as failed when run on alpine:edge --- .github/workflows/push.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 09bc661..fe93d9a 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -10,6 +10,7 @@ on: jobs: build: + continue-on-error: ${{ matrix.docker_from == 'alpine:edge' }} strategy: matrix: build_cmd: From 5109e340ca92542ace5665f7e299a286695711c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Ma=CC=88der?= Date: Thu, 28 Jan 2021 10:22:48 +0100 Subject: [PATCH 32/32] Prepare for Version 1.0.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 697f087..3eefcb9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.28.0 +1.0.0