Skip to content

Commit

Permalink
#9047 - Documentation and some more test fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
DanSheps committed Mar 22, 2023
1 parent 1a6bd72 commit 51fe68c
Show file tree
Hide file tree
Showing 14 changed files with 80 additions and 39 deletions.
1 change: 1 addition & 0 deletions docs/development/models.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ The Django [content types](https://docs.djangoproject.com/en/stable/ref/contrib/

* [circuits.Circuit](../models/circuits/circuit.md)
* [circuits.Provider](../models/circuits/provider.md)
* [circuits.ProviderAccount](../models/circuits/provideracount.md)
* [circuits.ProviderNetwork](../models/circuits/providernetwork.md)
* [dcim.Cable](../models/dcim/cable.md)
* [dcim.Device](../models/dcim/device.md)
Expand Down
2 changes: 1 addition & 1 deletion docs/development/search.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ A SearchIndex subclass defines both its model and a list of two-tuples specifyin
| 60 | Unique serialized attribute (per related object) | Device.serial |
| 100 | Primary human identifier | Device.name, Circuit.cid, Cable.label |
| 110 | Slug | Site.slug |
| 200 | Secondary identifier | Provider.account, DeviceType.part_number |
| 200 | Secondary identifier | ProviderAccount.account, DeviceType.part_number |
| 300 | Highly unique descriptive attribute | CircuitTermination.xconnect_id, IPAddress.dns_name |
| 500 | Description | Site.description |
| 1000 | Custom field default | - |
Expand Down
6 changes: 4 additions & 2 deletions docs/features/circuits.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ NetBox is ideal for managing your network's transit and peering providers and ci
```mermaid
flowchart TD
ASN --> Provider
Provider --> ProviderNetwork & Circuit
Provider --> ProviderAccount --> Circuit
Provider --> ProviderNetwork
CircuitType --> Circuit
click ASN "../../models/circuits/asn/"
click Circuit "../../models/circuits/circuit/"
click CircuitType "../../models/circuits/circuittype/"
click Provider "../../models/circuits/provider/"
click ProviderAccount "../../models/circuits/provideraccount/"
click ProviderNetwork "../../models/circuits/providernetwork/"
```

Expand All @@ -25,7 +27,7 @@ Sometimes you'll need to model provider networks into which you don't have full

A circuit is a physical connection between two points, which is installed and maintained by an external provider. For example, an Internet connection delivered as a fiber optic cable would be modeled as a circuit in NetBox.

Each circuit is associated with a provider and assigned a circuit ID, which must be unique to that provider. A circuit is also assigned a user-defined type, operational status, and various other operating characteristics.
Each circuit is associated with a provider account and assigned a circuit ID, which must be unique to that provider. A circuit is also assigned a user-defined type, operational status, and various other operating characteristics.

Each circuit may have up to two terminations (A and Z) defined. Each termination can be associated with a particular site or provider network. In the case of the former, a cable can be connected between the circuit termination and a device component to map its physical connectivity.

Expand Down
1 change: 1 addition & 0 deletions docs/features/contacts.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ The following models support the assignment of contacts:

* circuits.Circuit
* circuits.Provider
* circuits.ProviderAccount
* dcim.Device
* dcim.Location
* dcim.Manufacturer
Expand Down
2 changes: 1 addition & 1 deletion docs/getting-started/planning.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Below is the (rough) recommended order in which NetBox objects should be created
4. Manufacturers, device types, and module types
5. Platforms and device roles
6. Devices and modules
7. Providers and provider networks
7. Providers, provider accounts and provider networks
8. Circuit types and circuits
9. Wireless LAN groups and wireless LANs
10. Route targets and VRFs
Expand Down
4 changes: 2 additions & 2 deletions docs/models/circuits/circuit.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ A circuit represents a physical point-to-point data connection, typically used t

## Fields

### Provider
### Provider Account

The [provider](./provider.md) to which this circuit belongs.
The [provider account](./provideraccount.md) to which this circuit belongs.

### Circuit ID

Expand Down
4 changes: 0 additions & 4 deletions docs/models/circuits/provider.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ The AS number assigned to this provider.

The [AS numbers](../ipam/asn.md) assigned to this provider (optional).

### Account Number

The administrative account identifier tied to this provider for your organization.

### Portal URL

The URL for the provider's customer service portal.
Expand Down
17 changes: 17 additions & 0 deletions docs/models/circuits/provideraccount.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Provider Accounts

This model can be used to represent individual accounts associated with a provider.

## Fields

### Provider

The [provider](./provider.md) the account belongs to.

### Name

A human-friendly name, unique to the provider.

### Account Number

The administrative account identifier tied to this provider for your organization.
6 changes: 3 additions & 3 deletions netbox/circuits/models/circuits.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ def get_absolute_url(self):

class Circuit(PrimaryModel):
"""
A communications circuit connects two points. Each Circuit belongs to a Provider; Providers may have multiple
circuits. Each circuit is also assigned a CircuitType and a Site. Circuit port speed and commit rate are measured
in Kbps.
A communications circuit connects two points. Each Circuit belongs to a Provider Account; ProviderAccounts may have
multiple circuits. Each circuit is also assigned a CircuitType and a Site. Circuit port speed and commit rate are
measured in Kbps.
"""
cid = models.CharField(
max_length=100,
Expand Down
6 changes: 3 additions & 3 deletions netbox/circuits/models/providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@

class Provider(PrimaryModel):
"""
Each Circuit belongs to a Provider. This is usually a telecommunications company or similar organization. This model
stores information pertinent to the user's relationship with the Provider.
This is usually a telecommunications company or similar organization. This model stores information pertinent to
the user's relationship with the Provider.
"""
name = models.CharField(
max_length=100,
Expand Down Expand Up @@ -50,7 +50,7 @@ def get_absolute_url(self):

class ProviderAccount(PrimaryModel):
"""
This represents a provider account
This is a discrete account within a provider. Each Circuit belongs to a Provider Account.
"""
account = models.CharField(
max_length=30,
Expand Down
17 changes: 13 additions & 4 deletions netbox/circuits/tests/test_filtersets.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ def setUpTestData(cls):
providers[1].asns.set([asns[1]])
providers[2].asns.set([asns[2]])

provider_accounts = (
ProviderAccount(name='Account A', account='AAAA', provider=providers[0]),
ProviderAccount(name='Account B', account='BBBB', provider=providers[1]),
ProviderAccount(name='Account C', account='CCCC', provider=providers[2]),
ProviderAccount(name='Account D', account='DDDD', provider=providers[3]),
ProviderAccount(name='Account E', account='EEEE', provider=providers[4]),
)
ProviderAccount.objects.bulk_create(provider_accounts)

regions = (
Region(name='Test Region 1', slug='test-region-1'),
Region(name='Test Region 2', slug='test-region-2'),
Expand Down Expand Up @@ -64,8 +73,8 @@ def setUpTestData(cls):
CircuitType.objects.bulk_create(circuit_types)

circuits = (
Circuit(provider=providers[0], type=circuit_types[0], cid='Test Circuit 1'),
Circuit(provider=providers[1], type=circuit_types[1], cid='Test Circuit 1'),
Circuit(provider_account=provider_accounts[0], type=circuit_types[0], cid='Test Circuit 1'),
Circuit(provider_account=provider_accounts[1], type=circuit_types[1], cid='Test Circuit 1'),
)
Circuit.objects.bulk_create(circuits)

Expand Down Expand Up @@ -249,8 +258,8 @@ def test_provider(self):
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3)

def test_provider_account(self):
provider = ProviderAccount.objects.first()
params = {'provider_id': [provider.pk]}
provider_account = ProviderAccount.objects.first()
params = {'provider_account_id': [provider_account.pk]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3)

def test_provider_network(self):
Expand Down
7 changes: 4 additions & 3 deletions netbox/dcim/tests/test_cablepaths.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ def setUpTestData(cls):
cls.powerpanel = PowerPanel.objects.create(site=cls.site, name='Power Panel')

provider = Provider.objects.create(name='Provider', slug='provider')
provider_account = ProviderAccount.objects.create(name='Account', account='AAAA1111', provider=provider)
circuit_type = CircuitType.objects.create(name='Circuit Type', slug='circuit-type')
cls.circuit = Circuit.objects.create(provider=provider, type=circuit_type, cid='Circuit 1')
cls.circuit = Circuit.objects.create(provider_account=provider_account, type=circuit_type, cid='Circuit 1')

def assertPathExists(self, nodes, **kwargs):
"""
Expand Down Expand Up @@ -1308,7 +1309,7 @@ def test_214_interface_to_providernetwork_via_circuit(self):
[IF1] --C1-- [CT1] [CT2] --> [PN1]
"""
interface1 = Interface.objects.create(device=self.device, name='Interface 1')
providernetwork = ProviderNetwork.objects.create(name='Provider Network 1', provider=self.circuit.provider)
providernetwork = ProviderNetwork.objects.create(name='Provider Network 1', provider=self.circuit.provider_account.provider)
circuittermination1 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='A')
circuittermination2 = CircuitTermination.objects.create(circuit=self.circuit, provider_network=providernetwork, term_side='Z')

Expand Down Expand Up @@ -1436,7 +1437,7 @@ def test_216_interface_to_interface_via_multiple_circuits(self):
"""
interface1 = Interface.objects.create(device=self.device, name='Interface 1')
interface2 = Interface.objects.create(device=self.device, name='Interface 2')
circuit2 = Circuit.objects.create(provider=self.circuit.provider, type=self.circuit.type, cid='Circuit 2')
circuit2 = Circuit.objects.create(provider_account=self.circuit.provider_account, type=self.circuit.type, cid='Circuit 2')
circuittermination1 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='A')
circuittermination2 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='Z')
circuittermination3 = CircuitTermination.objects.create(circuit=circuit2, site=self.site, term_side='A')
Expand Down
5 changes: 3 additions & 2 deletions netbox/dcim/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -504,10 +504,11 @@ def setUpTestData(cls):
device=patch_pannel, name='FP4', type='8p8c', rear_port=rear_port4, rear_port_position=1
)
provider = Provider.objects.create(name='Provider 1', slug='provider-1')
provider_account = ProviderAccount.objects.create(name='Provider Account 1', account='A1', provider=provider)
provider_network = ProviderNetwork.objects.create(name='Provider Network 1', provider=provider)
circuittype = CircuitType.objects.create(name='Circuit Type 1', slug='circuit-type-1')
circuit1 = Circuit.objects.create(provider=provider, type=circuittype, cid='1')
circuit2 = Circuit.objects.create(provider=provider, type=circuittype, cid='2')
circuit1 = Circuit.objects.create(provider_account=provider_account, type=circuittype, cid='1')
circuit2 = Circuit.objects.create(provider_account=provider_account, type=circuittype, cid='2')
circuittermination1 = CircuitTermination.objects.create(circuit=circuit1, site=site, term_side='A')
circuittermination2 = CircuitTermination.objects.create(circuit=circuit1, site=site, term_side='Z')
circuittermination3 = CircuitTermination.objects.create(circuit=circuit2, provider_network=provider_network, term_side='A')
Expand Down
41 changes: 27 additions & 14 deletions netbox/netbox/tests/test_staging.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.test import TransactionTestCase

from circuits.models import Provider, Circuit, CircuitType
from circuits.models import Provider, Circuit, CircuitType, ProviderAccount
from extras.choices import ChangeActionChoices
from extras.models import Branch, StagedChange, Tag
from ipam.models import ASN, RIR
Expand Down Expand Up @@ -28,18 +28,25 @@ def setUp(self):
)
Provider.objects.bulk_create(providers)

provider_accounts = (
ProviderAccount(name='Account A', provider=providers[0], account='AAAA'),
ProviderAccount(name='Account B', provider=providers[1], account='BBBB'),
ProviderAccount(name='Account C', provider=providers[2], account='CCCC'),
)
ProviderAccount.objects.bulk_create(provider_accounts)

circuit_type = CircuitType.objects.create(name='Circuit Type 1', slug='circuit-type-1')

Circuit.objects.bulk_create((
Circuit(provider=providers[0], cid='Circuit A1', type=circuit_type),
Circuit(provider=providers[0], cid='Circuit A2', type=circuit_type),
Circuit(provider=providers[0], cid='Circuit A3', type=circuit_type),
Circuit(provider=providers[1], cid='Circuit B1', type=circuit_type),
Circuit(provider=providers[1], cid='Circuit B2', type=circuit_type),
Circuit(provider=providers[1], cid='Circuit B3', type=circuit_type),
Circuit(provider=providers[2], cid='Circuit C1', type=circuit_type),
Circuit(provider=providers[2], cid='Circuit C2', type=circuit_type),
Circuit(provider=providers[2], cid='Circuit C3', type=circuit_type),
Circuit(provider_account=provider_accounts[0], cid='Circuit A1', type=circuit_type),
Circuit(provider_account=provider_accounts[0], cid='Circuit A2', type=circuit_type),
Circuit(provider_account=provider_accounts[0], cid='Circuit A3', type=circuit_type),
Circuit(provider_account=provider_accounts[1], cid='Circuit B1', type=circuit_type),
Circuit(provider_account=provider_accounts[1], cid='Circuit B2', type=circuit_type),
Circuit(provider_account=provider_accounts[1], cid='Circuit B3', type=circuit_type),
Circuit(provider_account=provider_accounts[2], cid='Circuit C1', type=circuit_type),
Circuit(provider_account=provider_accounts[2], cid='Circuit C2', type=circuit_type),
Circuit(provider_account=provider_accounts[2], cid='Circuit C3', type=circuit_type),
))

def test_object_creation(self):
Expand All @@ -50,7 +57,8 @@ def test_object_creation(self):
with checkout(branch):
provider = Provider.objects.create(name='Provider D', slug='provider-d')
provider.asns.set(asns)
circuit = Circuit.objects.create(provider=provider, cid='Circuit D1', type=CircuitType.objects.first())
provider_account = ProviderAccount.objects.create(name='Account D', provider=provider, account='DDDD')
circuit = Circuit.objects.create(provider_account=provider_account, cid='Circuit D1', type=CircuitType.objects.first())
circuit.tags.set(tags)

# Sanity-checking
Expand All @@ -62,7 +70,7 @@ def test_object_creation(self):
# Verify that changes have been rolled back after exiting the context
self.assertEqual(Provider.objects.count(), 3)
self.assertEqual(Circuit.objects.count(), 9)
self.assertEqual(StagedChange.objects.count(), 5)
self.assertEqual(StagedChange.objects.count(), 6)

# Verify that changes are replayed upon entering the context
with checkout(branch):
Expand Down Expand Up @@ -145,26 +153,31 @@ def test_object_deletion(self):

with checkout(branch):
provider = Provider.objects.get(name='Provider A')
provider.circuits.all().delete()
Circuit.objects.filter(provider_account__provider=provider).delete()
provider.accounts.all().delete()
provider.delete()

# Sanity-checking
self.assertEqual(Provider.objects.count(), 2)
self.assertEqual(ProviderAccount.objects.count(), 2)
self.assertEqual(Circuit.objects.count(), 6)

# Verify that changes have been rolled back after exiting the context
self.assertEqual(Provider.objects.count(), 3)
self.assertEqual(ProviderAccount.objects.count(), 3)
self.assertEqual(Circuit.objects.count(), 9)
self.assertEqual(StagedChange.objects.count(), 4)
self.assertEqual(StagedChange.objects.count(), 5)

# Verify that changes are replayed upon entering the context
with checkout(branch):
self.assertEqual(Provider.objects.count(), 2)
self.assertEqual(ProviderAccount.objects.count(), 2)
self.assertEqual(Circuit.objects.count(), 6)

# Verify that changes are applied and deleted upon branch merge
branch.merge()
self.assertEqual(Provider.objects.count(), 2)
self.assertEqual(ProviderAccount.objects.count(), 2)
self.assertEqual(Circuit.objects.count(), 6)
self.assertEqual(StagedChange.objects.count(), 0)

Expand Down

0 comments on commit 51fe68c

Please sign in to comment.