2020 referenceTime time.Time
2121 output []concourse.Version
2222 err error
23+ siteRegionCache map [int32 ]string
2324)
2425
2526func Query (input concourse.Input , ctx context.Context ) ([]concourse.Version , error ) {
@@ -35,6 +36,12 @@ func Query(input concourse.Input, ctx context.Context) ([]concourse.Version, err
3536 return nil , fmt .Errorf ("error during device query: %w" , err )
3637 }
3738
39+ // Pre-fetch all site regions to avoid per-device API calls
40+ siteRegionCache , err = fetchSiteRegions (client , ctx )
41+ if err != nil {
42+ return nil , fmt .Errorf ("error during site region query: %w" , err )
43+ }
44+
3845 output , err = fetchDetailsFromDeviceList (input , deviceList , ctx )
3946 if err != nil {
4047 return nil , fmt .Errorf ("error during device details query: %w" , err )
@@ -47,6 +54,9 @@ func createDeviceQuery(client *netbox.APIClient, netboxFilter filter.NetboxObjec
4754 if len (netboxFilter .SiteName ) > 0 {
4855 query = query .Site (netboxFilter .SiteName )
4956 }
57+ if len (netboxFilter .RegionName ) > 0 {
58+ query = query .Region (netboxFilter .RegionName )
59+ }
5060 if len (netboxFilter .Tag ) > 0 {
5161 query = query .Tag (netboxFilter .Tag )
5262 }
@@ -149,12 +159,12 @@ func fetchDetailsFromDeviceList(input concourse.Input, deviceList []netbox.Devic
149159 return nil , fmt .Errorf ("error during server interface query: %w" , err )
150160 }
151161
152- output , err = populateInterfaceDetails (name , input , d , interfaceList )
162+ output , err = populateInterfaceDetails (name , input , d , interfaceList , ctx )
153163 if err != nil {
154164 return nil , fmt .Errorf ("error during server interface details query: %w" , err )
155165 }
156166 } else {
157- output , err = populateDeviceDetails (name , input , d )
167+ output , err = populateDeviceDetails (name , input , d , ctx )
158168 if err != nil {
159169 return nil , fmt .Errorf ("error during device details query: %w" , err )
160170 }
@@ -167,7 +177,7 @@ func fetchDetailsFromDeviceList(input concourse.Input, deviceList []netbox.Devic
167177 return output , nil
168178}
169179
170- func populateInterfaceDetails (name string , input concourse.Input , device netbox.DeviceWithConfigContext , interfaceList []netbox.Interface ) ([]concourse.Version , error ) {
180+ func populateInterfaceDetails (name string , input concourse.Input , device netbox.DeviceWithConfigContext , interfaceList []netbox.Interface , ctx context. Context ) ([]concourse.Version , error ) {
171181 for _ , iface := range interfaceList {
172182 lastUpdatedTime , referenceTime , err = getTimestamps (device , input )
173183 if err != nil {
@@ -195,13 +205,19 @@ func populateInterfaceDetails(name string, input concourse.Input, device netbox.
195205 interfaceDisplayUrl = * iface .DisplayUrl
196206 }
197207
208+ deviceRegion := getSiteRegion (device .Site .GetId ())
209+ deviceTags := getDeviceTags (device )
210+
198211 output = append (output , concourse.Version {
199212 Id : fmt .Sprintf ("%d" , iface .Id ),
200213 LastUpdated : lastUpdatedTime .Format (time .RFC3339 ),
201214 ObjectType : "interfaces" ,
202215 DeviceId : fmt .Sprintf ("%d" , device .Id ),
203216 DeviceName : name ,
204217 DeviceRole : device .Role .GetSlug (),
218+ DeviceSite : device .Site .GetSlug (),
219+ DeviceRegion : deviceRegion ,
220+ DeviceTags : deviceTags ,
205221 DeviceApiUrl : device .Url ,
206222 DeviceDisplayUrl : deviceDisplayUrl ,
207223 ConfigContext : configContext ,
@@ -215,7 +231,7 @@ func populateInterfaceDetails(name string, input concourse.Input, device netbox.
215231 return output , nil
216232}
217233
218- func populateDeviceDetails (name string , input concourse.Input , device netbox.DeviceWithConfigContext ) ([]concourse.Version , error ) {
234+ func populateDeviceDetails (name string , input concourse.Input , device netbox.DeviceWithConfigContext , ctx context. Context ) ([]concourse.Version , error ) {
219235 lastUpdatedTime , referenceTime , err = getTimestamps (device , input )
220236 if err != nil {
221237 return nil , fmt .Errorf ("error parsing netbox timestamps because of: %w" , err )
@@ -237,12 +253,18 @@ func populateDeviceDetails(name string, input concourse.Input, device netbox.Dev
237253 displayUrl = * device .DisplayUrl
238254 }
239255
256+ deviceRegion := getSiteRegion (device .Site .GetId ())
257+ deviceTags := getDeviceTags (device )
258+
240259 output = append (output , concourse.Version {
241260 Id : fmt .Sprintf ("%d" , device .Id ),
242261 LastUpdated : lastUpdatedTime .Format (time .RFC3339 ),
243262 ObjectType : "devices" ,
244263 DeviceName : name ,
245264 DeviceRole : device .Role .GetSlug (),
265+ DeviceSite : device .Site .GetSlug (),
266+ DeviceRegion : deviceRegion ,
267+ DeviceTags : deviceTags ,
246268 DeviceApiUrl : device .Url ,
247269 DeviceDisplayUrl : displayUrl ,
248270 ConfigContext : configContext ,
@@ -298,3 +320,54 @@ func getTimestamps(device any, input concourse.Input) (*time.Time, time.Time, er
298320 }
299321 return lastUpdatedTime , referenceTime , nil
300322}
323+
324+ func fetchSiteRegions (client * netbox.APIClient , ctx context.Context ) (map [int32 ]string , error ) {
325+ cache := make (map [int32 ]string )
326+ if client == nil {
327+ return cache , nil
328+ }
329+
330+ limit := int32 (100 )
331+ offset := int32 (0 )
332+ for {
333+ query := client .DcimAPI .DcimSitesList (ctx ).Limit (limit ).Offset (offset )
334+ siteResponse , _ , err := query .Execute ()
335+ if err != nil {
336+ return nil , fmt .Errorf ("error during DcimSitesList query: %w" , err )
337+ }
338+ for _ , site := range siteResponse .Results {
339+ region := ""
340+ if site .Region .IsSet () && site .Region .Get () != nil {
341+ region = site .Region .Get ().GetSlug ()
342+ }
343+ cache [site .Id ] = region
344+ }
345+ if ! siteResponse .Next .IsSet () || siteResponse .Next .Get () == nil || * siteResponse .Next .Get () == "" || len (siteResponse .Results ) == 0 {
346+ break
347+ }
348+ offset += limit
349+ }
350+ return cache , nil
351+ }
352+
353+ func getSiteRegion (siteId int32 ) string {
354+ if siteRegionCache == nil {
355+ return ""
356+ }
357+ if region , ok := siteRegionCache [siteId ]; ok {
358+ return region
359+ }
360+ return ""
361+ }
362+
363+ func getDeviceTags (device netbox.DeviceWithConfigContext ) string {
364+ tags := device .GetTags ()
365+ if len (tags ) == 0 {
366+ return ""
367+ }
368+ tagSlugs := make ([]string , 0 , len (tags ))
369+ for _ , tag := range tags {
370+ tagSlugs = append (tagSlugs , tag .GetSlug ())
371+ }
372+ return strings .Join (tagSlugs , "," )
373+ }
0 commit comments