diff --git a/go_exporter/RBDFactory.go b/go_exporter/RBDFactory.go index 3cad87c..f36f070 100644 --- a/go_exporter/RBDFactory.go +++ b/go_exporter/RBDFactory.go @@ -28,7 +28,7 @@ func PoolFactory(cephConn CephConnector, poolName string) (Pool, error) { } return Pool{ Name: poolName, - hasRBD: len(imageList) != 0, + HasRBD: len(imageList) != 0, RBDlist: rbdlist, }, nil } @@ -36,7 +36,7 @@ func PoolFactory(cephConn CephConnector, poolName string) (Pool, error) { func RBDFacroty(ioctx IOContexter, rbdname string) (RBD, error) { defer func() { if v := recover(); v != nil { - fmt.Println("Shit happened") + fmt.Println("Shit happened in RBDFactory") } }() diff --git a/go_exporter/connection.go b/go_exporter/connection.go index 083ff67..35b4d8d 100644 --- a/go_exporter/connection.go +++ b/go_exporter/connection.go @@ -20,12 +20,12 @@ func connect() (_ CephConnection, err error) { return CephConnection{}, err } - err = cephConn.conn.ReadConfigFile(params.config) + err = cephConn.conn.ReadConfigFile(params.Config) if err != nil { return CephConnection{}, err } - err = cephConn.conn.SetConfigOption("keyring", params.keyring) + err = cephConn.conn.SetConfigOption("keyring", params.Keyring) if err != nil { return CephConnection{}, err } diff --git a/go_exporter/getOpts.go b/go_exporter/getOpts.go index 331352c..b542486 100644 --- a/go_exporter/getOpts.go +++ b/go_exporter/getOpts.go @@ -16,8 +16,8 @@ func init() { _keyring := flag.String("keyring", "/etc/ceph/ceph.client.admin.keyring", "placement of ceph keyring file") flag.Parse() - params.config = *config_file - params.keyring = *_keyring + params.Config = *config_file + params.Keyring = *_keyring logger = loggerInit() logger.Info("Setting up logger is complete successfully") diff --git a/go_exporter/go.mod b/go_exporter/go.mod index de4f279..0bc9075 100644 --- a/go_exporter/go.mod +++ b/go_exporter/go.mod @@ -3,19 +3,11 @@ module main.go go 1.25.5 require ( - github.com/ceph/go-ceph v0.36.0 + github.com/ceph/go-ceph v0.37.0 github.com/prometheus/client_golang v1.23.2 go.uber.org/zap v1.27.1 ) -require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/kylelemons/godebug v1.1.0 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/stretchr/objx v0.5.2 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) - require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -23,9 +15,8 @@ require ( github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/common v0.66.1 // indirect github.com/prometheus/procfs v0.16.1 // indirect - github.com/stretchr/testify v1.11.1 go.uber.org/multierr v1.10.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect - golang.org/x/sys v0.36.0 // indirect + golang.org/x/sys v0.38.0 // indirect google.golang.org/protobuf v1.36.8 // indirect ) diff --git a/go_exporter/go.sum b/go_exporter/go.sum index 900c68a..af21308 100644 --- a/go_exporter/go.sum +++ b/go_exporter/go.sum @@ -1,13 +1,13 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/ceph/go-ceph v0.36.0 h1:IDE4vEF+4fmjve+CPjD1WStgfQ+Lh6vD+9PMUI712KI= -github.com/ceph/go-ceph v0.36.0/go.mod h1:fGCbndVDLuHW7q2954d6y+tgPFOBnRLqJRe2YXyngw4= +github.com/ceph/go-ceph v0.37.0 h1:KXliBe3ZDr3/AtfY7n9d1MG7ippYNCVhMPcAgm05CFI= +github.com/ceph/go-ceph v0.37.0/go.mod h1:3y2tOlITlyuVFhy8v6PpCEfjMwKPfXJiH0/2hKZZQRE= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/gofrs/uuid/v5 v5.3.2 h1:2jfO8j3XgSwlz/wHqemAEugfnTlikAYHhnqQ8Xh4fE0= -github.com/gofrs/uuid/v5 v5.3.2/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= +github.com/gofrs/uuid/v5 v5.4.0 h1:EfbpCTjqMuGyq5ZJwxqzn3Cbr2d0rUZU7v5ycAk/e/0= +github.com/gofrs/uuid/v5 v5.4.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= @@ -32,8 +32,6 @@ github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzM github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -44,8 +42,8 @@ go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= -golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= -golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/go_exporter/main.go b/go_exporter/main.go index 8bb9f91..8044dfc 100644 --- a/go_exporter/main.go +++ b/go_exporter/main.go @@ -6,7 +6,6 @@ import ( "net/http" "os" "time" - "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "go.uber.org/zap" @@ -19,7 +18,7 @@ func getMetrics(cephConn CephConnector) { metrics := InitMetrics() prometheus.MustRegister( - metrics.total_rbd_requested_size_per_pool, + metrics.Total_rbd_requested_size_per_pool, ) ticker := time.NewTicker(2 * time.Second) @@ -39,9 +38,9 @@ func getMetrics(cephConn CephConnector) { result = append(result, x) } - metrics.total_rbd_requested_size_per_pool.Reset() + metrics.Total_rbd_requested_size_per_pool.Reset() for _,v := range result { - if !v.hasRBD {continue} + if !v.HasRBD {continue} FillMetrics(v,metrics) } fmt.Println("====================") diff --git a/go_exporter/metrics.go b/go_exporter/metrics.go index ab5c0e4..cfc420a 100644 --- a/go_exporter/metrics.go +++ b/go_exporter/metrics.go @@ -6,7 +6,7 @@ import ( func InitMetrics() *Metrics { m := &Metrics{ - total_rbd_requested_size_per_pool: prometheus.NewGaugeVec( + Total_rbd_requested_size_per_pool: prometheus.NewGaugeVec( prometheus.GaugeOpts{ Name: "total_rbd_requested_size_per_pool", Help: "total size of all requested RBDs in a specific pool", @@ -30,11 +30,11 @@ func FillMetrics(pool Pool,metrics *Metrics) { logger.Debugf("Processing pool %s",pool.Name) for _,v := range pool.RBDlist { - totalSizePerPool += uint64(v.getSize()) + totalSizePerPool += uint64(v.GetSize()) } logger.Debugf("Total size of RBDs in pool %s is %d",pool.Name,totalSizePerPool) - metrics.total_rbd_requested_size_per_pool.WithLabelValues(pool.Name, + metrics.Total_rbd_requested_size_per_pool.WithLabelValues(pool.Name, ).Set( float64(totalSizePerPool)) diff --git a/go_exporter/mock_test.go b/go_exporter/mock_test.go deleted file mode 100644 index 15c1100..0000000 --- a/go_exporter/mock_test.go +++ /dev/null @@ -1,66 +0,0 @@ -package main - -import ( - "github.com/ceph/go-ceph/rbd" - "github.com/stretchr/testify/mock" -) - -// MockCephConnector -type MockCephConnector struct { - mock.Mock -} - -func (m *MockCephConnector) ListPools() ([]string, error) { - args := m.Called() - return args.Get(0).([]string), args.Error(1) -} - -func (m *MockCephConnector) OpenIOContext(poolName string) (IOContexter, error) { - args := m.Called(poolName) - if args.Get(0) == nil { - return nil, args.Error(1) - } - return args.Get(0).(IOContexter), args.Error(1) -} - -// MockIOContexter -type MockIOContexter struct { - mock.Mock -} - -func (m *MockIOContexter) Destroy() { - m.Called() -} - -func (m *MockIOContexter) GetImageNames() ([]string, error) { - args := m.Called() - return args.Get(0).([]string), args.Error(1) -} - -func (m *MockIOContexter) GetImage(name string) RBDImager { - args := m.Called(name) - return args.Get(0).(RBDImager) -} - -// MockRBDImager -type MockRBDImager struct { - mock.Mock -} - -func (m *MockRBDImager) Open() error { - args := m.Called() - return args.Error(0) -} - -func (m *MockRBDImager) Close() error { - args := m.Called() - return args.Error(0) -} - -func (m *MockRBDImager) Stat() (*rbd.ImageInfo, error) { - args := m.Called() - if args.Get(0) == nil { - return nil, args.Error(1) - } - return args.Get(0).(*rbd.ImageInfo), args.Error(1) -} \ No newline at end of file diff --git a/go_exporter/types.go b/go_exporter/types.go index 9a21094..42dc068 100644 --- a/go_exporter/types.go +++ b/go_exporter/types.go @@ -7,8 +7,8 @@ import ( ) type Params struct { - config string - keyring string + Config string + Keyring string } type CephConnector interface { @@ -82,8 +82,8 @@ func (riw RBDImageWrapper) Stat() (*rbd.ImageInfo,error) { } type iRBD interface { - getName() string - getSize() int64 + GetName() string + GetSize() int64 } type RBDUsage struct { @@ -95,21 +95,21 @@ type RBD struct { rbd.ImageInfo } -func (r RBD) getName() string { +func (r RBD) GetName() string { return r.Name } -func (r RBD) getSize() int64 { +func (r RBD) GetSize() int64 { return int64(r.Size) } type Pool struct { Name string - hasRBD bool + HasRBD bool RBDlist []iRBD } type Metrics struct { - total_rbd_requested_size_per_pool *prometheus.GaugeVec - total_rbd_requested_size prometheus.Gauge + Total_rbd_requested_size_per_pool *prometheus.GaugeVec + Total_rbd_requested_size prometheus.Gauge } \ No newline at end of file diff --git a/mod_prj/go.mod b/mod_prj/go.mod new file mode 100644 index 0000000..6173058 --- /dev/null +++ b/mod_prj/go.mod @@ -0,0 +1,3 @@ +module mod_prj + +go 1.25.5 diff --git a/mod_prj/main.go b/mod_prj/main.go new file mode 100644 index 0000000..119ee74 --- /dev/null +++ b/mod_prj/main.go @@ -0,0 +1,10 @@ +package main + + +import "mod_prj/message" + +func main() { + + messages.Hello_en() + messages.Bye_en() +} diff --git a/mod_prj/message/message.go b/mod_prj/message/message.go new file mode 100644 index 0000000..42ba198 --- /dev/null +++ b/mod_prj/message/message.go @@ -0,0 +1,11 @@ +package messages +import "fmt" + +func Hello_en() { + + fmt.Println("Hello") +} +func Bye_en() { + + fmt.Println("Good Bye") +} \ No newline at end of file diff --git a/rbd_exporter/RBDFactory/RBDFactory.go b/rbd_exporter/RBDFactory/RBDFactory.go new file mode 100644 index 0000000..217e1f7 --- /dev/null +++ b/rbd_exporter/RBDFactory/RBDFactory.go @@ -0,0 +1,64 @@ +package RBDFactory + +import ( + "fmt" + "rbd_exporter/logger" + "rbd_exporter/mytypes" +) + +func PoolFactory(cephConn mytypes.CephConnector, poolName string) (mytypes.Pool, error) { + var rbdlist []mytypes.IRBD = []mytypes.IRBD{} + + ioctx, err := cephConn.OpenIOContext(poolName) + if err != nil { + return mytypes.Pool{}, fmt.Errorf("Couldn't set context for pool %s %w", poolName, err) + } + + defer ioctx.Destroy() + + imageList, err := ioctx.GetImageNames() + if err != nil { + return mytypes.Pool{}, fmt.Errorf("Couldn't get list of rbds %w", err) + } + for _, rbdname := range imageList { + stat, err := RBDFacroty(ioctx, rbdname) + if err != nil { + fmt.Errorf("Coundn't get stat from disk %s %w", rbdname, err) + panic(err) + } + rbdlist = append(rbdlist, stat) + } + return mytypes.Pool{ + Name: poolName, + HasRBD: len(imageList) != 0, + RBDlist: rbdlist, + }, nil +} + +func RBDFacroty(ioctx mytypes.IOContexter, rbdname string) (mytypes.RBD, error) { + defer func() { + if v := recover(); v != nil { + logger.Logger.Errorf("No such RBD exists (probably just deleted)") + } + }() + + image := ioctx.GetImage(rbdname) + err := image.Open() + if err != nil { + panic(err) + // logger.Logger.Errorf("Shit happened in RBDFactory") + } + + defer image.Close() + + + info,err := image.Stat() + if err != nil { + return mytypes.RBD{},fmt.Errorf("Couldn't get stats for image %s %w",rbdname,err) + } + + return mytypes.RBD{ + Name: rbdname, + ImageInfo: *info, + },nil +} diff --git a/rbd_exporter/connection/connection.go b/rbd_exporter/connection/connection.go new file mode 100644 index 0000000..ca51edf --- /dev/null +++ b/rbd_exporter/connection/connection.go @@ -0,0 +1,39 @@ +package connection + +import ( + "fmt" + "rbd_exporter/mytypes" + "github.com/ceph/go-ceph/rados" +) + +func Connect(params mytypes.Params) (_ mytypes.CephConnection, err error) { + var cephConn mytypes.CephConnection = mytypes.CephConnection{} + + defer func() { + if err != nil { + err = fmt.Errorf("Error in func connect() %w", err) + } + }() + + cephConn.Conn, err = rados.NewConnWithClusterAndUser("ceph", "client.admin") + if err != nil { + return mytypes.CephConnection{}, err + } + + err = cephConn.Conn.ReadConfigFile(params.Config) + if err != nil { + return mytypes.CephConnection{}, err + } + + err = cephConn.Conn.SetConfigOption("keyring", params.Keyring) + if err != nil { + return mytypes.CephConnection{}, err + } + + err = cephConn.Conn.Connect() + if err != nil { + return mytypes.CephConnection{}, err + } + + return cephConn, nil +} diff --git a/rbd_exporter/go.mod b/rbd_exporter/go.mod new file mode 100644 index 0000000..3925caa --- /dev/null +++ b/rbd_exporter/go.mod @@ -0,0 +1,29 @@ +module rbd_exporter + +go 1.25.5 + +require github.com/prometheus/client_golang v1.23.2 + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/golang/mock v1.6.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + go.uber.org/mock v0.6.0 // indirect + go.uber.org/multierr v1.10.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/ceph/go-ceph v0.37.0 + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.66.1 // indirect + github.com/prometheus/procfs v0.16.1 // indirect + github.com/stretchr/testify v1.11.1 + go.uber.org/zap v1.27.1 + go.yaml.in/yaml/v2 v2.4.2 // indirect + golang.org/x/sys v0.38.0 // indirect + google.golang.org/protobuf v1.36.8 // indirect +) diff --git a/rbd_exporter/go.sum b/rbd_exporter/go.sum new file mode 100644 index 0000000..64ca904 --- /dev/null +++ b/rbd_exporter/go.sum @@ -0,0 +1,64 @@ +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/ceph/go-ceph v0.37.0 h1:KXliBe3ZDr3/AtfY7n9d1MG7ippYNCVhMPcAgm05CFI= +github.com/ceph/go-ceph v0.37.0/go.mod h1:3y2tOlITlyuVFhy8v6PpCEfjMwKPfXJiH0/2hKZZQRE= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= +github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= +go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= +google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/rbd_exporter/logger/logger.go b/rbd_exporter/logger/logger.go new file mode 100644 index 0000000..956f0e0 --- /dev/null +++ b/rbd_exporter/logger/logger.go @@ -0,0 +1,10 @@ +package logger + +import "go.uber.org/zap" + +var Logger *zap.SugaredLogger + +// SetLogger is called from init() +func SetLogger(l *zap.SugaredLogger) { + Logger = l +} \ No newline at end of file diff --git a/rbd_exporter/main.go b/rbd_exporter/main.go new file mode 100644 index 0000000..511cabe --- /dev/null +++ b/rbd_exporter/main.go @@ -0,0 +1,81 @@ +package main + +import ( + "errors" + "flag" + "fmt" + "net/http" + "os" + "rbd_exporter/mytypes" + "rbd_exporter/metrics" + "rbd_exporter/logger" + "rbd_exporter/connection" + "github.com/prometheus/client_golang/prometheus/promhttp" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + + +var params mytypes.Params +var mainlogger *zap.SugaredLogger + +// Here I initialize logger +func loggerInit() *zap.SugaredLogger { + config := zap.NewDevelopmentConfig() + config.EncoderConfig.TimeKey = "timestamp" + config.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder + logger, err := config.Build() + if err != nil { + panic(fmt.Sprintf("Logger set up failed: %v", err)) + } + defer logger.Sync() + return logger.Sugar() +} + +// This func runs even before main() +func init() { + + config_file := flag.String("config", "/etc/ceph/ceph.conf", "placement of ceph config file") + _keyring := flag.String("keyring", "/etc/ceph/ceph.client.admin.keyring", "placement of ceph keyring file") + flag.Parse() + + params.Config = *config_file + params.Keyring = *_keyring + + mainlogger = loggerInit() + logger.SetLogger(mainlogger) + mainlogger.Info("Setting up logger is complete successfully") + mainlogger.Info("Registering prom metrics") +} + + +func main() { + cephConn, err := connection.Connect(params) + if err != nil { + fmt.Println(err) + if wrapped := errors.Unwrap(err); wrapped != nil { + fmt.Println(wrapped) + } + os.Exit(1) + } + defer cephConn.Conn.Shutdown() + mainlogger.Info("Successfully connected") + + http.Handle("/metrics", promhttp.Handler()) + + // HTTP runs in separate thread cuz it blocks futher execution of main + go func() { + mainlogger.Info("Starting http server") + // Here I check for errors if HTTP fails + if err := http.ListenAndServe(":9040", nil); err != nil { + mainlogger.Fatalf("HTTP server failed to start %v", err) + } + mainlogger.Info("HTTP server started") + }() + + + go metrics.GetMetrics(cephConn) + + select {} + +} diff --git a/rbd_exporter/metrics/metrics.go b/rbd_exporter/metrics/metrics.go new file mode 100644 index 0000000..ed9dee9 --- /dev/null +++ b/rbd_exporter/metrics/metrics.go @@ -0,0 +1,83 @@ +package metrics + +import ( + "fmt" + "rbd_exporter/RBDFactory" + "rbd_exporter/mytypes" + "rbd_exporter/logger" + "time" + "github.com/prometheus/client_golang/prometheus" +) + + +func GetMetrics(cephConn mytypes.CephConnector) { + + metrics := InitMetrics() + prometheus.MustRegister( + metrics.Total_rbd_requested_size_per_pool, + ) + + ticker := time.NewTicker(2 * time.Second) + defer ticker.Stop() + + for range ticker.C { + var result []mytypes.Pool = []mytypes.Pool{} + poolList, err := cephConn.ListPools() + if err != nil { + logger.Logger.Error("Cannot get list of pools") + // do not exit but continue checking + continue + } + + for _, v := range poolList { + x, _ := RBDFactory.PoolFactory(cephConn, v) + result = append(result, x) + } + + metrics.Total_rbd_requested_size_per_pool.Reset() + for _,v := range result { + if !v.HasRBD {continue} + FillMetrics(v,metrics) + } + fmt.Println("====================") + // fmt.Println(result) + + } +} + + +func InitMetrics() *mytypes.Metrics { + m := &mytypes.Metrics{ + Total_rbd_requested_size_per_pool: prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "total_rbd_requested_size_per_pool", + Help: "total size of all requested RBDs in a specific pool", + }, + []string{"poolname"}, + ), + + // total_rbd_requested_size: prometheus.NewGauge( + // prometheus.GaugeOpts{ + // Name: "total_rbd_requested_size", + // Help: "total size of all RBDs in the cluster", + // }, + // ), + } + return m +} + + +func FillMetrics(pool mytypes.Pool,metrics *mytypes.Metrics) { + var totalSizePerPool uint64 = 0 + + logger.Logger.Debugf("Processing pool %s",pool.Name) + for _,v := range pool.RBDlist { + totalSizePerPool += uint64(v.GetSize()) + } + logger.Logger.Debugf("Total size of RBDs in pool %s is %d",pool.Name,totalSizePerPool) + + metrics.Total_rbd_requested_size_per_pool.WithLabelValues(pool.Name, + ).Set( + float64(totalSizePerPool)) + +} \ No newline at end of file diff --git a/rbd_exporter/mytypes/mock/types_mockgen_mock.go b/rbd_exporter/mytypes/mock/types_mockgen_mock.go new file mode 100644 index 0000000..c87f213 --- /dev/null +++ b/rbd_exporter/mytypes/mock/types_mockgen_mock.go @@ -0,0 +1,256 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: mytypes/types.go +// +// Generated by this command: +// +// mockgen -source=mytypes/types.go -destination=mytypes/types_mockgen_mock.go -package=mocks +// + +// Package mocks is a generated GoMock package. +package mocks + +import ( + mytypes "rbd_exporter/mytypes" + reflect "reflect" + + rbd "github.com/ceph/go-ceph/rbd" + gomock "go.uber.org/mock/gomock" +) + +// MockCephConnector is a mock of CephConnector interface. +type MockCephConnector struct { + ctrl *gomock.Controller + recorder *MockCephConnectorMockRecorder + isgomock struct{} +} + +// MockCephConnectorMockRecorder is the mock recorder for MockCephConnector. +type MockCephConnectorMockRecorder struct { + mock *MockCephConnector +} + +// NewMockCephConnector creates a new mock instance. +func NewMockCephConnector(ctrl *gomock.Controller) *MockCephConnector { + mock := &MockCephConnector{ctrl: ctrl} + mock.recorder = &MockCephConnectorMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockCephConnector) EXPECT() *MockCephConnectorMockRecorder { + return m.recorder +} + +// ListPools mocks base method. +func (m *MockCephConnector) ListPools() ([]string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListPools") + ret0, _ := ret[0].([]string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ListPools indicates an expected call of ListPools. +func (mr *MockCephConnectorMockRecorder) ListPools() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListPools", reflect.TypeOf((*MockCephConnector)(nil).ListPools)) +} + +// OpenIOContext mocks base method. +func (m *MockCephConnector) OpenIOContext(poolName string) (mytypes.IOContexter, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "OpenIOContext", poolName) + ret0, _ := ret[0].(mytypes.IOContexter) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// OpenIOContext indicates an expected call of OpenIOContext. +func (mr *MockCephConnectorMockRecorder) OpenIOContext(poolName any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OpenIOContext", reflect.TypeOf((*MockCephConnector)(nil).OpenIOContext), poolName) +} + +// MockIOContexter is a mock of IOContexter interface. +type MockIOContexter struct { + ctrl *gomock.Controller + recorder *MockIOContexterMockRecorder + isgomock struct{} +} + +// MockIOContexterMockRecorder is the mock recorder for MockIOContexter. +type MockIOContexterMockRecorder struct { + mock *MockIOContexter +} + +// NewMockIOContexter creates a new mock instance. +func NewMockIOContexter(ctrl *gomock.Controller) *MockIOContexter { + mock := &MockIOContexter{ctrl: ctrl} + mock.recorder = &MockIOContexterMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockIOContexter) EXPECT() *MockIOContexterMockRecorder { + return m.recorder +} + +// Destroy mocks base method. +func (m *MockIOContexter) Destroy() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Destroy") +} + +// Destroy indicates an expected call of Destroy. +func (mr *MockIOContexterMockRecorder) Destroy() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Destroy", reflect.TypeOf((*MockIOContexter)(nil).Destroy)) +} + +// GetImage mocks base method. +func (m *MockIOContexter) GetImage(name string) mytypes.RBDImager { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetImage", name) + ret0, _ := ret[0].(mytypes.RBDImager) + return ret0 +} + +// GetImage indicates an expected call of GetImage. +func (mr *MockIOContexterMockRecorder) GetImage(name any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetImage", reflect.TypeOf((*MockIOContexter)(nil).GetImage), name) +} + +// GetImageNames mocks base method. +func (m *MockIOContexter) GetImageNames() ([]string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetImageNames") + ret0, _ := ret[0].([]string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetImageNames indicates an expected call of GetImageNames. +func (mr *MockIOContexterMockRecorder) GetImageNames() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetImageNames", reflect.TypeOf((*MockIOContexter)(nil).GetImageNames)) +} + +// MockRBDImager is a mock of RBDImager interface. +type MockRBDImager struct { + ctrl *gomock.Controller + recorder *MockRBDImagerMockRecorder + isgomock struct{} +} + +// MockRBDImagerMockRecorder is the mock recorder for MockRBDImager. +type MockRBDImagerMockRecorder struct { + mock *MockRBDImager +} + +// NewMockRBDImager creates a new mock instance. +func NewMockRBDImager(ctrl *gomock.Controller) *MockRBDImager { + mock := &MockRBDImager{ctrl: ctrl} + mock.recorder = &MockRBDImagerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockRBDImager) EXPECT() *MockRBDImagerMockRecorder { + return m.recorder +} + +// Close mocks base method. +func (m *MockRBDImager) Close() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Close") + ret0, _ := ret[0].(error) + return ret0 +} + +// Close indicates an expected call of Close. +func (mr *MockRBDImagerMockRecorder) Close() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockRBDImager)(nil).Close)) +} + +// Open mocks base method. +func (m *MockRBDImager) Open() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Open") + ret0, _ := ret[0].(error) + return ret0 +} + +// Open indicates an expected call of Open. +func (mr *MockRBDImagerMockRecorder) Open() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Open", reflect.TypeOf((*MockRBDImager)(nil).Open)) +} + +// Stat mocks base method. +func (m *MockRBDImager) Stat() (*rbd.ImageInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Stat") + ret0, _ := ret[0].(*rbd.ImageInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Stat indicates an expected call of Stat. +func (mr *MockRBDImagerMockRecorder) Stat() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Stat", reflect.TypeOf((*MockRBDImager)(nil).Stat)) +} + +// MockIRBD is a mock of IRBD interface. +type MockIRBD struct { + ctrl *gomock.Controller + recorder *MockIRBDMockRecorder + isgomock struct{} +} + +// MockIRBDMockRecorder is the mock recorder for MockIRBD. +type MockIRBDMockRecorder struct { + mock *MockIRBD +} + +// NewMockIRBD creates a new mock instance. +func NewMockIRBD(ctrl *gomock.Controller) *MockIRBD { + mock := &MockIRBD{ctrl: ctrl} + mock.recorder = &MockIRBDMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockIRBD) EXPECT() *MockIRBDMockRecorder { + return m.recorder +} + +// GetName mocks base method. +func (m *MockIRBD) GetName() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetName") + ret0, _ := ret[0].(string) + return ret0 +} + +// GetName indicates an expected call of GetName. +func (mr *MockIRBDMockRecorder) GetName() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetName", reflect.TypeOf((*MockIRBD)(nil).GetName)) +} + +// GetSize mocks base method. +func (m *MockIRBD) GetSize() int64 { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSize") + ret0, _ := ret[0].(int64) + return ret0 +} + +// GetSize indicates an expected call of GetSize. +func (mr *MockIRBDMockRecorder) GetSize() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSize", reflect.TypeOf((*MockIRBD)(nil).GetSize)) +} diff --git a/rbd_exporter/mytypes/types.go b/rbd_exporter/mytypes/types.go new file mode 100644 index 0000000..68af6e8 --- /dev/null +++ b/rbd_exporter/mytypes/types.go @@ -0,0 +1,115 @@ +package mytypes + +import ( + "github.com/ceph/go-ceph/rados" + "github.com/ceph/go-ceph/rbd" + "github.com/prometheus/client_golang/prometheus" +) + +type Params struct { + Config string + Keyring string +} + +type CephConnector interface { + ListPools() ([]string,error) + OpenIOContext(poolName string) (IOContexter, error) +} + +type CephConnection struct { + Conn *rados.Conn +} + +// Here I do implement CephConnector interface +func (cc CephConnection) ListPools() ([]string,error) { + return cc.Conn.ListPools() +} + +// Here I do implement CephConnector interface +func (cc CephConnection) OpenIOContext(poolName string) (IOContexter,error) { + ioctx,err := cc.Conn.OpenIOContext(poolName) + if err != nil { + return nil,err + } + return IOContextWrapper{ioctx: ioctx},nil +} + + +type IOContexter interface { + Destroy() + GetImageNames() ([]string, error) + GetImage(name string) RBDImager +} + +type IOContextWrapper struct { + ioctx *rados.IOContext +} + +func (iocw IOContextWrapper) Destroy() { + iocw.ioctx.Destroy() +} + +func (iocw IOContextWrapper) GetImageNames() ([]string,error){ + return rbd.GetImageNames(iocw.ioctx) +} + +func (iocw IOContextWrapper) GetImage(rbdName string) RBDImager { + img := rbd.GetImage(iocw.ioctx,rbdName) + return RBDImageWrapper{image: img} +} + + +type RBDImager interface { + Open() error + Close() error + Stat() (*rbd.ImageInfo,error) +} + +type RBDImageWrapper struct { + image *rbd.Image +} + +func (riw RBDImageWrapper) Open() error { + return riw.image.Open() +} + +func (riw RBDImageWrapper) Close() error { + return riw.image.Close() +} + +func (riw RBDImageWrapper) Stat() (*rbd.ImageInfo,error) { + return riw.image.Stat() +} + +type IRBD interface { + GetName() string + GetSize() int64 +} + +type RBDUsage struct { + Images []RBD +} + +type RBD struct { + Name string + rbd.ImageInfo +} + +func (r RBD) GetName() string { + return r.Name +} + +func (r RBD) GetSize() int64 { + return int64(r.Size) +} + +type Pool struct { + Name string + HasRBD bool + RBDlist []IRBD +} + +type Metrics struct { + Total_rbd_requested_size_per_pool *prometheus.GaugeVec + Total_rbd_requested_size prometheus.Gauge +} diff --git a/rbd_exporter/tests/RBDFactory_test.go b/rbd_exporter/tests/RBDFactory_test.go new file mode 100644 index 0000000..b30f3b2 --- /dev/null +++ b/rbd_exporter/tests/RBDFactory_test.go @@ -0,0 +1,73 @@ +package tests + +import ( + "rbd_exporter/RBDFactory" + mock "rbd_exporter/mytypes/mock" + "testing" + + "github.com/ceph/go-ceph/rbd" + gomock "go.uber.org/mock/gomock" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + + +func TestRBDFactory(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + MockIOContexter := mock.NewMockIOContexter(mockCtrl) + MockRBDImager := mock.NewMockRBDImager(mockCtrl) + + rbdName := "test-rbd" + expectedImageInfo := &rbd.ImageInfo{ + Size: 1488, + } + + MockIOContexter.EXPECT().GetImage(rbdName).Return(MockRBDImager) + MockRBDImager.EXPECT().Open().Return(nil) + MockRBDImager.EXPECT().Close().Return(nil) + MockRBDImager.EXPECT().Stat().Return(expectedImageInfo,nil) + + + result,err := RBDFactory.RBDFacroty(MockIOContexter,rbdName) + + require.NoError(t, err) + assert.Equal(t, rbdName, result.Name) + assert.Equal(t, expectedImageInfo.Size, result.ImageInfo.Size) +} + + +func TestPoolFactory(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + mockCephConn := mock.NewMockCephConnector(mockCtrl) + mockIOCtx := mock.NewMockIOContexter(mockCtrl) + mockImage := mock.NewMockRBDImager(mockCtrl) + + + poolName := "test-pool" + imageNames := []string{"rbd1", "rbd2"} + expectedImageInfo := &rbd.ImageInfo{Size: 1024} + + mockCephConn.EXPECT().OpenIOContext(poolName).Return(mockIOCtx,nil) + mockIOCtx.EXPECT().GetImageNames().Return(imageNames,nil) + mockIOCtx.EXPECT().Destroy() + + for _, imageName := range imageNames { + mockIOCtx.EXPECT().GetImage(imageName).Return(mockImage) + mockImage.EXPECT().Open().Return(nil) + mockImage.EXPECT().Close().Return(nil) + mockImage.EXPECT().Stat().Return(expectedImageInfo, nil) + } + + result, err := RBDFactory.PoolFactory(mockCephConn, poolName) + + require.NoError(t, err) + assert.Equal(t, poolName, result.Name) + assert.True(t, result.HasRBD) + assert.Len(t, result.RBDlist, 2) + assert.Equal(t, "rbd1", result.RBDlist[0].GetName()) + assert.Equal(t, "rbd2", result.RBDlist[1].GetName()) +} \ No newline at end of file diff --git a/testing/go-code-samples/mock-testing/fetchuser/.idea/.gitignore b/testing/go-code-samples/mock-testing/fetchuser/.idea/.gitignore deleted file mode 100644 index 13566b8..0000000 --- a/testing/go-code-samples/mock-testing/fetchuser/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/testing/go-code-samples/mock-testing/fetchuser/.idea/fetchuser.iml b/testing/go-code-samples/mock-testing/fetchuser/.idea/fetchuser.iml deleted file mode 100644 index 7ee078d..0000000 --- a/testing/go-code-samples/mock-testing/fetchuser/.idea/fetchuser.iml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/testing/go-code-samples/mock-testing/fetchuser/.idea/runConfigurations/TestProcessUser_All.xml b/testing/go-code-samples/mock-testing/fetchuser/.idea/runConfigurations/TestProcessUser_All.xml deleted file mode 100644 index e5cb9a1..0000000 --- a/testing/go-code-samples/mock-testing/fetchuser/.idea/runConfigurations/TestProcessUser_All.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/testing/go-code-samples/mock-testing/fetchuser/.idea/runConfigurations/TestProcessUser_HigherOrderFunctions.xml b/testing/go-code-samples/mock-testing/fetchuser/.idea/runConfigurations/TestProcessUser_HigherOrderFunctions.xml deleted file mode 100644 index 2f0e715..0000000 --- a/testing/go-code-samples/mock-testing/fetchuser/.idea/runConfigurations/TestProcessUser_HigherOrderFunctions.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/testing/go-code-samples/mock-testing/fetchuser/.idea/runConfigurations/TestProcessUser_HttpTest.xml b/testing/go-code-samples/mock-testing/fetchuser/.idea/runConfigurations/TestProcessUser_HttpTest.xml deleted file mode 100644 index 95b6f6e..0000000 --- a/testing/go-code-samples/mock-testing/fetchuser/.idea/runConfigurations/TestProcessUser_HttpTest.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/testing/go-code-samples/mock-testing/fetchuser/.idea/runConfigurations/TestProcessUser_InterfaceMock1.xml b/testing/go-code-samples/mock-testing/fetchuser/.idea/runConfigurations/TestProcessUser_InterfaceMock1.xml deleted file mode 100644 index 84b46fd..0000000 --- a/testing/go-code-samples/mock-testing/fetchuser/.idea/runConfigurations/TestProcessUser_InterfaceMock1.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/testing/go-code-samples/mock-testing/fetchuser/.idea/runConfigurations/TestProcessUser_InterfaceMock2.xml b/testing/go-code-samples/mock-testing/fetchuser/.idea/runConfigurations/TestProcessUser_InterfaceMock2.xml deleted file mode 100644 index 8356b43..0000000 --- a/testing/go-code-samples/mock-testing/fetchuser/.idea/runConfigurations/TestProcessUser_InterfaceMock2.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/testing/go-code-samples/mock-testing/fetchuser/.idea/runConfigurations/TestProcessUser_Mockgen.xml b/testing/go-code-samples/mock-testing/fetchuser/.idea/runConfigurations/TestProcessUser_Mockgen.xml deleted file mode 100644 index 6995d67..0000000 --- a/testing/go-code-samples/mock-testing/fetchuser/.idea/runConfigurations/TestProcessUser_Mockgen.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/testing/go-code-samples/mock-testing/fetchuser/.idea/runConfigurations/TestProcessUser_TestifyMock.xml b/testing/go-code-samples/mock-testing/fetchuser/.idea/runConfigurations/TestProcessUser_TestifyMock.xml deleted file mode 100644 index f31bb64..0000000 --- a/testing/go-code-samples/mock-testing/fetchuser/.idea/runConfigurations/TestProcessUser_TestifyMock.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/testing/go-code-samples/mock-testing/fetchuser/.idea/vcs.xml b/testing/go-code-samples/mock-testing/fetchuser/.idea/vcs.xml deleted file mode 100644 index b2bdec2..0000000 --- a/testing/go-code-samples/mock-testing/fetchuser/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/testing/go-code-samples/mock-testing/fetchuser/fetchuser_mockgen_mocks.go b/testing/go-code-samples/mock-testing/fetchuser/fetchuser_mockgen_mocks.go index 47422fc..46678ba 100644 --- a/testing/go-code-samples/mock-testing/fetchuser/fetchuser_mockgen_mocks.go +++ b/testing/go-code-samples/mock-testing/fetchuser/fetchuser_mockgen_mocks.go @@ -1,5 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: fetchuser.go +// +// Generated by this command: +// +// mockgen -source=fetchuser.go -destination=fetchuser_mockgen_mocks.go -package=fetchuser +// // Package fetchuser is a generated GoMock package. package fetchuser @@ -14,6 +19,7 @@ import ( type MockAPIFetcher struct { ctrl *gomock.Controller recorder *MockAPIFetcherMockRecorder + isgomock struct{} } // MockAPIFetcherMockRecorder is the mock recorder for MockAPIFetcher. @@ -43,7 +49,7 @@ func (m *MockAPIFetcher) FetchData(id int) (User, error) { } // FetchData indicates an expected call of FetchData. -func (mr *MockAPIFetcherMockRecorder) FetchData(id interface{}) *gomock.Call { +func (mr *MockAPIFetcherMockRecorder) FetchData(id any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchData", reflect.TypeOf((*MockAPIFetcher)(nil).FetchData), id) } diff --git a/testing/go-code-samples/mock-testing/fetchuser/fetchuser_mockgen_test.go b/testing/go-code-samples/mock-testing/fetchuser/fetchuser_mockgen_test.go deleted file mode 100644 index fd7ed43..0000000 --- a/testing/go-code-samples/mock-testing/fetchuser/fetchuser_mockgen_test.go +++ /dev/null @@ -1,25 +0,0 @@ -package fetchuser - -import ( - "testing" - - "go.uber.org/mock/gomock" -) - -func TestProcessUser_Mockgen(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - user := User{ID: 1, Name: "Alice"} - mockFetcher := NewMockAPIFetcher(ctrl) - mockFetcher.EXPECT().FetchData(1).Return(user, nil) - - result, err := ProcessUser(mockFetcher, 1) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - if result != user { - t.Errorf("expected user: %v, got: %v", user, result) - } -} diff --git a/testing/go-code-samples/mock-testing/fetchuser/go.mod b/testing/go-code-samples/mock-testing/fetchuser/go.mod index b941b01..6587c17 100644 --- a/testing/go-code-samples/mock-testing/fetchuser/go.mod +++ b/testing/go-code-samples/mock-testing/fetchuser/go.mod @@ -1,15 +1,15 @@ -module github.com/JetBrains/go-code-samples/mock-testing/fetchuser +module fetcher -go 1.20 +go 1.25.5 require ( - github.com/stretchr/testify v1.8.4 - go.uber.org/mock v0.2.0 + github.com/stretchr/testify v1.11.1 + go.uber.org/mock v0.6.0 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/stretchr/objx v0.5.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/testing/go-code-samples/mock-testing/fetchuser/go.sum b/testing/go-code-samples/mock-testing/fetchuser/go.sum index 7b5f618..ff1eeb2 100644 --- a/testing/go-code-samples/mock-testing/fetchuser/go.sum +++ b/testing/go-code-samples/mock-testing/fetchuser/go.sum @@ -1,20 +1,39 @@ -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -go.uber.org/mock v0.2.0 h1:TaP3xedm7JaAgScZO7tlvlKrqT0p7I6OsdGB5YNSMDU= -go.uber.org/mock v0.2.0/go.mod h1:J0y0rp9L3xiff1+ZBfKxlC1fz2+aO16tw0tsDOixfuM= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= +go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/testing/go-code-samples/mock-testing/fetchuser/test_fetchuser.go b/testing/go-code-samples/mock-testing/fetchuser/test_fetchuser.go new file mode 100644 index 0000000..e70244d --- /dev/null +++ b/testing/go-code-samples/mock-testing/fetchuser/test_fetchuser.go @@ -0,0 +1,25 @@ +package fetchuser + +import ( + "testing" + + gomock "go.uber.org/mock/gomock") + +func TestProcessUser_Mockgen(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + user := User{ID: 1, Name: "Alice"} + + mockFetcher := NewMockAPIFetcher(ctrl) + mockFetcher.EXPECT().FetchData(1).Return(user, nil) + + result, err := ProcessUser(mockFetcher, 1) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + if result != user { + t.Errorf("expected user: %v, got: %v", user, result) + } +}