mirror of
https://github.com/h44z/wg-portal.git
synced 2025-06-28 01:07:03 +00:00
wip: create different backend handlers (#426)
This commit is contained in:
parent
e934232e0b
commit
ea6da4114f
@ -80,6 +80,7 @@ watch(() => props.visible, async (newValue, oldValue) => {
|
|||||||
formData.value.Identifier = interfaces.Prepared.Identifier
|
formData.value.Identifier = interfaces.Prepared.Identifier
|
||||||
formData.value.DisplayName = interfaces.Prepared.DisplayName
|
formData.value.DisplayName = interfaces.Prepared.DisplayName
|
||||||
formData.value.Mode = interfaces.Prepared.Mode
|
formData.value.Mode = interfaces.Prepared.Mode
|
||||||
|
formData.value.Backend = interfaces.Prepared.Backend
|
||||||
|
|
||||||
formData.value.PublicKey = interfaces.Prepared.PublicKey
|
formData.value.PublicKey = interfaces.Prepared.PublicKey
|
||||||
formData.value.PrivateKey = interfaces.Prepared.PrivateKey
|
formData.value.PrivateKey = interfaces.Prepared.PrivateKey
|
||||||
@ -118,6 +119,7 @@ watch(() => props.visible, async (newValue, oldValue) => {
|
|||||||
formData.value.Identifier = selectedInterface.value.Identifier
|
formData.value.Identifier = selectedInterface.value.Identifier
|
||||||
formData.value.DisplayName = selectedInterface.value.DisplayName
|
formData.value.DisplayName = selectedInterface.value.DisplayName
|
||||||
formData.value.Mode = selectedInterface.value.Mode
|
formData.value.Mode = selectedInterface.value.Mode
|
||||||
|
formData.value.Backend = selectedInterface.value.Backend
|
||||||
|
|
||||||
formData.value.PublicKey = selectedInterface.value.PublicKey
|
formData.value.PublicKey = selectedInterface.value.PublicKey
|
||||||
formData.value.PrivateKey = selectedInterface.value.PrivateKey
|
formData.value.PrivateKey = selectedInterface.value.PrivateKey
|
||||||
|
@ -134,7 +134,7 @@ func (c LocalController) convertWireGuardInterface(device *wgtypes.Device) (doma
|
|||||||
Mtu: 0,
|
Mtu: 0,
|
||||||
FirewallMark: uint32(device.FirewallMark),
|
FirewallMark: uint32(device.FirewallMark),
|
||||||
DeviceUp: false,
|
DeviceUp: false,
|
||||||
ImportSource: "wgctrl",
|
ImportSource: domain.ControllerTypeLocal,
|
||||||
DeviceType: device.Type.String(),
|
DeviceType: device.Type.String(),
|
||||||
BytesUpload: 0,
|
BytesUpload: 0,
|
||||||
BytesDownload: 0,
|
BytesDownload: 0,
|
||||||
@ -199,6 +199,7 @@ func (c LocalController) convertWireGuardPeer(peer *wgtypes.Peer) (domain.Physic
|
|||||||
ProtocolVersion: peer.ProtocolVersion,
|
ProtocolVersion: peer.ProtocolVersion,
|
||||||
BytesUpload: uint64(peer.ReceiveBytes),
|
BytesUpload: uint64(peer.ReceiveBytes),
|
||||||
BytesDownload: uint64(peer.TransmitBytes),
|
BytesDownload: uint64(peer.TransmitBytes),
|
||||||
|
ImportSource: domain.ControllerTypeLocal,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, addr := range peer.AllowedIPs {
|
for _, addr := range peer.AllowedIPs {
|
||||||
|
@ -40,7 +40,7 @@ func (c MikrotikController) GetId() domain.InterfaceBackend {
|
|||||||
func (c MikrotikController) GetInterfaces(ctx context.Context) ([]domain.PhysicalInterface, error) {
|
func (c MikrotikController) GetInterfaces(ctx context.Context) ([]domain.PhysicalInterface, error) {
|
||||||
wgReply := c.client.Query(ctx, "/interface/wireguard", &lowlevel.MikrotikRequestOptions{
|
wgReply := c.client.Query(ctx, "/interface/wireguard", &lowlevel.MikrotikRequestOptions{
|
||||||
PropList: []string{
|
PropList: []string{
|
||||||
".id", "name", "public-key", "private-key", "listen-port", "mtu", "disabled", "running",
|
".id", "name", "public-key", "private-key", "listen-port", "mtu", "disabled", "running", "comment",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
if wgReply.Status != lowlevel.MikrotikApiStatusOk {
|
if wgReply.Status != lowlevel.MikrotikApiStatusOk {
|
||||||
@ -167,12 +167,17 @@ func (c MikrotikController) convertWireGuardInterface(
|
|||||||
Mtu: wg.GetInt("mtu"),
|
Mtu: wg.GetInt("mtu"),
|
||||||
FirewallMark: 0,
|
FirewallMark: 0,
|
||||||
DeviceUp: wg.GetBool("running"),
|
DeviceUp: wg.GetBool("running"),
|
||||||
ImportSource: "mikrotik",
|
ImportSource: domain.ControllerTypeMikrotik,
|
||||||
DeviceType: "Mikrotik",
|
DeviceType: domain.ControllerTypeMikrotik,
|
||||||
BytesUpload: uint64(iface.GetInt("tx-byte")),
|
BytesUpload: uint64(iface.GetInt("tx-byte")),
|
||||||
BytesDownload: uint64(iface.GetInt("rx-byte")),
|
BytesDownload: uint64(iface.GetInt("rx-byte")),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pi.SetExtras(domain.MikrotikInterfaceExtras{
|
||||||
|
Comment: wg.GetString("comment"),
|
||||||
|
Disabled: wg.GetBool("disabled"),
|
||||||
|
})
|
||||||
|
|
||||||
return pi, nil
|
return pi, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,7 +215,10 @@ func (c MikrotikController) GetPeers(ctx context.Context, deviceId domain.Interf
|
|||||||
return peers, nil
|
return peers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c MikrotikController) convertWireGuardPeer(peer lowlevel.GenericJsonObject) (domain.PhysicalPeer, error) {
|
func (c MikrotikController) convertWireGuardPeer(peer lowlevel.GenericJsonObject) (
|
||||||
|
domain.PhysicalPeer,
|
||||||
|
error,
|
||||||
|
) {
|
||||||
keepAliveSeconds := 0
|
keepAliveSeconds := 0
|
||||||
duration, err := time.ParseDuration(peer.GetString("client-keepalive"))
|
duration, err := time.ParseDuration(peer.GetString("client-keepalive"))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -246,15 +254,17 @@ func (c MikrotikController) convertWireGuardPeer(peer lowlevel.GenericJsonObject
|
|||||||
ProtocolVersion: 0, // Mikrotik does not support protocol versioning, so we set it to 0
|
ProtocolVersion: 0, // Mikrotik does not support protocol versioning, so we set it to 0
|
||||||
BytesUpload: uint64(peer.GetInt("rx")),
|
BytesUpload: uint64(peer.GetInt("rx")),
|
||||||
BytesDownload: uint64(peer.GetInt("tx")),
|
BytesDownload: uint64(peer.GetInt("tx")),
|
||||||
|
ImportSource: domain.ControllerTypeMikrotik,
|
||||||
BackendExtras: make(map[string]interface{}),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
peerModel.BackendExtras["MT-NAME"] = peer.GetString("name")
|
peerModel.SetExtras(domain.MikrotikPeerExtras{
|
||||||
peerModel.BackendExtras["MT-COMMENT"] = peer.GetString("comment")
|
Name: peer.GetString("name"),
|
||||||
peerModel.BackendExtras["MT-RESPONDER"] = peer.GetString("responder")
|
Comment: peer.GetString("comment"),
|
||||||
peerModel.BackendExtras["MT-ENDPOINT"] = peer.GetString("client-endpoint")
|
IsResponder: peer.GetBool("responder"),
|
||||||
peerModel.BackendExtras["MT-IP"] = peer.GetString("client-address")
|
ClientEndpoint: peer.GetString("client-endpoint"),
|
||||||
|
ClientAddress: peer.GetString("client-address"),
|
||||||
|
Disabled: peer.GetBool("disabled"),
|
||||||
|
})
|
||||||
|
|
||||||
return peerModel, nil
|
return peerModel, nil
|
||||||
}
|
}
|
||||||
|
@ -335,6 +335,8 @@ func (c *StatisticsCollector) isPeerPingable(ctx context.Context, peer domain.Pe
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: implement ping check on Mikrotik (or any other controller)
|
||||||
|
|
||||||
pinger, err := probing.NewPinger(checkAddr)
|
pinger, err := probing.NewPinger(checkAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Debug("failed to instantiate pinger", "peer", peer.Identifier, "address", checkAddr, "error", err)
|
slog.Debug("failed to instantiate pinger", "peer", peer.Identifier, "address", checkAddr, "error", err)
|
||||||
|
@ -837,28 +837,20 @@ func (m Manager) importPeer(ctx context.Context, in *domain.Interface, p *domain
|
|||||||
peer.Interface.PreDown = domain.NewConfigOption(in.PeerDefPreDown, true)
|
peer.Interface.PreDown = domain.NewConfigOption(in.PeerDefPreDown, true)
|
||||||
peer.Interface.PostDown = domain.NewConfigOption(in.PeerDefPostDown, true)
|
peer.Interface.PostDown = domain.NewConfigOption(in.PeerDefPostDown, true)
|
||||||
|
|
||||||
|
var displayName string
|
||||||
switch in.Type {
|
switch in.Type {
|
||||||
case domain.InterfaceTypeAny:
|
case domain.InterfaceTypeAny:
|
||||||
peer.Interface.Type = domain.InterfaceTypeAny
|
peer.Interface.Type = domain.InterfaceTypeAny
|
||||||
peer.DisplayName = "Autodetected Peer (" + peer.Interface.PublicKey[0:8] + ")"
|
displayName = "Autodetected Peer (" + peer.Interface.PublicKey[0:8] + ")"
|
||||||
case domain.InterfaceTypeClient:
|
case domain.InterfaceTypeClient:
|
||||||
peer.Interface.Type = domain.InterfaceTypeServer
|
peer.Interface.Type = domain.InterfaceTypeServer
|
||||||
peer.DisplayName = "Autodetected Endpoint (" + peer.Interface.PublicKey[0:8] + ")"
|
displayName = "Autodetected Endpoint (" + peer.Interface.PublicKey[0:8] + ")"
|
||||||
case domain.InterfaceTypeServer:
|
case domain.InterfaceTypeServer:
|
||||||
peer.Interface.Type = domain.InterfaceTypeClient
|
peer.Interface.Type = domain.InterfaceTypeClient
|
||||||
peer.DisplayName = "Autodetected Client (" + peer.Interface.PublicKey[0:8] + ")"
|
displayName = "Autodetected Client (" + peer.Interface.PublicKey[0:8] + ")"
|
||||||
}
|
|
||||||
|
|
||||||
if p.BackendExtras != nil {
|
|
||||||
if val, ok := p.BackendExtras["MT-NAME"]; ok {
|
|
||||||
peer.DisplayName = val.(string)
|
|
||||||
}
|
|
||||||
if val, ok := p.BackendExtras["MT-COMMENT"]; ok {
|
|
||||||
peer.Notes = val.(string)
|
|
||||||
}
|
|
||||||
if val, ok := p.BackendExtras["MT-ENDPOINT"]; ok {
|
|
||||||
peer.Endpoint = domain.NewConfigOption(val.(string), true)
|
|
||||||
}
|
}
|
||||||
|
if peer.DisplayName == "" {
|
||||||
|
peer.DisplayName = displayName // use auto-generated display name if not set
|
||||||
}
|
}
|
||||||
|
|
||||||
err := m.db.SavePeer(ctx, peer.Identifier, func(_ *domain.Peer) (*domain.Peer, error) {
|
err := m.db.SavePeer(ctx, peer.Identifier, func(_ *domain.Peer) (*domain.Peer, error) {
|
||||||
|
24
internal/domain/controller.go
Normal file
24
internal/domain/controller.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package domain
|
||||||
|
|
||||||
|
// ControllerType defines the type of controller used to manage interfaces.
|
||||||
|
|
||||||
|
const (
|
||||||
|
ControllerTypeMikrotik = "mikrotik"
|
||||||
|
ControllerTypeLocal = "wgctrl"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Controller extras can be used to store additional information available for specific controllers only.
|
||||||
|
|
||||||
|
type MikrotikInterfaceExtras struct {
|
||||||
|
Comment string
|
||||||
|
Disabled bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type MikrotikPeerExtras struct {
|
||||||
|
Name string
|
||||||
|
Comment string
|
||||||
|
IsResponder bool
|
||||||
|
ClientEndpoint string
|
||||||
|
ClientAddress string
|
||||||
|
Disabled bool
|
||||||
|
}
|
@ -208,9 +208,26 @@ type PhysicalInterface struct {
|
|||||||
|
|
||||||
BytesUpload uint64
|
BytesUpload uint64
|
||||||
BytesDownload uint64
|
BytesDownload uint64
|
||||||
|
|
||||||
|
backendExtras any // additional backend-specific extras, e.g., domain.MikrotikInterfaceExtras
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PhysicalInterface) GetExtras() any {
|
||||||
|
return p.backendExtras
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PhysicalInterface) SetExtras(extras any) {
|
||||||
|
switch extras.(type) {
|
||||||
|
case MikrotikInterfaceExtras: // OK
|
||||||
|
default: // we only support MikrotikInterfaceExtras for now
|
||||||
|
panic(fmt.Sprintf("unsupported interface backend extras type %T", extras))
|
||||||
|
}
|
||||||
|
|
||||||
|
p.backendExtras = extras
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConvertPhysicalInterface(pi *PhysicalInterface) *Interface {
|
func ConvertPhysicalInterface(pi *PhysicalInterface) *Interface {
|
||||||
|
// create a new basic interface with the data from the physical interface
|
||||||
iface := &Interface{
|
iface := &Interface{
|
||||||
Identifier: pi.Identifier,
|
Identifier: pi.Identifier,
|
||||||
KeyPair: pi.KeyPair,
|
KeyPair: pi.KeyPair,
|
||||||
@ -245,6 +262,23 @@ func ConvertPhysicalInterface(pi *PhysicalInterface) *Interface {
|
|||||||
PeerDefPostDown: "",
|
PeerDefPostDown: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if pi.GetExtras() == nil {
|
||||||
|
return iface
|
||||||
|
}
|
||||||
|
|
||||||
|
// enrich the data with controller-specific extras
|
||||||
|
now := time.Now()
|
||||||
|
switch pi.ImportSource {
|
||||||
|
case ControllerTypeMikrotik:
|
||||||
|
extras := pi.GetExtras().(MikrotikInterfaceExtras)
|
||||||
|
iface.DisplayName = extras.Comment
|
||||||
|
if extras.Disabled {
|
||||||
|
iface.Disabled = &now
|
||||||
|
} else {
|
||||||
|
iface.Disabled = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return iface
|
return iface
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ func (p *Peer) GenerateDisplayName(prefix string) {
|
|||||||
p.DisplayName = fmt.Sprintf("%sPeer %s", prefix, internal.TruncateString(string(p.Identifier), 8))
|
p.DisplayName = fmt.Sprintf("%sPeer %s", prefix, internal.TruncateString(string(p.Identifier), 8))
|
||||||
}
|
}
|
||||||
|
|
||||||
// OverwriteUserEditableFields overwrites the user editable fields of the peer with the values from the userPeer
|
// OverwriteUserEditableFields overwrites the user-editable fields of the peer with the values from the userPeer
|
||||||
func (p *Peer) OverwriteUserEditableFields(userPeer *Peer, cfg *config.Config) {
|
func (p *Peer) OverwriteUserEditableFields(userPeer *Peer, cfg *config.Config) {
|
||||||
p.DisplayName = userPeer.DisplayName
|
p.DisplayName = userPeer.DisplayName
|
||||||
if cfg.Core.EditableKeys {
|
if cfg.Core.EditableKeys {
|
||||||
@ -182,10 +182,11 @@ type PhysicalPeer struct {
|
|||||||
BytesUpload uint64 // upload bytes are the number of bytes that the remote peer has sent to the server
|
BytesUpload uint64 // upload bytes are the number of bytes that the remote peer has sent to the server
|
||||||
BytesDownload uint64 // upload bytes are the number of bytes that the remote peer has received from the server
|
BytesDownload uint64 // upload bytes are the number of bytes that the remote peer has received from the server
|
||||||
|
|
||||||
BackendExtras map[string]any // additional backend specific extras, e.g. for the mikrotik backend this contains the name of the peer
|
ImportSource string // import source (wgctrl, file, ...)
|
||||||
|
backendExtras any // additional backend-specific extras, e.g., domain.MikrotikPeerExtras
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p PhysicalPeer) GetPresharedKey() *wgtypes.Key {
|
func (p *PhysicalPeer) GetPresharedKey() *wgtypes.Key {
|
||||||
if p.PresharedKey == "" {
|
if p.PresharedKey == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -197,7 +198,7 @@ func (p PhysicalPeer) GetPresharedKey() *wgtypes.Key {
|
|||||||
return &key
|
return &key
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p PhysicalPeer) GetEndpointAddress() *net.UDPAddr {
|
func (p *PhysicalPeer) GetEndpointAddress() *net.UDPAddr {
|
||||||
if p.Endpoint == "" {
|
if p.Endpoint == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -209,7 +210,7 @@ func (p PhysicalPeer) GetEndpointAddress() *net.UDPAddr {
|
|||||||
return addr
|
return addr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p PhysicalPeer) GetPersistentKeepaliveTime() *time.Duration {
|
func (p *PhysicalPeer) GetPersistentKeepaliveTime() *time.Duration {
|
||||||
if p.PersistentKeepalive == 0 {
|
if p.PersistentKeepalive == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -218,7 +219,7 @@ func (p PhysicalPeer) GetPersistentKeepaliveTime() *time.Duration {
|
|||||||
return &keepAliveDuration
|
return &keepAliveDuration
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p PhysicalPeer) GetAllowedIPs() []net.IPNet {
|
func (p *PhysicalPeer) GetAllowedIPs() []net.IPNet {
|
||||||
allowedIPs := make([]net.IPNet, len(p.AllowedIPs))
|
allowedIPs := make([]net.IPNet, len(p.AllowedIPs))
|
||||||
for i, ip := range p.AllowedIPs {
|
for i, ip := range p.AllowedIPs {
|
||||||
allowedIPs[i] = *ip.IpNet()
|
allowedIPs[i] = *ip.IpNet()
|
||||||
@ -227,6 +228,20 @@ func (p PhysicalPeer) GetAllowedIPs() []net.IPNet {
|
|||||||
return allowedIPs
|
return allowedIPs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *PhysicalPeer) GetExtras() any {
|
||||||
|
return p.backendExtras
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PhysicalPeer) SetExtras(extras any) {
|
||||||
|
switch extras.(type) {
|
||||||
|
case MikrotikPeerExtras: // OK
|
||||||
|
default: // we only support MikrotikPeerExtras for now
|
||||||
|
panic(fmt.Sprintf("unsupported peer backend extras type %T", extras))
|
||||||
|
}
|
||||||
|
|
||||||
|
p.backendExtras = extras
|
||||||
|
}
|
||||||
|
|
||||||
func ConvertPhysicalPeer(pp *PhysicalPeer) *Peer {
|
func ConvertPhysicalPeer(pp *PhysicalPeer) *Peer {
|
||||||
peer := &Peer{
|
peer := &Peer{
|
||||||
Endpoint: NewConfigOption(pp.Endpoint, true),
|
Endpoint: NewConfigOption(pp.Endpoint, true),
|
||||||
@ -245,6 +260,27 @@ func ConvertPhysicalPeer(pp *PhysicalPeer) *Peer {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if pp.GetExtras() == nil {
|
||||||
|
return peer
|
||||||
|
}
|
||||||
|
|
||||||
|
// enrich the data with controller-specific extras
|
||||||
|
now := time.Now()
|
||||||
|
switch pp.ImportSource {
|
||||||
|
case ControllerTypeMikrotik:
|
||||||
|
extras := pp.GetExtras().(MikrotikPeerExtras)
|
||||||
|
peer.Notes = extras.Comment
|
||||||
|
peer.DisplayName = extras.Name
|
||||||
|
peer.Endpoint = NewConfigOption(extras.ClientEndpoint, true)
|
||||||
|
if extras.Disabled {
|
||||||
|
peer.Disabled = &now
|
||||||
|
peer.DisabledReason = "Disabled by Mikrotik controller"
|
||||||
|
} else {
|
||||||
|
peer.Disabled = nil
|
||||||
|
peer.DisabledReason = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return peer
|
return peer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,20 @@ import (
|
|||||||
"github.com/h44z/wg-portal/internal/config"
|
"github.com/h44z/wg-portal/internal/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// region models
|
||||||
|
|
||||||
|
const (
|
||||||
|
MikrotikApiStatusOk = "success"
|
||||||
|
MikrotikApiStatusError = "error"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MikrotikApiErrorCodeUnknown = iota + 600
|
||||||
|
MikrotikApiErrorCodeRequestPreparationFailed
|
||||||
|
MikrotikApiErrorCodeRequestFailed
|
||||||
|
MikrotikApiErrorCodeResponseDecodeFailed
|
||||||
|
)
|
||||||
|
|
||||||
type MikrotikApiResponse[T any] struct {
|
type MikrotikApiResponse[T any] struct {
|
||||||
Status string
|
Status string
|
||||||
Code int
|
Code int
|
||||||
@ -113,6 +127,10 @@ func (o *MikrotikRequestOptions) GetPath(base string) string {
|
|||||||
return path.String()
|
return path.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// region models
|
||||||
|
|
||||||
|
// region API-client
|
||||||
|
|
||||||
type MikrotikApiClient struct {
|
type MikrotikApiClient struct {
|
||||||
coreCfg *config.Config
|
coreCfg *config.Config
|
||||||
cfg *config.BackendMikrotik
|
cfg *config.BackendMikrotik
|
||||||
@ -192,18 +210,6 @@ func (m *MikrotikApiClient) prepareGetRequest(ctx context.Context, fullUrl strin
|
|||||||
return req, nil
|
return req, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
MikrotikApiStatusOk = "success"
|
|
||||||
MikrotikApiStatusError = "error"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
MikrotikApiErrorCodeUnknown = iota + 600
|
|
||||||
MikrotikApiErrorCodeRequestPreparationFailed
|
|
||||||
MikrotikApiErrorCodeRequestFailed
|
|
||||||
MikrotikApiErrorCodeResponseDecodeFailed
|
|
||||||
)
|
|
||||||
|
|
||||||
func errToApiResponse[T any](code int, message string, err error) MikrotikApiResponse[T] {
|
func errToApiResponse[T any](code int, message string, err error) MikrotikApiResponse[T] {
|
||||||
return MikrotikApiResponse[T]{
|
return MikrotikApiResponse[T]{
|
||||||
Status: MikrotikApiStatusError,
|
Status: MikrotikApiStatusError,
|
||||||
@ -289,3 +295,5 @@ func (m *MikrotikApiClient) Get(
|
|||||||
m.debugLog("retrieved API get result", "url", fullUrl, "duration", time.Since(start).String())
|
m.debugLog("retrieved API get result", "url", fullUrl, "duration", time.Since(start).String())
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// endregion API-client
|
||||||
|
Loading…
x
Reference in New Issue
Block a user