diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ed08ccd..6f182a2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,8 +19,8 @@ jobs: with: go-version: '1.19' - - name: Install make - run: sudo apt update && sudo apt install -y make + - name: Install dependencies + run: sudo apt update && sudo apt install -y make libpcap-dev - name: Build run: make diff --git a/go.mod b/go.mod index 4d38921..0eb6273 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/apenella/go-ansible v1.1.7 github.com/gdamore/tcell/v2 v2.6.0 github.com/golang/mock v1.6.0 - github.com/imdario/mergo v0.3.16 + github.com/google/gopacket v1.1.19 github.com/jackpal/gateway v1.0.10 github.com/projectdiscovery/mapcidr v1.1.2 github.com/rivo/tview v0.0.0-20230621164836-6cc0565babaf diff --git a/go.sum b/go.sum index 48feea8..a14bab1 100644 --- a/go.sum +++ b/go.sum @@ -155,6 +155,8 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= +github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -203,8 +205,6 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= -github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= diff --git a/internal/core/core_test.go b/internal/core/core_test.go index 27953b5..0ad9c61 100644 --- a/internal/core/core_test.go +++ b/internal/core/core_test.go @@ -28,6 +28,7 @@ func TestCore(t *testing.T) { mockDetailsScanner := mock_discovery.NewMockDetailScanner(ctrl) mockConfig := mock_config.NewMockService(ctrl) mockServerService := mock_server.NewMockService(ctrl) + resultChan := make(chan *discovery.DiscoveryResult) networkInfo := &util.NetworkInfo{ Hostname: "hostname", @@ -41,6 +42,7 @@ func TestCore(t *testing.T) { mockScanner, mockDetailsScanner, mockServerService, + resultChan, ) conf := config.Config{ @@ -229,11 +231,11 @@ func TestCore(t *testing.T) { Do(func([]string) { wg.Done() }) - mockScanner.EXPECT().Scan(gomock.Any()).DoAndReturn(func(rchan chan *discovery.DiscoveryResult) error { + mockScanner.EXPECT().Scan().DoAndReturn(func() error { defer wg.Done() go func() { for _, r := range discoveryResults { - rchan <- r + resultChan <- r } }() return nil diff --git a/internal/core/create.go b/internal/core/create.go index 6075cfb..9fa0dd1 100644 --- a/internal/core/create.go +++ b/internal/core/create.go @@ -83,7 +83,13 @@ func CreateNewAppCore(networkInfo *util.NetworkInfo) (*Core, error) { serverRepo := server.NewSqliteRepo(db) serverService := server.NewService(*conf, serverRepo) - netScanner, err := discovery.NewNetScanner(conf.Targets) + resultChan := make(chan *discovery.DiscoveryResult) + + netScanner, err := discovery.NewARPScanner( + networkInfo, + conf.Targets, + resultChan, + ) if err != nil { return nil, err @@ -95,6 +101,7 @@ func CreateNewAppCore(networkInfo *util.NetworkInfo) (*Core, error) { netScanner, detailScanner, serverService, + resultChan, ) return New( diff --git a/internal/discovery/arpscan.go b/internal/discovery/arpscan.go new file mode 100644 index 0000000..871f957 --- /dev/null +++ b/internal/discovery/arpscan.go @@ -0,0 +1,275 @@ +package discovery + +import ( + "bytes" + "context" + "net" + "regexp" + + "github.com/google/gopacket" + "github.com/google/gopacket/layers" + "github.com/google/gopacket/pcap" + "github.com/projectdiscovery/mapcidr" + "github.com/robgonnella/ops/internal/logger" + "github.com/robgonnella/ops/internal/server" + "github.com/robgonnella/ops/internal/util" + "github.com/rs/zerolog/log" +) + +var cidrSuffix = regexp.MustCompile(`\/\d{2}$`) + +type ARPScanner struct { + ctx context.Context + cancel context.CancelFunc + targets []string + networkInfo *util.NetworkInfo + handle *pcap.Handle + packetSource *gopacket.PacketSource + arpMap map[string]net.HardwareAddr + resultChan chan *DiscoveryResult + log logger.Logger +} + +func NewARPScanner( + networkInfo *util.NetworkInfo, + targets []string, + resultChan chan *DiscoveryResult, +) (*ARPScanner, error) { + ipList := []string{} + + for _, t := range targets { + if cidrSuffix.MatchString(t) { + ips, err := mapcidr.IPAddresses(t) + + if err != nil { + return nil, err + } + + ipList = append(ipList, ips...) + } else { + ipList = append(ipList, t) + } + } + + // Open up a pcap handle for packet reads/writes. + handle, err := pcap.OpenLive( + networkInfo.Interface.Name, + 65536, + true, + pcap.BlockForever, + ) + + if err != nil { + return nil, err + } + + src := gopacket.NewPacketSource(handle, layers.LayerTypeEthernet) + + ctx, cancel := context.WithCancel(context.Background()) + + scanner := &ARPScanner{ + ctx: ctx, + cancel: cancel, + targets: ipList, + handle: handle, + packetSource: src, + networkInfo: networkInfo, + arpMap: map[string]net.HardwareAddr{}, + resultChan: resultChan, + log: logger.New(), + } + + go scanner.readPackets() + + return scanner, nil +} + +func (s *ARPScanner) Scan() error { + return s.writeARP() +} + +func (s *ARPScanner) Stop() { + s.cancel() + s.handle.Close() +} + +func (s *ARPScanner) readPackets() { + for { + select { + case <-s.ctx.Done(): + return + case packet := <-s.packetSource.Packets(): + arpLayer := packet.Layer(layers.LayerTypeARP) + + if arpLayer != nil { + s.handleARPLayer(arpLayer.(*layers.ARP)) + continue + } + + s.handleNonARPPacket(packet) + } + } +} + +func (s *ARPScanner) handleARPLayer(arp *layers.ARP) { + if arp.Operation != layers.ARPReply { + // not an arp reply + return + } + + if bytes.Equal([]byte(s.networkInfo.Interface.HardwareAddr), arp.SourceHwAddress) { + // This is a packet I sent. + return + } + + ip := net.IP(arp.SourceProtAddress) + mac := net.HardwareAddr(arp.SourceHwAddress) + + s.arpMap[ip.String()] = mac + + s.writeSyn(ip, mac) +} + +func (s *ARPScanner) handleNonARPPacket(packet gopacket.Packet) { + // Find the packets we care about, and print out logging + // information about them. All others are ignored. + net := packet.NetworkLayer() + + if net == nil { + return + } + + srcIP := net.NetworkFlow().Src().String() + + mac, ok := s.arpMap[srcIP] + + if !ok { + return + } + + tcpLayer := packet.Layer(layers.LayerTypeTCP) + + if tcpLayer == nil { + return + } + + tcp, ok := tcpLayer.(*layers.TCP) + + if !ok { + // this should never happen. + return + } + + if tcp.DstPort != 54321 { + return + } + + if tcp.SrcPort != 22 { + return + } + + res := &DiscoveryResult{ + ID: mac.String(), + IP: srcIP, + Hostname: "", + OS: "", + Status: server.StatusOnline, + } + + port := Port{ + ID: 22, + Status: PortClosed, + } + + if tcp.SYN && tcp.ACK { + port.Status = PortOpen + } + + res.Ports = []Port{port} + + s.resultChan <- res +} + +func (s *ARPScanner) writeARP() error { + // Set up all the layers' fields we can. + eth := layers.Ethernet{ + SrcMAC: s.networkInfo.Interface.HardwareAddr, + DstMAC: net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + EthernetType: layers.EthernetTypeARP, + } + + arp := layers.ARP{ + AddrType: layers.LinkTypeEthernet, + Protocol: layers.EthernetTypeIPv4, + HwAddressSize: 6, + ProtAddressSize: 4, + Operation: layers.ARPRequest, + SourceHwAddress: []byte(s.networkInfo.Interface.HardwareAddr), + SourceProtAddress: []byte(s.networkInfo.UserIP.To4()), + DstHwAddress: []byte{0, 0, 0, 0, 0, 0}, + } + + // Set up buffer and options for serialization. + buf := gopacket.NewSerializeBuffer() + + opts := gopacket.SerializeOptions{ + FixLengths: true, + ComputeChecksums: true, + } + + // Send one packet for every address. + for _, ip := range s.targets { + arp.DstProtAddress = []byte(net.ParseIP(ip).To4()) + + if err := gopacket.SerializeLayers(buf, opts, ð, &arp); err != nil { + return err + } + + if err := s.handle.WritePacketData(buf.Bytes()); err != nil { + log.Error().Err(err).Msg("") + } + } + + return nil +} + +func (s *ARPScanner) writeSyn(ip net.IP, mac net.HardwareAddr) { + // Construct all the network layers we need. + eth := layers.Ethernet{ + SrcMAC: s.networkInfo.Interface.HardwareAddr, + DstMAC: mac, + EthernetType: layers.EthernetTypeIPv4, + } + + ip4 := layers.IPv4{ + SrcIP: s.networkInfo.UserIP.To4(), + DstIP: ip.To4(), + Version: 4, + TTL: 64, + Protocol: layers.IPProtocolTCP, + } + + tcp := layers.TCP{ + SrcPort: 54321, + DstPort: 22, + SYN: true, + } + + tcp.SetNetworkLayerForChecksum(&ip4) + + buf := gopacket.NewSerializeBuffer() + + opts := gopacket.SerializeOptions{ + FixLengths: true, + ComputeChecksums: true, + } + + if err := gopacket.SerializeLayers(buf, opts, ð, &ip4, &tcp); err != nil { + s.log.Error().Err(err).Msg("failed to serialize syn layers") + return + } + + if err := s.handle.WritePacketData(buf.Bytes()); err != nil { + s.log.Error().Err(err).Msg("failed to send syn packet") + } +} diff --git a/internal/discovery/interface.go b/internal/discovery/interface.go index 195bbfc..f75dc5d 100644 --- a/internal/discovery/interface.go +++ b/internal/discovery/interface.go @@ -1,6 +1,8 @@ package discovery -import "context" +import ( + "context" +) //go:generate mockgen -destination=../mock/discovery/mock_discovery.go -package=mock_discovery . DetailScanner,Scanner @@ -11,7 +13,7 @@ type DetailScanner interface { // Scanner interface for scanning a network for devices type Scanner interface { - Scan(resultChan chan *DiscoveryResult) error + Scan() error Stop() } diff --git a/internal/discovery/net.go b/internal/discovery/net.go deleted file mode 100644 index 632d307..0000000 --- a/internal/discovery/net.go +++ /dev/null @@ -1,113 +0,0 @@ -package discovery - -import ( - "crypto/sha1" - "encoding/hex" - "errors" - "net" - "regexp" - "strings" - "sync" - "time" - - "github.com/projectdiscovery/mapcidr" - "github.com/robgonnella/ops/internal/logger" - "github.com/robgonnella/ops/internal/server" -) - -var cidrSuffix = regexp.MustCompile(`\/\d{2}$`) - -type NetScanner struct { - canceled bool - targets []string - semaphore chan struct{} - log logger.Logger -} - -func NewNetScanner(targets []string) (*NetScanner, error) { - ipList := []string{} - - for _, t := range targets { - if cidrSuffix.MatchString(t) { - ips, err := mapcidr.IPAddresses(t) - - if err != nil { - return nil, err - } - - ipList = append(ipList, ips...) - } else { - ipList = append(ipList, t) - } - } - - return &NetScanner{ - canceled: false, - targets: ipList, - semaphore: make(chan struct{}, 1000), - log: logger.New(), - }, nil -} - -func (s *NetScanner) Scan(resultChan chan *DiscoveryResult) error { - if s.canceled { - return errors.New("network scanner is in a canceled state") - } - - s.log.Info().Msg("Scanning network...") - - wg := &sync.WaitGroup{} - - for _, ip := range s.targets { - s.semaphore <- struct{}{} // acquire - wg.Add(1) - go func(i string, w *sync.WaitGroup, res chan *DiscoveryResult) { - r := s.scanIP(i) - res <- r - <-s.semaphore // release - w.Done() - }(ip, wg, resultChan) - } - - wg.Wait() - - return nil -} - -func (s *NetScanner) Stop() { - s.canceled = true -} - -func (s *NetScanner) scanIP(ip string) *DiscoveryResult { - hashedIP := sha1.Sum([]byte(ip)) - id := hex.EncodeToString(hashedIP[:]) - - r := DiscoveryResult{ - ID: id, - Hostname: "", - IP: ip, - OS: "", - Status: server.StatusOffline, - } - - s.log.Debug().Str("ip", ip).Msg("Scanning target") - - timeOut := time.Millisecond * 200 - conn, err := net.DialTimeout("tcp", ip+":22", timeOut) - - if err != nil { - r.Ports = []Port{{ID: 22, Status: PortClosed}} - - if _, ok := err.(*net.OpError); ok { - if strings.HasSuffix(err.Error(), "connect: connection refused") { - r.Status = server.StatusOnline - } - } - } else { - defer conn.Close() - r.Status = server.StatusOnline - r.Ports = []Port{{ID: 22, Status: PortOpen}} - } - - return &r -} diff --git a/internal/discovery/nmap.go b/internal/discovery/nmap.go index f92c108..3ee16e8 100644 --- a/internal/discovery/nmap.go +++ b/internal/discovery/nmap.go @@ -13,14 +13,15 @@ import ( // NmapScanner is an implementation of the Scanner interface type NmapScanner struct { - ctx context.Context - cancel context.CancelFunc - scanner *nmap.Scanner - log logger.Logger + ctx context.Context + cancel context.CancelFunc + scanner *nmap.Scanner + resultChan chan *DiscoveryResult + log logger.Logger } // NewNmapScanner returns a new instance of NmapScanner -func NewNmapScanner(targets []string) (*NmapScanner, error) { +func NewNmapScanner(targets []string, resultChan chan *DiscoveryResult) (*NmapScanner, error) { log := logger.New() // Use a cancelable context so we can properly cleanup when needed @@ -41,10 +42,11 @@ func NewNmapScanner(targets []string) (*NmapScanner, error) { } return &NmapScanner{ - ctx: ctxWithCancel, - cancel: cancel, - log: log, - scanner: scanner, + ctx: ctxWithCancel, + cancel: cancel, + log: log, + scanner: scanner, + resultChan: resultChan, }, nil } @@ -55,7 +57,7 @@ func (s *NmapScanner) Stop() { } // scan targets and ports and return network results -func (s *NmapScanner) Scan(resultChan chan *DiscoveryResult) error { +func (s *NmapScanner) Scan() error { s.log.Info().Msg("Scanning network...") result, warnings, err := s.scanner.Run() @@ -120,7 +122,7 @@ func (s *NmapScanner) Scan(resultChan chan *DiscoveryResult) error { Ports: ports, } - resultChan <- res + s.resultChan <- res } return nil diff --git a/internal/discovery/service.go b/internal/discovery/service.go index e0d9bb4..7c108ba 100644 --- a/internal/discovery/service.go +++ b/internal/discovery/service.go @@ -15,6 +15,7 @@ type ScannerService struct { scanner Scanner detailScanner DetailScanner serverService server.Service + resultChan chan *DiscoveryResult log logger.Logger } @@ -23,6 +24,7 @@ func NewScannerService( scanner Scanner, detailScanner DetailScanner, serverService server.Service, + resultChan chan *DiscoveryResult, ) *ScannerService { log := logger.New() @@ -35,6 +37,7 @@ func NewScannerService( scanner: scanner, detailScanner: detailScanner, serverService: serverService, + resultChan: resultChan, log: log, } } @@ -58,12 +61,11 @@ func (s *ScannerService) Stop() { // make polling calls to scanner.Scan() func (s *ScannerService) pollNetwork() { ticker := time.NewTicker(time.Second * 30) - resultChan := make(chan *DiscoveryResult) // start first scan // always scan in goroutine to prevent blocking result channel go func() { - if err := s.scanner.Scan(resultChan); err != nil { + if err := s.scanner.Scan(); err != nil { s.cancel() } }() @@ -75,12 +77,12 @@ func (s *ScannerService) pollNetwork() { ticker.Stop() s.cancel() return - case r := <-resultChan: + case r := <-s.resultChan: s.handleDiscoveryResult(r) case <-ticker.C: // always scan in goroutine to prevent blocking result channel go func() { - if err := s.scanner.Scan(resultChan); err != nil { + if err := s.scanner.Scan(); err != nil { s.cancel() } }() diff --git a/internal/discovery/service_test.go b/internal/discovery/service_test.go index 2394535..f5cd2f1 100644 --- a/internal/discovery/service_test.go +++ b/internal/discovery/service_test.go @@ -20,11 +20,13 @@ func TestDiscoveryService(t *testing.T) { mockScanner := mock_discovery.NewMockScanner(ctrl) mockDetailScanner := mock_discovery.NewMockDetailScanner(ctrl) mockServerService := mock_server.NewMockService(ctrl) + resultChan := make(chan *discovery.DiscoveryResult) service := discovery.NewScannerService( mockScanner, mockDetailScanner, mockServerService, + resultChan, ) port := discovery.Port{ @@ -41,9 +43,9 @@ func TestDiscoveryService(t *testing.T) { Ports: []discovery.Port{port}, } - mockScanner.EXPECT().Scan(gomock.Any()).DoAndReturn(func(rchan chan *discovery.DiscoveryResult) error { + mockScanner.EXPECT().Scan().DoAndReturn(func() error { go func() { - rchan <- result + resultChan <- result }() return nil }) @@ -61,11 +63,13 @@ func TestDiscoveryService(t *testing.T) { mockScanner := mock_discovery.NewMockScanner(ctrl) mockDetailScanner := mock_discovery.NewMockDetailScanner(ctrl) mockServerService := mock_server.NewMockService(ctrl) + resultChan := make(chan *discovery.DiscoveryResult) service := discovery.NewScannerService( mockScanner, mockDetailScanner, mockServerService, + resultChan, ) port := discovery.Port{ @@ -91,9 +95,9 @@ func TestDiscoveryService(t *testing.T) { SshStatus: server.SSHDisabled, } - mockScanner.EXPECT().Scan(gomock.Any()).DoAndReturn(func(rchan chan *discovery.DiscoveryResult) error { + mockScanner.EXPECT().Scan().DoAndReturn(func() error { go func() { - rchan <- result + resultChan <- result }() return nil }) @@ -111,11 +115,13 @@ func TestDiscoveryService(t *testing.T) { mockScanner := mock_discovery.NewMockScanner(ctrl) mockDetailScanner := mock_discovery.NewMockDetailScanner(ctrl) mockServerService := mock_server.NewMockService(ctrl) + resultChan := make(chan *discovery.DiscoveryResult) service := discovery.NewScannerService( mockScanner, mockDetailScanner, mockServerService, + resultChan, ) port := discovery.Port{ @@ -146,9 +152,9 @@ func TestDiscoveryService(t *testing.T) { SshStatus: server.SSHEnabled, } - mockScanner.EXPECT().Scan(gomock.Any()).DoAndReturn(func(rchan chan *discovery.DiscoveryResult) error { + mockScanner.EXPECT().Scan().DoAndReturn(func() error { go func() { - rchan <- result + resultChan <- result }() return nil }) diff --git a/internal/mock/discovery/mock_discovery.go b/internal/mock/discovery/mock_discovery.go index d0364a5..874ec2f 100644 --- a/internal/mock/discovery/mock_discovery.go +++ b/internal/mock/discovery/mock_discovery.go @@ -74,17 +74,17 @@ func (m *MockScanner) EXPECT() *MockScannerMockRecorder { } // Scan mocks base method. -func (m *MockScanner) Scan(arg0 chan *discovery.DiscoveryResult) error { +func (m *MockScanner) Scan() error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Scan", arg0) + ret := m.ctrl.Call(m, "Scan") ret0, _ := ret[0].(error) return ret0 } // Scan indicates an expected call of Scan. -func (mr *MockScannerMockRecorder) Scan(arg0 interface{}) *gomock.Call { +func (mr *MockScannerMockRecorder) Scan() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Scan", reflect.TypeOf((*MockScanner)(nil).Scan), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Scan", reflect.TypeOf((*MockScanner)(nil).Scan)) } // Stop mocks base method. diff --git a/internal/server/repo.go b/internal/server/repo.go index cb839ce..d77ddde 100644 --- a/internal/server/repo.go +++ b/internal/server/repo.go @@ -45,9 +45,9 @@ func (r *SqliteRepo) GetServerByID(serverID string) (*Server, error) { // GetServerByIP returns a server from the SqliteRepo based on current ip func (r *SqliteRepo) GetServerByIP(ip string) (*Server, error) { - server := Server{IP: ip} + server := Server{} - if result := r.db.First(&server); result.Error != nil { + if result := r.db.First(&server, "ip = ?", ip); result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { return nil, exception.ErrRecordNotFound } @@ -86,7 +86,7 @@ func (r *SqliteRepo) UpdateServer(server *Server) (*Server, error) { return nil, errors.New("server id cannot be empty") } - if result := r.db.Save(server); result.Error != nil { + if result := r.db.Updates(server); result.Error != nil { return nil, result.Error } diff --git a/internal/server/service.go b/internal/server/service.go index e0c9787..fff1b29 100644 --- a/internal/server/service.go +++ b/internal/server/service.go @@ -5,7 +5,6 @@ import ( "net" "sync" - "github.com/imdario/mergo" "github.com/robgonnella/ops/internal/config" "github.com/robgonnella/ops/internal/event" "github.com/robgonnella/ops/internal/exception" @@ -82,10 +81,6 @@ func (s *ServerService) GetAllServersInNetworkTargets(targets []string) ([]*Serv if err != nil { // non CIDR target just check if target matches IP if server.IP == target { - s.log.Debug(). - Str("serverIP", server.IP). - Str("target", target). - Msg("serverIP matches network target") result = append(result, server) break } @@ -105,12 +100,14 @@ func (s *ServerService) GetAllServersInNetworkTargets(targets []string) ([]*Serv } } + // s.log.Error().Interface("result", result).Msg("returning all servers in target") + return result, nil } // AddOrUpdateServer adds or updates a server func (s *ServerService) AddOrUpdateServer(req *Server) error { - currentServer, err := s.repo.GetServerByID(req.ID) + _, err := s.repo.GetServerByID(req.ID) if errors.Is(err, exception.ErrRecordNotFound) { // handle add case @@ -132,8 +129,6 @@ func (s *ServerService) AddOrUpdateServer(req *Server) error { // handle update case - mergo.Merge(req, currentServer) - updatedServer, err := s.repo.UpdateServer(req) if err != nil { diff --git a/internal/ui/component/event.go b/internal/ui/component/event.go index 2f2db61..de6973c 100644 --- a/internal/ui/component/event.go +++ b/internal/ui/component/event.go @@ -24,7 +24,7 @@ func NewEventTable() *EventTable { "EVENT TYPE", "HOSTNAME", "IP", - "ID", + "MAC", "OS", "SSH", "STATUS", diff --git a/internal/ui/component/server.go b/internal/ui/component/server.go index 9237a30..d610188 100644 --- a/internal/ui/component/server.go +++ b/internal/ui/component/server.go @@ -18,7 +18,7 @@ type ServerTable struct { // NewServerTable returns a new instance of ServerTable func NewServerTable(hostHostname, hostIP string, OnSSH func(ip string)) *ServerTable { - columnHeaders := []string{"HOSTNAME", "IP", "ID", "OS", "SSH", "STATUS"} + columnHeaders := []string{"HOSTNAME", "IP", "MAC", "OS", "SSH", "STATUS"} table := createTable("servers", columnHeaders)