Skip to content

Commit

Permalink
fix(dnac): protect map from race condition
Browse files Browse the repository at this point in the history
  • Loading branch information
bl4ko committed Nov 11, 2024
1 parent 5259419 commit 48836d4
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 13 deletions.
10 changes: 5 additions & 5 deletions internal/source/dnac/dnac.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,18 @@ type DnacSource struct {
SSID2WirelessProfileDetails map[string]dnac.ResponseItemWirelessGetWirelessProfileProfileDetailsSSIDDetails
SSID2WlanGroupName map[string]string // SSID -> WirelessLANGroup name
SSID2SecurityDetails map[string]dnac.ResponseItemWirelessGetEnterpriseSSIDSSIDDetails // WirelessLANName -> SSIDDetails
DeviceID2isMissingPrimaryIP map[string]bool // Variable for storing devices without primary IP. See ds.syncMissingDevicePrimaryIPs

// Relations between dnac data. Initialized in init functions.
Site2Devices map[string]map[string]bool // Site ID - > set of device IDs
Device2Site map[string]string // Device ID -> Site ID
DeviceID2InterfaceIDs map[string][]string // DeviceID -> []InterfaceID

// Netbox related data for easier access. Initialized in sync functions.
VID2nbVlan sync.Map // VlanID -> nbVlan
SiteID2nbSite sync.Map // SiteID -> nbSite
DeviceID2nbDevice sync.Map // DeviceID -> nbDevice
InterfaceID2nbInterface sync.Map // InterfaceID -> nbInterface
DeviceID2isMissingPrimaryIP sync.Map // Variable for storing devices without primary IP. See ds.syncMissingDevicePrimaryIPs
VID2nbVlan sync.Map // VlanID -> nbVlan
SiteID2nbSite sync.Map // SiteID -> nbSite
DeviceID2nbDevice sync.Map // DeviceID -> nbDevice
InterfaceID2nbInterface sync.Map // InterfaceID -> nbInterface

// User defined relations
HostTenantRelations map[string]string
Expand Down
3 changes: 1 addition & 2 deletions internal/source/dnac/dnac_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,9 @@ func (ds *DnacSource) initDevices(c *dnac.Client) error {

ds.Devices = make(map[string]dnac.ResponseDevicesGetDeviceListResponse, len(allDevices))
ds.Vlans = make(map[int]dnac.ResponseDevicesGetDeviceInterfaceVLANsResponse)
ds.DeviceID2isMissingPrimaryIP = make(map[string]bool)
for _, device := range allDevices {
ds.Devices[device.ID] = device
ds.DeviceID2isMissingPrimaryIP[device.ID] = true
ds.DeviceID2isMissingPrimaryIP.Store(device.ID, true)
ds.initVlansForDevice(c, device.ID)
}
return nil
Expand Down
31 changes: 25 additions & 6 deletions internal/source/dnac/dnac_sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ func (ds *DnacSource) addIPAddressToInterface(nbi *inventory.NetboxInventory, if
if deviceManagementIP == ifaceDetails.IPv4Address {
deviceCopy := *ifaceDevice
deviceCopy.PrimaryIPv4 = nbIPAddress
ds.DeviceID2isMissingPrimaryIP[dnacDevice.ID] = false
ds.DeviceID2isMissingPrimaryIP.Store(dnacDevice.ID, false)
_, err := nbi.AddDevice(ds.Ctx, &deviceCopy)
if err != nil {
ds.Logger.Errorf(ds.Ctx, "adding primary IPv4 address: %s", err)
Expand Down Expand Up @@ -577,12 +577,24 @@ func (ds *DnacSource) syncWirelessLANs(nbi *inventory.NetboxInventory) error {
// These devices are usually APs, whose interfaces are not returned
// by the /interface endpoint.
func (ds *DnacSource) syncMissingDevicePrimaryIPs(nbi *inventory.NetboxInventory) error {
for dnacDeviceID, isMissingPrimaryIP := range ds.DeviceID2isMissingPrimaryIP {
var syncErr error
ds.DeviceID2isMissingPrimaryIP.Range(func(key, value interface{}) bool {
dnacDeviceID, ok := key.(string)
if !ok {
ds.Logger.Errorf(ds.Ctx, "Invalid type for key in DeviceID2isMissingPrimaryIP map")
return false
}
isMissingPrimaryIP, ok := value.(bool)
if !ok {
ds.Logger.Errorf(ds.Ctx, "Invalid type for value in DeviceID2isMissingPrimaryIP map")
return false
}

if isMissingPrimaryIP {
device := ds.Devices[dnacDeviceID]
if device.ManagementIPAddress == "" {
ds.Logger.Debugf(ds.Ctx, "Device %s has no management IP assigned", dnacDeviceID)
continue
return true
}

nbDeviceAny, _ := ds.DeviceID2nbDevice.Load(dnacDeviceID)
Expand All @@ -602,7 +614,8 @@ func (ds *DnacSource) syncMissingDevicePrimaryIPs(nbi *inventory.NetboxInventory
}
nbiIface, err := nbi.AddInterface(ds.Ctx, managementInterfaceStruct)
if err != nil {
return fmt.Errorf("add interface %+v: %s", managementInterfaceStruct, err)
syncErr = fmt.Errorf("add interface %+v: %s", managementInterfaceStruct, err)
return false
}

nbIPAddressStruct := &objects.IPAddress{
Expand All @@ -622,15 +635,21 @@ func (ds *DnacSource) syncMissingDevicePrimaryIPs(nbi *inventory.NetboxInventory
}
nbIPAddress, err := nbi.AddIPAddress(ds.Ctx, nbIPAddressStruct)
if err != nil {
return fmt.Errorf("add IP address %+v: %s", nbIPAddressStruct, err)
syncErr = fmt.Errorf("add IP address %+v: %s", nbIPAddressStruct, err)
return false
}
updatedDevice := *nbDevice
updatedDevice.PrimaryIPv4 = nbIPAddress
_, err = nbi.AddDevice(ds.Ctx, &updatedDevice)
if err != nil {
return fmt.Errorf("add primary IPv4 address %+v: %s", updatedDevice, err)
syncErr = fmt.Errorf("add primary IPv4 address %+v: %s", updatedDevice, err)
return false
}
}
return true
})
if syncErr != nil {
return syncErr
}
return nil
}

0 comments on commit 48836d4

Please sign in to comment.