Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
N
netbox-awx-plugin
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Jira
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
ICS Control System Infrastructure
netbox-awx-plugin
Commits
b3315612
Commit
b3315612
authored
5 months ago
by
Fahrudin Halilovic
Browse files
Options
Downloads
Patches
Plain Diff
add tests for synchronization -
INFRA-10732
parent
39cdde76
No related branches found
No related tags found
1 merge request
!7
add tests for signals - INFRA-10664
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
netbox_awx_plugin/synchronization.py
+5
-5
5 additions, 5 deletions
netbox_awx_plugin/synchronization.py
netbox_awx_plugin/tests/test_synchronization.py
+300
-0
300 additions, 0 deletions
netbox_awx_plugin/tests/test_synchronization.py
with
305 additions
and
5 deletions
netbox_awx_plugin/synchronization.py
+
5
−
5
View file @
b3315612
...
@@ -92,7 +92,7 @@ class DeviceSerializer(serializers.BaseSerializer):
...
@@ -92,7 +92,7 @@ class DeviceSerializer(serializers.BaseSerializer):
serializer
=
InterfaceSerializer
(
interface
)
serializer
=
InterfaceSerializer
(
interface
)
variables
[
"
netbox_interfaces
"
].
append
(
serializer
.
data
)
variables
[
"
netbox_interfaces
"
].
append
(
serializer
.
data
)
return
{
return
{
"
name
"
:
instance
.
primary_ip4
.
dns_name
,
"
name
"
:
getattr
(
instance
.
primary_ip4
,
'
dns_name
'
,
instance
.
name
)
,
"
description
"
:
instance
.
description
,
"
description
"
:
instance
.
description
,
"
enabled
"
:
instance
.
status
==
DeviceStatusChoices
.
STATUS_ACTIVE
,
"
enabled
"
:
instance
.
status
==
DeviceStatusChoices
.
STATUS_ACTIVE
,
"
variables
"
:
json
.
dumps
(
variables
),
"
variables
"
:
json
.
dumps
(
variables
),
...
@@ -116,16 +116,16 @@ class VMSerializer(serializers.BaseSerializer):
...
@@ -116,16 +116,16 @@ class VMSerializer(serializers.BaseSerializer):
def
to_representation
(
self
,
instance
):
def
to_representation
(
self
,
instance
):
variables
=
{
variables
=
{
"
netbox_virtualmachine_name
"
:
instance
.
name
,
"
netbox_virtualmachine_name
"
:
instance
.
name
,
"
netbox_virtualmachine_vcpus
"
:
float
(
instance
.
vcpus
),
"
netbox_virtualmachine_vcpus
"
:
float
(
instance
.
vcpus
)
if
instance
.
vcpus
is
not
None
else
0.0
,
"
netbox_virtualmachine_memory
"
:
instance
.
memory
,
"
netbox_virtualmachine_memory
"
:
instance
.
memory
or
0
,
"
netbox_virtualmachine_disk
"
:
instance
.
disk
,
"
netbox_virtualmachine_disk
"
:
instance
.
disk
or
0
,
}
}
variables
[
"
netbox_interfaces
"
]
=
[]
variables
[
"
netbox_interfaces
"
]
=
[]
for
interface
in
instance
.
interfaces
.
all
():
for
interface
in
instance
.
interfaces
.
all
():
serializer
=
VMInterfaceSerializer
(
interface
)
serializer
=
VMInterfaceSerializer
(
interface
)
variables
[
"
netbox_interfaces
"
].
append
(
serializer
.
data
)
variables
[
"
netbox_interfaces
"
].
append
(
serializer
.
data
)
return
{
return
{
"
name
"
:
instance
.
primary_ip4
.
dns_name
,
"
name
"
:
getattr
(
instance
.
primary_ip4
,
'
dns_name
'
,
instance
.
name
)
,
"
description
"
:
instance
.
description
,
"
description
"
:
instance
.
description
,
"
enabled
"
:
instance
.
status
==
VirtualMachineStatusChoices
.
STATUS_ACTIVE
,
"
enabled
"
:
instance
.
status
==
VirtualMachineStatusChoices
.
STATUS_ACTIVE
,
"
variables
"
:
json
.
dumps
(
variables
),
"
variables
"
:
json
.
dumps
(
variables
),
...
...
This diff is collapsed.
Click to expand it.
netbox_awx_plugin/tests/test_synchronization.py
0 → 100644
+
300
−
0
View file @
b3315612
# tests/test_synchronization.py
from
django.test
import
TestCase
from
unittest.mock
import
patch
,
Mock
,
ANY
from
netbox_awx_plugin.models
import
AWX
,
AWXInventory
from
dcim.models
import
Device
,
DeviceRole
,
DeviceType
,
Manufacturer
,
Site
from
virtualization.models
import
VirtualMachine
from
ipam.models
import
IPAddress
from
extras.models
import
Tag
from
netbox_awx_plugin.synchronization
import
(
sync_host
,
sync_group
,
delete_host
,
delete_group
,
sync_all
,
sync_host_group_association
,
disassociate_removed_groups
,
)
from
netbox_awx_plugin.synchronization
import
serializers
,
group_prefixes
from
django.contrib.contenttypes.models
import
ContentType
class
SynchronizationTestCase
(
TestCase
):
def
setUp
(
self
):
# Create an AWX instance and inventory
self
.
awx
=
AWX
.
objects
.
create
(
name
=
'
Test AWX
'
,
url
=
'
https://awx.example.com
'
,
token
=
'
token123
'
)
self
.
awx_inventory
=
AWXInventory
.
objects
.
create
(
awx
=
self
.
awx
,
inventory_id
=
1
,
enabled
=
True
,
)
# Create related objects
self
.
manufacturer
=
Manufacturer
.
objects
.
create
(
name
=
'
Test Manufacturer
'
,
slug
=
'
test-manufacturer
'
)
self
.
device_role
=
DeviceRole
.
objects
.
create
(
name
=
'
Switch
'
,
slug
=
'
switch
'
)
self
.
device_type
=
DeviceType
.
objects
.
create
(
model
=
'
TestModel
'
,
slug
=
'
testmodel
'
,
manufacturer
=
self
.
manufacturer
,
)
self
.
site
=
Site
.
objects
.
create
(
name
=
'
Test Site
'
,
slug
=
'
test-site
'
,
status
=
'
active
'
)
self
.
device
=
Device
.
objects
.
create
(
name
=
'
Test Device
'
,
device_role
=
self
.
device_role
,
device_type
=
self
.
device_type
,
site
=
self
.
site
,
status
=
'
active
'
,
)
self
.
ip_address
=
IPAddress
.
objects
.
create
(
address
=
'
192.0.2.1/24
'
,
dns_name
=
'
test-device.example.com
'
)
self
.
device
.
primary_ip4
=
self
.
ip_address
self
.
device
.
save
()
@patch
(
'
netbox_awx_plugin.models.AWXInventory.disassociate_host_group
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.associate_host_group
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.get_group
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.get_host
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.create_host
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.update_host
'
)
def
test_sync_host_create
(
self
,
mock_update_host
,
mock_create_host
,
mock_get_host
,
mock_get_group
,
mock_associate_host_group
,
mock_disassociate_host_group
):
# Simulate that the host does not exist on first call, but exists after creation
mock_get_host
.
side_effect
=
[
None
,
# First call returns None
{
'
id
'
:
1
,
'
name
'
:
'
test-device.example.com
'
,
'
summary_fields
'
:
{
'
groups
'
:
{
'
results
'
:
[]}}
}
# Second call returns a mock host
]
# Simulate that the group exists
mock_get_group
.
return_value
=
{
'
id
'
:
2
,
'
name
'
:
'
site_test_site
'
}
sync_host
(
self
.
awx_inventory
,
Device
,
self
.
device
)
mock_create_host
.
assert_called
()
mock_update_host
.
assert_not_called
()
mock_associate_host_group
.
assert_called_with
(
1
,
2
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.disassociate_host_group
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.associate_host_group
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.get_group
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.get_host
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.create_host
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.update_host
'
)
def
test_sync_host_update
(
self
,
mock_update_host
,
mock_create_host
,
mock_get_host
,
mock_get_group
,
mock_associate_host_group
,
mock_disassociate_host_group
):
# Simulate that the host exists
mock_get_host
.
return_value
=
{
'
id
'
:
1
,
'
name
'
:
'
test-device.example.com
'
,
'
summary_fields
'
:
{
'
groups
'
:
{
'
results
'
:
[]}}
}
# Simulate that the group exists
mock_get_group
.
return_value
=
{
'
id
'
:
2
,
'
name
'
:
'
site_test_site
'
}
sync_host
(
self
.
awx_inventory
,
Device
,
self
.
device
)
mock_update_host
.
assert_called
()
mock_create_host
.
assert_not_called
()
mock_associate_host_group
.
assert_called_with
(
1
,
2
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.delete_host
'
)
def
test_delete_host
(
self
,
mock_delete_host
):
delete_host
(
self
.
awx_inventory
,
Device
,
self
.
device
)
mock_delete_host
.
assert_called_with
(
'
test-device.example.com
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.get_group
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.create_group
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.update_group
'
)
def
test_sync_group_create
(
self
,
mock_update_group
,
mock_create_group
,
mock_get_group
):
# Simulate that the group does not exist
mock_get_group
.
return_value
=
None
sync_group
(
self
.
awx_inventory
,
Site
,
self
.
site
)
mock_create_group
.
assert_called
()
mock_update_group
.
assert_not_called
()
@patch
(
'
netbox_awx_plugin.models.AWXInventory.get_group
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.create_group
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.update_group
'
)
def
test_sync_group_update
(
self
,
mock_update_group
,
mock_create_group
,
mock_get_group
):
# Simulate that the group exists but needs updating
mock_get_group
.
return_value
=
{
'
id
'
:
1
,
'
name
'
:
'
site_test_site
'
}
sync_group
(
self
.
awx_inventory
,
Site
,
self
.
site
)
mock_update_group
.
assert_called
()
mock_create_group
.
assert_not_called
()
@patch
(
'
netbox_awx_plugin.models.AWXInventory.delete_group
'
)
def
test_delete_group
(
self
,
mock_delete_group
):
delete_group
(
self
.
awx_inventory
,
Site
,
self
.
site
)
mock_delete_group
.
assert_called_with
(
'
site_test_site
'
)
# Additional Tests
@patch
(
'
netbox_awx_plugin.models.AWXInventory.update_host
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.create_host
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.get_host
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.associate_host_group
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.get_group
'
)
def
test_sync_host_with_tags
(
self
,
mock_get_group
,
mock_associate_host_group
,
mock_get_host
,
mock_create_host
,
mock_update_host
):
# Add a tag to the device
tag
=
Tag
.
objects
.
create
(
name
=
'
Test Tag
'
,
slug
=
'
test-tag
'
)
self
.
device
.
tags
.
add
(
tag
)
self
.
device
.
save
()
# Simulate that the group for the tag exists
mock_get_group
.
return_value
=
{
'
id
'
:
3
,
'
name
'
:
'
tag_test_tag
'
}
# Simulate that the host exists
mock_get_host
.
return_value
=
{
'
id
'
:
1
,
'
name
'
:
'
test-device.example.com
'
,
'
summary_fields
'
:
{
'
groups
'
:
{
'
results
'
:
[]}}
}
sync_host
(
self
.
awx_inventory
,
Device
,
self
.
device
)
# Check that the host is associated with the tag group
mock_associate_host_group
.
assert_any_call
(
1
,
3
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.disassociate_host_group
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.get_host
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.get_group
'
)
def
test_disassociate_removed_groups
(
self
,
mock_get_group
,
mock_get_host
,
mock_disassociate_host_group
):
# Simulate that the host is associated with groups that are no longer valid
mock_get_host
.
return_value
=
{
'
id
'
:
1
,
'
name
'
:
'
test-device.example.com
'
,
'
summary_fields
'
:
{
'
groups
'
:
{
'
results
'
:
[
{
'
id
'
:
2
,
'
name
'
:
'
site_old_site
'
},
{
'
id
'
:
3
,
'
name
'
:
'
devicerole_old_role
'
},
{
'
id
'
:
4
,
'
name
'
:
'
tag_old_tag
'
},
]
}
}
}
# Simulate that the group exists for the current site
mock_get_group
.
return_value
=
{
'
id
'
:
5
,
'
name
'
:
'
site_test_site
'
}
# Assume the device only has site_test_site group now
sync_host
(
self
.
awx_inventory
,
Device
,
self
.
device
)
# Check that the host is disassociated from 'site_old_site', 'devicerole_old_role', and 'tag_old_tag'
mock_disassociate_host_group
.
assert_any_call
(
1
,
2
)
mock_disassociate_host_group
.
assert_any_call
(
1
,
3
)
mock_disassociate_host_group
.
assert_any_call
(
1
,
4
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.create_host
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.get_host
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.associate_host_group
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.get_group
'
)
def
test_sync_virtual_machine
(
self
,
mock_get_group
,
mock_associate_host_group
,
mock_get_host
,
mock_create_host
):
# Create a role for the virtual machine
vm_content_type
=
ContentType
.
objects
.
get_for_model
(
VirtualMachine
)
vm_role
=
DeviceRole
.
objects
.
create
(
name
=
'
Web Server
'
,
slug
=
'
web-server
'
)
# Create a virtual machine with a primary IP and a role
vm
=
VirtualMachine
.
objects
.
create
(
name
=
'
Test VM
'
,
status
=
'
active
'
,
role
=
vm_role
)
ip_address
=
IPAddress
.
objects
.
create
(
address
=
'
192.0.2.2/24
'
,
dns_name
=
'
test-vm.example.com
'
)
vm
.
primary_ip4
=
ip_address
vm
.
save
()
# Simulate that the host does not exist on first call, but exists after creation
mock_get_host
.
side_effect
=
[
None
,
# First call returns None
{
'
id
'
:
1
,
'
name
'
:
'
test-vm.example.com
'
,
'
summary_fields
'
:
{
'
groups
'
:
{
'
results
'
:
[]}}
}
# Second call returns a mock host
]
# Simulate that the group exists for the VM role
mock_get_group
.
return_value
=
{
'
id
'
:
2
,
'
name
'
:
'
devicerole_web_server
'
}
# Run the sync_host function
sync_host
(
self
.
awx_inventory
,
VirtualMachine
,
vm
)
# Ensure that create_host was called
mock_create_host
.
assert_called_with
(
ANY
)
# Ensure that the host is associated with the group
mock_associate_host_group
.
assert_called_with
(
1
,
2
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.update_host
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.get_host
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.get_group
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.associate_host_group
'
)
@patch
(
'
netbox_awx_plugin.models.AWXInventory.disassociate_host_group
'
)
def
test_sync_host_missing_primary_ip
(
self
,
mock_disassociate_host_group
,
mock_associate_host_group
,
mock_get_group
,
mock_get_host
,
mock_update_host
):
# Remove the primary IP from the device
self
.
device
.
primary_ip4
=
None
self
.
device
.
save
()
# Mock get_host to return a mock host
mock_get_host
.
return_value
=
{
'
id
'
:
1
,
'
name
'
:
self
.
device
.
name
,
'
summary_fields
'
:
{
'
groups
'
:
{
'
results
'
:
[]}}
}
# Mock get_group to prevent network calls
mock_get_group
.
return_value
=
{
'
id
'
:
2
,
'
name
'
:
'
site_test_site
'
}
# Run the sync_host function
sync_host
(
self
.
awx_inventory
,
Device
,
self
.
device
)
# Ensure that update_host was called
mock_update_host
.
assert_called_with
(
1
,
ANY
)
# Ensure that associate_host_group was called
mock_associate_host_group
.
assert_called_with
(
1
,
2
)
@patch
(
'
netbox_awx_plugin.synchronization.sync_host
'
)
@patch
(
'
netbox_awx_plugin.synchronization.sync_group
'
)
def
test_sync_all
(
self
,
mock_sync_group
,
mock_sync_host
):
job
=
Mock
()
job
.
object
=
self
.
awx_inventory
sync_all
(
job
)
# Ensure that sync_host and sync_group are called appropriately
self
.
assertTrue
(
mock_sync_group
.
called
)
self
.
assertTrue
(
mock_sync_host
.
called
)
# Additional tests for helper functions
def
test_sync_host_group_association
(
self
):
# Create a mock inventory
inventory
=
Mock
()
# Create a mock host
host
=
{
'
id
'
:
1
,
'
name
'
:
'
test-device.example.com
'
,
'
summary_fields
'
:
{
'
groups
'
:
{
'
results
'
:
[]}}}
# Create a mock group
group
=
{
'
id
'
:
2
,
'
name
'
:
'
site_test_site
'
}
inventory
.
get_group
.
return_value
=
group
# Call the function
instance
=
self
.
device
.
site
sync_host_group_association
(
inventory
,
host
,
Site
,
instance
,
host
[
'
summary_fields
'
][
'
groups
'
][
'
results
'
])
# Check that associate_host_group was called
inventory
.
associate_host_group
.
assert_called_with
(
1
,
2
)
def
test_disassociate_removed_groups
(
self
):
# Create a mock inventory
inventory
=
Mock
()
# Create a mock host
host
=
{
'
id
'
:
1
,
'
name
'
:
'
test-device.example.com
'
,
'
summary_fields
'
:
{
'
groups
'
:
{
'
results
'
:
[
{
'
id
'
:
2
,
'
name
'
:
'
site_old_site
'
},
{
'
id
'
:
3
,
'
name
'
:
'
devicerole_old_role
'
},
{
'
id
'
:
4
,
'
name
'
:
'
tag_old_tag
'
},
]
}
}
}
# Create an instance with current attributes
self
.
device
.
tags
.
clear
()
disassociate_removed_groups
(
inventory
,
host
,
self
.
device
,
host
[
'
summary_fields
'
][
'
groups
'
][
'
results
'
])
# Check that disassociate_host_group was called for each group
inventory
.
disassociate_host_group
.
assert_any_call
(
1
,
2
)
inventory
.
disassociate_host_group
.
assert_any_call
(
1
,
3
)
inventory
.
disassociate_host_group
.
assert_any_call
(
1
,
4
)
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment