diff --git a/Dockerfile b/Dockerfile index cbb32b6..f3c3404 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.23-alpine AS dev +FROM golang:1.25-alpine AS dev RUN go install github.com/air-verse/air@latest WORKDIR /app COPY . /app/ diff --git a/app/app.go b/app/app.go index 05c3975..ef90f42 100644 --- a/app/app.go +++ b/app/app.go @@ -2,6 +2,9 @@ package app import ( "context" + "net/http" + "os" + "github.com/megadata-dev/go-snmp-olt-zte-c320/config" "github.com/megadata-dev/go-snmp-olt-zte-c320/internal/handler" "github.com/megadata-dev/go-snmp-olt-zte-c320/internal/repository" @@ -12,18 +15,30 @@ import ( "github.com/megadata-dev/go-snmp-olt-zte-c320/pkg/snmp" rds "github.com/redis/go-redis/v9" "github.com/rs/zerolog/log" - "net/http" - "os" ) +// App represents the main application structure that holds the HTTP router +// and manages the application lifecycle including dependencies initialization +// and server startup. type App struct { router http.Handler } +// New creates and returns a new instance of the App with initialized dependencies. +// It prepares the application for startup but does not start the server. func New() *App { return &App{} } +// Start initializes the application components, sets up connections to external services +// (Redis and SNMP), and starts the HTTP server. It handles graceful shutdown on context +// cancellation and ensures proper cleanup of resources. +// +// Parameters: +// - ctx: context.Context for cancellation and timeout propagation +// +// Returns: +// - error: returns any error that occurs during application startup or shutdown func (a *App) Start(ctx context.Context) error { // Get config path from APP_ENV environment variable diff --git a/app/routes.go b/app/routes.go index 83193c3..da190a9 100644 --- a/app/routes.go +++ b/app/routes.go @@ -1,13 +1,14 @@ package app import ( + "net/http" + "os" + "github.com/go-chi/chi/v5" "github.com/megadata-dev/go-snmp-olt-zte-c320/internal/handler" "github.com/megadata-dev/go-snmp-olt-zte-c320/internal/middleware" "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "net/http" - "os" ) func loadRoutes(onuHandler *handler.OnuHandler) http.Handler { diff --git a/cmd/api/main.go b/cmd/api/main.go index 40d7594..86d7e8f 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -2,6 +2,7 @@ package main import ( "context" + "github.com/megadata-dev/go-snmp-olt-zte-c320/app" "github.com/rs/zerolog/log" ) diff --git a/config/config.go b/config/config.go index af72b68..52c88b9 100644 --- a/config/config.go +++ b/config/config.go @@ -6,6 +6,8 @@ import ( "github.com/spf13/viper" ) +// Config represents the main application configuration structure +// that contains all sub-configurations for SNMP, Redis, OLT, and individual PON boards. type Config struct { SnmpCfg SnmpConfig RedisCfg RedisConfig @@ -44,12 +46,16 @@ type Config struct { Board2Pon16 Board2Pon16 } +// SnmpConfig contains configuration parameters for SNMP connection +// including target IP address, port, and community string. type SnmpConfig struct { - Ip string `mapstructure:"ip"` + IP string `mapstructure:"ip"` // Target IP address of the SNMP device Port uint16 `mapstructure:"port"` Community string `mapstructure:"community"` } +// RedisConfig contains configuration parameters for Redis connection +// including host, port, authentication, and connection pooling settings. type RedisConfig struct { Host string `mapstructure:"host"` Port string `mapstructure:"port"` @@ -61,6 +67,8 @@ type RedisConfig struct { PoolTimeout int `mapstructure:"pool_timeout"` } +// OltConfig contains base OID configurations for OLT device management +// including common OIDs for ONU identification and type mapping. type OltConfig struct { BaseOID1 string `mapstructure:"base_oid_1"` BaseOID2 string `mapstructure:"base_oid_2"` @@ -68,6 +76,8 @@ type OltConfig struct { OnuTypeAllPon string `mapstructure:"onu_type"` } +// Board1Pon1 contains OID configurations for Board 1 Port 1 ONU management +// including identifiers, status, power levels, and diagnostic information. type Board1Pon1 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -83,6 +93,7 @@ type Board1Pon1 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board1Pon2 contains OID configurations for Board 1 Port 2 ONU management. type Board1Pon2 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -98,6 +109,7 @@ type Board1Pon2 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board1Pon3 contains OID configurations for Board 1 Port 3 ONU management. type Board1Pon3 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -113,6 +125,7 @@ type Board1Pon3 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board1Pon4 contains OID configurations for Board 1 Port 4 ONU management. type Board1Pon4 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -128,6 +141,7 @@ type Board1Pon4 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board1Pon5 contains OID configurations for Board 1 Port 5 ONU management. type Board1Pon5 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -143,6 +157,7 @@ type Board1Pon5 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board1Pon6 contains OID configurations for Board 1 Port 6 ONU management. type Board1Pon6 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -158,6 +173,7 @@ type Board1Pon6 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board1Pon7 contains OID configurations for Board 1 Port 7 ONU management. type Board1Pon7 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -173,6 +189,7 @@ type Board1Pon7 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board1Pon8 contains OID configurations for Board 1 Port 8 ONU management. type Board1Pon8 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -188,6 +205,7 @@ type Board1Pon8 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board1Pon9 contains OID configurations for Board 1 Port 9 ONU management. type Board1Pon9 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -203,6 +221,7 @@ type Board1Pon9 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board1Pon10 contains OID configurations for Board 1 Port 10 ONU management. type Board1Pon10 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -218,6 +237,7 @@ type Board1Pon10 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board1Pon11 contains OID configurations for Board 1 Port 11 ONU management. type Board1Pon11 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -233,6 +253,7 @@ type Board1Pon11 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board1Pon12 contains OID configurations for Board 1 Port 12 ONU management. type Board1Pon12 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -248,6 +269,7 @@ type Board1Pon12 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board1Pon13 contains OID configurations for Board 1 Port 13 ONU management. type Board1Pon13 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -263,6 +285,7 @@ type Board1Pon13 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board1Pon14 contains OID configurations for Board 1 Port 14 ONU management. type Board1Pon14 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -278,6 +301,7 @@ type Board1Pon14 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board1Pon15 contains OID configurations for Board 1 Port 15 ONU management. type Board1Pon15 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -293,6 +317,7 @@ type Board1Pon15 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board1Pon16 contains OID configurations for Board 1 Port 16 ONU management. type Board1Pon16 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -307,6 +332,8 @@ type Board1Pon16 struct { OnuLastOfflineReasonOID string `mapstructure:"onu_last_offline_reason"` OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } + +// Board2Pon1 contains OID configurations for Board 2 Port 1 ONU management. type Board2Pon1 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -322,6 +349,7 @@ type Board2Pon1 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board2Pon2 contains OID configurations for Board 2 Port 2 ONU management. type Board2Pon2 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -337,6 +365,7 @@ type Board2Pon2 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board2Pon3 contains OID configurations for Board 2 Port 3 ONU management. type Board2Pon3 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -352,6 +381,7 @@ type Board2Pon3 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board2Pon4 contains OID configurations for Board 2 Port 4 ONU management. type Board2Pon4 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -367,6 +397,7 @@ type Board2Pon4 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board2Pon5 contains OID configurations for Board 2 Port 5 ONU management. type Board2Pon5 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -382,6 +413,7 @@ type Board2Pon5 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board2Pon6 contains OID configurations for Board 2 Port 6 ONU management. type Board2Pon6 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -397,6 +429,7 @@ type Board2Pon6 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board2Pon7 contains OID configurations for Board 2 Port 7 ONU management. type Board2Pon7 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -412,6 +445,7 @@ type Board2Pon7 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board2Pon8 contains OID configurations for Board 2 Port 8 ONU management. type Board2Pon8 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -427,6 +461,7 @@ type Board2Pon8 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board2Pon9 contains OID configurations for Board 2 Port 9 ONU management. type Board2Pon9 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -442,6 +477,7 @@ type Board2Pon9 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board2Pon10 contains OID configurations for Board 2 Port 10 ONU management. type Board2Pon10 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -457,6 +493,7 @@ type Board2Pon10 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board2Pon11 contains OID configurations for Board 2 Port 11 ONU management. type Board2Pon11 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -472,6 +509,7 @@ type Board2Pon11 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board2Pon12 contains OID configurations for Board 2 Port 12 ONU management. type Board2Pon12 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -487,6 +525,7 @@ type Board2Pon12 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board2Pon13 contains OID configurations for Board 2 Port 13 ONU management. type Board2Pon13 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -502,6 +541,7 @@ type Board2Pon13 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board2Pon14 contains OID configurations for Board 2 Port 14 ONU management. type Board2Pon14 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -517,6 +557,7 @@ type Board2Pon14 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board2Pon15 contains OID configurations for Board 2 Port 15 ONU management. type Board2Pon15 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` @@ -532,6 +573,7 @@ type Board2Pon15 struct { OnuGponOpticalDistanceOID string `mapstructure:"onu_gpon_optical_distance"` } +// Board2Pon16 contains OID configurations for Board 2 Port 16 ONU management. type Board2Pon16 struct { OnuIDNameOID string `mapstructure:"onu_id_name"` OnuTypeOID string `mapstructure:"onu_type"` diff --git a/docker-compose.yaml b/docker-compose.yaml index 7fe0df1..6133313 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,7 +1,7 @@ services: app: - image: sumitroajiprabowo/go-snmp-olt-zte-c320:latest - container_name: go-snmp-olt-zte-c320 + image: cepatkilatteknologi/go-snmp-olt-zte-c320:latest + container_name: snmp-olt-zte-c320 environment: - REDIS_HOST=redis - REDIS_PORT=6379 @@ -18,7 +18,7 @@ services: - "8081:8081" redis: - container_name: redis + container_name: redis-snmp-olt-zte-c320 image: redis:7.2 ports: - "6379:6379" \ No newline at end of file diff --git a/internal/handler/onu.go b/internal/handler/onu.go index afe814a..2c3992a 100644 --- a/internal/handler/onu.go +++ b/internal/handler/onu.go @@ -12,6 +12,7 @@ import ( "github.com/rs/zerolog/log" ) +// OnuHandlerInterface is an interface that represent the auth's handler contract type OnuHandlerInterface interface { GetByBoardIDAndPonID(w http.ResponseWriter, r *http.Request) GetByBoardIDPonIDAndOnuID(w http.ResponseWriter, r *http.Request) @@ -21,14 +22,18 @@ type OnuHandlerInterface interface { GetByBoardIDAndPonIDWithPaginate(w http.ResponseWriter, r *http.Request) } +// OnuHandler is a struct that represent the auth handler type OnuHandler struct { ponUsecase usecase.OnuUseCaseInterface } +// NewOnuHandler will create an object that represent the auth handler func NewOnuHandler(ponUsecase usecase.OnuUseCaseInterface) *OnuHandler { return &OnuHandler{ponUsecase: ponUsecase} } +// GetByBoardIDAndPonID is a method to get onu info by board id and pon id +// example: http://localhost:8080/board/1/pon/1 func (o *OnuHandler) GetByBoardIDAndPonID(w http.ResponseWriter, r *http.Request) { boardID := chi.URLParam(r, "board_id") // 1 or 2 @@ -97,6 +102,8 @@ func (o *OnuHandler) GetByBoardIDAndPonID(w http.ResponseWriter, r *http.Request } +// GetByBoardIDPonIDAndOnuID is a method to get onu info by board id, pon id, and onu id +// example: http://localhost:8080/board/1/pon/1/onu func (o *OnuHandler) GetByBoardIDPonIDAndOnuID(w http.ResponseWriter, r *http.Request) { boardID := chi.URLParam(r, "board_id") // 1 or 2 @@ -165,6 +172,8 @@ func (o *OnuHandler) GetByBoardIDPonIDAndOnuID(w http.ResponseWriter, r *http.Re utils.SendJSONResponse(w, http.StatusOK, response) // 200 } +// GetEmptyOnuID is a method to get empty onu id by board id and pon id +// example: http://localhost:8080/board/1/pon/1/empty func (o *OnuHandler) GetEmptyOnuID(w http.ResponseWriter, r *http.Request) { boardID := chi.URLParam(r, "board_id") // 1 or 2 @@ -211,6 +220,8 @@ func (o *OnuHandler) GetEmptyOnuID(w http.ResponseWriter, r *http.Request) { utils.SendJSONResponse(w, http.StatusOK, response) // 200 } +// GetOnuIDAndSerialNumber is a method to get onu id and serial number by board id and pon id +// example: http://localhost:8080/board/1/pon/1/serial func (o *OnuHandler) GetOnuIDAndSerialNumber(w http.ResponseWriter, r *http.Request) { boardID := chi.URLParam(r, "board_id") // 1 or 2 @@ -257,6 +268,8 @@ func (o *OnuHandler) GetOnuIDAndSerialNumber(w http.ResponseWriter, r *http.Requ utils.SendJSONResponse(w, http.StatusOK, response) // 200 } +// UpdateEmptyOnuID is a method to update empty onu id by board id and pon id +// example: http://localhost:8080/board/1/pon/1/empty func (o *OnuHandler) UpdateEmptyOnuID(w http.ResponseWriter, r *http.Request) { boardID := chi.URLParam(r, "board_id") // 1 or 2 ponID := chi.URLParam(r, "pon_id") // 1 - 8 @@ -302,6 +315,8 @@ func (o *OnuHandler) UpdateEmptyOnuID(w http.ResponseWriter, r *http.Request) { utils.SendJSONResponse(w, http.StatusOK, response) // 200 } +// GetByBoardIDAndPonIDWithPaginate is a method to get onu info by board id and pon id with pagination +// example: http://localhost:8080/board/1/pon/1/paginate?page=1&page_size=10 func (o *OnuHandler) GetByBoardIDAndPonIDWithPaginate(w http.ResponseWriter, r *http.Request) { boardID := chi.URLParam(r, "board_id") // 1 or 2 diff --git a/internal/middleware/cors.go b/internal/middleware/cors.go index 193bcca..36d7db0 100644 --- a/internal/middleware/cors.go +++ b/internal/middleware/cors.go @@ -1,10 +1,13 @@ package middleware import ( - "github.com/go-chi/cors" "net/http" + + "github.com/go-chi/cors" ) +// CorsMiddleware is a middleware function that sets up CORS (Cross-Origin Resource Sharing) +// for the HTTP server. It allows requests from any origin and supports common HTTP methods func CorsMiddleware() func(next http.Handler) http.Handler { return cors.Handler(cors.Options{ AllowedOrigins: []string{"https://*", "http://*"}, diff --git a/internal/middleware/logger.go b/internal/middleware/logger.go index 75bf5ef..b3be87d 100644 --- a/internal/middleware/logger.go +++ b/internal/middleware/logger.go @@ -9,6 +9,10 @@ import ( "github.com/rs/zerolog" ) +// Logger is a middleware function that logs incoming HTTP requests and their details +// using the provided zerolog.Logger instance. It captures information such as request +// time, remote address, request path, protocol, method, user agent, response status, +// bytes in/out, and elapsed time. It also handles panics and logs them as errors func Logger(logger zerolog.Logger) func(next http.Handler) http.Handler { return func(next http.Handler) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { @@ -25,7 +29,7 @@ func Logger(logger zerolog.Logger) func(next http.Handler) http.Handler { } logger.Info().Fields(map[string]interface{}{ - "time": startTime.Format(time.RFC3339), // Format waktu RFC3339 + "time": startTime.Format(time.RFC3339), // Format using RFC3339 "remote_addr": r.RemoteAddr, "path": r.URL.Path, "proto": r.Proto, diff --git a/internal/model/onu.go b/internal/model/onu.go index 1a372fb..f1dcd6a 100644 --- a/internal/model/onu.go +++ b/internal/model/onu.go @@ -1,5 +1,6 @@ package model +// OltConfig struct is a struct that represent the OLT configuration type OltConfig struct { BaseOID string OnuIDNameOID string @@ -16,11 +17,13 @@ type OltConfig struct { OnuGponOpticalDistanceOID string } +// ONUInfo struct is a struct that represent the ONU information type ONUInfo struct { ID string `json:"onu_id"` Name string `json:"name"` } +// ONUInfoPerBoard struct is a struct that represent the ONU information per board type ONUInfoPerBoard struct { Board int `json:"board"` PON int `json:"pon"` @@ -32,6 +35,7 @@ type ONUInfoPerBoard struct { Status string `json:"status"` } +// ONUCustomerInfo struct is a struct that represent the detailed ONU information for customer type ONUCustomerInfo struct { Board int `json:"board"` PON int `json:"pon"` @@ -52,16 +56,19 @@ type ONUCustomerInfo struct { GponOpticalDistance string `json:"gpon_optical_distance"` } +// OnuID struct is a struct that represent the ONU ID type OnuID struct { Board int `json:"board"` PON int `json:"pon"` ID int `json:"onu_id"` } +// OnuOnlyID struct is a struct that represent only the ONU ID without board and PON type OnuOnlyID struct { ID int `json:"onu_id"` } +// SNMPWalkTask struct is a struct that represent the SNMP walk task type SNMPWalkTask struct { BaseOID string TargetOID string @@ -69,6 +76,7 @@ type SNMPWalkTask struct { PON int } +// OnuSerialNumber struct is a struct that represent the ONU serial number type OnuSerialNumber struct { Board int `json:"board"` PON int `json:"pon"` @@ -76,6 +84,7 @@ type OnuSerialNumber struct { SerialNumber string `json:"serial_number"` } +// PaginationResult struct is a struct that represent the pagination result type PaginationResult struct { OnuInformationList []ONUInfoPerBoard Count int diff --git a/internal/repository/redis.go b/internal/repository/redis.go index 6c4c7cc..3d7ac88 100644 --- a/internal/repository/redis.go +++ b/internal/repository/redis.go @@ -3,22 +3,23 @@ package repository import ( "context" "encoding/json" + "time" + "github.com/megadata-dev/go-snmp-olt-zte-c320/internal/model" "github.com/pkg/errors" "github.com/redis/go-redis/v9" "github.com/rs/zerolog/log" - "time" ) // OnuRedisRepositoryInterface is an interface that represent the auth's repository contract type OnuRedisRepositoryInterface interface { GetOnuIDCtx(ctx context.Context, key string) ([]model.OnuID, error) - SetOnuIDCtx(ctx context.Context, key string, seconds int, onuId []model.OnuID) error + SetOnuIDCtx(ctx context.Context, key string, seconds int, onuID []model.OnuID) error DeleteOnuIDCtx(ctx context.Context, key string) error SaveONUInfoList(ctx context.Context, key string, seconds int, onuInfoList []model.ONUInfoPerBoard) error GetONUInfoList(ctx context.Context, key string) ([]model.ONUInfoPerBoard, error) GetOnlyOnuIDCtx(ctx context.Context, key string) ([]model.OnuOnlyID, error) - SaveOnlyOnuIDCtx(ctx context.Context, key string, seconds int, onuId []model.OnuOnlyID) error + SaveOnlyOnuIDCtx(ctx context.Context, key string, seconds int, onuID []model.OnuOnlyID) error } // Auth redis repository @@ -39,18 +40,18 @@ func (r *onuRedisRepo) GetOnuIDCtx(ctx context.Context, key string) ([]model.Onu return nil, errors.Wrap(err, "onuRedisRepo.GetOnuIDCtx.redisClient.Get") } - var onuId []model.OnuID - if err := json.Unmarshal(onuBytes, &onuId); err != nil { + var onuID []model.OnuID + if err := json.Unmarshal(onuBytes, &onuID); err != nil { log.Error().Err(err).Msg("Failed to unmarshal onu id") return nil, errors.Wrap(err, "onuRedisRepo.GetOnuIDCtx.json.Unmarshal") } - return onuId, nil + return onuID, nil } // SetOnuIDCtx is a method to set onu id to redis -func (r *onuRedisRepo) SetOnuIDCtx(ctx context.Context, key string, seconds int, onuId []model.OnuID) error { - onuBytes, err := json.Marshal(onuId) +func (r *onuRedisRepo) SetOnuIDCtx(ctx context.Context, key string, seconds int, onuID []model.OnuID) error { + onuBytes, err := json.Marshal(onuID) if err != nil { log.Error().Err(err).Msg("Failed to marshal onu id") return errors.Wrap(err, "setRedisRepo.SetNewsCtx.json.Marshal") @@ -117,18 +118,18 @@ func (r *onuRedisRepo) GetOnlyOnuIDCtx(ctx context.Context, key string) ([]model return nil, errors.Wrap(err, "onuRedisRepo.GetOnlyOnuIDCtx.redisClient.Get") } - var onuId []model.OnuOnlyID - if err := json.Unmarshal(onuBytes, &onuId); err != nil { + var onuID []model.OnuOnlyID + if err := json.Unmarshal(onuBytes, &onuID); err != nil { log.Error().Err(err).Msg("Failed to unmarshal onu id") return nil, errors.Wrap(err, "onuRedisRepo.GetOnlyOnuIDCtx.json.Unmarshal") } - return onuId, nil + return onuID, nil } // SaveOnlyOnuIDCtx is a method to save only onu id to redis -func (r *onuRedisRepo) SaveOnlyOnuIDCtx(ctx context.Context, key string, seconds int, onuId []model.OnuOnlyID) error { - onuBytes, err := json.Marshal(onuId) +func (r *onuRedisRepo) SaveOnlyOnuIDCtx(ctx context.Context, key string, seconds int, onuID []model.OnuOnlyID) error { + onuBytes, err := json.Marshal(onuID) if err != nil { log.Error().Err(err).Msg("Failed to marshal onu id") return errors.Wrap(err, "onuRedisRepo.SaveOnlyOnuIDCtx.json.Marshal") diff --git a/internal/repository/snmp.go b/internal/repository/snmp.go index 770891e..e4647af 100644 --- a/internal/repository/snmp.go +++ b/internal/repository/snmp.go @@ -2,6 +2,7 @@ package repository import ( "fmt" + "net" "time" "github.com/gosnmp/gosnmp" @@ -53,7 +54,12 @@ func (r *snmpRepository) Get(oids []string) (*gosnmp.SnmpPacket, error) { if err != nil { return nil, err } - defer snmp.Conn.Close() + defer func(Conn net.Conn) { + err := Conn.Close() + if err != nil { + fmt.Printf("Error closing SNMP connection: %v\n", err) + } + }(snmp.Conn) result, err := snmp.Get(oids) if err != nil { @@ -68,7 +74,12 @@ func (r *snmpRepository) Walk(oid string, walkFunc func(pdu gosnmp.SnmpPDU) erro if err != nil { return err } - defer snmp.Conn.Close() + defer func(Conn net.Conn) { + err := Conn.Close() + if err != nil { + fmt.Printf("Error closing SNMP connection: %v\n", err) + } + }(snmp.Conn) err = snmp.Walk(oid, walkFunc) if err != nil { diff --git a/internal/usecase/onu.go b/internal/usecase/onu.go index 24de2b2..a834762 100644 --- a/internal/usecase/onu.go +++ b/internal/usecase/onu.go @@ -17,6 +17,7 @@ import ( "golang.org/x/sync/singleflight" ) +// OnuUseCaseInterface is an interface that represent the auth's usecase contract type OnuUseCaseInterface interface { GetByBoardIDAndPonID(ctx context.Context, boardID, ponID int) ([]model.ONUInfoPerBoard, error) GetByBoardIDPonIDAndOnuID(boardID, ponID, onuID int) (model.ONUCustomerInfo, error) @@ -28,6 +29,7 @@ type OnuUseCaseInterface interface { ) } +// onuUsecase represent the auth's usecase type onuUsecase struct { snmpRepository repository.SnmpRepositoryInterface redisRepository repository.OnuRedisRepositoryInterface @@ -35,6 +37,7 @@ type onuUsecase struct { sg singleflight.Group } +// NewOnuUsecase will create an object that represent the auth usecase func NewOnuUsecase( snmpRepository repository.SnmpRepositoryInterface, redisRepository repository.OnuRedisRepositoryInterface, cfg *config.Config, @@ -791,7 +794,7 @@ func (u *onuUsecase) GetByBoardIDPonIDAndOnuID(boardID, ponID, onuID int) ( onuInfo.Uptime = uptime } - // Get Data ONU Last Down Time Duration from SNMP Walk using getLastDownDuration method + // Get Data ONU Last Downtime Duration from SNMP Walk using getLastDownDuration method if downtime, err := u.getLastDownDuration(onuInfo.LastOffline, onuInfo.LastOnline); err == nil { onuInfo.LastDownTimeDuration = downtime } @@ -1164,7 +1167,7 @@ func (u *onuUsecase) GetByBoardIDAndPonIDWithPagination( return nil, 0 } - // Extract the result from the simpleflight result and return it + // Extract the result from the simple flight result and return it paginationResult := result.(model.PaginationResult) return paginationResult.OnuInformationList, paginationResult.Count diff --git a/internal/utils/converter_test.go b/internal/utils/converter_test.go index 4c23961..35a3170 100644 --- a/internal/utils/converter_test.go +++ b/internal/utils/converter_test.go @@ -1,9 +1,10 @@ package utils import ( - "github.com/stretchr/testify/assert" "testing" "time" + + "github.com/stretchr/testify/assert" ) func TestConvertStringToUint16(t *testing.T) { diff --git a/internal/utils/error.go b/internal/utils/error.go index 9b14286..09ffd80 100644 --- a/internal/utils/error.go +++ b/internal/utils/error.go @@ -5,6 +5,7 @@ import ( "net/http" ) +// SendJSONResponse is a helper function to send a JSON response func SendJSONResponse(w http.ResponseWriter, statusCode int, response interface{}) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(statusCode) @@ -14,6 +15,7 @@ func SendJSONResponse(w http.ResponseWriter, statusCode int, response interface{ } } +// ErrorBadRequest is a helper function to send a 400 Bad Request response func ErrorBadRequest(w http.ResponseWriter, err error) { webResponse := ErrorResponse{ Code: http.StatusBadRequest, @@ -23,6 +25,7 @@ func ErrorBadRequest(w http.ResponseWriter, err error) { SendJSONResponse(w, http.StatusBadRequest, webResponse) } +// ErrorInternalServerError is a helper function to send a 500 Internal Server Error response func ErrorInternalServerError(w http.ResponseWriter, err error) { webResponse := ErrorResponse{ Code: http.StatusInternalServerError, @@ -32,6 +35,7 @@ func ErrorInternalServerError(w http.ResponseWriter, err error) { SendJSONResponse(w, http.StatusInternalServerError, webResponse) } +// ErrorNotFound is a helper function to send a 404 Not Found response func ErrorNotFound(w http.ResponseWriter, err error) { webResponse := ErrorResponse{ Code: http.StatusNotFound, diff --git a/internal/utils/error_test.go b/internal/utils/error_test.go index 027f9fc..d56936c 100644 --- a/internal/utils/error_test.go +++ b/internal/utils/error_test.go @@ -3,32 +3,32 @@ package utils import ( "encoding/json" "errors" - "github.com/megadata-dev/go-snmp-olt-zte-c320/internal/model" "net/http" "net/http/httptest" "testing" + + "github.com/megadata-dev/go-snmp-olt-zte-c320/internal/model" ) func TestSendJSONResponse(t *testing.T) { - // Inisialisasi ResponseWriter dan Request + // Initiate ResponseWriter dan Request rr := httptest.NewRecorder() - // Contoh respons yang ingin Anda kirim response := model.OnuID{ Board: 2, PON: 8, ID: 1, } - // Panggil fungsi SendJSONResponse + // Call the SendJSONResponse function SendJSONResponse(rr, http.StatusOK, response) - // Periksa kode status respons + // Check the status code if status := rr.Code; status != http.StatusOK { t.Errorf("Status code tidak sesuai: got %v want %v", status, http.StatusOK) } - // Periksa tipe konten + // Check the content type expectedContentType := "application/json" if contentType := rr.Header().Get("Content-Type"); contentType != expectedContentType { t.Errorf("Content-Type tidak sesuai: got %v want %v", contentType, expectedContentType) diff --git a/internal/utils/extractor.go b/internal/utils/extractor.go index eec8567..9d27974 100644 --- a/internal/utils/extractor.go +++ b/internal/utils/extractor.go @@ -6,6 +6,7 @@ import ( "strings" ) +// ExtractONUID function is used to extract ONU ID from OID string func ExtractONUID(oid string) string { // Split the OID name and take the last component parts := strings.Split(oid, ".") @@ -19,6 +20,7 @@ func ExtractONUID(oid string) string { return "" // Return an empty string if the OID is invalid or empty (default value) } +// ExtractIDOnuID function is used to extract ONU ID from OID interface{} func ExtractIDOnuID(oid interface{}) int { if oid == nil { return 0 @@ -40,6 +42,7 @@ func ExtractIDOnuID(oid interface{}) int { } } +// ExtractName function is used to extract name from OID value func ExtractName(oidValue interface{}) string { switch v := oidValue.(type) { case string: @@ -76,6 +79,7 @@ func ExtractSerialNumber(oidValue interface{}) string { } } +// ConvertAndMultiply function is used to convert the PDU value to string after multiplying by 0.002 and subtracting 30 func ConvertAndMultiply(pduValue interface{}) (string, error) { // Type assert pduValue to an integer type intValue, ok := pduValue.(int) @@ -95,6 +99,7 @@ func ConvertAndMultiply(pduValue interface{}) (string, error) { return resultStr, nil } +// ExtractAndGetStatus function is used to extract and get status from OID value func ExtractAndGetStatus(oidValue interface{}) string { // Check if oidValue is not an integer intValue, ok := oidValue.(int) @@ -122,6 +127,7 @@ func ExtractAndGetStatus(oidValue interface{}) string { } } +// ExtractLastOfflineReason function is used to extract last offline reason from OID value func ExtractLastOfflineReason(oidValue interface{}) string { // Check if oidValue is not an integer intValue, ok := oidValue.(int) @@ -161,6 +167,7 @@ func ExtractLastOfflineReason(oidValue interface{}) string { } } +// ExtractGponOpticalDistance function is used to extract GPON optical distance from OID value func ExtractGponOpticalDistance(oidValue interface{}) string { // Check if oidValue is not an integer intValue, ok := oidValue.(int) diff --git a/internal/utils/response.go b/internal/utils/response.go index 63cb7e6..a290983 100644 --- a/internal/utils/response.go +++ b/internal/utils/response.go @@ -1,11 +1,13 @@ package utils +// WebResponse defines the structure for standard web responses type WebResponse struct { Code int32 `json:"code"` Status string `json:"status"` Data interface{} `json:"data"` } +// ErrorResponse defines the structure for error responses type ErrorResponse struct { Code int32 `json:"code"` Status string `json:"status"` diff --git a/pkg/graceful/graceful.go b/pkg/graceful/graceful.go index e87fc9a..52c8da7 100644 --- a/pkg/graceful/graceful.go +++ b/pkg/graceful/graceful.go @@ -12,6 +12,7 @@ import ( "time" ) +// Shutdown gracefully shuts down the HTTP server when the context is done or an OS signal is received. func Shutdown(ctx context.Context, server *http.Server) error { ch := make(chan error, 1) diff --git a/pkg/pagination/pagination.go b/pkg/pagination/pagination.go index 4c48338..954bcf7 100644 --- a/pkg/pagination/pagination.go +++ b/pkg/pagination/pagination.go @@ -5,6 +5,7 @@ import ( "strconv" ) +// Constants for default and maximum page sizes, and query parameter names var ( DefaultPageSize = 10 MaxPageSize = 100 @@ -12,6 +13,7 @@ var ( PageSizeVar = "limit" ) +// Pages struct defines the structure for paginated responses type Pages struct { Code int32 `json:"code"` Status string `json:"status"` @@ -22,6 +24,7 @@ type Pages struct { Data interface{} `json:"data"` } +// New creates a new Pages instance with the provided parameters func New(page, pageSize, total int) *Pages { if page <= 0 { page = 0 @@ -46,12 +49,14 @@ func New(page, pageSize, total int) *Pages { } } +// GetPaginationParametersFromRequest extracts pagination parameters from the HTTP request func GetPaginationParametersFromRequest(r *http.Request) (pageIndex, pageSize int) { pageIndex = parseInt(r.URL.Query().Get(PageVar), 1) pageSize = parseInt(r.URL.Query().Get(PageSizeVar), DefaultPageSize) return pageIndex, pageSize } +// parseInt is a helper function to parse string to int with a default value func parseInt(value string, defaultValue int) int { if value == "" { return defaultValue diff --git a/pkg/redis/redis.go b/pkg/redis/redis.go index e836cb1..bb05b9b 100644 --- a/pkg/redis/redis.go +++ b/pkg/redis/redis.go @@ -1,11 +1,12 @@ package redis import ( + "os" + "time" + "github.com/megadata-dev/go-snmp-olt-zte-c320/config" "github.com/megadata-dev/go-snmp-olt-zte-c320/internal/utils" "github.com/redis/go-redis/v9" - "os" - "time" ) var ( @@ -18,6 +19,7 @@ var ( redisPoolTimeout int ) +// NewRedisClient creates and returns a new Redis client based on the provided configuration. func NewRedisClient(cfg *config.Config) *redis.Client { if os.Getenv("APP_ENV") == "development" || os.Getenv("APP_ENV") == "production" { redisHost = os.Getenv("REDIS_HOST") diff --git a/pkg/snmp/snmp.go b/pkg/snmp/snmp.go index 56f2085..6a64efc 100644 --- a/pkg/snmp/snmp.go +++ b/pkg/snmp/snmp.go @@ -2,12 +2,13 @@ package snmp import ( "fmt" - "github.com/gosnmp/gosnmp" - "github.com/megadata-dev/go-snmp-olt-zte-c320/config" - "github.com/megadata-dev/go-snmp-olt-zte-c320/internal/utils" "log" "os" "time" + + "github.com/gosnmp/gosnmp" + "github.com/megadata-dev/go-snmp-olt-zte-c320/config" + "github.com/megadata-dev/go-snmp-olt-zte-c320/internal/utils" ) var ( @@ -28,7 +29,7 @@ func SetupSnmpConnection(config *config.Config) (*gosnmp.GoSNMP, error) { snmpCommunity = os.Getenv("SNMP_COMMUNITY") logSnmp = gosnmp.Logger{} } else { - snmpHost = config.SnmpCfg.Ip + snmpHost = config.SnmpCfg.IP snmpPort = config.SnmpCfg.Port snmpCommunity = config.SnmpCfg.Community logSnmp = gosnmp.NewLogger(log.New(os.Stdout, "", 0)) diff --git a/taskfile.yml b/taskfile.yml index 500fd70..2f30fcd 100644 --- a/taskfile.yml +++ b/taskfile.yml @@ -1,7 +1,7 @@ version: '3' vars: - EXE: sumitroajiprabowo/go-snmp-olt-zte-c320{{exeExt}} + EXE: cepatkilatteknologi/go-snmp-olt-zte-c320{{exeExt}} tasks: default: