diff --git a/.golangci.yml b/.golangci.yml index 4371a7ca..41de441f 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,4 +1,6 @@ linters-settings: + lll: + line-length: 120 misspell: locale: US errcheck: @@ -23,12 +25,12 @@ linters: enable: - revive - gocyclo + - lll # - dupl # TODO: enable in future # - errorlint # TODO: enable in future # - gocognit # TODO: enable in future # - cyclop # TODO: enable in future # - paralleltest # TODO: enable in future - # - lll # TODO: enable in future # - nestif # TODO: enable in future # - maintidx # TODO: enable in future # - exhaustive # TODO: enable in future diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 645784f4..26f9ece3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,15 +15,16 @@ repos: hooks: - id: golangci-lint - # - repo: https://github.com/segmentio/golines - # rev: v0.12.2 - # hooks: - # - id: golines - # name: golines - # description: A golang formatter that fixes long lines. - # entry: golines -w - # types: [go] - # language: golang + - repo: https://github.com/segmentio/golines + rev: v0.12.2 + hooks: + - id: golines + name: golines + description: A golang formatter that fixes long lines. + entry: golines -w ./internal + pass_filenames: true + types: [go] + language: golang - repo: https://github.com/dnephin/pre-commit-golang rev: v0.5.1 @@ -32,15 +33,21 @@ repos: - id: go-mod-tidy - repo: https://github.com/gitleaks/gitleaks - rev: v8.23.1 + rev: v8.23.3 hooks: - id: gitleaks - repo: https://github.com/streetsidesoftware/cspell-cli - rev: v8.17.1 + rev: v8.17.2 hooks: - id: cspell + - repo: https://github.com/google/osv-scanner/ + rev: v2.0.0-beta1 + hooks: + - id: osv-scanner + args: ["-r", "."] + - repo: https://github.com/mxab/pre-commit-trivy.git rev: v0.14.0 hooks: diff --git a/README.md b/README.md index 59ebecb5..e84c5812 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ Example configuration can be found [here](#example-config). | Parameter | Description | Type | Possible values | Default | Required | | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | --------------- | ------------- | -------- | -| `netbox.apiToken` | Netbox [API token](https://demo.netbox.dev/static/docs/rest-api/authentication/). | str | Any valid token | "" | Yes | +| `netbox.apiToken` | Netbox API token | str | Any valid token | "" | Yes | | `netbox.hostname` | Hostname of your netbox instance (e.g `netbox.example.com`). | str | Valid hostname | "" | Yes | | `netbox.port` | Port of your netbox instance. | int | 0-65536 | 443 | No | | `netbox.httpScheme` | HTTP scheme of your netbox instance. | str | [http, https] | https | No | diff --git a/go.mod b/go.mod index c8d11e88..f5f64359 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,10 @@ module github.com/bl4ko/netbox-ssot -go 1.23.1 +go 1.23.6 require ( github.com/PaloAltoNetworks/pango v0.10.2 github.com/bl4ko/go-devicetype-library v0.1.45 - github.com/cisco-en-programmability/dnacenter-go-sdk/v6 v6.0.0 github.com/cisco-en-programmability/dnacenter-go-sdk/v7 v7.0.0 github.com/luthermonson/go-proxmox v0.2.1 github.com/ovirt/go-ovirt v4.3.4+incompatible @@ -20,13 +19,13 @@ require ( github.com/creack/pty v1.1.24 // indirect github.com/diskfs/go-diskfs v1.4.2 // indirect github.com/djherbis/times v1.6.0 // indirect - github.com/go-resty/resty/v2 v2.16.2 // indirect + github.com/go-resty/resty/v2 v2.16.5 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect github.com/jinzhu/copier v0.4.0 // indirect github.com/magefile/mage v1.15.0 // indirect github.com/sirikothe/gotextfsm v1.0.1-0.20200816110946-6aa2cfd355e4 // indirect - golang.org/x/crypto v0.31.0 // indirect - golang.org/x/net v0.33.0 // indirect - golang.org/x/sys v0.28.0 // indirect + golang.org/x/crypto v0.32.0 // indirect + golang.org/x/net v0.34.0 // indirect + golang.org/x/sys v0.30.0 // indirect ) diff --git a/go.sum b/go.sum index 12e54c33..f9585c95 100644 --- a/go.sum +++ b/go.sum @@ -1,21 +1,10 @@ github.com/PaloAltoNetworks/pango v0.10.2 h1:Tjn6vIzzAq6Dd7N0mDuiP8w8pz8k5W9zz/TTSUQCsQY= github.com/PaloAltoNetworks/pango v0.10.2/go.mod h1:GztcRnVLur7G+VFG7Z5ZKNFgScLtsycwPMp1qVebE5g= -github.com/bl4ko/go-devicetype-library v0.1.39 h1:kbNz5SLevOZfU+1/azfCMrIFoO1dYap6bt9OE+tdoL8= -github.com/bl4ko/go-devicetype-library v0.1.39/go.mod h1:Pzm1BlRyR4uECezsRINDA6ZieFPumdFL+6yySpXM6t8= -github.com/bl4ko/go-devicetype-library v0.1.40 h1:LOmVYWKRlr2EZmMbP4G39LCimcdNyCYSmqVUVjddnL8= -github.com/bl4ko/go-devicetype-library v0.1.40/go.mod h1:Pzm1BlRyR4uECezsRINDA6ZieFPumdFL+6yySpXM6t8= -github.com/bl4ko/go-devicetype-library v0.1.41 h1:3oLwoLfEnd3Doz5ao/MkxUDWd2yHMBUbRk88mz+02WU= -github.com/bl4ko/go-devicetype-library v0.1.41/go.mod h1:Pzm1BlRyR4uECezsRINDA6ZieFPumdFL+6yySpXM6t8= -github.com/bl4ko/go-devicetype-library v0.1.42 h1:oWRXPI8+VGbdlQM7bqEW1Z0ng0OrOWdBlKeybX8WwgM= -github.com/bl4ko/go-devicetype-library v0.1.42/go.mod h1:Pzm1BlRyR4uECezsRINDA6ZieFPumdFL+6yySpXM6t8= -github.com/bl4ko/go-devicetype-library v0.1.43 h1:WUJDxXo01fxuk6EEtkLQB/giXNGxK9JO7REqf0ntv7o= -github.com/bl4ko/go-devicetype-library v0.1.43/go.mod h1:Pzm1BlRyR4uECezsRINDA6ZieFPumdFL+6yySpXM6t8= github.com/bl4ko/go-devicetype-library v0.1.45 h1:UsxWYNHBrpNAcp8OA6PQzzCk2OqtWuarh6OEb0JHirQ= github.com/bl4ko/go-devicetype-library v0.1.45/go.mod h1:Pzm1BlRyR4uECezsRINDA6ZieFPumdFL+6yySpXM6t8= github.com/buger/goterm v1.0.4 h1:Z9YvGmOih81P0FbVtEYTFF6YsSgxSUKEhf/f9bTMXbY= github.com/buger/goterm v1.0.4/go.mod h1:HiFWV3xnkolgrBV3mY8m0X0Pumt4zg4QhbdOzQtB8tE= -github.com/cisco-en-programmability/dnacenter-go-sdk/v6 v6.0.0 h1:UAkph9VReeOVkE3pX6G12IuJOWFg41Q7PL4er3zD3Sc= -github.com/cisco-en-programmability/dnacenter-go-sdk/v6 v6.0.0/go.mod h1:Chafvg+TCkqlROEOlX/WlK5Wk8nTtMCqhuCZSYtlLCE= +github.com/cisco-en-programmability/dnacenter-go-sdk/v7 v7.0.0 h1:oAHsGmf+Vvs3lHRshDEFA+nKoTLcfL0NHBr4kGN46M0= github.com/cisco-en-programmability/dnacenter-go-sdk/v7 v7.0.0/go.mod h1:UcGpH8J9EboPCWB4UEH/p2ZfUzJ3LpH2qCL7Fk1EAMo= github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= @@ -27,8 +16,8 @@ github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= github.com/elliotwutingfeng/asciiset v0.0.0-20230602022725-51bbb787efab h1:h1UgjJdAAhj+uPL68n7XASS6bU+07ZX1WJvVS2eyoeY= github.com/elliotwutingfeng/asciiset v0.0.0-20230602022725-51bbb787efab/go.mod h1:GLo/8fDswSAniFG+BFIaiSPcK610jyzgEhWYPQwuQdw= -github.com/go-resty/resty/v2 v2.16.2 h1:CpRqTjIzq/rweXUt9+GxzzQdlkqMdt8Lm/fuK/CAbAg= -github.com/go-resty/resty/v2 v2.16.2/go.mod h1:0fHAoK7JoBy/Ch36N8VFeMsK7xQOHhvWaC3iOktwmIU= +github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM= +github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA= github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -72,18 +61,16 @@ github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/vmware/govmomi v0.48.0 h1:CP5bCvkDNGkmn29UlcJKTWMLwDg3iusP8anrZnedWrg= github.com/vmware/govmomi v0.48.0/go.mod h1:bYwUHpGpisE4AOlDl5eph90T+cjJMIcKx/kaa5v5rQM= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= -golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= +golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= diff --git a/internal/constants/constants.go b/internal/constants/constants.go index 91e53d33..11cf6f2d 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -25,7 +25,8 @@ const OrphanTagDescription = "Tag used by netbox-ssot to mark orphaned objects" const DefaultVlanGroupName = "DefaultVlanGroup" -const DefaultVlanGroupDescription = "Default netbox-ssot VlanGroup for all vlans that are not part of any other vlanGroup. This group is required for netbox-ssot vlan index to work." +const DefaultVlanGroupDescription = "Default netbox-ssot VlanGroup for all vlans that are not part of " + + "any other vlanGroup. This group is required for netbox-ssot vlan index to work." const DefaultArpTagName = "arp-entry" const DefaultArpTagColor = ColorRed @@ -330,7 +331,8 @@ const ( MaxVMNameLength = 64 MaxVMInterfaceNameLength = 64 - // Limitations for devices: https://github.com/netbox-community/netbox/blob/d03d302eef3819db64cad8ae74dc5255647045f6/netbox/dcim/models/device_components.py. + //nolint:lll + // Limitations for devices https://github.com/netbox-community/netbox/blob/d03d302eef3819db64cad8ae74dc5255647045f6/netbox/dcim/models/device_components.py. MaxDeviceNameLength = 64 MaxSerialNumberLength = 50 MaxAssetTagLength = 50 diff --git a/internal/logger/logger.go b/internal/logger/logger.go index e634a2c6..0c749284 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -28,7 +28,8 @@ type Logger struct { level int } -// New creates a new Logger instance, which writes to the specified destination (file) or stdout if dest is empty. It also sets the log level. +// New creates a new Logger instance, which writes to the specified destination (file) or stdout if dest is empty. +// It also sets the log level. func New(dest string, logLevel int) (*Logger, error) { var output io.Writer if dest == "" { @@ -72,7 +73,15 @@ func (l *Logger) Output(calldepth int, s string) error { func (l *Logger) Debug(ctx context.Context, v ...interface{}) error { if l.level <= DEBUG { - return l.Output(logCallDepth, fmt.Sprintf("%-7s (%s): %s", "DEBUG", ctx.Value(constants.CtxSourceKey), fmt.Sprint(v...))) + return l.Output( + logCallDepth, + fmt.Sprintf( + "%-7s (%s): %s", + "DEBUG", + ctx.Value(constants.CtxSourceKey), + fmt.Sprint(v...), + ), + ) } return nil } @@ -80,14 +89,30 @@ func (l *Logger) Debug(ctx context.Context, v ...interface{}) error { // Debugf logs a formatted debug message. func (l *Logger) Debugf(ctx context.Context, format string, v ...interface{}) error { if l.level <= DEBUG { - return l.Output(logCallDepth, fmt.Sprintf("%-7s (%s): %s", "DEBUG", ctx.Value(constants.CtxSourceKey), fmt.Sprintf(format, v...))) + return l.Output( + logCallDepth, + fmt.Sprintf( + "%-7s (%s): %s", + "DEBUG", + ctx.Value(constants.CtxSourceKey), + fmt.Sprintf(format, v...), + ), + ) } return nil } func (l *Logger) Info(ctx context.Context, v ...interface{}) error { if l.level <= INFO { - return l.Output(logCallDepth, fmt.Sprintf("%-7s (%s): %s", "INFO", ctx.Value(constants.CtxSourceKey), fmt.Sprint(v...))) + return l.Output( + logCallDepth, + fmt.Sprintf( + "%-7s (%s): %s", + "INFO", + ctx.Value(constants.CtxSourceKey), + fmt.Sprint(v...), + ), + ) } return nil } @@ -95,14 +120,30 @@ func (l *Logger) Info(ctx context.Context, v ...interface{}) error { // Infof logs a formatted info message. func (l *Logger) Infof(ctx context.Context, format string, v ...interface{}) error { if l.level <= INFO { - return l.Output(logCallDepth, fmt.Sprintf("%-7s (%s): %s", "INFO", ctx.Value(constants.CtxSourceKey), fmt.Sprintf(format, v...))) + return l.Output( + logCallDepth, + fmt.Sprintf( + "%-7s (%s): %s", + "INFO", + ctx.Value(constants.CtxSourceKey), + fmt.Sprintf(format, v...), + ), + ) } return nil } func (l *Logger) Warning(ctx context.Context, v ...interface{}) error { if l.level <= WARNING { - return l.Output(logCallDepth, fmt.Sprintf("%-7s (%s): %s", "WARNING", ctx.Value(constants.CtxSourceKey), fmt.Sprint(v...))) + return l.Output( + logCallDepth, + fmt.Sprintf( + "%-7s (%s): %s", + "WARNING", + ctx.Value(constants.CtxSourceKey), + fmt.Sprint(v...), + ), + ) } return nil } @@ -110,14 +151,30 @@ func (l *Logger) Warning(ctx context.Context, v ...interface{}) error { // Warningf logs a formatted warning message. func (l *Logger) Warningf(ctx context.Context, format string, v ...interface{}) error { if l.level <= WARNING { - return l.Output(logCallDepth, fmt.Sprintf("%-7s (%s): %s", "WARNING", ctx.Value(constants.CtxSourceKey), fmt.Sprintf(format, v...))) + return l.Output( + logCallDepth, + fmt.Sprintf( + "%-7s (%s): %s", + "WARNING", + ctx.Value(constants.CtxSourceKey), + fmt.Sprintf(format, v...), + ), + ) } return nil } func (l *Logger) Error(ctx context.Context, v ...interface{}) error { if l.level <= ERROR { - return l.Output(logCallDepth, fmt.Sprintf("%-7s (%s): %s", "ERROR", ctx.Value(constants.CtxSourceKey), fmt.Sprint(v...))) + return l.Output( + logCallDepth, + fmt.Sprintf( + "%-7s (%s): %s", + "ERROR", + ctx.Value(constants.CtxSourceKey), + fmt.Sprint(v...), + ), + ) } return nil } @@ -125,7 +182,15 @@ func (l *Logger) Error(ctx context.Context, v ...interface{}) error { // Errorf logs a formatted error message. func (l *Logger) Errorf(ctx context.Context, format string, v ...interface{}) error { if l.level <= ERROR { - return l.Output(logCallDepth, fmt.Sprintf("%-7s (%s): %s", "ERROR", ctx.Value(constants.CtxSourceKey), fmt.Sprintf(format, v...))) + return l.Output( + logCallDepth, + fmt.Sprintf( + "%-7s (%s): %s", + "ERROR", + ctx.Value(constants.CtxSourceKey), + fmt.Sprintf(format, v...), + ), + ) } return nil } diff --git a/internal/netbox/inventory/add_items.go b/internal/netbox/inventory/add_items.go index 2efaff5a..554e914e 100644 --- a/internal/netbox/inventory/add_items.go +++ b/internal/netbox/inventory/add_items.go @@ -339,24 +339,24 @@ func (nbi *NetboxInventory) AddContactAssignment( newCA.SetCustomField(constants.CustomFieldOrphanLastSeenName, nil) nbi.contactAssignmentsLock.Lock() defer nbi.contactAssignmentsLock.Unlock() - if nbi.contactAssignmentsIndexByObjectTypeAndObjectIDAndContactIDAndRoleID[newCA.ModelType] == nil { - nbi.contactAssignmentsIndexByObjectTypeAndObjectIDAndContactIDAndRoleID[newCA.ModelType] = make( + if nbi.contactAssignmentsIndex[newCA.ModelType] == nil { + nbi.contactAssignmentsIndex[newCA.ModelType] = make( map[int]map[int]map[int]*objects.ContactAssignment, ) } - if nbi.contactAssignmentsIndexByObjectTypeAndObjectIDAndContactIDAndRoleID[newCA.ModelType][newCA.ObjectID] == nil { - nbi.contactAssignmentsIndexByObjectTypeAndObjectIDAndContactIDAndRoleID[newCA.ModelType][newCA.ObjectID] = make( + if nbi.contactAssignmentsIndex[newCA.ModelType][newCA.ObjectID] == nil { + nbi.contactAssignmentsIndex[newCA.ModelType][newCA.ObjectID] = make( map[int]map[int]*objects.ContactAssignment, ) } - if nbi.contactAssignmentsIndexByObjectTypeAndObjectIDAndContactIDAndRoleID[newCA.ModelType][newCA.ObjectID][newCA.Contact.ID] == nil { - nbi.contactAssignmentsIndexByObjectTypeAndObjectIDAndContactIDAndRoleID[newCA.ModelType][newCA.ObjectID][newCA.Contact.ID] = make( + if nbi.contactAssignmentsIndex[newCA.ModelType][newCA.ObjectID][newCA.Contact.ID] == nil { + nbi.contactAssignmentsIndex[newCA.ModelType][newCA.ObjectID][newCA.Contact.ID] = make( map[int]*objects.ContactAssignment, ) } newCA.Tags = append(newCA.Tags, nbi.SsotTag) - if _, ok := nbi.contactAssignmentsIndexByObjectTypeAndObjectIDAndContactIDAndRoleID[newCA.ModelType][newCA.ObjectID][newCA.Contact.ID][newCA.Role.ID]; ok { - oldCA := nbi.contactAssignmentsIndexByObjectTypeAndObjectIDAndContactIDAndRoleID[newCA.ModelType][newCA.ObjectID][newCA.Contact.ID][newCA.Role.ID] + if _, ok := nbi.contactAssignmentsIndex[newCA.ModelType][newCA.ObjectID][newCA.Contact.ID][newCA.Role.ID]; ok { + oldCA := nbi.contactAssignmentsIndex[newCA.ModelType][newCA.ObjectID][newCA.Contact.ID][newCA.Role.ID] nbi.OrphanManager.RemoveItem(oldCA) diffMap, err := utils.JSONDiffMapExceptID(newCA, oldCA, false, nbi.SourcePriority) if err != nil { @@ -378,7 +378,7 @@ func (nbi *NetboxInventory) AddContactAssignment( if err != nil { return nil, err } - nbi.contactAssignmentsIndexByObjectTypeAndObjectIDAndContactIDAndRoleID[newCA.ModelType][newCA.ObjectID][newCA.Contact.ID][newCA.Role.ID] = patchedCA + nbi.contactAssignmentsIndex[newCA.ModelType][newCA.ObjectID][newCA.Contact.ID][newCA.Role.ID] = patchedCA } else { nbi.Logger.Debug(ctx, "ContactAssignment ", newCA.ID, " already exists in Netbox and is up to date...") } @@ -388,13 +388,14 @@ func (nbi *NetboxInventory) AddContactAssignment( if err != nil { return nil, err } - nbi.contactAssignmentsIndexByObjectTypeAndObjectIDAndContactIDAndRoleID[newCA.ModelType][newCA.ObjectID][newCA.Contact.ID][newCA.Role.ID] = newCA + nbi.contactAssignmentsIndex[newCA.ModelType][newCA.ObjectID][newCA.Contact.ID][newCA.Role.ID] = newCA } - return nbi.contactAssignmentsIndexByObjectTypeAndObjectIDAndContactIDAndRoleID[newCA.ModelType][newCA.ObjectID][newCA.Contact.ID][newCA.Role.ID], nil + return nbi.contactAssignmentsIndex[newCA.ModelType][newCA.ObjectID][newCA.Contact.ID][newCA.Role.ID], nil } // AddCustomField adds a custom field to the Netbox inventory. -// It takes a context and a newCf object as input and returns the created or patched custom field along with any error encountered. +// It takes a context and a newCf object as input and +// returns the created or patched custom field along with any error encountered. // If the custom field already exists in Netbox but is out of date, it will be patched with the new values. // If the custom field does not exist, it will be created. func (nbi *NetboxInventory) AddCustomField( @@ -494,8 +495,10 @@ func (nbi *NetboxInventory) AddClusterGroup( } // AddClusterType adds a new cluster type to the Netbox inventory. -// It takes a context and a newClusterType object as input and returns the created or updated cluster type object and an error, if any. -// If the cluster type already exists in Netbox, it checks if it is up to date. If not, it patches the existing cluster type. +// It takes a context and a newClusterType object as input and +// returns the created or updated cluster type object and an error, if any. +// If the cluster type already exists in Netbox, it checks if it is up to date. +// If not, it patches the existing cluster type. // If the cluster type does not exist, it creates a new one. func (nbi *NetboxInventory) AddClusterType( ctx context.Context, @@ -614,7 +617,8 @@ func (nbi *NetboxInventory) AddCluster( } // AddDeviceRole adds a new device role to the Netbox inventory. -// It takes a context and a newDeviceRole object as input and returns the created device role object and an error, if any. +// It takes a context and a newDeviceRole object as input and +// returns the created device role object and an error, if any. // If the device role already exists in Netbox, it checks if it is up to date and patches it if necessary. // If the device role does not exist, it creates a new one. func (nbi *NetboxInventory) AddDeviceRole( @@ -728,7 +732,8 @@ func (nbi *NetboxInventory) AddManufacturer( } // AddDeviceType adds a new device type to the Netbox inventory. -// It takes a context and a newDeviceType object as input and returns the created or updated device type object and an error, if any. +// It takes a context and a newDeviceType object as input and +// returns the created or updated device type object and an error, if any. // If the device type already exists in Netbox, it checks if it is up to date and patches it if necessary. // If the device type does not exist, it creates a new one. func (nbi *NetboxInventory) AddDeviceType( @@ -783,7 +788,8 @@ func (nbi *NetboxInventory) AddDeviceType( } // AddPlatform adds a new platform to the Netbox inventory. -// It takes a context and a newPlatform object as input and returns the created or updated platform object and an error, if any. +// It takes a context and a newPlatform object as input and +// returns the created or updated platform object and an error, if any. // If the platform already exists in Netbox, it checks if it is up to date and patches it if necessary. // If the platform does not exist, it creates a new one. func (nbi *NetboxInventory) AddPlatform( @@ -839,7 +845,8 @@ func (nbi *NetboxInventory) AddPlatform( } // AddRackRole adds a new rack role to the Netbox inventory. -// It takes a context and a newRackRole object as input and returns the created or updated rack role object and an error, if any. +// It takes a context and a newRackRole object as input and +// returns the created or updated rack role object and an error, if any. // If the rack role already exists in Netbox, it checks if it is up to date and patches it if necessary. // If the rack role does not exist, it creates a new one. func (nbi *NetboxInventory) AddDevice( @@ -899,7 +906,8 @@ func (nbi *NetboxInventory) AddDevice( } // AddVirtualDeviceContext adds new virtual device context to the local inventory. -// It takes a context and a newVDC object as input and returns the created or updated virtual device context object and an error, if any. +// It takes a context and a newVDC object as input and +// returns the created or updated virtual device context object and an error, if any. // If the virtual device context already exists in Netbox, it checks if it is up to date and patches it if necessary. // If the virtual device context does not exist, it creates a new one. func (nbi *NetboxInventory) AddVirtualDeviceContext( @@ -917,8 +925,8 @@ func (nbi *NetboxInventory) AddVirtualDeviceContext( newVDC, ) } - if _, ok := nbi.virtualDeviceContextsIndexByNameAndDeviceID[newVDC.Name][newVDC.Device.ID]; ok { - oldVDC := nbi.virtualDeviceContextsIndexByNameAndDeviceID[newVDC.Name][newVDC.Device.ID] + if _, ok := nbi.virtualDeviceContextsIndex[newVDC.Name][newVDC.Device.ID]; ok { + oldVDC := nbi.virtualDeviceContextsIndex[newVDC.Name][newVDC.Device.ID] nbi.OrphanManager.RemoveItem(oldVDC) diffMap, err := utils.JSONDiffMapExceptID(newVDC, oldVDC, false, nbi.SourcePriority) if err != nil { @@ -940,7 +948,7 @@ func (nbi *NetboxInventory) AddVirtualDeviceContext( if err != nil { return nil, err } - nbi.virtualDeviceContextsIndexByNameAndDeviceID[newVDC.Name][newVDC.Device.ID] = patchedVDC + nbi.virtualDeviceContextsIndex[newVDC.Name][newVDC.Device.ID] = patchedVDC } else { nbi.Logger.Debug(ctx, "VirtualDeviceContext ", newVDC.Name, " already exists in Netbox and is up to date...") } @@ -950,16 +958,17 @@ func (nbi *NetboxInventory) AddVirtualDeviceContext( if err != nil { return nil, err } - if nbi.virtualDeviceContextsIndexByNameAndDeviceID[newDevice.Name] == nil { - nbi.virtualDeviceContextsIndexByNameAndDeviceID[newDevice.Name] = make(map[int]*objects.VirtualDeviceContext) + if nbi.virtualDeviceContextsIndex[newDevice.Name] == nil { + nbi.virtualDeviceContextsIndex[newDevice.Name] = make(map[int]*objects.VirtualDeviceContext) } - nbi.virtualDeviceContextsIndexByNameAndDeviceID[newDevice.Name][newDevice.Device.ID] = newDevice + nbi.virtualDeviceContextsIndex[newDevice.Name][newDevice.Device.ID] = newDevice } - return nbi.virtualDeviceContextsIndexByNameAndDeviceID[newVDC.Name][newVDC.Device.ID], nil + return nbi.virtualDeviceContextsIndex[newVDC.Name][newVDC.Device.ID], nil } // AddVlanGroup adds a new vlan group to the Netbox inventory. -// It takes a context and a newVlanGroup object as input and returns the created or updated vlan group object and an error, if any. +// It takes a context and a newVlanGroup object as input and +// returns the created or updated vlan group object and an error, if any. // If the vlan group already exists in Netbox, it checks if it is up to date and patches it if necessary. // If the vlan group does not exist, it creates a new one. func (nbi *NetboxInventory) AddVlanGroup( @@ -1065,7 +1074,8 @@ func (nbi *NetboxInventory) AddVlan( } // AddInterface adds a new interface to the Netbox inventory. -// It takes a context and a newInterface object as input and returns the created or updated interface object and an error, if any. +// It takes a context and a newInterface object as input and +// returns the created or updated interface object and an error, if any. // If the interface already exists in Netbox, it checks if it is up to date and patches it if necessary. // If the interface does not exist, it creates a new one. func (nbi *NetboxInventory) AddInterface( @@ -1075,11 +1085,11 @@ func (nbi *NetboxInventory) AddInterface( newInterface.NetboxObject.AddTag(nbi.SsotTag) addSourceNameCustomField(ctx, &newInterface.NetboxObject) newInterface.SetCustomField(constants.CustomFieldOrphanLastSeenName, nil) - nbi.interfacesLock.Lock() - defer nbi.interfacesLock.Unlock() if len(newInterface.Name) > constants.MaxInterfaceNameLength { newInterface.Name = newInterface.Name[:constants.MaxInterfaceNameLength] } + nbi.interfacesLock.Lock() + defer nbi.interfacesLock.Unlock() if _, ok := nbi.interfacesIndexByDeviceIDAndName[newInterface.Device.ID][newInterface.Name]; ok { oldInterface := nbi.interfacesIndexByDeviceIDAndName[newInterface.Device.ID][newInterface.Name] nbi.OrphanManager.RemoveItem(oldInterface) @@ -1124,12 +1134,14 @@ func (nbi *NetboxInventory) AddInterface( } nbi.interfacesIndexByDeviceIDAndName[newInterface.Device.ID][newInterface.Name] = newInterface nbi.interfacesIndexByID[newInterface.ID] = newInterface + return newInterface, nil } return nbi.interfacesIndexByDeviceIDAndName[newInterface.Device.ID][newInterface.Name], nil } // AddVM adds a new virtual machine to the Netbox inventory. -// It takes a context and a newVM object as input and returns the created or updated virtual machine object and an error, if any. +// It takes a context and a newVM object as input and +// returns the created or updated virtual machine object and an error, if any. // If the virtual machine already exists in Netbox, it checks if it is up to date and patches it if necessary. // If the virtual machine does not exist, it creates a new one. func (nbi *NetboxInventory) AddVM(ctx context.Context, newVM *objects.VM) (*objects.VM, error) { @@ -1183,7 +1195,8 @@ func (nbi *NetboxInventory) AddVM(ctx context.Context, newVM *objects.VM) (*obje } // AddVMInterface adds a new virtual machine interface to the Netbox inventory. -// It takes a context and a newVMInterface object as input and returns the created or updated virtual machine interface object and an error, if any. +// It takes a context and a newVMInterface object as input and +// returns the created or updated virtual machine interface object and an error, if any. // If the virtual machine interface already exists in Netbox, it checks if it is up to date and patches it if necessary. // If the virtual machine interface does not exist, it creates a new one. func (nbi *NetboxInventory) AddVMInterface( @@ -1247,7 +1260,8 @@ func (nbi *NetboxInventory) AddVMInterface( } // AddIPAddress adds a new IP address to the Netbox inventory. -// It takes a context and a newIPAddress object as input and returns the created or updated IP address object and an error, if any. +// It takes a context and a newIPAddress object as input and +// returns the created or updated IP address object and an error, if any. // If the IP address already exists in Netbox, it checks if it is up to date and patches it if necessary. // If the IP address does not exist, it creates a new one. func (nbi *NetboxInventory) AddIPAddress( @@ -1321,7 +1335,8 @@ func (nbi *NetboxInventory) AddIPAddress( } // AddMACAddress adds a new MAC address to the Netbox inventory. -// It takes a context and a newMACAddress object as input and returns the created or updated MAC address object and an error, if any. +// It takes a context and a newMACAddress object as input and +// returns the created or updated MAC address object and an error, if any. // If the MAC address already exists in Netbox, it checks if it is up to date and patches it if necessary. // If the MAC address does not exist, it creates a new one. func (nbi *NetboxInventory) AddMACAddress( @@ -1395,7 +1410,8 @@ func (nbi *NetboxInventory) AddMACAddress( } // AddPrefix adds a new prefix to the Netbox inventory. -// It takes a context and a newPrefix object as input and returns the created or updated prefix object and an error, if any. +// It takes a context and a newPrefix object as input and +// returns the created or updated prefix object and an error, if any. // If the prefix already exists in Netbox, it checks if it is up to date and patches it if necessary. // If the prefix does not exist, it creates a new one. func (nbi *NetboxInventory) AddPrefix( @@ -1409,7 +1425,8 @@ func (nbi *NetboxInventory) AddPrefix( if newPrefix.NetboxObject.CustomFields == nil { newPrefix.NetboxObject.CustomFields = make(map[string]interface{}) } - newPrefix.NetboxObject.CustomFields[constants.CustomFieldSourceName] = ctx.Value(constants.CtxSourceKey).(string) //nolint:forcetypeassert + //nolint:forcetypeassert + newPrefix.NetboxObject.CustomFields[constants.CustomFieldSourceName] = ctx.Value(constants.CtxSourceKey).(string) defer nbi.prefixesLock.Unlock() if _, ok := nbi.prefixesIndexByPrefix[newPrefix.Prefix]; ok { oldPrefix := nbi.prefixesIndexByPrefix[newPrefix.Prefix] @@ -1451,7 +1468,8 @@ func (nbi *NetboxInventory) AddPrefix( } // AddWirelessLAN adds a new wireless LAN to the Netbox inventory. -// It takes a context and a newWirelessLan object as input and returns the created or updated wireless LAN object and an error, if any. +// It takes a context and a newWirelessLan object as input and +// returns the created or updated wireless LAN object and an error, if any. // If the wireless LAN already exists in Netbox, it checks if it is up to date and patches it if necessary. // If the wireless LAN does not exist, it creates a new one. func (nbi *NetboxInventory) AddWirelessLAN( @@ -1507,7 +1525,8 @@ func (nbi *NetboxInventory) AddWirelessLAN( } // AddWirelessLANGroup adds a new wireless LAN group to the Netbox inventory. -// It takes a context and a newWirelessLANGroup object as input and returns the created or updated wireless LAN group object and an error, if any. +// It takes a context and a newWirelessLANGroup object as input and +// returns the created or updated wireless LAN group object and an error, if any. // If the wireless LAN group already exists in Netbox, it checks if it is up to date and patches it if necessary. // If the wireless LAN group does not exist, it creates a new one. func (nbi *NetboxInventory) AddWirelessLANGroup( @@ -1549,7 +1568,12 @@ func (nbi *NetboxInventory) AddWirelessLANGroup( } nbi.wirelessLANGroupsIndexByName[newWirelessLANGroup.Name] = patchedWirelessLANGroup } else { - nbi.Logger.Debug(ctx, "WirelessLANGroup ", newWirelessLANGroup.Name, " already exists in Netbox and is up to date...") + nbi.Logger.Debug( + ctx, + "WirelessLANGroup ", + newWirelessLANGroup.Name, + " already exists in Netbox and is up to date...", + ) } } else { nbi.Logger.Debug(ctx, "WirelessLANGroup ", newWirelessLANGroup.Name, " does not exist in Netbox. Creating it...") diff --git a/internal/netbox/inventory/add_items_test.go b/internal/netbox/inventory/add_items_test.go index 9245f2a6..ac12f510 100644 --- a/internal/netbox/inventory/add_items_test.go +++ b/internal/netbox/inventory/add_items_test.go @@ -25,19 +25,38 @@ func TestNetboxInventory_AddTag(t *testing.T) { { name: "Test add new tag", nbi: MockInventory, - args: args{ctx: context.WithValue(context.Background(), constants.CtxSourceKey, "test"), newTag: &objects.Tag{Name: "new tag", Description: "New Tag", Color: constants.ColorBlack, Slug: "new_tag"}}, + args: args{ + ctx: context.WithValue(context.Background(), constants.CtxSourceKey, "test"), + newTag: &objects.Tag{ + Name: "new tag", + Description: "New Tag", + Color: constants.ColorBlack, + Slug: "new_tag", + }, + }, want: &service.MockTagCreateResponse, }, { name: "Test update existing tag", nbi: MockInventory, - args: args{ctx: context.WithValue(context.Background(), constants.CtxSourceKey, "test"), newTag: &objects.Tag{Name: "existing_tag1", Description: "New Tag", Color: constants.ColorBlack, Slug: "new_tag"}}, + args: args{ + ctx: context.WithValue(context.Background(), constants.CtxSourceKey, "test"), + newTag: &objects.Tag{ + Name: "existing_tag1", + Description: "New Tag", + Color: constants.ColorBlack, + Slug: "new_tag", + }, + }, want: &service.MockTagPatchResponse, }, { name: "Test add the same tag", nbi: MockInventory, - args: args{ctx: context.WithValue(context.Background(), constants.CtxSourceKey, "test"), newTag: MockExistingTags["existing_tag2"]}, + args: args{ + ctx: context.WithValue(context.Background(), constants.CtxSourceKey, "test"), + newTag: MockExistingTags["existing_tag2"], + }, want: MockExistingTags["existing_tag2"], }, } @@ -78,19 +97,28 @@ func TestNetboxInventory_AddTenant(t *testing.T) { { name: "Test add new tenant", nbi: MockInventory, - args: args{ctx: context.WithValue(context.Background(), constants.CtxSourceKey, "test"), newTenant: &objects.Tenant{Name: "new tenant", Slug: "new_tenant"}}, + args: args{ + ctx: context.WithValue(context.Background(), constants.CtxSourceKey, "test"), + newTenant: &objects.Tenant{Name: "new tenant", Slug: "new_tenant"}, + }, want: &service.MockTenantCreateResponse, }, { name: "Test update existing tenant", nbi: MockInventory, - args: args{ctx: context.WithValue(context.Background(), constants.CtxSourceKey, "test"), newTenant: &objects.Tenant{Name: "existing_tenant1", Slug: "new_tenant"}}, + args: args{ + ctx: context.WithValue(context.Background(), constants.CtxSourceKey, "test"), + newTenant: &objects.Tenant{Name: "existing_tenant1", Slug: "new_tenant"}, + }, want: &service.MockTenantPatchResponse, }, { name: "Test add the same tenant", nbi: MockInventory, - args: args{ctx: context.WithValue(context.Background(), constants.CtxSourceKey, "test"), newTenant: &objects.Tenant{Name: "existing_tenant2"}}, + args: args{ + ctx: context.WithValue(context.Background(), constants.CtxSourceKey, "test"), + newTenant: &objects.Tenant{Name: "existing_tenant2"}, + }, want: MockExistingTenants["existing_tenant2"], }, } @@ -127,19 +155,28 @@ func TestNetboxInventory_AddSite(t *testing.T) { { name: "Test add new site", nbi: MockInventory, - args: args{ctx: context.WithValue(context.Background(), constants.CtxSourceKey, "test"), newSite: &objects.Site{Name: "new site", Slug: "new_site"}}, + args: args{ + ctx: context.WithValue(context.Background(), constants.CtxSourceKey, "test"), + newSite: &objects.Site{Name: "new site", Slug: "new_site"}, + }, want: &service.MockSiteCreateResponse, }, { name: "Test update existing site", nbi: MockInventory, - args: args{ctx: context.WithValue(context.Background(), constants.CtxSourceKey, "test"), newSite: &objects.Site{Name: "existing_site1", Slug: "new_site"}}, + args: args{ + ctx: context.WithValue(context.Background(), constants.CtxSourceKey, "test"), + newSite: &objects.Site{Name: "existing_site1", Slug: "new_site"}, + }, want: &service.MockSitePatchResponse, }, { name: "Test add the same site", nbi: MockInventory, - args: args{ctx: context.WithValue(context.Background(), constants.CtxSourceKey, "test"), newSite: &objects.Site{Name: "existing_site2"}}, + args: args{ + ctx: context.WithValue(context.Background(), constants.CtxSourceKey, "test"), + newSite: &objects.Site{Name: "existing_site2"}, + }, want: MockExistingSites["existing_site2"], }, } @@ -207,7 +244,11 @@ func TestNetboxInventory_AddContactGroup(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, err := tt.nbi.AddContactGroup(tt.args.ctx, tt.args.newContactGroup) if (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.AddContactGroup() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.AddContactGroup() error = %v, wantErr %v", + err, + tt.wantErr, + ) return } if !reflect.DeepEqual(got, tt.want) { @@ -263,7 +304,11 @@ func TestNetboxInventory_AddContactAssignment(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, err := tt.nbi.AddContactAssignment(tt.args.ctx, tt.args.newCA) if (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.AddContactAssignment() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.AddContactAssignment() error = %v, wantErr %v", + err, + tt.wantErr, + ) return } if !reflect.DeepEqual(got, tt.want) { @@ -319,7 +364,11 @@ func TestNetboxInventory_AddClusterGroup(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, err := tt.nbi.AddClusterGroup(tt.args.ctx, tt.args.newCg) if (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.AddClusterGroup() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.AddClusterGroup() error = %v, wantErr %v", + err, + tt.wantErr, + ) return } if !reflect.DeepEqual(got, tt.want) { @@ -431,7 +480,11 @@ func TestNetboxInventory_AddManufacturer(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, err := tt.nbi.AddManufacturer(tt.args.ctx, tt.args.newManufacturer) if (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.AddManufacturer() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.AddManufacturer() error = %v, wantErr %v", + err, + tt.wantErr, + ) return } if !reflect.DeepEqual(got, tt.want) { @@ -739,7 +792,11 @@ func TestNetboxInventory_AddVirtualDeviceContext(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, err := tt.nbi.AddVirtualDeviceContext(tt.args.ctx, tt.args.newVDC) if (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.AddVirtualDeviceContext() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.AddVirtualDeviceContext() error = %v, wantErr %v", + err, + tt.wantErr, + ) return } if !reflect.DeepEqual(got, tt.want) { @@ -795,7 +852,11 @@ func TestNetboxInventory_AddWirelessLANGroup(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, err := tt.nbi.AddWirelessLANGroup(tt.args.ctx, tt.args.newWirelessLANGroup) if (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.AddWirelessLANGroup() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.AddWirelessLANGroup() error = %v, wantErr %v", + err, + tt.wantErr, + ) return } if !reflect.DeepEqual(got, tt.want) { @@ -818,7 +879,11 @@ func Test_addSourceNameCustomField(t *testing.T) { { name: "Add source custom field to netbox object", args: args{ - ctx: context.WithValue(context.Background(), constants.CtxSourceKey, "testSource"), + ctx: context.WithValue( + context.Background(), + constants.CtxSourceKey, + "testSource", + ), netboxObject: &objects.NetboxObject{}, }, want: &objects.NetboxObject{ diff --git a/internal/netbox/inventory/add_predefined_items.go b/internal/netbox/inventory/add_predefined_items.go index e3e4eadc..76dea449 100644 --- a/internal/netbox/inventory/add_predefined_items.go +++ b/internal/netbox/inventory/add_predefined_items.go @@ -8,7 +8,9 @@ import ( "github.com/bl4ko/netbox-ssot/internal/utils" ) -func (nbi *NetboxInventory) AddContainerDeviceRole(ctx context.Context) (*objects.DeviceRole, error) { +func (nbi *NetboxInventory) AddContainerDeviceRole( + ctx context.Context, +) (*objects.DeviceRole, error) { newRole, err := nbi.AddDeviceRole(ctx, &objects.DeviceRole{ NetboxObject: objects.NetboxObject{ Description: constants.DeviceRoleContainerDescription, @@ -25,7 +27,9 @@ func (nbi *NetboxInventory) AddContainerDeviceRole(ctx context.Context) (*object return newRole, nil } -func (nbi *NetboxInventory) AddFirewallDeviceRole(ctx context.Context) (*objects.DeviceRole, error) { +func (nbi *NetboxInventory) AddFirewallDeviceRole( + ctx context.Context, +) (*objects.DeviceRole, error) { newRole, err := nbi.AddDeviceRole(ctx, &objects.DeviceRole{ NetboxObject: objects.NetboxObject{ Description: constants.DeviceRoleFirewallDescription, @@ -93,7 +97,9 @@ func (nbi *NetboxInventory) AddVMDeviceRole(ctx context.Context) (*objects.Devic return newRole, nil } -func (nbi *NetboxInventory) AddVMTemplateDeviceRole(ctx context.Context) (*objects.DeviceRole, error) { +func (nbi *NetboxInventory) AddVMTemplateDeviceRole( + ctx context.Context, +) (*objects.DeviceRole, error) { newRole, err := nbi.AddDeviceRole(ctx, &objects.DeviceRole{ NetboxObject: objects.NetboxObject{ Description: constants.DeviceRoleVMTemplateDescription, diff --git a/internal/netbox/inventory/add_predefined_items_test.go b/internal/netbox/inventory/add_predefined_items_test.go index 5fd77e13..aaa3f925 100644 --- a/internal/netbox/inventory/add_predefined_items_test.go +++ b/internal/netbox/inventory/add_predefined_items_test.go @@ -25,7 +25,11 @@ func TestNetboxInventory_AddContainerDeviceRole(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, err := tt.nbi.AddContainerDeviceRole(tt.args.ctx) if (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.AddContainerDeviceRole() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.AddContainerDeviceRole() error = %v, wantErr %v", + err, + tt.wantErr, + ) return } if !reflect.DeepEqual(got, tt.want) { @@ -52,7 +56,11 @@ func TestNetboxInventory_AddFirewallDeviceRole(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, err := tt.nbi.AddFirewallDeviceRole(tt.args.ctx) if (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.AddFirewallDeviceRole() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.AddFirewallDeviceRole() error = %v, wantErr %v", + err, + tt.wantErr, + ) return } if !reflect.DeepEqual(got, tt.want) { @@ -79,7 +87,11 @@ func TestNetboxInventory_AddSwitchDeviceRole(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, err := tt.nbi.AddSwitchDeviceRole(tt.args.ctx) if (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.AddSwitchDeviceRole() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.AddSwitchDeviceRole() error = %v, wantErr %v", + err, + tt.wantErr, + ) return } if !reflect.DeepEqual(got, tt.want) { @@ -106,7 +118,11 @@ func TestNetboxInventory_AddServerDeviceRole(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, err := tt.nbi.AddServerDeviceRole(tt.args.ctx) if (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.AddServerDeviceRole() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.AddServerDeviceRole() error = %v, wantErr %v", + err, + tt.wantErr, + ) return } if !reflect.DeepEqual(got, tt.want) { @@ -133,7 +149,11 @@ func TestNetboxInventory_AddVMDeviceRole(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, err := tt.nbi.AddVMDeviceRole(tt.args.ctx) if (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.AddVMDeviceRole() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.AddVMDeviceRole() error = %v, wantErr %v", + err, + tt.wantErr, + ) return } if !reflect.DeepEqual(got, tt.want) { @@ -160,7 +180,11 @@ func TestNetboxInventory_AddVMTemplateDeviceRole(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, err := tt.nbi.AddVMTemplateDeviceRole(tt.args.ctx) if (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.AddVMTemplateDeviceRole() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.AddVMTemplateDeviceRole() error = %v, wantErr %v", + err, + tt.wantErr, + ) return } if !reflect.DeepEqual(got, tt.want) { diff --git a/internal/netbox/inventory/delete_items.go b/internal/netbox/inventory/delete_items.go index b81ecfcd..ebd3fbe3 100644 --- a/internal/netbox/inventory/delete_items.go +++ b/internal/netbox/inventory/delete_items.go @@ -22,8 +22,18 @@ func (nbi *NetboxInventory) DeleteOrphans(hard bool) error { continue } - nbi.OrphanManager.Logger.Infof(nbi.Ctx, "Performing %s deletion of orphaned objects of type %s", deleteTypeStr, objectAPIPath) - nbi.OrphanManager.Logger.Debugf(nbi.Ctx, "IDs of objects to be %s deleted: %v", deleteTypeStr, id2orphanItem) + nbi.OrphanManager.Logger.Infof( + nbi.Ctx, + "Performing %s deletion of orphaned objects of type %s", + deleteTypeStr, + objectAPIPath, + ) + nbi.OrphanManager.Logger.Debugf( + nbi.Ctx, + "IDs of objects to be %s deleted: %v", + deleteTypeStr, + id2orphanItem, + ) for _, orphanItem := range id2orphanItem { if hard { @@ -58,11 +68,18 @@ func (nbi *NetboxInventory) softDelete(orphanItem objects.OrphanItem) error { // Perform soft deletion // Add tag to the object to mark it as orphaned todayDate := time.Now().Format(constants.CustomFieldOrphanLastSeenFormat) - if !orphanItem.GetNetboxObject().HasTag(nbi.OrphanManager.Tag) || orphanItem.GetNetboxObject().GetCustomField(constants.CustomFieldOrphanLastSeenName) == nil { + if !orphanItem.GetNetboxObject().HasTag(nbi.OrphanManager.Tag) || + orphanItem.GetNetboxObject(). + GetCustomField(constants.CustomFieldOrphanLastSeenName) == + nil { // This OrphanItem has been marked as orphan for the first time orphanItem.GetNetboxObject().AddTag(nbi.OrphanManager.Tag) - orphanItem.GetNetboxObject().SetCustomField(constants.CustomFieldOrphanLastSeenName, todayDate) - diffMap := utils.ExtractFieldsFromDiffMap(utils.StructToNetboxJSONMap(orphanItem.GetNetboxObject()), []string{"tags", "custom_fields"}) + orphanItem.GetNetboxObject(). + SetCustomField(constants.CustomFieldOrphanLastSeenName, todayDate) + diffMap := utils.ExtractFieldsFromDiffMap( + utils.StructToNetboxJSONMap(orphanItem.GetNetboxObject()), + []string{"tags", "custom_fields"}, + ) // Update object on the API var err error switch orphanItem.(type) { @@ -75,7 +92,12 @@ func (nbi *NetboxInventory) softDelete(orphanItem objects.OrphanItem) error { case *objects.IPAddress: _, err = service.Patch[objects.IPAddress](nbi.OrphanManager.Ctx, nbi.NetboxAPI, orphanItem.GetID(), diffMap) case *objects.VirtualDeviceContext: - _, err = service.Patch[objects.VirtualDeviceContext](nbi.OrphanManager.Ctx, nbi.NetboxAPI, orphanItem.GetID(), diffMap) + _, err = service.Patch[objects.VirtualDeviceContext]( + nbi.OrphanManager.Ctx, + nbi.NetboxAPI, + orphanItem.GetID(), + diffMap, + ) case *objects.Interface: _, err = service.Patch[objects.Interface](nbi.OrphanManager.Ctx, nbi.NetboxAPI, orphanItem.GetID(), diffMap) case *objects.VMInterface: @@ -114,7 +136,10 @@ func (nbi *NetboxInventory) softDelete(orphanItem objects.OrphanItem) error { } } else { nbi.Logger.Debugf(nbi.Ctx, "%s is already marked as orphan", orphanItem) - lastSeen, err := time.Parse(constants.CustomFieldOrphanLastSeenFormat, orphanItem.GetNetboxObject().GetCustomField(constants.CustomFieldOrphanLastSeenName).(string)) + lastSeen, err := time.Parse( + constants.CustomFieldOrphanLastSeenFormat, + orphanItem.GetNetboxObject().GetCustomField(constants.CustomFieldOrphanLastSeenName).(string), + ) if err != nil { return fmt.Errorf("failed parsing last seen date: %s", err) } diff --git a/internal/netbox/inventory/get_items.go b/internal/netbox/inventory/get_items.go index 9ed42bfa..5ea16508 100644 --- a/internal/netbox/inventory/get_items.go +++ b/internal/netbox/inventory/get_items.go @@ -187,7 +187,7 @@ func (nbi *NetboxInventory) GetVirtualDeviceContext( ) (*objects.VirtualDeviceContext, bool) { nbi.virtualDeviceContextsLock.Lock() defer nbi.virtualDeviceContextsLock.Unlock() - vdc, vdcExists := nbi.virtualDeviceContextsIndexByNameAndDeviceID[zoneName][deviceID] + vdc, vdcExists := nbi.virtualDeviceContextsIndex[zoneName][deviceID] if !vdcExists { return nil, false } @@ -222,7 +222,7 @@ func (nbi *NetboxInventory) GetContactAssignment( ) (*objects.ContactAssignment, bool) { nbi.contactAssignmentsLock.Lock() defer nbi.contactAssignmentsLock.Unlock() - contactAssignment, contactAssignmentExists := nbi.contactAssignmentsIndexByObjectTypeAndObjectIDAndContactIDAndRoleID[contentType][objectID][contactID][roleID] + contactAssignment, contactAssignmentExists := nbi.contactAssignmentsIndex[contentType][objectID][contactID][roleID] if !contactAssignmentExists { return nil, false } diff --git a/internal/netbox/inventory/get_items_test.go b/internal/netbox/inventory/get_items_test.go index 73fc6a4b..82ce0b04 100644 --- a/internal/netbox/inventory/get_items_test.go +++ b/internal/netbox/inventory/get_items_test.go @@ -340,10 +340,18 @@ func TestNetboxInventory_GetVirtualDeviceContext(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, got1 := tt.nbi.GetVirtualDeviceContext(tt.args.zoneName, tt.args.deviceID) if !reflect.DeepEqual(got, tt.want) { - t.Errorf("NetboxInventory.GetVirtualDeviceContext() got = %v, want %v", got, tt.want) + t.Errorf( + "NetboxInventory.GetVirtualDeviceContext() got = %v, want %v", + got, + tt.want, + ) } if got1 != tt.want1 { - t.Errorf("NetboxInventory.GetVirtualDeviceContext() got1 = %v, want %v", got1, tt.want1) + t.Errorf( + "NetboxInventory.GetVirtualDeviceContext() got1 = %v, want %v", + got1, + tt.want1, + ) } }) } @@ -394,12 +402,21 @@ func TestNetboxInventory_GetContactAssignment(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, got1 := tt.nbi.GetContactAssignment(tt.args.contentType, tt.args.objectID, tt.args.contactID, tt.args.roleID) + got, got1 := tt.nbi.GetContactAssignment( + tt.args.contentType, + tt.args.objectID, + tt.args.contactID, + tt.args.roleID, + ) if !reflect.DeepEqual(got, tt.want) { t.Errorf("NetboxInventory.GetContactAssignment() got = %v, want %v", got, tt.want) } if got1 != tt.want1 { - t.Errorf("NetboxInventory.GetContactAssignment() got1 = %v, want %v", got1, tt.want1) + t.Errorf( + "NetboxInventory.GetContactAssignment() got1 = %v, want %v", + got1, + tt.want1, + ) } }) } diff --git a/internal/netbox/inventory/init_items.go b/internal/netbox/inventory/init_items.go index 2b825d08..ae1a27b8 100644 --- a/internal/netbox/inventory/init_items.go +++ b/internal/netbox/inventory/init_items.go @@ -136,7 +136,7 @@ func (nbi *NetboxInventory) initContactAssignments(ctx context.Context) error { return err } // We also create an index of contacts by name for easier access - nbi.contactAssignmentsIndexByObjectTypeAndObjectIDAndContactIDAndRoleID = make( + nbi.contactAssignmentsIndex = make( map[constants.ContentType]map[int]map[int]map[int]*objects.ContactAssignment, ) debugIDs := map[int]bool{} // Netbox pagination bug duplicates @@ -146,22 +146,22 @@ func (nbi *NetboxInventory) initContactAssignments(ctx context.Context) error { fmt.Printf("Already been here: %d", cA.ID) } debugIDs[cA.ID] = true - if nbi.contactAssignmentsIndexByObjectTypeAndObjectIDAndContactIDAndRoleID[cA.ModelType] == nil { - nbi.contactAssignmentsIndexByObjectTypeAndObjectIDAndContactIDAndRoleID[cA.ModelType] = make( + if nbi.contactAssignmentsIndex[cA.ModelType] == nil { + nbi.contactAssignmentsIndex[cA.ModelType] = make( map[int]map[int]map[int]*objects.ContactAssignment, ) } - if nbi.contactAssignmentsIndexByObjectTypeAndObjectIDAndContactIDAndRoleID[cA.ModelType][cA.ObjectID] == nil { - nbi.contactAssignmentsIndexByObjectTypeAndObjectIDAndContactIDAndRoleID[cA.ModelType][cA.ObjectID] = make( + if nbi.contactAssignmentsIndex[cA.ModelType][cA.ObjectID] == nil { + nbi.contactAssignmentsIndex[cA.ModelType][cA.ObjectID] = make( map[int]map[int]*objects.ContactAssignment, ) } - if nbi.contactAssignmentsIndexByObjectTypeAndObjectIDAndContactIDAndRoleID[cA.ModelType][cA.ObjectID][cA.Contact.ID] == nil { - nbi.contactAssignmentsIndexByObjectTypeAndObjectIDAndContactIDAndRoleID[cA.ModelType][cA.ObjectID][cA.Contact.ID] = make( + if nbi.contactAssignmentsIndex[cA.ModelType][cA.ObjectID][cA.Contact.ID] == nil { + nbi.contactAssignmentsIndex[cA.ModelType][cA.ObjectID][cA.Contact.ID] = make( map[int]*objects.ContactAssignment, ) } - nbi.contactAssignmentsIndexByObjectTypeAndObjectIDAndContactIDAndRoleID[cA.ModelType][cA.ObjectID][cA.Contact.ID][cA.Role.ID] = cA + nbi.contactAssignmentsIndex[cA.ModelType][cA.ObjectID][cA.Contact.ID][cA.Role.ID] = cA nbi.OrphanManager.AddItem(cA) } nbi.Logger.Debug(ctx, "Successfully collected contacts from Netbox: ", nbi.contactsIndexByName) @@ -372,24 +372,24 @@ func (nbi *NetboxInventory) initVirtualDeviceContexts(ctx context.Context) error return err } // Initialize internal index of devices by Name and SiteId - nbi.virtualDeviceContextsIndexByNameAndDeviceID = make( + nbi.virtualDeviceContextsIndex = make( map[string]map[int]*objects.VirtualDeviceContext, ) for i, virtualDeviceContext := range nbVirtualDeviceContexts { nbVirtualDeviceContext := &nbVirtualDeviceContexts[i] - if nbi.virtualDeviceContextsIndexByNameAndDeviceID[virtualDeviceContext.Name] == nil { - nbi.virtualDeviceContextsIndexByNameAndDeviceID[virtualDeviceContext.Name] = make( + if nbi.virtualDeviceContextsIndex[virtualDeviceContext.Name] == nil { + nbi.virtualDeviceContextsIndex[virtualDeviceContext.Name] = make( map[int]*objects.VirtualDeviceContext, ) } - nbi.virtualDeviceContextsIndexByNameAndDeviceID[virtualDeviceContext.Name][virtualDeviceContext.Device.ID] = nbVirtualDeviceContext + nbi.virtualDeviceContextsIndex[virtualDeviceContext.Name][virtualDeviceContext.Device.ID] = nbVirtualDeviceContext nbi.OrphanManager.AddItem(nbVirtualDeviceContext) } nbi.Logger.Debug( ctx, "Successfully collected VirtualDeviceContexts from Netbox: ", - nbi.virtualDeviceContextsIndexByNameAndDeviceID, + nbi.virtualDeviceContextsIndex, ) return nil } diff --git a/internal/netbox/inventory/init_items_test.go b/internal/netbox/inventory/init_items_test.go index 72ce3772..a4a52a51 100644 --- a/internal/netbox/inventory/init_items_test.go +++ b/internal/netbox/inventory/init_items_test.go @@ -83,7 +83,11 @@ func TestNetboxInventory_InitContactRoles(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initContactRoles(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.InitContactRoles() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.InitContactRoles() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -104,7 +108,11 @@ func TestNetboxInventory_InitContactAssignments(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initContactAssignments(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.InitContactAssignments() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.InitContactAssignments() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -125,7 +133,11 @@ func TestNetboxInventory_InitAdminContactRole(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initAdminContactRole(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.InitAdminContactRole() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.InitAdminContactRole() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -146,7 +158,11 @@ func TestNetboxInventory_InitContactGroups(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initContactGroups(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.InitContactGroups() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.InitContactGroups() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -188,7 +204,11 @@ func TestNetboxInventory_InitManufacturers(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initManufacturers(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.InitManufacturers() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.InitManufacturers() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -251,7 +271,11 @@ func TestNetboxInventory_InitDeviceRoles(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initDeviceRoles(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.InitDeviceRoles() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.InitDeviceRoles() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -272,7 +296,11 @@ func TestNetboxInventory_InitCustomFields(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initCustomFields(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.InitCustomFields() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.InitCustomFields() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -293,7 +321,11 @@ func TestNetboxInventory_InitSsotCustomFields(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initSsotCustomFields(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.InitSsotCustomFields() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.InitSsotCustomFields() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -314,7 +346,11 @@ func TestNetboxInventory_InitClusterGroups(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initClusterGroups(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.InitClusterGroups() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.InitClusterGroups() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -335,7 +371,11 @@ func TestNetboxInventory_InitClusterTypes(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initClusterTypes(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.InitClusterTypes() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.InitClusterTypes() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -377,7 +417,11 @@ func TestNetboxInventory_InitDeviceTypes(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initDeviceTypes(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.InitDeviceTypes() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.InitDeviceTypes() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -482,7 +526,11 @@ func TestNetboxInventory_InitVMInterfaces(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initVMInterfaces(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.InitVMInterfaces() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.InitVMInterfaces() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -503,7 +551,11 @@ func TestNetboxInventory_InitIPAddresses(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initIPAddresses(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.InitIPAddresses() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.InitIPAddresses() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -608,7 +660,11 @@ func TestNetboxInventory_initContactRoles(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initContactRoles(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.initContactRoles() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.initContactRoles() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -629,7 +685,11 @@ func TestNetboxInventory_initContactAssignments(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initContactAssignments(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.initContactAssignments() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.initContactAssignments() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -650,7 +710,11 @@ func TestNetboxInventory_initAdminContactRole(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initAdminContactRole(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.initAdminContactRole() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.initAdminContactRole() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -671,7 +735,11 @@ func TestNetboxInventory_initContactGroups(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initContactGroups(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.initContactGroups() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.initContactGroups() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -713,7 +781,11 @@ func TestNetboxInventory_initDefaultSite(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initDefaultSite(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.initDefaultSite() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.initDefaultSite() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -734,7 +806,11 @@ func TestNetboxInventory_initManufacturers(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initManufacturers(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.initManufacturers() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.initManufacturers() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -797,7 +873,11 @@ func TestNetboxInventory_initVirtualDeviceContexts(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initVirtualDeviceContexts(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.initVirtualDeviceContexts() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.initVirtualDeviceContexts() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -818,7 +898,11 @@ func TestNetboxInventory_initDeviceRoles(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initDeviceRoles(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.initDeviceRoles() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.initDeviceRoles() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -839,7 +923,11 @@ func TestNetboxInventory_initCustomFields(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initCustomFields(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.initCustomFields() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.initCustomFields() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -860,7 +948,11 @@ func TestNetboxInventory_initSsotCustomFields(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initSsotCustomFields(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.initSsotCustomFields() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.initSsotCustomFields() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -881,7 +973,11 @@ func TestNetboxInventory_initClusterGroups(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initClusterGroups(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.initClusterGroups() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.initClusterGroups() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -902,7 +998,11 @@ func TestNetboxInventory_initClusterTypes(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initClusterTypes(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.initClusterTypes() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.initClusterTypes() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -944,7 +1044,11 @@ func TestNetboxInventory_initDeviceTypes(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initDeviceTypes(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.initDeviceTypes() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.initDeviceTypes() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -1049,7 +1153,11 @@ func TestNetboxInventory_initVMInterfaces(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initVMInterfaces(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.initVMInterfaces() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.initVMInterfaces() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -1070,7 +1178,11 @@ func TestNetboxInventory_initIPAddresses(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initIPAddresses(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.initIPAddresses() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.initIPAddresses() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -1112,7 +1224,11 @@ func TestNetboxInventory_initWirelessLANs(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initWirelessLANs(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.initWirelessLANs() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.initWirelessLANs() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } @@ -1133,7 +1249,11 @@ func TestNetboxInventory_initWirelessLANGroups(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := tt.nbi.initWirelessLANGroups(tt.args.ctx); (err != nil) != tt.wantErr { - t.Errorf("NetboxInventory.initWirelessLANGroups() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf( + "NetboxInventory.initWirelessLANGroups() error = %v, wantErr %v", + err, + tt.wantErr, + ) } }) } diff --git a/internal/netbox/inventory/inventory.go b/internal/netbox/inventory/inventory.go index 44de3c78..91005474 100644 --- a/internal/netbox/inventory/inventory.go +++ b/internal/netbox/inventory/inventory.go @@ -57,11 +57,11 @@ type NetboxInventory struct { contactsIndexByName map[string]*objects.Contact contactsLock sync.Mutex - // contactAssignmentsIndexByObjectTypeAndObjectIDAndContactIDAndRoleID is a + // contactAssignmentsIndex is a // map of all contact assignments indexed by their // content type, object id, contact id and role id. - contactAssignmentsIndexByObjectTypeAndObjectIDAndContactIDAndRoleID map[constants.ContentType]map[int]map[int]map[int]*objects.ContactAssignment - contactAssignmentsLock sync.Mutex + contactAssignmentsIndex map[constants.ContentType]map[int]map[int]map[int]*objects.ContactAssignment + contactAssignmentsLock sync.Mutex // sitesIndexByName is a map of all sites in the Netbox's inventory, // indexed by their name @@ -100,10 +100,10 @@ type NetboxInventory struct { devicesIndexByID map[int]*objects.Device devicesLock sync.Mutex - // virtualDeviceContextsIndexByNameAndDeviceID is a map of all virtual device contexts + // virtualDeviceContextsIndex is a map of all virtual device contexts // in the Netbox's inventory indexed by their name and device ID. - virtualDeviceContextsIndexByNameAndDeviceID map[string]map[int]*objects.VirtualDeviceContext - virtualDeviceContextsLock sync.Mutex + virtualDeviceContextsIndex map[string]map[int]*objects.VirtualDeviceContext + virtualDeviceContextsLock sync.Mutex // prefixesIndexByPrefix is a map of all prefixes in the Netbox's inventory, // indexed by their prefix. diff --git a/internal/netbox/inventory/inventory_test.go b/internal/netbox/inventory/inventory_test.go index 84ff889b..761cc29e 100644 --- a/internal/netbox/inventory/inventory_test.go +++ b/internal/netbox/inventory/inventory_test.go @@ -41,7 +41,10 @@ func TestNewNetboxInventory(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := NewNetboxInventory(tt.args.ctx, tt.args.logger, tt.args.nbConfig); !reflect.DeepEqual(got, tt.want) { + if got := NewNetboxInventory(tt.args.ctx, tt.args.logger, tt.args.nbConfig); !reflect.DeepEqual( + got, + tt.want, + ) { t.Errorf("NewNetboxInventory() = %v, want %v", got, tt.want) } }) diff --git a/internal/netbox/inventory/test_objects.go b/internal/netbox/inventory/test_objects.go index 36e65a68..048e7c2a 100644 --- a/internal/netbox/inventory/test_objects.go +++ b/internal/netbox/inventory/test_objects.go @@ -72,7 +72,11 @@ var MockInventory = &NetboxInventory{ sitesIndexByName: MockExistingSites, sitesLock: sync.Mutex{}, NetboxAPI: service.MockNetboxClient, - Ctx: context.WithValue(context.Background(), constants.CustomFieldSourceName, "testInventory"), //nolint + Ctx: context.WithValue( + context.Background(), + constants.CtxSourceKey, + "testInventory", + ), SsotTag: &objects.Tag{ ID: 0, Name: "netbox-ssot", diff --git a/internal/netbox/objects/dcim.go b/internal/netbox/objects/dcim.go index 965099ea..5b8876c5 100644 --- a/internal/netbox/objects/dcim.go +++ b/internal/netbox/objects/dcim.go @@ -415,7 +415,8 @@ type InterfaceType struct { Choice } -// Predefined types: https://github.com/netbox-community/netbox/blob/ec245b968f50bdbafaadd5d6b885832d858fa167/netbox/dcim/choices.py#L800 +// Predefined types see : +// https://github.com/netbox-community/netbox/blob/ec245b968f50bdbafaadd5d6b885832d858fa167/netbox/dcim/choices.py#L800 var ( // Netbox's Virtual interface types. VirtualInterfaceType = InterfaceType{Choice{Value: "virtual", Label: "Virtual"}} @@ -602,7 +603,8 @@ var IfaceSpeed2IfaceType = map[InterfaceSpeed]*InterfaceType{ // Interface speed in kbps. type InterfaceSpeed int64 -// Available interface speeds: https://github.com/netbox-community/netbox/blob/ec245b968f50bdbafaadd5d6b885832d858fa167/netbox/dcim/choices.py#L1139 +// Available interface speeds: +// https://github.com/netbox-community/netbox/blob/72e93b04daf38b0a5f7dab70e96a9f96edd02649/netbox/dcim/choices.py#L1229 const ( MBPS10 InterfaceSpeed = 10000 MBPS100 InterfaceSpeed = 100000 @@ -785,7 +787,12 @@ type MACAddress struct { } func (m MACAddress) String() string { - return fmt.Sprintf("MACAddress{MAC: %s}", m.MAC) + return fmt.Sprintf( + "MACAddress{MAC: %s, AssignedObjectType: %s, AssignedObjectID: %d}", + m.MAC, + m.AssignedObjectType, + m.AssignedObjectID, + ) } // MACAddress implements IDItem interface. diff --git a/internal/netbox/objects/dcim_test.go b/internal/netbox/objects/dcim_test.go index fe62664e..522157bf 100644 --- a/internal/netbox/objects/dcim_test.go +++ b/internal/netbox/objects/dcim_test.go @@ -47,7 +47,11 @@ func TestPlatform_String(t *testing.T) { Name: "TestManufacturer", }, }, - want: fmt.Sprintf("Platform{Name: %s, Manufacturer: %s}", "TestPlatform", Manufacturer{Name: "TestManufacturer"}), + want: fmt.Sprintf( + "Platform{Name: %s, Manufacturer: %s}", + "TestPlatform", + Manufacturer{Name: "TestManufacturer"}, + ), }, // TODO: Add test cases. } @@ -98,7 +102,11 @@ func TestDeviceType_String(t *testing.T) { }, Model: "test model", }, - want: fmt.Sprintf("DeviceType{Manufacturer: %s, Model: %s}", "Test manufacturer", "test model"), + want: fmt.Sprintf( + "DeviceType{Manufacturer: %s, Model: %s}", + "Test manufacturer", + "test model", + ), }, } for _, tt := range tests { @@ -156,7 +164,13 @@ func TestDevice_String(t *testing.T) { Name: "Test site", }, }, - want: fmt.Sprintf("Device{Name: %s, Type: %s, Role: %s, Site: %s}", "Test device", "DeviceType{Manufacturer: Test manufacturer, Model: test model}", "DeviceRole{Name: Test device-role}", "Site{Name: Test site}"), + want: fmt.Sprintf( + "Device{Name: %s, Type: %s, Role: %s, Site: %s}", + "Test device", + "DeviceType{Manufacturer: Test manufacturer, Model: test model}", + "DeviceRole{Name: Test device-role}", + "Site{Name: Test site}", + ), }, } for _, tt := range tests { @@ -195,7 +209,12 @@ func TestInterface_String(t *testing.T) { }, }, }, - want: fmt.Sprintf("Interface{Name: %s, Device: %s, Type: %s}", "Test interface", "Test device", OtherInterfaceType.Label), + want: fmt.Sprintf( + "Interface{Name: %s, Device: %s, Type: %s}", + "Test interface", + "Test device", + OtherInterfaceType.Label, + ), }, } for _, tt := range tests { @@ -220,7 +239,12 @@ func TestVirtualDeviceContext_String(t *testing.T) { Device: &Device{Name: "testdevice"}, Status: &VDCStatusActive, }, - want: fmt.Sprintf("VirtualDeviceContext{Name: %s, Device: %s, Status: %s}", "test", &Device{Name: "testdevice"}, &VDCStatusActive), + want: fmt.Sprintf( + "VirtualDeviceContext{Name: %s, Device: %s, Status: %s}", + "test", + &Device{Name: "testdevice"}, + &VDCStatusActive, + ), }, } for _, tt := range tests { diff --git a/internal/netbox/objects/extras.go b/internal/netbox/objects/extras.go index 7f6fd4a3..ffdd01e0 100644 --- a/internal/netbox/objects/extras.go +++ b/internal/netbox/objects/extras.go @@ -42,8 +42,10 @@ var ( CustomFieldTypeLongText = CustomFieldType{Choice{Value: "longtext", Label: "Text (long)"}} CustomFieldTypeInteger = CustomFieldType{Choice{Value: "integer", Label: "Integer"}} CustomFieldTypeDecimal = CustomFieldType{Choice{Value: "decimal", Label: "Decimal"}} - CustomFieldTypeBoolean = CustomFieldType{Choice{Value: "boolean", Label: "Boolean (true/false)"}} - CustomFieldTypeDate = CustomFieldType{Choice{Value: "date", Label: "Date"}} + CustomFieldTypeBoolean = CustomFieldType{ + Choice{Value: "boolean", Label: "Boolean (true/false)"}, + } + CustomFieldTypeDate = CustomFieldType{Choice{Value: "date", Label: "Date"}} ) type FilterLogic struct { @@ -83,9 +85,11 @@ type CustomField struct { ID int `json:"id,omitempty"` // Name of the custom field (e.g. host_cpu_cores). This field is required. Name string `json:"name,omitempty"` - // Label represents name of the field as displayed to users (e.g. Physical CPU cores). If not provided, the name will be used instead. + // Label represents name of the field as displayed to users (e.g. Physical CPU cores). + // If not provided, the name will be used instead. Label string `json:"label,omitempty"` - // Type is the type of the custom field. Valid choices are: text, integer, boolean, date, url, select, multiselect. This field is required. + // Type is the type of the custom field. + // Valid choices are: text, integer, boolean, date, url, select, multiselect. This field is required. Type CustomFieldType `json:"type,omitempty"` // Type of the related object (for object/multi-object fields only) (e.g. objects.device). This field is required. ObjectTypes []constants.ContentType `json:"object_types,omitempty"` diff --git a/internal/netbox/objects/tenancy.go b/internal/netbox/objects/tenancy.go index 0f640711..da0164eb 100644 --- a/internal/netbox/objects/tenancy.go +++ b/internal/netbox/objects/tenancy.go @@ -163,11 +163,21 @@ type ContactAssignmentPriority struct { } // https://github.com/netbox-community/netbox/blob/487f1ccfde26ef3c1f8a28089826acc0cd6fadb2/netbox/tenancy/choices.py#L10 +// +//nolint:lll var ( - ContactAssignmentPriorityPrimary = ContactAssignmentPriority{Choice{Value: "primary", Label: "Primary"}} - ContactAssignmentPrioritySecondary = ContactAssignmentPriority{Choice{Value: "secondary", Label: "Secondary"}} - ContactAssignmentPriorityTertiary = ContactAssignmentPriority{Choice{Value: "tertiary", Label: "Tertiary"}} - ContactAssignmentPriorityInactive = ContactAssignmentPriority{Choice{Value: "inactive", Label: "Inactive"}} + ContactAssignmentPriorityPrimary = ContactAssignmentPriority{ + Choice{Value: "primary", Label: "Primary"}, + } + ContactAssignmentPrioritySecondary = ContactAssignmentPriority{ + Choice{Value: "secondary", Label: "Secondary"}, + } + ContactAssignmentPriorityTertiary = ContactAssignmentPriority{ + Choice{Value: "tertiary", Label: "Tertiary"}, + } + ContactAssignmentPriorityInactive = ContactAssignmentPriority{ + Choice{Value: "inactive", Label: "Inactive"}, + } ) type ContactAssignment struct { @@ -185,7 +195,13 @@ type ContactAssignment struct { } func (ca ContactAssignment) String() string { - return fmt.Sprintf("ContactAssignment{ObjectType: %s, ObjectID: %d, %v, %v}", ca.ModelType, ca.ObjectID, ca.Contact, ca.Role) + return fmt.Sprintf( + "ContactAssignment{ObjectType: %s, ObjectID: %d, %v, %v}", + ca.ModelType, + ca.ObjectID, + ca.Contact, + ca.Role, + ) } // ContactAssignment implements IDItem interface. diff --git a/internal/netbox/objects/tenancy_test.go b/internal/netbox/objects/tenancy_test.go index 6c21112c..86939037 100644 --- a/internal/netbox/objects/tenancy_test.go +++ b/internal/netbox/objects/tenancy_test.go @@ -98,7 +98,13 @@ func TestContactAssignment_String(t *testing.T) { }, ObjectID: 5, }, - want: fmt.Sprintf("ContactAssignment{ObjectType: %s, ObjectID: %d, %v, %v}", constants.ContentTypeVirtualizationVirtualMachine, 5, Contact{Name: "Test contact"}, ContactRole{Name: "Test contact role"}), + want: fmt.Sprintf( + "ContactAssignment{ObjectType: %s, ObjectID: %d, %v, %v}", + constants.ContentTypeVirtualizationVirtualMachine, + 5, + Contact{Name: "Test contact"}, + ContactRole{Name: "Test contact role"}, + ), }, } for _, tt := range tests { diff --git a/internal/netbox/objects/wireless.go b/internal/netbox/objects/wireless.go index cf8b852a..b752b644 100644 --- a/internal/netbox/objects/wireless.go +++ b/internal/netbox/objects/wireless.go @@ -36,7 +36,6 @@ func (wlg *WirelessLANGroup) GetNetboxObject() *NetboxObject { return &wlg.NetboxObject } -// https://github.com/netbox-community/netbox/blob/2e74952ac6cc68348284dee8b9517fe0a36179a2/netbox/wireless/choices.py#L16 type WirelessLANStatus struct { Choice } @@ -45,7 +44,9 @@ var ( WirelessLanStatusActive = WirelessLANStatus{Choice{Value: "active", Label: "Active"}} WirelessLanStatusReserved = WirelessLANStatus{Choice{Value: "reserved", Label: "Reserved"}} WirelessLanStatusDisabled = WirelessLANStatus{Choice{Value: "disabled", Label: "Disabled"}} - WirelessLanStatusDeprecated = WirelessLANStatus{Choice{Value: "deprecated", Label: "Deprecated"}} + WirelessLanStatusDeprecated = WirelessLANStatus{ + Choice{Value: "deprecated", Label: "Deprecated"}, + } ) type WirelessLANAuthType struct { @@ -53,10 +54,14 @@ type WirelessLANAuthType struct { } var ( - WirelessLanAuthTypeOpen = WirelessLANAuthType{Choice{Value: "open", Label: "Open"}} - WirelessLanAuthTypeWep = WirelessLANAuthType{Choice{Value: "wep", Label: "WEP"}} - WirelessLanAuthTypeWpaPersonal = WirelessLANAuthType{Choice{Value: "wpa-personal", Label: "WPA Personal (PSK)"}} - WirelessLanAuthTypeWpaEnterprise = WirelessLANAuthType{Choice{Value: "wpa-enterprise", Label: "WPA Enterprise"}} + WirelessLanAuthTypeOpen = WirelessLANAuthType{Choice{Value: "open", Label: "Open"}} + WirelessLanAuthTypeWep = WirelessLANAuthType{Choice{Value: "wep", Label: "WEP"}} + WirelessLanAuthTypeWpaPersonal = WirelessLANAuthType{ + Choice{Value: "wpa-personal", Label: "WPA Personal (PSK)"}, + } + WirelessLanAuthTypeWpaEnterprise = WirelessLANAuthType{ + Choice{Value: "wpa-enterprise", Label: "WPA Enterprise"}, + } ) type WirelessLANAuthCipher struct { diff --git a/internal/netbox/service/client.go b/internal/netbox/service/client.go index 243b8444..bb98be88 100644 --- a/internal/netbox/service/client.go +++ b/internal/netbox/service/client.go @@ -29,7 +29,14 @@ type APIResponse struct { } // Constructor function for creating a new netBoxAPI instance. -func NewNetboxClient(logger *logger.Logger, baseURL string, apiToken string, validateCert bool, timeout int, caCert string) (*NetboxClient, error) { +func NewNetboxClient( + logger *logger.Logger, + baseURL string, + apiToken string, + validateCert bool, + timeout int, + caCert string, +) (*NetboxClient, error) { httpClient, err := utils.NewHTTPClient(validateCert, caCert) if err != nil { return nil, fmt.Errorf("create new HTTP client: %s", err) @@ -43,8 +50,15 @@ func NewNetboxClient(logger *logger.Logger, baseURL string, apiToken string, val }, nil } -func (api *NetboxClient) doRequest(method string, path string, body io.Reader) (*APIResponse, error) { - ctx, cancelCtx := context.WithTimeout(context.Background(), time.Second*time.Duration(api.Timeout)) +func (api *NetboxClient) doRequest( + method string, + path string, + body io.Reader, +) (*APIResponse, error) { + ctx, cancelCtx := context.WithTimeout( + context.Background(), + time.Second*time.Duration(api.Timeout), + ) defer cancelCtx() req, err := http.NewRequestWithContext(ctx, method, api.BaseURL+path, body) diff --git a/internal/netbox/service/client_test.go b/internal/netbox/service/client_test.go index 0bfd146b..7bb06fb8 100644 --- a/internal/netbox/service/client_test.go +++ b/internal/netbox/service/client_test.go @@ -37,11 +37,15 @@ func TestNewNetBoxAPI(t *testing.T) { caCert: "", }, want: &NetboxClient{ - Logger: &logger.Logger{Logger: log.Default()}, - BaseURL: "netbox.example.com", - APIToken: "apitoken", - HTTPClient: &http.Client{Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}}, - Timeout: constants.DefaultAPITimeout, + Logger: &logger.Logger{Logger: log.Default()}, + BaseURL: "netbox.example.com", + APIToken: "apitoken", + HTTPClient: &http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + }, + }, + Timeout: constants.DefaultAPITimeout, }, }, { @@ -67,13 +71,21 @@ func TestNewNetBoxAPI(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := NewNetboxClient(tt.args.logger, tt.args.baseURL, tt.args.apiToken, tt.args.validateCert, tt.args.timeout, tt.args.caCert) + got, err := NewNetboxClient( + tt.args.logger, + tt.args.baseURL, + tt.args.apiToken, + tt.args.validateCert, + tt.args.timeout, + tt.args.caCert, + ) if err != nil { t.Errorf("NewNetboxClient() error = %v", err) return } // Check non-pointer fields for simplicity or use an interface to mock clients - if got.BaseURL != tt.want.BaseURL || got.APIToken != tt.want.APIToken || got.Timeout != tt.want.Timeout { + if got.BaseURL != tt.want.BaseURL || got.APIToken != tt.want.APIToken || + got.Timeout != tt.want.Timeout { t.Errorf("NewNetboxClient() got = %v, want %v", got, tt.want) } // Optionally check if HTTPClient is not nil to confirm it's initialized diff --git a/internal/netbox/service/rest_test.go b/internal/netbox/service/rest_test.go index b9686e3f..006800e4 100644 --- a/internal/netbox/service/rest_test.go +++ b/internal/netbox/service/rest_test.go @@ -24,7 +24,11 @@ func TestGetAll(t *testing.T) { { name: "TestGetAll_Success", args: args{ - ctx: context.WithValue(context.Background(), constants.CtxSourceKey, "test"), + ctx: context.WithValue( + context.Background(), + constants.CtxSourceKey, + "test", + ), api: MockNetboxClient, extraParams: "", }, @@ -99,7 +103,12 @@ func TestPatch(t *testing.T) { defer mockServer.Close() MockNetboxClient.BaseURL = mockServer.URL t.Run(tt.name, func(t *testing.T) { - response, err := Patch[objects.Tag](tt.args.ctx, tt.args.api, tt.args.objectID, tt.args.body) + response, err := Patch[objects.Tag]( + tt.args.ctx, + tt.args.api, + tt.args.objectID, + tt.args.body, + ) if (err != nil) != tt.wantErr { t.Errorf("GetAll() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/internal/netbox/service/test_objects.go b/internal/netbox/service/test_objects.go index 277f4e87..23e95e5a 100644 --- a/internal/netbox/service/test_objects.go +++ b/internal/netbox/service/test_objects.go @@ -201,81 +201,87 @@ func CreateMockServer() *httptest.Server { } }) - handler.HandleFunc(string(constants.TenantsAPIPath), func(w http.ResponseWriter, r *http.Request) { - switch r.Method { - case http.MethodPatch: - tenantStr, err := json.Marshal(MockTenantPatchResponse) - if err != nil { - log.Printf("Error marshaling tenant patch response: %v", err) - } - _, err = w.Write(tenantStr) - if err != nil { - log.Printf("Error writing response: %v", err) - } - case http.MethodGet: - w.WriteHeader(http.StatusOK) - tenantsResponseStr, err := json.Marshal(MockTenantsGetResponse) - if err != nil { - log.Printf("Error marshaling tenants response: %v", err) + handler.HandleFunc( + string(constants.TenantsAPIPath), + func(w http.ResponseWriter, r *http.Request) { + switch r.Method { + case http.MethodPatch: + tenantStr, err := json.Marshal(MockTenantPatchResponse) + if err != nil { + log.Printf("Error marshaling tenant patch response: %v", err) + } + _, err = w.Write(tenantStr) + if err != nil { + log.Printf("Error writing response: %v", err) + } + case http.MethodGet: + w.WriteHeader(http.StatusOK) + tenantsResponseStr, err := json.Marshal(MockTenantsGetResponse) + if err != nil { + log.Printf("Error marshaling tenants response: %v", err) + } + _, err = w.Write(tenantsResponseStr) + if err != nil { + log.Printf("Error writing response") + } + case http.MethodPost: + w.WriteHeader(http.StatusCreated) + tenantStr, err := json.Marshal(MockTenantCreateResponse) + if err != nil { + log.Printf("Error marshaling tenant create response: %v", err) + } + _, err = w.Write(tenantStr) + if err != nil { + log.Printf("Error writing response") + } + case http.MethodDelete: + w.WriteHeader(http.StatusNoContent) + default: + log.Printf("Wrong http method: %v", r.Method) } - _, err = w.Write(tenantsResponseStr) - if err != nil { - log.Printf("Error writing response") - } - case http.MethodPost: - w.WriteHeader(http.StatusCreated) - tenantStr, err := json.Marshal(MockTenantCreateResponse) - if err != nil { - log.Printf("Error marshaling tenant create response: %v", err) - } - _, err = w.Write(tenantStr) - if err != nil { - log.Printf("Error writing response") - } - case http.MethodDelete: - w.WriteHeader(http.StatusNoContent) - default: - log.Printf("Wrong http method: %v", r.Method) - } - }) + }, + ) - handler.HandleFunc(string(constants.SitesAPIPath), func(w http.ResponseWriter, r *http.Request) { - switch r.Method { - case http.MethodPatch: - siteStr, err := json.Marshal(MockSitePatchResponse) - if err != nil { - log.Printf("Error marshaling site patch response: %v", err) - } - _, err = w.Write(siteStr) - if err != nil { - log.Printf("Error writing response: %v", err) - } - case http.MethodGet: - w.WriteHeader(http.StatusOK) - siteResponseStr, err := json.Marshal(MockSitesGetResponse) - if err != nil { - log.Printf("Error marshaling sites response: %v", err) + handler.HandleFunc( + string(constants.SitesAPIPath), + func(w http.ResponseWriter, r *http.Request) { + switch r.Method { + case http.MethodPatch: + siteStr, err := json.Marshal(MockSitePatchResponse) + if err != nil { + log.Printf("Error marshaling site patch response: %v", err) + } + _, err = w.Write(siteStr) + if err != nil { + log.Printf("Error writing response: %v", err) + } + case http.MethodGet: + w.WriteHeader(http.StatusOK) + siteResponseStr, err := json.Marshal(MockSitesGetResponse) + if err != nil { + log.Printf("Error marshaling sites response: %v", err) + } + _, err = w.Write(siteResponseStr) + if err != nil { + log.Printf("Error writing response") + } + case http.MethodPost: + w.WriteHeader(http.StatusCreated) + siteStr, err := json.Marshal(MockSiteCreateResponse) + if err != nil { + log.Printf("Error marshaling site create response: %v", err) + } + _, err = w.Write(siteStr) + if err != nil { + log.Printf("Error writing response") + } + case http.MethodDelete: + w.WriteHeader(http.StatusNoContent) + default: + log.Printf("Wrong http method: %v", r.Method) } - _, err = w.Write(siteResponseStr) - if err != nil { - log.Printf("Error writing response") - } - case http.MethodPost: - w.WriteHeader(http.StatusCreated) - siteStr, err := json.Marshal(MockSiteCreateResponse) - if err != nil { - log.Printf("Error marshaling site create response: %v", err) - } - _, err = w.Write(siteStr) - if err != nil { - log.Printf("Error writing response") - } - case http.MethodDelete: - w.WriteHeader(http.StatusNoContent) - default: - log.Printf("Wrong http method: %v", r.Method) - } - }) + }, + ) handler.HandleFunc("/api/read-error", func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusInternalServerError) // or any relevant status diff --git a/internal/parser/parser.go b/internal/parser/parser.go index 5392ab3b..70e62b28 100644 --- a/internal/parser/parser.go +++ b/internal/parser/parser.go @@ -94,7 +94,21 @@ type NetboxConfig struct { } func (n NetboxConfig) String() string { - return fmt.Sprintf("NetboxConfig{ApiToken: %s, Hostname: %s, Port: %d, HTTPScheme: %s, ValidateCert: %t, Timeout: %d, Tag: %s, TagColor: %s, RemoveOrphans: %t, RemoveOrphansAfterDays: %d}", n.APIToken, n.Hostname, n.Port, n.HTTPScheme, n.ValidateCert, n.Timeout, n.Tag, n.TagColor, n.RemoveOrphans, n.RemoveOrphansAfterDays) + return fmt.Sprintf( + "NetboxConfig{ApiToken: %s, Hostname: %s, Port: %d, "+ + "HTTPScheme: %s, ValidateCert: %t, Timeout: %d, "+ + "Tag: %s, TagColor: %s, RemoveOrphans: %t, RemoveOrphansAfterDays: %d}", + n.APIToken, + n.Hostname, + n.Port, + n.HTTPScheme, + n.ValidateCert, + n.Timeout, + n.Tag, + n.TagColor, + n.RemoveOrphans, + n.RemoveOrphansAfterDays, + ) } // Configuration that can be used for each of the sources. @@ -203,7 +217,9 @@ func (sc *SourceConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { if err != nil { return fmt.Errorf("%s.datacenterClusterGroupRelations: %s", rawMarshal.Name, err) } - sc.DatacenterClusterGroupRelations = utils.ConvertStringsToRegexPairs(rawMarshal.DatacenterClusterGroupRelations) + sc.DatacenterClusterGroupRelations = utils.ConvertStringsToRegexPairs( + rawMarshal.DatacenterClusterGroupRelations, + ) } if len(rawMarshal.HostSiteRelations) > 0 { err := utils.ValidateRegexRelations(rawMarshal.HostSiteRelations) @@ -231,7 +247,9 @@ func (sc *SourceConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { if err != nil { return fmt.Errorf("%s.clusterTenantRelations: %s", rawMarshal.Name, err) } - sc.ClusterTenantRelations = utils.ConvertStringsToRegexPairs(rawMarshal.ClusterTenantRelations) + sc.ClusterTenantRelations = utils.ConvertStringsToRegexPairs( + rawMarshal.ClusterTenantRelations, + ) } if len(rawMarshal.HostTenantRelations) > 0 { err := utils.ValidateRegexRelations(rawMarshal.HostTenantRelations) @@ -280,7 +298,9 @@ func (sc *SourceConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { if err != nil { return fmt.Errorf("%s.vlanGroupSiteRelations: %v", rawMarshal.Name, err) } - sc.VlanGroupSiteRelations = utils.ConvertStringsToRegexPairs(rawMarshal.VlanGroupSiteRelations) + sc.VlanGroupSiteRelations = utils.ConvertStringsToRegexPairs( + rawMarshal.VlanGroupSiteRelations, + ) } if len(rawMarshal.WlanTenantRelations) > 0 { err := utils.ValidateRegexRelations((rawMarshal.WlanTenantRelations)) @@ -300,7 +320,34 @@ func (sc *SourceConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { } func (sc SourceConfig) String() string { - return fmt.Sprintf("SourceConfig{Name: %s, Type: %s, HTTPScheme: %s, Hostname: %s, Port: %d, Username: %s, Password: %s, PermittedSubnets: %v, ValidateCert: %t, Tag: %s, TagColor: %s, DatacenterClusterGroupRelations: %s, HostSiteRelations: %v, ClusterSiteRelations: %v, clusterTenantRelations: %v, HostTenantRelations: %v, VmTenantRelations %v, VlanGroupRelations: %v, VlanTenantRelations: %v, WlanTenantRelations: %v}", sc.Name, sc.Type, sc.HTTPScheme, sc.Hostname, sc.Port, sc.Username, sc.Password, sc.IgnoredSubnets, sc.ValidateCert, sc.Tag, sc.TagColor, sc.DatacenterClusterGroupRelations, sc.HostSiteRelations, sc.ClusterSiteRelations, sc.ClusterTenantRelations, sc.HostTenantRelations, sc.VMTenantRelations, sc.VlanGroupRelations, sc.VlanTenantRelations, sc.WlanTenantRelations) + return fmt.Sprintf( + "SourceConfig{Name: %s, Type: %s, HTTPScheme: %s, Hostname: %s, Port: %d, "+ + "Username: %s, Password: %s, PermittedSubnets: %v, ValidateCert: %t, "+ + "Tag: %s, TagColor: %s, DatacenterClusterGroupRelations: %s, "+ + "HostSiteRelations: %v, ClusterSiteRelations: %v, ClusterTenantRelations: %v, "+ + "HostTenantRelations: %v, VmTenantRelations: %v, VlanGroupRelations: %v, "+ + "VlanTenantRelations: %v, WlanTenantRelations: %v}", + sc.Name, + sc.Type, + sc.HTTPScheme, + sc.Hostname, + sc.Port, + sc.Username, + sc.Password, + sc.IgnoredSubnets, + sc.ValidateCert, + sc.Tag, + sc.TagColor, + sc.DatacenterClusterGroupRelations, + sc.HostSiteRelations, + sc.ClusterSiteRelations, + sc.ClusterTenantRelations, + sc.HostTenantRelations, + sc.VMTenantRelations, + sc.VlanGroupRelations, + sc.VlanTenantRelations, + sc.WlanTenantRelations, + ) } // Validates the user's config for limits and required fields. @@ -337,13 +384,19 @@ func validateNetboxConfig(config *Config) error { return errors.New("netbox.apiToken: cannot be empty") } if config.Netbox.HTTPScheme != HTTP && config.Netbox.HTTPScheme != HTTPS { - return errors.New("netbox.httpScheme: must be either http or https. Is " + string(config.Netbox.HTTPScheme)) + return errors.New( + "netbox.httpScheme: must be either http or https. Is " + string( + config.Netbox.HTTPScheme, + ), + ) } if config.Netbox.Hostname == "" { return errors.New("netbox.hostname: cannot be empty") } if config.Netbox.Port < 0 || config.Netbox.Port > 65535 { - return errors.New("netbox.port: must be between 0 and 65535. Is " + fmt.Sprintf("%d", config.Netbox.Port)) + return errors.New( + "netbox.port: must be between 0 and 65535. Is " + fmt.Sprintf("%d", config.Netbox.Port), + ) } if config.Netbox.Timeout < 0 { return errors.New("netbox.timeout: cannot be negative") @@ -376,7 +429,9 @@ func validateNetboxConfig(config *Config) error { } if len(config.Netbox.SourcePriority) > 0 { if len(config.Netbox.SourcePriority) != len(config.Sources) { - return fmt.Errorf("netbox.sourcePriority: len(config.Netbox.SourcePriority) != len(config.Sources)") + return fmt.Errorf( + "netbox.sourcePriority: len(config.Netbox.SourcePriority) != len(config.Sources)", + ) } for _, sourceName := range config.Netbox.SourcePriority { contains := false @@ -387,7 +442,10 @@ func validateNetboxConfig(config *Config) error { } } if !contains { - return fmt.Errorf("netbox.sourcePriority: %s doesn't exist in the sources array", sourceName) + return fmt.Errorf( + "netbox.sourcePriority: %s doesn't exist in the sources array", + sourceName, + ) } } } @@ -424,7 +482,11 @@ func validateSourceConfig(config *Config) error { if externalSource.HTTPScheme == "" { externalSource.HTTPScheme = "https" } else if externalSource.HTTPScheme != HTTP && externalSource.HTTPScheme != HTTPS { - return fmt.Errorf("%s.httpScheme: must be either http or https. Is %s", externalSourceStr, string(externalSource.HTTPScheme)) + return fmt.Errorf( + "%s.httpScheme: must be either http or https. Is %s", + externalSourceStr, + string(externalSource.HTTPScheme), + ) } if externalSource.Hostname == "" { return fmt.Errorf("%s.hostname: cannot be empty", externalSourceStr) @@ -435,7 +497,11 @@ func validateSourceConfig(config *Config) error { return fmt.Errorf("%s.port: must be between 0 and 65535. Is %d", externalSourceStr, externalSource.Port) } if externalSource.APIToken == "" && externalSource.Type == constants.Fortigate { - return fmt.Errorf("%s.apiToken is required for %s", externalSourceStr, constants.Fortigate) + return fmt.Errorf( + "%s.apiToken is required for %s", + externalSourceStr, + constants.Fortigate, + ) } if externalSource.Username == "" && externalSource.Type != constants.Fortigate { return fmt.Errorf("%s.username: cannot be empty", externalSourceStr) @@ -457,14 +523,22 @@ func validateSourceConfig(config *Config) error { if len(externalSource.IgnoredSubnets) > 0 { for _, ignoredSubnet := range externalSource.IgnoredSubnets { if !utils.VerifySubnet(ignoredSubnet) { - return fmt.Errorf("%s.ignoredSubnets: wrong format: %s", externalSourceStr, ignoredSubnet) + return fmt.Errorf( + "%s.ignoredSubnets: wrong format: %s", + externalSourceStr, + ignoredSubnet, + ) } } } if len(externalSource.PermittedSubnets) > 0 { for _, permittedSubnet := range externalSource.PermittedSubnets { if !utils.VerifySubnet(permittedSubnet) { - return fmt.Errorf("%s.permittedSubnets: wrong format: %s", externalSourceStr, permittedSubnet) + return fmt.Errorf( + "%s.permittedSubnets: wrong format: %s", + externalSourceStr, + permittedSubnet, + ) } } } diff --git a/internal/parser/parser_test.go b/internal/parser/parser_test.go index 009d18a7..d29fb4fe 100644 --- a/internal/parser/parser_test.go +++ b/internal/parser/parser_test.go @@ -177,54 +177,173 @@ type configTestCase struct { func TestParseConfigInvalidConfigs(t *testing.T) { testCases := []configTestCase{ {filename: "invalid_config1.yaml", expectedErr: "netbox.hostname: cannot be empty"}, - {filename: "invalid_config2.yaml", expectedErr: "netbox.port: must be between 0 and 65535. Is 333333"}, + { + filename: "invalid_config2.yaml", + expectedErr: "netbox.port: must be between 0 and 65535. Is 333333", + }, {filename: "invalid_config3.yaml", expectedErr: "testolvm.type is not valid"}, - {filename: "invalid_config4.yaml", expectedErr: "netbox.httpScheme: must be either http or https. Is httpd"}, - {filename: "invalid_config5.yaml", expectedErr: "prodovirt.httpScheme: must be either http or https. Is httpd"}, - {filename: "invalid_config6.yaml", expectedErr: "testolvm.hostTenantRelations: invalid regex relation: This should not work. Should be of format: regex = value"}, - {filename: "invalid_config7.yaml", expectedErr: "prodolvm.hostTenantRelations: invalid regex: [a-z++, in relation: [a-z++ = Should not work"}, - {filename: "invalid_config8.yaml", expectedErr: "testolvm.port: must be between 0 and 65535. Is 1111111"}, + { + filename: "invalid_config4.yaml", + expectedErr: "netbox.httpScheme: must be either http or https. Is httpd", + }, + { + filename: "invalid_config5.yaml", + expectedErr: "prodovirt.httpScheme: must be either http or https. Is httpd", + }, + { + filename: "invalid_config6.yaml", + expectedErr: "testolvm.hostTenantRelations: invalid regex relation: This should not work. " + + "Should be of format: regex = value", + }, + { + filename: "invalid_config7.yaml", + expectedErr: "prodolvm.hostTenantRelations: invalid regex: [a-z++, in relation: [a-z++ = Should not work", + }, + { + filename: "invalid_config8.yaml", + expectedErr: "testolvm.port: must be between 0 and 65535. Is 1111111", + }, {filename: "invalid_config9.yaml", expectedErr: "logger.level: must be between 0 and 3"}, {filename: "invalid_config10.yaml", expectedErr: "netbox.timeout: cannot be negative"}, {filename: "invalid_config11.yaml", expectedErr: "netbox.apiToken: cannot be empty"}, - {filename: "invalid_config12.yaml", expectedErr: "netbox.tagColor: must be a string of 6 hexadecimal characters"}, - {filename: "invalid_config13.yaml", expectedErr: "netbox.tagColor: must be a string of 6 lowercase hexadecimal characters"}, - {filename: "invalid_config14.yaml", expectedErr: "netbox.sourcePriority: len(config.Netbox.SourcePriority) != len(config.Sources)"}, - {filename: "invalid_config15.yaml", expectedErr: "netbox.sourcePriority: wrongone doesn't exist in the sources array"}, + { + filename: "invalid_config12.yaml", + expectedErr: "netbox.tagColor: must be a string of 6 hexadecimal characters", + }, + { + filename: "invalid_config13.yaml", + expectedErr: "netbox.tagColor: must be a string of 6 lowercase hexadecimal characters", + }, + { + filename: "invalid_config14.yaml", + expectedErr: "netbox.sourcePriority: len(config.Netbox.SourcePriority) != len(config.Sources)", + }, + { + filename: "invalid_config15.yaml", + expectedErr: "netbox.sourcePriority: wrongone doesn't exist in the sources array", + }, {filename: "invalid_config16.yaml", expectedErr: "source name: cannot be empty"}, {filename: "invalid_config17.yaml", expectedErr: "wrong.hostname: cannot be empty"}, {filename: "invalid_config18.yaml", expectedErr: "wrong.username: cannot be empty"}, {filename: "invalid_config19.yaml", expectedErr: "wrong.password: cannot be empty"}, - {filename: "invalid_config20.yaml", expectedErr: "wrong.ignoredSubnets: wrong format: 172.16.0.1"}, - {filename: "invalid_config21.yaml", expectedErr: "wrong.interfaceFilter: wrong format: error parsing regexp: missing closing ): `($a[ba]`"}, - {filename: "invalid_config22.yaml", expectedErr: "wrong.hostSiteRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong"}, - {filename: "invalid_config23.yaml", expectedErr: "wrong.clusterSiteRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong"}, - {filename: "invalid_config24.yaml", expectedErr: "wrong.clusterTenantRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong"}, - {filename: "invalid_config25.yaml", expectedErr: "wrong.hostTenantRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong"}, - {filename: "invalid_config26.yaml", expectedErr: "wrong.vmTenantRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong"}, - {filename: "invalid_config27.yaml", expectedErr: "wrong.vlanGroupRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong"}, - {filename: "invalid_config28.yaml", expectedErr: "wrong.vlanTenantRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong"}, - {filename: "invalid_config29.yaml", expectedErr: "logger.level: 2dasf is not a valid level"}, - {filename: "invalid_config30.yaml", expectedErr: "fortigate.apiToken is required for fortigate"}, - {filename: "invalid_config31.yaml", expectedErr: "netbox.removeOrphansAfterDays has no effect when netbox.removeOrphans is set to true"}, - {filename: "invalid_config32.yaml", expectedErr: "wrong.datacenterClusterGroupRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong"}, - {filename: "invalid_config33.yaml", expectedErr: "wrong.caFile: open \\//: no such file or directory"}, - {filename: "invalid_config34.yaml", expectedErr: "netbox.caFile: open wrong path: no such file or directory"}, - {filename: "invalid_config35.yaml", expectedErr: "netbox.RemoveOrphansAfterDays: must be positive integer"}, - {filename: "invalid_config36.yaml", expectedErr: "wrong.wlanTenantRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong"}, + { + filename: "invalid_config20.yaml", + expectedErr: "wrong.ignoredSubnets: wrong format: 172.16.0.1", + }, + { + filename: "invalid_config21.yaml", + expectedErr: "wrong.interfaceFilter: wrong format: error parsing regexp: missing closing ): `($a[ba]`", + }, + { + filename: "invalid_config22.yaml", + expectedErr: "wrong.hostSiteRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong", + }, + { + filename: "invalid_config23.yaml", + expectedErr: "wrong.clusterSiteRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong", + }, + { + filename: "invalid_config24.yaml", + expectedErr: "wrong.clusterTenantRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong", + }, + { + filename: "invalid_config25.yaml", + expectedErr: "wrong.hostTenantRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong", + }, + { + filename: "invalid_config26.yaml", + expectedErr: "wrong.vmTenantRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong", + }, + { + filename: "invalid_config27.yaml", + expectedErr: "wrong.vlanGroupRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong", + }, + { + filename: "invalid_config28.yaml", + expectedErr: "wrong.vlanTenantRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong", + }, + { + filename: "invalid_config29.yaml", + expectedErr: "logger.level: 2dasf is not a valid level", + }, + { + filename: "invalid_config30.yaml", + expectedErr: "fortigate.apiToken is required for fortigate", + }, + { + filename: "invalid_config31.yaml", + expectedErr: "netbox.removeOrphansAfterDays has no effect when netbox.removeOrphans is set to true", + }, + { + filename: "invalid_config32.yaml", + expectedErr: "wrong.datacenterClusterGroupRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong", + }, + { + filename: "invalid_config33.yaml", + expectedErr: "wrong.caFile: open \\//: no such file or directory", + }, + { + filename: "invalid_config34.yaml", + expectedErr: "netbox.caFile: open wrong path: no such file or directory", + }, + { + filename: "invalid_config35.yaml", + expectedErr: "netbox.RemoveOrphansAfterDays: must be positive integer", + }, + { + filename: "invalid_config36.yaml", + expectedErr: "wrong.wlanTenantRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong", + }, {filename: "invalid_config37.yaml", expectedErr: "logger.dest: 7 is not a valid type"}, - {filename: "invalid_config38.yaml", expectedErr: "logger: yaml: unmarshal errors:\n line 1: cannot unmarshal !!str `this sh...` into map[string]interface {}"}, - {filename: "invalid_config39.yaml", expectedErr: "wrong.vmRoleRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong"}, - {filename: "invalid_config40.yaml", expectedErr: "wrong.hostRoleRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong"}, - {filename: "invalid_config41.yaml", expectedErr: "wrong.datacenterClusterGroupRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong"}, - {filename: "invalid_config42.yaml", expectedErr: "wrong.vlanTenantRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong"}, - {filename: "invalid_config43.yaml", expectedErr: "wrong.vlanGroupRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong"}, - {filename: "invalid_config44.yaml", expectedErr: "wrong.customFieldMappings: invalid regex: (wrong(), in relation: (wrong() = wwrong"}, - {filename: "invalid_config45.yaml", expectedErr: "yaml: unmarshal errors:\n line 18: cannot unmarshal !!int `123421334` into parser.realSourceConfig"}, - {filename: "invalid_config46.yaml", expectedErr: "wrong.permittedSubnets: wrong format: 172.16.0.1"}, - {filename: "invalid_config47.yaml", expectedErr: "wrong.vlanSiteRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong"}, - {filename: "invalid_config48.yaml", expectedErr: "wrong.vlanGroupSiteRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong"}, - {filename: "invalid_config1111.yaml", expectedErr: "open ../../testdata/parser/invalid_config1111.yaml: no such file or directory"}, + { + filename: "invalid_config38.yaml", + expectedErr: "logger: yaml: unmarshal errors:\n line 1: cannot unmarshal !!str `this sh...`" + + " into map[string]interface {}", + }, + { + filename: "invalid_config39.yaml", + expectedErr: "wrong.vmRoleRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong", + }, + { + filename: "invalid_config40.yaml", + expectedErr: "wrong.hostRoleRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong", + }, + { + filename: "invalid_config41.yaml", + expectedErr: "wrong.datacenterClusterGroupRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong", + }, + { + filename: "invalid_config42.yaml", + expectedErr: "wrong.vlanTenantRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong", + }, + { + filename: "invalid_config43.yaml", + expectedErr: "wrong.vlanGroupRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong", + }, + { + filename: "invalid_config44.yaml", + expectedErr: "wrong.customFieldMappings: invalid regex: (wrong(), in relation: (wrong() = wwrong", + }, + { + filename: "invalid_config45.yaml", + expectedErr: "yaml: unmarshal errors:\n line 18: cannot unmarshal !!int `123421334` into parser.realSourceConfig", + }, + { + filename: "invalid_config46.yaml", + expectedErr: "wrong.permittedSubnets: wrong format: 172.16.0.1", + }, + { + filename: "invalid_config47.yaml", + expectedErr: "wrong.vlanSiteRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong", + }, + { + filename: "invalid_config48.yaml", + expectedErr: "wrong.vlanGroupSiteRelations: invalid regex: (wrong(), in relation: (wrong() = wwrong", + }, + { + filename: "invalid_config1111.yaml", + expectedErr: "open ../../testdata/parser/invalid_config1111.yaml: no such file or directory", + }, } for _, tc := range testCases { diff --git a/internal/source/common/utils.go b/internal/source/common/utils.go index 22be8413..d0b953ce 100644 --- a/internal/source/common/utils.go +++ b/internal/source/common/utils.go @@ -13,7 +13,12 @@ import ( // Function that matches cluster to tenant using regexRelationsMap. // // In case there is no match or regexRelations is nil, it will return nil. -func MatchClusterToTenant(ctx context.Context, nbi *inventory.NetboxInventory, clusterName string, clusterTenantRelations map[string]string) (*objects.Tenant, error) { +func MatchClusterToTenant( + ctx context.Context, + nbi *inventory.NetboxInventory, + clusterName string, + clusterTenantRelations map[string]string, +) (*objects.Tenant, error) { if clusterTenantRelations == nil { return nil, nil } @@ -41,7 +46,12 @@ func MatchClusterToTenant(ctx context.Context, nbi *inventory.NetboxInventory, c // Function that matches cluster to tenant using regexRelationsMap. // // In case there is no match or regexRelations is nil, it will return nil. -func MatchClusterToSite(ctx context.Context, nbi *inventory.NetboxInventory, clusterName string, clusterSiteRelations map[string]string) (*objects.Site, error) { +func MatchClusterToSite( + ctx context.Context, + nbi *inventory.NetboxInventory, + clusterName string, + clusterSiteRelations map[string]string, +) (*objects.Site, error) { if clusterSiteRelations == nil { return nil, nil } @@ -69,7 +79,14 @@ func MatchClusterToSite(ctx context.Context, nbi *inventory.NetboxInventory, clu // Function that matches vlanName to vlanGroupName using regexRelationsMap. // // In case there is no match or regexRelations is nil, it will return default VlanGroup. -func MatchVlanToGroup(ctx context.Context, nbi *inventory.NetboxInventory, vlanName string, vlanSite *objects.Site, vlanGroupRelations map[string]string, vlanGroupSiteRelations map[string]string) (*objects.VlanGroup, error) { +func MatchVlanToGroup( + ctx context.Context, + nbi *inventory.NetboxInventory, + vlanName string, + vlanSite *objects.Site, + vlanGroupRelations map[string]string, + vlanGroupSiteRelations map[string]string, +) (*objects.VlanGroup, error) { if vlanGroupRelations == nil { vlanGroup, _ := nbi.CreateDefaultVlanGroupForVlan(ctx, vlanSite) return vlanGroup, nil @@ -117,7 +134,12 @@ func MatchVlanToGroup(ctx context.Context, nbi *inventory.NetboxInventory, vlanN // Function that matches vlanName to tenant using vlanTenantRelations regex relations map. // // In case there is no match or vlanTenantRelations is nil, it will return nil. -func MatchVlanToTenant(ctx context.Context, nbi *inventory.NetboxInventory, vlanName string, vlanTenantRelations map[string]string) (*objects.Tenant, error) { +func MatchVlanToTenant( + ctx context.Context, + nbi *inventory.NetboxInventory, + vlanName string, + vlanTenantRelations map[string]string, +) (*objects.Tenant, error) { if vlanTenantRelations == nil { return nil, nil } @@ -146,7 +168,12 @@ func MatchVlanToTenant(ctx context.Context, nbi *inventory.NetboxInventory, vlan // MathcVlanToSite matches vlanName to Site using vlanSiteRelations. // // In case there is no match or vlanSiteRelations is nil, it returns nil. -func MatchVlanToSite(ctx context.Context, nbi *inventory.NetboxInventory, vlanName string, vlanSiteRelations map[string]string) (*objects.Site, error) { +func MatchVlanToSite( + ctx context.Context, + nbi *inventory.NetboxInventory, + vlanName string, + vlanSiteRelations map[string]string, +) (*objects.Site, error) { if vlanSiteRelations == nil { return nil, nil } @@ -174,7 +201,12 @@ func MatchVlanToSite(ctx context.Context, nbi *inventory.NetboxInventory, vlanNa // Function that matches Host from hostName to Site using hostSiteRelations. // // In case that there is not match or hostSiteRelations is nil, it will return default site. -func MatchHostToSite(ctx context.Context, nbi *inventory.NetboxInventory, hostName string, hostSiteRelations map[string]string) (*objects.Site, error) { +func MatchHostToSite( + ctx context.Context, + nbi *inventory.NetboxInventory, + hostName string, + hostSiteRelations map[string]string, +) (*objects.Site, error) { if hostSiteRelations == nil { return nil, nil } @@ -203,7 +235,12 @@ func MatchHostToSite(ctx context.Context, nbi *inventory.NetboxInventory, hostNa // Function that matches Host from hostName to Tenant using hostTenantRelations. // // In case that there is not match or hostTenantRelations is nil, it will return nil. -func MatchHostToTenant(ctx context.Context, nbi *inventory.NetboxInventory, hostName string, hostTenantRelations map[string]string) (*objects.Tenant, error) { +func MatchHostToTenant( + ctx context.Context, + nbi *inventory.NetboxInventory, + hostName string, + hostTenantRelations map[string]string, +) (*objects.Tenant, error) { if hostTenantRelations == nil { return nil, nil } @@ -231,7 +268,12 @@ func MatchHostToTenant(ctx context.Context, nbi *inventory.NetboxInventory, host // MatchHostToRole matches Host from hostName to DeviceRole using hostRoleRelations. // // In case that there is not match or hostRoleRelations is nil, it will return nil. -func MatchHostToRole(ctx context.Context, nbi *inventory.NetboxInventory, hostName string, hostRoleRelations map[string]string) (*objects.DeviceRole, error) { +func MatchHostToRole( + ctx context.Context, + nbi *inventory.NetboxInventory, + hostName string, + hostRoleRelations map[string]string, +) (*objects.DeviceRole, error) { if hostRoleRelations == nil { return nil, nil } @@ -255,7 +297,12 @@ func MatchHostToRole(ctx context.Context, nbi *inventory.NetboxInventory, hostNa // Function that matches Vm from vmName to Tenant using vmTenantRelations. // // In case that there is not match or hostTenantRelations is nil, it will return nil. -func MatchVMToTenant(ctx context.Context, nbi *inventory.NetboxInventory, vmName string, vmTenantRelations map[string]string) (*objects.Tenant, error) { +func MatchVMToTenant( + ctx context.Context, + nbi *inventory.NetboxInventory, + vmName string, + vmTenantRelations map[string]string, +) (*objects.Tenant, error) { if vmTenantRelations == nil { return nil, nil } @@ -283,7 +330,12 @@ func MatchVMToTenant(ctx context.Context, nbi *inventory.NetboxInventory, vmName // MatchVMToRole matches VM from vmName to DeviceRole using vmRoleRelations. // // In case that there is not match or hostRoleRelations is nil, it will return nil. -func MatchVMToRole(ctx context.Context, nbi *inventory.NetboxInventory, vmName string, vmRoleRelations map[string]string) (*objects.DeviceRole, error) { +func MatchVMToRole( + ctx context.Context, + nbi *inventory.NetboxInventory, + vmName string, + vmRoleRelations map[string]string, +) (*objects.DeviceRole, error) { if vmRoleRelations == nil { return nil, nil } @@ -305,7 +357,12 @@ func MatchVMToRole(ctx context.Context, nbi *inventory.NetboxInventory, vmName s } // CreateMACAddressForObjectType creates MAC address for object type. -func CreateMACAddressForObjectType(ctx context.Context, nbi *inventory.NetboxInventory, mac string, targetInterface objects.MACAddressOwner) (*objects.MACAddress, error) { +func CreateMACAddressForObjectType( + ctx context.Context, + nbi *inventory.NetboxInventory, + mac string, + targetInterface objects.MACAddressOwner, +) (*objects.MACAddress, error) { macAddress := &objects.MACAddress{ MAC: mac, AssignedObjectType: targetInterface.GetObjectType(), @@ -313,12 +370,23 @@ func CreateMACAddressForObjectType(ctx context.Context, nbi *inventory.NetboxInv } nbMACAddress, err := nbi.AddMACAddress(ctx, macAddress) if err != nil { - return nil, fmt.Errorf("add mac address %+v: %s", macAddress, err) + return nil, fmt.Errorf( + "add mac address %+v for interface %+v: %s", + macAddress, + targetInterface, + err, + ) } return nbMACAddress, nil } -func SetPrimaryIPAddressForObject(ctx context.Context, nbi *inventory.NetboxInventory, targetObject objects.IPAddressOwner, ipv4 *objects.IPAddress, ipv6 *objects.IPAddress) error { +func SetPrimaryIPAddressForObject( + ctx context.Context, + nbi *inventory.NetboxInventory, + targetObject objects.IPAddressOwner, + ipv4 *objects.IPAddress, + ipv6 *objects.IPAddress, +) error { switch targetObject := targetObject.(type) { case *objects.Device: deviceCopy := *targetObject @@ -340,7 +408,12 @@ func SetPrimaryIPAddressForObject(ctx context.Context, nbi *inventory.NetboxInve return nil } -func SetPrimaryMACForInterface(ctx context.Context, nbi *inventory.NetboxInventory, targetInterface objects.MACAddressOwner, mac *objects.MACAddress) error { +func SetPrimaryMACForInterface( + ctx context.Context, + nbi *inventory.NetboxInventory, + targetInterface objects.MACAddressOwner, + mac *objects.MACAddress, +) error { switch targetInterface := targetInterface.(type) { case *objects.Interface: interfaceCopy := *targetInterface diff --git a/internal/source/dnac/dnac.go b/internal/source/dnac/dnac.go index f896a1fb..4f1ac421 100644 --- a/internal/source/dnac/dnac.go +++ b/internal/source/dnac/dnac.go @@ -9,7 +9,7 @@ import ( "github.com/bl4ko/netbox-ssot/internal/netbox/inventory" "github.com/bl4ko/netbox-ssot/internal/source/common" "github.com/bl4ko/netbox-ssot/internal/utils" - dnac "github.com/cisco-en-programmability/dnacenter-go-sdk/v6/sdk" + dnac "github.com/cisco-en-programmability/dnacenter-go-sdk/v7/sdk" ) //nolint:revive @@ -23,8 +23,10 @@ type DnacSource struct { Vlans map[int]dnac.ResponseDevicesGetDeviceInterfaceVLANsResponse // VlanID -> Vlan WirelessLANInterfaceName2VlanID map[string]int // InterfaceName -> VlanID SSID2WirelessProfileDetails map[string]dnac.ResponseItemWirelessGetWirelessProfileProfileDetailsSSIDDetails - SSID2WlanGroupName map[string]string // SSID -> WirelessLANGroup name - SSID2SecurityDetails map[string]dnac.ResponseItemWirelessGetEnterpriseSSIDSSIDDetails // WirelessLANName -> SSIDDetails + // SSID2WlanGroupName SSID -> WirelessLANGroup name + SSID2WlanGroupName map[string]string + // SSID2SecurityDetails WirelessLANName -> SSIDDetails + SSID2SecurityDetails map[string]dnac.ResponseItemWirelessGetEnterpriseSSIDSSIDDetails // Relations between dnac data. Initialized in init functions. Site2Parent map[string]string // Site ID -> Parent Site ID @@ -33,11 +35,14 @@ type DnacSource struct { DeviceID2InterfaceIDs map[string][]string // DeviceID -> []InterfaceID // Netbox related data for easier access. Initialized in sync functions. - 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 + // DeviceID2isMissingPrimaryIP stores devices without primary IP. See ds.syncMissingDevicePrimaryIPs + DeviceID2isMissingPrimaryIP sync.Map + // VID2nbVlan: VlanID -> nbVlan + VID2nbVlan sync.Map + // SiteID2nbSite: SiteID -> nbSite + SiteID2nbSite sync.Map + DeviceID2nbDevice sync.Map // DeviceID -> nbDevice + InterfaceID2nbInterface sync.Map // InterfaceID -> nbInterface } func (ds *DnacSource) Init() error { diff --git a/internal/source/dnac/dnac_init.go b/internal/source/dnac/dnac_init.go index cc8616a1..d02fdbbf 100644 --- a/internal/source/dnac/dnac_init.go +++ b/internal/source/dnac/dnac_init.go @@ -4,7 +4,7 @@ import ( "fmt" "net/http" - dnac "github.com/cisco-en-programmability/dnacenter-go-sdk/v6/sdk" + dnac "github.com/cisco-en-programmability/dnacenter-go-sdk/v7/sdk" ) // Collects all sites from DNAC API and stores them in the diff --git a/internal/source/dnac/dnac_sync.go b/internal/source/dnac/dnac_sync.go index 6ad2374d..2aedaec2 100644 --- a/internal/source/dnac/dnac_sync.go +++ b/internal/source/dnac/dnac_sync.go @@ -11,7 +11,7 @@ import ( "github.com/bl4ko/netbox-ssot/internal/netbox/objects" "github.com/bl4ko/netbox-ssot/internal/source/common" "github.com/bl4ko/netbox-ssot/internal/utils" - dnac "github.com/cisco-en-programmability/dnacenter-go-sdk/v6/sdk" + dnac "github.com/cisco-en-programmability/dnacenter-go-sdk/v7/sdk" ) // Syncs dnac sites to netbox inventory. @@ -230,7 +230,11 @@ func (ds *DnacSource) syncDevice( return nil } } else { - ds.Logger.Errorf(ds.Ctx, "DeviceSite is not existing for device %s, this should not happen. This device will be skipped", device.ID) + ds.Logger.Errorf( + ds.Ctx, + "DeviceSite is not existing for device %s, this should not happen. This device will be skipped", + device.ID, + ) return nil } diff --git a/internal/source/fmc/client/client.go b/internal/source/fmc/client/client.go index 3c54934a..22f34223 100644 --- a/internal/source/fmc/client/client.go +++ b/internal/source/fmc/client/client.go @@ -24,7 +24,16 @@ type FMCClient struct { // NewFMCClient creates a new FMC client with the given parameters. // It authenticates to the FMC API and stores the access and refresh tokens. -func NewFMCClient(context context.Context, username string, password string, httpScheme string, hostname string, port int, httpClient *http.Client, logger *logger.Logger) (*FMCClient, error) { +func NewFMCClient( + context context.Context, + username string, + password string, + httpScheme string, + hostname string, + port int, + httpClient *http.Client, + logger *logger.Logger, +) (*FMCClient, error) { c := &FMCClient{ HTTPClient: httpClient, BaseURL: fmt.Sprintf("%s://%s:%d/api", httpScheme, hostname, port), diff --git a/internal/source/fortigate/fortigate.go b/internal/source/fortigate/fortigate.go index 13e615ef..ca042552 100644 --- a/internal/source/fortigate/fortigate.go +++ b/internal/source/fortigate/fortigate.go @@ -44,7 +44,11 @@ func NewAPIClient(apiToken string, baseURL string, httpClient *http.Client) *For } } -func (c FortiClient) MakeRequest(ctx context.Context, method, path string, body io.Reader) (*http.Response, error) { +func (c FortiClient) MakeRequest( + ctx context.Context, + method, path string, + body io.Reader, +) (*http.Response, error) { req, err := http.NewRequestWithContext(ctx, method, fmt.Sprintf("%s/%s", c.BaseURL, path), body) if err != nil { return nil, err @@ -59,7 +63,16 @@ func (fs *FortigateSource) Init() error { if err != nil { return fmt.Errorf("create new http client: %s", err) } - c := NewAPIClient(fs.SourceConfig.APIToken, fmt.Sprintf("%s://%s:%d/api/v2", fs.SourceConfig.HTTPScheme, fs.SourceConfig.Hostname, fs.SourceConfig.Port), httpClient) + c := NewAPIClient( + fs.SourceConfig.APIToken, + fmt.Sprintf( + "%s://%s:%d/api/v2", + fs.SourceConfig.HTTPScheme, + fs.SourceConfig.Hostname, + fs.SourceConfig.Port, + ), + httpClient, + ) ctx := context.Background() defer ctx.Done() @@ -73,7 +86,12 @@ func (fs *FortigateSource) Init() error { return fmt.Errorf("fortigate initialization failure: %v", err) } duration := time.Since(startTime) - fs.Logger.Infof(fs.Ctx, "Successfully initialized %s in %f seconds", utils.ExtractFunctionNameWithTrimPrefix(initFunc, "init"), duration.Seconds()) + fs.Logger.Infof( + fs.Ctx, + "Successfully initialized %s in %f seconds", + utils.ExtractFunctionNameWithTrimPrefix(initFunc, "init"), + duration.Seconds(), + ) } return nil } @@ -91,7 +109,12 @@ func (fs *FortigateSource) Sync(nbi *inventory.NetboxInventory) error { return err } duration := time.Since(startTime) - fs.Logger.Infof(fs.Ctx, "Successfully synced %s in %f seconds", utils.ExtractFunctionNameWithTrimPrefix(syncFunc, "sync"), duration.Seconds()) + fs.Logger.Infof( + fs.Ctx, + "Successfully synced %s in %f seconds", + utils.ExtractFunctionNameWithTrimPrefix(syncFunc, "sync"), + duration.Seconds(), + ) } return nil } diff --git a/internal/source/ios-xe/iosxe.go b/internal/source/ios-xe/iosxe.go index ba65122a..6df56071 100644 --- a/internal/source/ios-xe/iosxe.go +++ b/internal/source/ios-xe/iosxe.go @@ -141,7 +141,12 @@ func (is *IOSXESource) Init() error { return fmt.Errorf("iosxe initialization failure: %v", err) } duration := time.Since(startTime) - is.Logger.Infof(is.Ctx, "Successfully initialized %s in %f seconds", utils.ExtractFunctionNameWithTrimPrefix(initFunc, "init"), duration.Seconds()) + is.Logger.Infof( + is.Ctx, + "Successfully initialized %s in %f seconds", + utils.ExtractFunctionNameWithTrimPrefix(initFunc, "init"), + duration.Seconds(), + ) } return nil } @@ -160,7 +165,12 @@ func (is *IOSXESource) Sync(nbi *inventory.NetboxInventory) error { return err } duration := time.Since(startTime) - is.Logger.Infof(is.Ctx, "Successfully synced %s in %f seconds", utils.ExtractFunctionNameWithTrimPrefix(syncFunc, "sync"), duration.Seconds()) + is.Logger.Infof( + is.Ctx, + "Successfully synced %s in %f seconds", + utils.ExtractFunctionNameWithTrimPrefix(syncFunc, "sync"), + duration.Seconds(), + ) } return nil } diff --git a/internal/source/ovirt/ovirt.go b/internal/source/ovirt/ovirt.go index f0777ecd..4a68591e 100644 --- a/internal/source/ovirt/ovirt.go +++ b/internal/source/ovirt/ovirt.go @@ -36,7 +36,13 @@ func (o *OVirtSource) Init() error { // Build the connection o.Logger.Debug(o.Ctx, "Initializing oVirt source ", o.SourceConfig.Name) connBuilder := ovirtsdk4.NewConnectionBuilder(). - URL(fmt.Sprintf("%s://%s:%d/ovirt-engine/api", o.SourceConfig.HTTPScheme, o.SourceConfig.Hostname, o.SourceConfig.Port)). + URL(fmt.Sprintf( + "%s://%s:%d/ovirt-engine/api", + o.SourceConfig.HTTPScheme, + o.SourceConfig.Hostname, + o.SourceConfig.Port, + ), + ). Username(o.SourceConfig.Username). Password(o.SourceConfig.Password). Insecure(!o.SourceConfig.ValidateCert). @@ -68,10 +74,19 @@ func (o *OVirtSource) Init() error { for _, initFunc := range initFunctions { startTime := time.Now() if err := initFunc(conn); err != nil { - return fmt.Errorf("failed to initialize oVirt %s: %v", strings.TrimPrefix(fmt.Sprintf("%T", initFunc), "*source.OVirtSource.Init"), err) + return fmt.Errorf( + "failed to initialize oVirt %s: %v", + strings.TrimPrefix(fmt.Sprintf("%T", initFunc), "*source.OVirtSource.Init"), + err, + ) } duration := time.Since(startTime) - o.Logger.Infof(o.Ctx, "Successfully initialized %s in %f seconds", utils.ExtractFunctionNameWithTrimPrefix(initFunc, "init"), duration.Seconds()) + o.Logger.Infof( + o.Ctx, + "Successfully initialized %s in %f seconds", + utils.ExtractFunctionNameWithTrimPrefix(initFunc, "init"), + duration.Seconds(), + ) } return nil } @@ -92,7 +107,12 @@ func (o *OVirtSource) Sync(nbi *inventory.NetboxInventory) error { return err } duration := time.Since(startTime) - o.Logger.Infof(o.Ctx, "Successfully synced %s in %f seconds", utils.ExtractFunctionNameWithTrimPrefix(syncFunc, "sync"), duration.Seconds()) + o.Logger.Infof( + o.Ctx, + "Successfully synced %s in %f seconds", + utils.ExtractFunctionNameWithTrimPrefix(syncFunc, "sync"), + duration.Seconds(), + ) } return nil } diff --git a/internal/source/ovirt/ovirt_init.go b/internal/source/ovirt/ovirt_init.go index c9b3d198..855794c7 100644 --- a/internal/source/ovirt/ovirt_init.go +++ b/internal/source/ovirt/ovirt_init.go @@ -8,7 +8,11 @@ import ( // Fetches networks from ovirt api and stores them to local object. func (o *OVirtSource) initNetworks(conn *ovirtsdk4.Connection) error { - networksResponse, err := conn.SystemService().NetworksService().List().Follow("vnicprofiles").Send() + networksResponse, err := conn.SystemService(). + NetworksService(). + List(). + Follow("vnicprofiles"). + Send() if err != nil { return fmt.Errorf("init oVirt networks: %v", err) } @@ -115,7 +119,11 @@ func (o *OVirtSource) initHosts(conn *ovirtsdk4.Connection) error { // Function that queries the ovirt api for vms and stores them locally. func (o *OVirtSource) initVms(conn *ovirtsdk4.Connection) error { - vmsResponse, err := conn.SystemService().VmsService().List().Follow("nics,diskattachments,reporteddevices").Send() + vmsResponse, err := conn.SystemService(). + VmsService(). + List(). + Follow("nics,diskattachments,reporteddevices"). + Send() if err != nil { return fmt.Errorf("failed to get oVirt vms: %+v", err) } diff --git a/internal/source/paloalto/paloalto.go b/internal/source/paloalto/paloalto.go index 7449baed..7da81a67 100644 --- a/internal/source/paloalto/paloalto.go +++ b/internal/source/paloalto/paloalto.go @@ -74,7 +74,12 @@ func (pas *PaloAltoSource) Init() error { return fmt.Errorf("paloalto initialization failure: %v", err) } duration := time.Since(startTime) - pas.Logger.Infof(pas.Ctx, "Successfully initialized %s in %f seconds", utils.ExtractFunctionNameWithTrimPrefix(initFunc, "init"), duration.Seconds()) + pas.Logger.Infof( + pas.Ctx, + "Successfully initialized %s in %f seconds", + utils.ExtractFunctionNameWithTrimPrefix(initFunc, "init"), + duration.Seconds(), + ) } return nil } @@ -94,7 +99,12 @@ func (pas *PaloAltoSource) Sync(nbi *inventory.NetboxInventory) error { return err } duration := time.Since(startTime) - pas.Logger.Infof(pas.Ctx, "Successfully synced %s in %f seconds", utils.ExtractFunctionNameWithTrimPrefix(syncFunc, "sync"), duration.Seconds()) + pas.Logger.Infof( + pas.Ctx, + "Successfully synced %s in %f seconds", + utils.ExtractFunctionNameWithTrimPrefix(syncFunc, "sync"), + duration.Seconds(), + ) } return nil } diff --git a/internal/source/paloalto/paloalto_init.go b/internal/source/paloalto/paloalto_init.go index b42de3d7..6c150ee2 100644 --- a/internal/source/paloalto/paloalto_init.go +++ b/internal/source/paloalto/paloalto_init.go @@ -69,7 +69,10 @@ func (pas *PaloAltoSource) initInterfaces(c *pango.Firewall) error { pas.Iface2SubIfaces = make(map[string][]layer3.Entry) for _, ethInterface := range ethInterfaces { pas.Ifaces[ethInterface.Name] = ethInterface - subInterfaces, err := c.Network.Layer3Subinterface.GetAll(layer3.EthernetInterface, ethInterface.Name) + subInterfaces, err := c.Network.Layer3Subinterface.GetAll( + layer3.EthernetInterface, + ethInterface.Name, + ) if err != nil { return fmt.Errorf("layer 3 subinterfaces: %s", err) } diff --git a/internal/source/proxmox/proxmox.go b/internal/source/proxmox/proxmox.go index ec9c2ecd..2d712f99 100644 --- a/internal/source/proxmox/proxmox.go +++ b/internal/source/proxmox/proxmox.go @@ -65,7 +65,12 @@ func (ps *ProxmoxSource) Init() error { return fmt.Errorf("proxmox initialization failure: %v", err) } duration := time.Since(startTime) - ps.Logger.Infof(ps.Ctx, "Successfully initialized %s in %f seconds", utils.ExtractFunctionNameWithTrimPrefix(initFunc, "init"), duration.Seconds()) + ps.Logger.Infof( + ps.Ctx, + "Successfully initialized %s in %f seconds", + utils.ExtractFunctionNameWithTrimPrefix(initFunc, "init"), + duration.Seconds(), + ) } return nil @@ -86,7 +91,12 @@ func (ps *ProxmoxSource) Sync(nbi *inventory.NetboxInventory) error { return err } duration := time.Since(startTime) - ps.Logger.Infof(ps.Ctx, "Successfully synced %s in %f seconds", utils.ExtractFunctionNameWithTrimPrefix(syncFunc, "sync"), duration.Seconds()) + ps.Logger.Infof( + ps.Ctx, + "Successfully synced %s in %f seconds", + utils.ExtractFunctionNameWithTrimPrefix(syncFunc, "sync"), + duration.Seconds(), + ) } return nil } diff --git a/internal/source/proxmox/proxmox_sync.go b/internal/source/proxmox/proxmox_sync.go index 2ff16bf5..c6870177 100644 --- a/internal/source/proxmox/proxmox_sync.go +++ b/internal/source/proxmox/proxmox_sync.go @@ -414,7 +414,8 @@ func (ps *ProxmoxSource) syncVMNetworks(nbi *inventory.NetboxInventory, nbVM *ob nbIPAddress.Address, err, ) - } else if (ipAddress.IPAddressType == "ipv4" && mask != constants.MaxIPv4MaskBits) || (ipAddress.IPAddressType == "ipv6" && mask != constants.MaxIPv6MaskBits) { + } else if (ipAddress.IPAddressType == "ipv4" && mask != constants.MaxIPv4MaskBits) || + (ipAddress.IPAddressType == "ipv6" && mask != constants.MaxIPv6MaskBits) { _, err = nbi.AddPrefix(ps.Ctx, &objects.Prefix{ Prefix: prefix, }) diff --git a/internal/source/vmware/vmware.go b/internal/source/vmware/vmware.go index d3fe5477..76920897 100644 --- a/internal/source/vmware/vmware.go +++ b/internal/source/vmware/vmware.go @@ -47,11 +47,16 @@ type VmwareSource struct { } type NetworkData struct { - DistributedVirtualPortgroups map[string]*DistributedPortgroupData // Portgroup.key -> PortgroupData - Vid2Name map[int]string // Helper map, for quickly obtaining name of the vid - HostVirtualSwitches map[string]map[string]*HostVirtualSwitchData // hostName -> VSwitchName-> VSwitchData - HostProxySwitches map[string]map[string]*HostProxySwitchData // hostName -> PSwitchName -> - HostPortgroups map[string]map[string]*HostPortgroupData // hostname -> Portgroup.Spec.Name -> HostPortgroupData + // DistributedVirtualPortgroups: Portgroup.key -> PortgroupData + DistributedVirtualPortgroups map[string]*DistributedPortgroupData + // Vid2Name is a Helper map, for quickly obtaining name of the vid + Vid2Name map[int]string + // HostVirtualSwitches: hostName -> VSwitchName-> VSwitchData + HostVirtualSwitches map[string]map[string]*HostVirtualSwitchData + // HostProxySwitches: hostName -> PSwitchName -> HostProxySwitchData + HostProxySwitches map[string]map[string]*HostProxySwitchData + // HostPortgroups: hostname -> Portgroup.Spec.Name -> HostPortgroupData + HostPortgroups map[string]map[string]*HostPortgroupData } type DistributedPortgroupData struct { @@ -89,7 +94,14 @@ func (vc *VmwareSource) Init() error { escapedUsername := url.PathEscape(vc.SourceConfig.Username) escapedPassword := url.PathEscape(vc.SourceConfig.Password) - vcURL := fmt.Sprintf("%s://%s:%s@%s:%d/sdk", vc.SourceConfig.HTTPScheme, escapedUsername, escapedPassword, vc.SourceConfig.Hostname, vc.SourceConfig.Port) + vcURL := fmt.Sprintf( + "%s://%s:%s@%s:%d/sdk", + vc.SourceConfig.HTTPScheme, + escapedUsername, + escapedPassword, + vc.SourceConfig.Hostname, + vc.SourceConfig.Port, + ) url, err := url.Parse(vcURL) if err != nil { @@ -129,12 +141,22 @@ func (vc *VmwareSource) Init() error { // A container view is a subset of the vSphere inventory, focusing on the specified // object types, making it easier to manage and retrieve data for these objects. - containerView, err := viewManager.CreateContainerView(ctx, vim25Client.ServiceContent.RootFolder, viewType, true) + containerView, err := viewManager.CreateContainerView( + ctx, + vim25Client.ServiceContent.RootFolder, + viewType, + true, + ) if err != nil { return fmt.Errorf("failed creating containerView: %s", err) } - vc.Logger.Debug(vc.Ctx, "Connection to vmware source ", vc.SourceConfig.Hostname, " established successfully") + vc.Logger.Debug( + vc.Ctx, + "Connection to vmware source ", + vc.SourceConfig.Hostname, + " established successfully", + ) // Create CustomFieldManager to map custom field ids to their names // This is required to determine which custom field key is used for @@ -172,7 +194,12 @@ func (vc *VmwareSource) Init() error { return fmt.Errorf("vmware initialization failure: %v", err) } duration := time.Since(startTime) - vc.Logger.Infof(vc.Ctx, "Successfully initialized %s in %f seconds", utils.ExtractFunctionNameWithTrimPrefix(initFunc, "init"), duration.Seconds()) + vc.Logger.Infof( + vc.Ctx, + "Successfully initialized %s in %f seconds", + utils.ExtractFunctionNameWithTrimPrefix(initFunc, "init"), + duration.Seconds(), + ) } // Ensure the containerView is destroyed after we are done with it @@ -183,10 +210,18 @@ func (vc *VmwareSource) Init() error { err = sessionManager.Logout(ctx) if err != nil { - return fmt.Errorf("error occurred when ending vmware connection to host %s: %s", vc.SourceConfig.Hostname, err) + return fmt.Errorf( + "error occurred when ending vmware connection to host %s: %s", + vc.SourceConfig.Hostname, + err, + ) } - vc.Logger.Debug(vc.Ctx, "Successfully closed connection to vmware host: ", vc.SourceConfig.Hostname) + vc.Logger.Debug( + vc.Ctx, + "Successfully closed connection to vmware host: ", + vc.SourceConfig.Hostname, + ) return nil } @@ -208,14 +243,22 @@ func (vc *VmwareSource) Sync(nbi *inventory.NetboxInventory) error { return err } duration := time.Since(startTime) - vc.Logger.Infof(vc.Ctx, "Successfully synced %s in %f seconds", utils.ExtractFunctionNameWithTrimPrefix(syncFunc, "sync"), duration.Seconds()) + vc.Logger.Infof( + vc.Ctx, + "Successfully synced %s in %f seconds", + utils.ExtractFunctionNameWithTrimPrefix(syncFunc, "sync"), + duration.Seconds(), + ) } return nil } // Currently we have to traverse the vsphere tree to get datacenter to cluster relation // For other objects relations are available in with containerView. -func (vc *VmwareSource) CreateClusterDataCenterRelation(ctx context.Context, client *vim25.Client) error { +func (vc *VmwareSource) CreateClusterDataCenterRelation( + ctx context.Context, + client *vim25.Client, +) error { finder := find.NewFinder(client, true) datacenters, err := finder.DatacenterList(ctx, "*") if err != nil { @@ -226,7 +269,11 @@ func (vc *VmwareSource) CreateClusterDataCenterRelation(ctx context.Context, cli finder.SetDatacenter(dc) clusters, err := finder.ClusterComputeResourceList(ctx, "*") if err != nil { - return fmt.Errorf("finder failed finding clusters for datacenter %s: %s", dc.InventoryPath, err) + return fmt.Errorf( + "finder failed finding clusters for datacenter %s: %s", + dc.InventoryPath, + err, + ) } for _, cluster := range clusters { vc.Cluster2Datacenter[cluster.Reference().Value] = dc.Reference().Value @@ -256,7 +303,11 @@ func (vc *VmwareSource) CreateCustomFieldRelation(ctx context.Context, client *v // Creates a map of object ids to their tags. This uses the rest api since tags // are not available in the containerView (see https://github.com/vmware/govmomi/issues/1825). -func (vc *VmwareSource) CreateObjectTagsRelation(ctx context.Context, vim25client *vim25.Client, userInfo *url.Userinfo) error { +func (vc *VmwareSource) CreateObjectTagsRelation( + ctx context.Context, + vim25client *vim25.Client, + userInfo *url.Userinfo, +) error { restClient := rest.NewClient(vim25client) _, err := restClient.Session(ctx) @@ -292,7 +343,10 @@ func (vc *VmwareSource) CreateObjectTagsRelation(ctx context.Context, vim25clien return fmt.Errorf("failed getting tag %+v info: %s", tag, err) } for _, elem := range objs[0].ObjectIDs { - objectNames2tags[elem.Reference().Value] = append(objectNames2tags[elem.Reference().Value], tagInfo) + objectNames2tags[elem.Reference().Value] = append( + objectNames2tags[elem.Reference().Value], + tagInfo, + ) } } } diff --git a/internal/source/vmware/vmware_init.go b/internal/source/vmware/vmware_init.go index 6a6b5451..99820225 100644 --- a/internal/source/vmware/vmware_init.go +++ b/internal/source/vmware/vmware_init.go @@ -13,7 +13,12 @@ import ( // In vsphere we get vlans from DistributedVirtualPortgroups. func (vc *VmwareSource) initNetworks(ctx context.Context, containerView *view.ContainerView) error { var dvpgs []mo.DistributedVirtualPortgroup - err := containerView.Retrieve(ctx, []string{"DistributedVirtualPortgroup"}, []string{"config"}, &dvpgs) + err := containerView.Retrieve( + ctx, + []string{"DistributedVirtualPortgroup"}, + []string{"config"}, + &dvpgs, + ) if err != nil { return fmt.Errorf("failed retrieving DistributedVirtualPortgroups: %s", err) } @@ -79,7 +84,12 @@ func (vc *VmwareSource) initNetworks(ctx context.Context, containerView *view.Co func (vc *VmwareSource) initDisks(ctx context.Context, containerView *view.ContainerView) error { var disks []mo.Datastore - err := containerView.Retrieve(ctx, []string{"Datastore"}, []string{"summary", "host", "vm"}, &disks) + err := containerView.Retrieve( + ctx, + []string{"Datastore"}, + []string{"summary", "host", "vm"}, + &disks, + ) if err != nil { return fmt.Errorf("failed retrieving disks: %s", err) } @@ -90,7 +100,10 @@ func (vc *VmwareSource) initDisks(ctx context.Context, containerView *view.Conta return nil } -func (vc *VmwareSource) initDataCenters(ctx context.Context, containerView *view.ContainerView) error { +func (vc *VmwareSource) initDataCenters( + ctx context.Context, + containerView *view.ContainerView, +) error { var datacenters []mo.Datacenter err := containerView.Retrieve(ctx, []string{"Datacenter"}, []string{"name"}, &datacenters) if err != nil { @@ -105,7 +118,12 @@ func (vc *VmwareSource) initDataCenters(ctx context.Context, containerView *view func (vc *VmwareSource) initClusters(ctx context.Context, containerView *view.ContainerView) error { var clusters []mo.ClusterComputeResource - err := containerView.Retrieve(ctx, []string{"ClusterComputeResource"}, []string{"summary", "host", "name"}, &clusters) + err := containerView.Retrieve( + ctx, + []string{"ClusterComputeResource"}, + []string{"summary", "host", "name"}, + &clusters, + ) if err != nil { return fmt.Errorf("failed retrieving clusters: %s", err) } @@ -122,7 +140,20 @@ func (vc *VmwareSource) initClusters(ctx context.Context, containerView *view.Co func (vc *VmwareSource) initHosts(ctx context.Context, containerView *view.ContainerView) error { var hosts []mo.HostSystem - err := containerView.Retrieve(ctx, []string{"HostSystem"}, []string{"name", "summary.host", "summary.hardware", "summary.runtime", "summary.config", "vm", "config.network"}, &hosts) + err := containerView.Retrieve( + ctx, + []string{"HostSystem"}, + []string{ + "name", + "summary.host", + "summary.hardware", + "summary.runtime", + "summary.config", + "vm", + "config.network", + }, + &hosts, + ) if err != nil { return fmt.Errorf("failed retrieving hosts: %s", err) } @@ -191,7 +222,20 @@ func (vc *VmwareSource) initHosts(ctx context.Context, containerView *view.Conta func (vc *VmwareSource) initVms(ctx context.Context, containerView *view.ContainerView) error { var vms []mo.VirtualMachine - err := containerView.Retrieve(ctx, []string{"VirtualMachine"}, []string{"summary", "name", "runtime", "guest", "config.hardware", "config.template", "config.guestFullName"}, &vms) + err := containerView.Retrieve( + ctx, + []string{"VirtualMachine"}, + []string{ + "summary", + "name", + "runtime", + "guest", + "config.hardware", + "config.template", + "config.guestFullName", + }, + &vms, + ) if err != nil { return fmt.Errorf("failed retrieving vms: %s", err) } diff --git a/internal/source/vmware/vmware_sync.go b/internal/source/vmware/vmware_sync.go index cd3d3dd8..1180e422 100644 --- a/internal/source/vmware/vmware_sync.go +++ b/internal/source/vmware/vmware_sync.go @@ -578,7 +578,14 @@ func (vc *VmwareSource) collectHostPhysicalNicData( if err != nil { return nil, "", fmt.Errorf("match vlan to site: %s", err) } - vlanGroup, err := common.MatchVlanToGroup(vc.Ctx, nbi, vlanName, vlanSite, vc.SourceConfig.VlanGroupRelations, vc.SourceConfig.VlanGroupSiteRelations) + vlanGroup, err := common.MatchVlanToGroup( + vc.Ctx, + nbi, + vlanName, + vlanSite, + vc.SourceConfig.VlanGroupRelations, + vc.SourceConfig.VlanGroupSiteRelations, + ) if err != nil { return nil, "", fmt.Errorf("match vlan to group: %s", err) } @@ -886,11 +893,23 @@ func (vc *VmwareSource) collectHostVirtualNicData( if vnicDvPortgroupDataVlanID == 0 { continue } - vnicTaggedVlanSite, err := common.MatchVlanToSite(vc.Ctx, nbi, vc.Networks.Vid2Name[vnicDvPortgroupDataVlanID], vc.SourceConfig.VlanSiteRelations) + vnicTaggedVlanSite, err := common.MatchVlanToSite( + vc.Ctx, + nbi, + vc.Networks.Vid2Name[vnicDvPortgroupDataVlanID], + vc.SourceConfig.VlanSiteRelations, + ) if err != nil { return nil, fmt.Errorf("match vlan to site: %s", err) } - vnicTaggedVlanGroup, err := common.MatchVlanToGroup(vc.Ctx, nbi, vc.Networks.Vid2Name[vnicDvPortgroupDataVlanID], vnicTaggedVlanSite, vc.SourceConfig.VlanGroupRelations, vc.SourceConfig.VlanGroupSiteRelations) + vnicTaggedVlanGroup, err := common.MatchVlanToGroup( + vc.Ctx, + nbi, + vc.Networks.Vid2Name[vnicDvPortgroupDataVlanID], + vnicTaggedVlanSite, + vc.SourceConfig.VlanGroupRelations, + vc.SourceConfig.VlanGroupSiteRelations, + ) if err != nil { return nil, fmt.Errorf("match vlan to vlan group: %s", err) } diff --git a/internal/utils/dcim_test.go b/internal/utils/dcim_test.go index c87795be..fe83030e 100644 --- a/internal/utils/dcim_test.go +++ b/internal/utils/dcim_test.go @@ -18,14 +18,16 @@ func TestExtractCPUArch(t *testing.T) { { name: "Extract cpu arch from BOOT_IMAGE", args: args{ - input: "BOOT_IMAGE=(hd0,msdos1)/vmlinuz-5.15.0-207.156.6.el8uek.x86_64 root=/dev/mapper/ol-root ro crashkernel=auto resume=/dev/mapper/ol-swap00 rd.lvm.lv=ol/root rd.lvm.lv=ol/swap00 rhgb quiet intel_iommu=on", + input: "BOOT_IMAGE=(hd0,msdos1)/vmlinuz-5.15.0-207.156.6.el8uek.x86_64 root=/dev/mapper/ol-root ro" + + " crashkernel=auto resume=/dev/mapper/ol-swap00 rd.lvm.lv=ol/root rd.lvm.lv=ol/swap00 rhgb quiet intel_iommu=on", }, want: "x86_64", }, { name: "Extract cpu arch from kernel version", args: args{ - input: "Linux version 4.15.0-1051-oem (buildd@lgw01-amd64-016) (gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1)) #60-Ubuntu SMP Fri Sep 13 13:51:54 UTC 2019 (x86_64)", + input: "Linux version 4.15.0-1051-oem (buildd@lgw01-amd64-016) " + + "(gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1)) #60-Ubuntu SMP Fri Sep 13 13:51:54 UTC 2019 (x86_64)", }, want: "x86_64", }, diff --git a/internal/utils/diff_map.go b/internal/utils/diff_map.go index 5bf2e660..4504c1eb 100644 --- a/internal/utils/diff_map.go +++ b/internal/utils/diff_map.go @@ -56,12 +56,14 @@ func hasPriorityOver(newObj, existingObj reflect.Value, source2priority map[stri } // 1. case - if newCustomFields[constants.CustomFieldSourceName] != nil && existingCustomFields[constants.CustomFieldSourceName] != nil { + if newCustomFields[constants.CustomFieldSourceName] != nil && + existingCustomFields[constants.CustomFieldSourceName] != nil { newPriority := int(^uint(0) >> 1) // max int if priority, newOk := source2priority[newCustomFields[constants.CustomFieldSourceName].(string)]; newOk { newPriority = priority } existingPriority := int(^uint(0) >> 1) + //nolint:lll if priority, existingOk := source2priority[existingCustomFields[constants.CustomFieldSourceName].(string)]; existingOk { existingPriority = priority } @@ -83,7 +85,11 @@ func hasPriorityOver(newObj, existingObj reflect.Value, source2priority map[stri // that are empty in newObj but might have a value in existingObj. // Also we check for priority, if newObject has priority over existingObject // we use the fields from newObject, otherwise we use the fields from exisingObject. -func JSONDiffMapExceptID(newObj, existingObj interface{}, resetFields bool, source2priority map[string]int) (map[string]interface{}, error) { +func JSONDiffMapExceptID( + newObj, existingObj interface{}, + resetFields bool, + source2priority map[string]int, +) (map[string]interface{}, error) { diff := make(map[string]interface{}) newObject := reflect.ValueOf(newObj) @@ -118,9 +124,17 @@ func JSONDiffMapExceptID(newObj, existingObj interface{}, resetFields bool, sour // Custom logic for all objects that inherit from NetboxObject if fieldName == "NetboxObject" { - netboxObjectDiffMap, err := JSONDiffMapExceptID(newObject.Field(i).Interface(), existingObject.Field(i).Interface(), resetFields, source2priority) + netboxObjectDiffMap, err := JSONDiffMapExceptID( + newObject.Field(i).Interface(), + existingObject.Field(i).Interface(), + resetFields, + source2priority, + ) if err != nil { - return nil, fmt.Errorf("error processing JsonDiffMapExceptID when processing NetboxObject %s", err) + return nil, fmt.Errorf( + "error processing JsonDiffMapExceptID when processing NetboxObject %s", + err, + ) } for k, v := range netboxObjectDiffMap { diff[k] = v @@ -165,19 +179,28 @@ func JSONDiffMapExceptID(newObj, existingObj interface{}, resetFields bool, sour case reflect.Slice: err := addSliceDiff(newObjectField, existingObjectField, jsonTag, hasPriority, diff) if err != nil { - return nil, fmt.Errorf("error processing JsonDiffMapExceptID when processing slice %s", err) + return nil, fmt.Errorf( + "error processing JsonDiffMapExceptID when processing slice %s", + err, + ) } case reflect.Struct: err := addStructDiff(newObjectField, existingObjectField, jsonTag, hasPriority, diff) if err != nil { - return nil, fmt.Errorf("error processing JsonDiffMapExceptID when processing struct %s", err) + return nil, fmt.Errorf( + "error processing JsonDiffMapExceptID when processing struct %s", + err, + ) } case reflect.Map: err := addMapDiff(newObjectField, existingObjectField, jsonTag, hasPriority, diff) if err != nil { - return nil, fmt.Errorf("error processing JsonDiffMapExceptID when processing map %s", err) + return nil, fmt.Errorf( + "error processing JsonDiffMapExceptID when processing map %s", + err, + ) } default: @@ -196,7 +219,13 @@ func JSONDiffMapExceptID(newObj, existingObj interface{}, resetFields bool, sour // // This function only works for slices with comparable elements (e.g. ints, strings) and // slices that contain objects that are structs but have ID attribute. -func addSliceDiff(newSlice reflect.Value, existingSlice reflect.Value, jsonTag string, hasPriority bool, diffMap map[string]interface{}) error { +func addSliceDiff( + newSlice reflect.Value, + existingSlice reflect.Value, + jsonTag string, + hasPriority bool, + diffMap map[string]interface{}, +) error { // If new slice doesn't have priority don't do anything if !hasPriority { return nil @@ -250,7 +279,11 @@ func convertSliceToComparableSlice(slice reflect.Value) (reflect.Value, error) { } if firstElement.Kind() == reflect.Struct { if !firstElement.FieldByName("ID").IsValid() { - return reflect.ValueOf(nil), fmt.Errorf("slice contains struct that don't contain id field") + return reflect.ValueOf( + nil, + ), fmt.Errorf( + "slice contains struct that don't contain id field", + ) } idSlice := make([]int, 0) for i := 0; i < slice.Len(); i++ { @@ -286,7 +319,13 @@ func sliceToSet(slice reflect.Value) map[interface{}]bool { } // Returns json form for patching the difference e.g. { "ID": 1 }. -func addStructDiff(newObj reflect.Value, existingObj reflect.Value, jsonTag string, hasPriority bool, diffMap map[string]interface{}) error { +func addStructDiff( + newObj reflect.Value, + existingObj reflect.Value, + jsonTag string, + hasPriority bool, + diffMap map[string]interface{}, +) error { // If first struct is nil, that means that we reset the attribute to nil if !newObj.IsValid() { diffMap[jsonTag] = nil @@ -332,7 +371,13 @@ func addStructDiff(newObj reflect.Value, existingObj reflect.Value, jsonTag stri return nil } -func addMapDiff(newMap reflect.Value, existingMap reflect.Value, jsonTag string, hasPriority bool, diffMap map[string]interface{}) error { +func addMapDiff( + newMap reflect.Value, + existingMap reflect.Value, + jsonTag string, + hasPriority bool, + diffMap map[string]interface{}, +) error { // If the new map is not set, we don't change anything if !newMap.IsValid() { return nil @@ -371,7 +416,13 @@ func addMapDiff(newMap reflect.Value, existingMap reflect.Value, jsonTag string, return nil } -func addPrimaryDiff(newField reflect.Value, existingField reflect.Value, jsonTag string, hasPriority bool, diffMap map[string]interface{}) { +func addPrimaryDiff( + newField reflect.Value, + existingField reflect.Value, + jsonTag string, + hasPriority bool, + diffMap map[string]interface{}, +) { switch { case newField.IsZero(): if !existingField.IsZero() { @@ -386,7 +437,10 @@ func addPrimaryDiff(newField reflect.Value, existingField reflect.Value, jsonTag } } -func ExtractFieldsFromDiffMap(diffMap map[string]interface{}, field []string) map[string]interface{} { +func ExtractFieldsFromDiffMap( + diffMap map[string]interface{}, + field []string, +) map[string]interface{} { extractedFields := make(map[string]interface{}) if len(diffMap) == 0 { return extractedFields diff --git a/internal/utils/diff_map_test.go b/internal/utils/diff_map_test.go index bfd7ea36..8f0d5788 100644 --- a/internal/utils/diff_map_test.go +++ b/internal/utils/diff_map_test.go @@ -1036,7 +1036,12 @@ func Test_addSliceDiff(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := addSliceDiff(tt.args.newSlice, tt.args.existingSlice, tt.args.jsonTag, tt.args.hasPriority, tt.args.diffMap); (err != nil) != tt.wantErr { + if err := addSliceDiff( + tt.args.newSlice, + tt.args.existingSlice, + tt.args.jsonTag, + tt.args.hasPriority, + tt.args.diffMap); (err != nil) != tt.wantErr { t.Errorf("addSliceDiff() error = %v, wantErr %v", err, tt.wantErr) } if tt.wantErr == false { @@ -1139,7 +1144,12 @@ func Test_addStructDiff(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := addStructDiff(tt.args.newObj, tt.args.existingObj, tt.args.jsonTag, tt.args.hasPriority, tt.args.diffMap); (err != nil) != tt.wantErr { + if err := addStructDiff( + tt.args.newObj, + tt.args.existingObj, + tt.args.jsonTag, + tt.args.hasPriority, + tt.args.diffMap); (err != nil) != tt.wantErr { t.Errorf("addStructDiff() error = %v, wantErr %v", err, tt.wantErr) } }) @@ -1216,7 +1226,12 @@ func Test_addMapDiff(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := addMapDiff(tt.args.newMap, tt.args.existingMap, tt.args.jsonTag, tt.args.hasPriority, tt.args.diffMap); (err != nil) != tt.wantErr { + if err := addMapDiff( + tt.args.newMap, + tt.args.existingMap, + tt.args.jsonTag, + tt.args.hasPriority, + tt.args.diffMap); (err != nil) != tt.wantErr { t.Errorf("addMapDiff() error = %v, wantErr %v", err, tt.wantErr) } diff --git a/internal/utils/json_test.go b/internal/utils/json_test.go index 97c0d08d..e3ba988c 100644 --- a/internal/utils/json_test.go +++ b/internal/utils/json_test.go @@ -28,33 +28,105 @@ func TestExtractJSONTagsFromStruct(t *testing.T) { args: args{ inputStruct: objects.CustomField{}, }, - want: []string{"id", "name", "label", "type", "object_types", "description", "search_weight", "filter_logic", "ui_visible", "ui_editable", "weight", "default", "required"}, + want: []string{ + "id", + "name", + "label", + "type", + "object_types", + "description", + "search_weight", + "filter_logic", + "ui_visible", + "ui_editable", + "weight", + "default", + "required", + }, }, { name: "Extract json fields from device", args: args{ inputStruct: objects.Device{}, }, - want: []string{"id", "tags", "description", "custom_fields", "name", "role", "device_type", "airflow", "serial", "asset_tag", "site", "location", "status", "platform", "primary_ip4", "primary_ip6", "cluster", "tenant", "comments"}, + want: []string{ + "id", + "tags", + "description", + "custom_fields", + "name", + "role", + "device_type", + "airflow", + "serial", + "asset_tag", + "site", + "location", + "status", + "platform", + "primary_ip4", + "primary_ip6", + "cluster", + "tenant", + "comments", + }, }, { name: "Extract fields from VMInterface", args: args{ inputStruct: objects.VMInterface{}, }, - want: []string{"id", "tags", "description", "custom_fields", "virtual_machine", "name", "primary_mac_address", "mtu", "enabled", "parent", "bridge", "mode", "tagged_vlans", "untagged_vlan"}, + want: []string{ + "id", + "tags", + "description", + "custom_fields", + "virtual_machine", + "name", + "primary_mac_address", + "mtu", + "enabled", + "parent", + "bridge", + "mode", + "tagged_vlans", + "untagged_vlan", + }, }, { name: "Extract fields from interface", args: args{ inputStruct: objects.Interface{}, }, - want: []string{"id", "tags", "description", "custom_fields", "device", "name", "enabled", "type", "speed", "parent", "bridge", "lag", "mtu", "primary_mac_address", "duplex", "mode", "tagged_vlans", "untagged_vlan", "vdcs"}, + want: []string{ + "id", + "tags", + "description", + "custom_fields", + "device", + "name", + "enabled", + "type", + "speed", + "parent", + "bridge", + "lag", + "mtu", + "primary_mac_address", + "duplex", + "mode", + "tagged_vlans", + "untagged_vlan", + "vdcs", + }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := ExtractJSONTagsFromStruct(tt.args.inputStruct); !reflect.DeepEqual(got, tt.want) { + if got := ExtractJSONTagsFromStruct(tt.args.inputStruct); !reflect.DeepEqual( + got, + tt.want, + ) { t.Errorf("ExtractStructJSONFields() = %v, want %v", got, tt.want) } }) diff --git a/internal/utils/netbox_marshal_test.go b/internal/utils/netbox_marshal_test.go index 8472ca35..d6d8c14c 100644 --- a/internal/utils/netbox_marshal_test.go +++ b/internal/utils/netbox_marshal_test.go @@ -26,7 +26,13 @@ func TestComplexClusterMarshal(t *testing.T) { ID: 2, Tags: []*objects.Tag{ {ID: 1, Name: "Test", Slug: "test", Color: "000000", Description: "Test tag"}, - {ID: 3, Name: "Test3", Slug: "test3", Color: "000000", Description: "Test tag 3"}, + { + ID: 3, + Name: "Test3", + Slug: "test3", + Color: "000000", + Description: "Test tag 3", + }, }, }, Name: "oVirt", @@ -37,7 +43,13 @@ func TestComplexClusterMarshal(t *testing.T) { ID: 4, Tags: []*objects.Tag{ {ID: 1, Name: "Test", Slug: "test", Color: "000000", Description: "Test tag"}, - {ID: 3, Name: "Test3", Slug: "test3", Color: "000000", Description: "Test tag 3"}, + { + ID: 3, + Name: "Test3", + Slug: "test3", + Color: "000000", + Description: "Test tag 3", + }, }, Description: "New cluster group", }, @@ -51,8 +63,20 @@ func TestComplexClusterMarshal(t *testing.T) { ID: 1, Tags: []*objects.Tag{ {ID: 1, Name: "Test", Slug: "test", Color: "000000", Description: "Test tag"}, - {ID: 3, Name: "Test3", Slug: "test3", Color: "000000", Description: "Test tag 3"}, - {ID: 4, Name: "Test3", Slug: "test3", Color: "000000", Description: "Test tag 3"}, + { + ID: 3, + Name: "Test3", + Slug: "test3", + Color: "000000", + Description: "Test tag 3", + }, + { + ID: 4, + Name: "Test3", + Slug: "test3", + Color: "000000", + Description: "Test tag 3", + }, }, }, Name: "Default", @@ -190,7 +214,9 @@ func TestNetboxJSONMarshal(t *testing.T) { { name: "Struct with slice attribute of structs with no ids", args: args{ - obj: structWithSliceAttributeOfStructs{Test: []testStruct{{Test: "one"}, {Test: "two"}}}, + obj: structWithSliceAttributeOfStructs{ + Test: []testStruct{{Test: "one"}, {Test: "two"}}, + }, }, want: []byte("{\"test\":[{\"test\":\"one\"},{\"test\":\"two\"}]}"), }, diff --git a/internal/utils/utils.go b/internal/utils/utils.go index 25e75bf9..3c2fc9a3 100644 --- a/internal/utils/utils.go +++ b/internal/utils/utils.go @@ -27,7 +27,10 @@ func ValidateRegexRelations(regexRelations []string) error { for _, regexRelation := range regexRelations { relation := strings.Split(regexRelation, "=") if len(relation) != len([]string{"regex", "value"}) { - return fmt.Errorf("invalid regex relation: %s. Should be of format: regex = value", regexRelation) + return fmt.Errorf( + "invalid regex relation: %s. Should be of format: regex = value", + regexRelation, + ) } regexStr := strings.TrimSpace(relation[0]) _, err := regexp.Compile(regexStr) @@ -156,7 +159,12 @@ func removeDiacritics(s string) string { // // E.g. names = ["John Doe", "Jane Doe"], emails = ["jane.doe@example"] // Output: map["Jane Doe"] = "jane.doe@example". -func MatchNamesWithEmails(ctx context.Context, names []string, emails []string, logger *logger.Logger) map[string]string { +func MatchNamesWithEmails( + ctx context.Context, + names []string, + emails []string, + logger *logger.Logger, +) map[string]string { normalizedNames := make(map[string]string) // Map for easy lookup for _, name := range names { // Normalize name: remove diacritics, spaces, and convert to lowercase diff --git a/internal/utils/utils_test.go b/internal/utils/utils_test.go index fcb57b01..3d32ac90 100644 --- a/internal/utils/utils_test.go +++ b/internal/utils/utils_test.go @@ -457,7 +457,10 @@ func TestMatchNamesWithEmails(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := MatchNamesWithEmails(tt.args.ctx, tt.args.names, tt.args.emails, tt.args.logger); !reflect.DeepEqual(got, tt.want) { + if got := MatchNamesWithEmails(tt.args.ctx, tt.args.names, tt.args.emails, tt.args.logger); !reflect.DeepEqual( + got, + tt.want, + ) { t.Errorf("MatchNamesWithEmails() = %v, want %v", got, tt.want) } })