interfaces

This commit is contained in:
a.pivkin 2025-12-20 08:48:06 +03:00
parent 05bd6f3c03
commit 4833874324
8 changed files with 178 additions and 11 deletions

19
go_exporter/Makefile Normal file
View File

@ -0,0 +1,19 @@
.PHONY: test test-unit test-integration test-coverage
test-unit:
go test -v -short ./...
test-integration:
go test -v -tags=integration ./...
test-coverage:
go test -v -coverprofile=coverage.out ./...
go tool cover -html=coverage.out -o coverage.html
test: test-unit
clean:
rm -f coverage.out coverage.html
total-rm:
rm -f main_test.go metrics_test.go pool_test.go types_test.go integration_test.go mock.go

View File

@ -2,21 +2,19 @@ package main
import (
"fmt"
"github.com/ceph/go-ceph/rados"
"github.com/ceph/go-ceph/rbd"
)
func PoolFactory(cephConn CephConnection, poolName string) (Pool, error) {
func PoolFactory(cephConn CephConnector, poolName string) (Pool, error) {
var rbdlist []iRBD = []iRBD{}
ioctx, err := cephConn.conn.OpenIOContext(poolName)
ioctx, err := cephConn.OpenIOContext(poolName)
if err != nil {
return Pool{}, fmt.Errorf("Couldn't set context for pool %s %w", poolName, err)
}
defer ioctx.Destroy()
imageList, err := rbd.GetImageNames(ioctx)
imageList, err := ioctx.GetImageNames()
if err != nil {
return Pool{}, fmt.Errorf("Couldn't get list of rbds %w", err)
}
@ -35,14 +33,14 @@ func PoolFactory(cephConn CephConnection, poolName string) (Pool, error) {
}, nil
}
func RBDFacroty(ioctx *rados.IOContext, rbdname string) (RBD, error) {
func RBDFacroty(ioctx IOContexter, rbdname string) (RBD, error) {
defer func() {
if v := recover(); v != nil {
fmt.Println("Shit happened")
}
}()
image := rbd.GetImage(ioctx,rbdname)
image := ioctx.GetImage(rbdname)
err := image.Open()
if err != nil {
panic(err)

1
go_exporter/coverage.out Normal file
View File

@ -0,0 +1 @@
mode: set

View File

@ -8,6 +8,14 @@ require (
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
@ -15,6 +23,7 @@ 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

View File

@ -10,10 +10,14 @@ 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/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=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
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=
@ -28,6 +32,8 @@ 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=

View File

@ -15,7 +15,7 @@ import (
var params Params
var logger *zap.SugaredLogger
func getMetrics(cephConn CephConnection) {
func getMetrics(cephConn CephConnector) {
metrics := InitMetrics()
prometheus.MustRegister(
@ -27,9 +27,11 @@ func getMetrics(cephConn CephConnection) {
for range ticker.C {
var result []Pool = []Pool{}
poolList, err := cephConn.conn.ListPools()
poolList, err := cephConn.ListPools()
if err != nil {
errors.New("Cannot get list of pools")
logger.Error("Cannot get list of pools")
// do not exit but continue checking
continue
}
for _, v := range poolList {

66
go_exporter/mock_test.go Normal file
View File

@ -0,0 +1,66 @@
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)
}

View File

@ -11,10 +11,76 @@ type Params struct {
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