mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-15 07:25:55 +08:00
feat(sqlmigration): update the alertmanager tables (#7513)
* feat(sqlmigration): update the alertmanager tables
This commit is contained in:
parent
b43a198fd8
commit
b89ce82e25
@ -8,6 +8,12 @@ import (
|
|||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
Identity = "id"
|
||||||
|
Integer = "bigint"
|
||||||
|
Text = "text"
|
||||||
|
)
|
||||||
|
|
||||||
type dialect struct {
|
type dialect struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,3 +224,49 @@ func (dialect *dialect) AddNotNullDefaultToColumn(ctx context.Context, bun bun.I
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dialect *dialect) UpdatePrimaryKey(ctx context.Context, bun bun.IDB, oldModel interface{}, newModel interface{}, cb func(context.Context) error) error {
|
||||||
|
oldTableName := bun.Dialect().Tables().Get(reflect.TypeOf(oldModel)).Name
|
||||||
|
newTableName := bun.Dialect().Tables().Get(reflect.TypeOf(newModel)).Name
|
||||||
|
|
||||||
|
columnType, err := dialect.GetColumnType(ctx, bun, oldTableName, Identity)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if columnType == Text {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = bun.
|
||||||
|
NewCreateTable().
|
||||||
|
IfNotExists().
|
||||||
|
Model(newModel).
|
||||||
|
ForeignKey(`("org_id") REFERENCES "organizations" ("id")`).
|
||||||
|
Exec(ctx)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = cb(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = bun.
|
||||||
|
NewDropTable().
|
||||||
|
IfExists().
|
||||||
|
Model(oldModel).
|
||||||
|
Exec(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = bun.
|
||||||
|
ExecContext(ctx, fmt.Sprintf("ALTER TABLE %s RENAME TO %s", newTableName, oldTableName))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/SigNoz/signoz/pkg/errors"
|
"github.com/SigNoz/signoz/pkg/errors"
|
||||||
"github.com/SigNoz/signoz/pkg/factory"
|
"github.com/SigNoz/signoz/pkg/factory"
|
||||||
"github.com/SigNoz/signoz/pkg/types/alertmanagertypes"
|
"github.com/SigNoz/signoz/pkg/types/alertmanagertypes"
|
||||||
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -33,16 +34,16 @@ type Alertmanager interface {
|
|||||||
ListAllChannels(context.Context) ([]*alertmanagertypes.Channel, error)
|
ListAllChannels(context.Context) ([]*alertmanagertypes.Channel, error)
|
||||||
|
|
||||||
// GetChannelByID gets a channel for the organization.
|
// GetChannelByID gets a channel for the organization.
|
||||||
GetChannelByID(context.Context, string, int) (*alertmanagertypes.Channel, error)
|
GetChannelByID(context.Context, string, valuer.UUID) (*alertmanagertypes.Channel, error)
|
||||||
|
|
||||||
// UpdateChannel updates a channel for the organization.
|
// UpdateChannel updates a channel for the organization.
|
||||||
UpdateChannelByReceiverAndID(context.Context, string, alertmanagertypes.Receiver, int) error
|
UpdateChannelByReceiverAndID(context.Context, string, alertmanagertypes.Receiver, valuer.UUID) error
|
||||||
|
|
||||||
// CreateChannel creates a channel for the organization.
|
// CreateChannel creates a channel for the organization.
|
||||||
CreateChannel(context.Context, string, alertmanagertypes.Receiver) error
|
CreateChannel(context.Context, string, alertmanagertypes.Receiver) error
|
||||||
|
|
||||||
// DeleteChannelByID deletes a channel for the organization.
|
// DeleteChannelByID deletes a channel for the organization.
|
||||||
DeleteChannelByID(context.Context, string, int) error
|
DeleteChannelByID(context.Context, string, valuer.UUID) error
|
||||||
|
|
||||||
// SetConfig sets the config for the organization.
|
// SetConfig sets the config for the organization.
|
||||||
SetConfig(context.Context, *alertmanagertypes.Config) error
|
SetConfig(context.Context, *alertmanagertypes.Config) error
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/SigNoz/signoz/pkg/errors"
|
"github.com/SigNoz/signoz/pkg/errors"
|
||||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||||
"github.com/SigNoz/signoz/pkg/types/alertmanagertypes"
|
"github.com/SigNoz/signoz/pkg/types/alertmanagertypes"
|
||||||
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
@ -99,7 +100,7 @@ func (store *config) CreateChannel(ctx context.Context, channel *alertmanagertyp
|
|||||||
}, opts...)
|
}, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (store *config) GetChannelByID(ctx context.Context, orgID string, id int) (*alertmanagertypes.Channel, error) {
|
func (store *config) GetChannelByID(ctx context.Context, orgID string, id valuer.UUID) (*alertmanagertypes.Channel, error) {
|
||||||
channel := new(alertmanagertypes.Channel)
|
channel := new(alertmanagertypes.Channel)
|
||||||
|
|
||||||
err := store.
|
err := store.
|
||||||
@ -108,11 +109,11 @@ func (store *config) GetChannelByID(ctx context.Context, orgID string, id int) (
|
|||||||
NewSelect().
|
NewSelect().
|
||||||
Model(channel).
|
Model(channel).
|
||||||
Where("org_id = ?", orgID).
|
Where("org_id = ?", orgID).
|
||||||
Where("id = ?", id).
|
Where("id = ?", id.StringValue()).
|
||||||
Scan(ctx)
|
Scan(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return nil, errors.Newf(errors.TypeNotFound, alertmanagertypes.ErrCodeAlertmanagerChannelNotFound, "cannot find channel with id %d", id)
|
return nil, errors.Newf(errors.TypeNotFound, alertmanagertypes.ErrCodeAlertmanagerChannelNotFound, "cannot find channel with id %s", id.StringValue())
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -136,7 +137,7 @@ func (store *config) UpdateChannel(ctx context.Context, orgID string, channel *a
|
|||||||
}, opts...)
|
}, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (store *config) DeleteChannelByID(ctx context.Context, orgID string, id int, opts ...alertmanagertypes.StoreOption) error {
|
func (store *config) DeleteChannelByID(ctx context.Context, orgID string, id valuer.UUID, opts ...alertmanagertypes.StoreOption) error {
|
||||||
return store.wrap(ctx, func(ctx context.Context) error {
|
return store.wrap(ctx, func(ctx context.Context) error {
|
||||||
channel := new(alertmanagertypes.Channel)
|
channel := new(alertmanagertypes.Channel)
|
||||||
|
|
||||||
@ -146,7 +147,7 @@ func (store *config) DeleteChannelByID(ctx context.Context, orgID string, id int
|
|||||||
NewDelete().
|
NewDelete().
|
||||||
Model(channel).
|
Model(channel).
|
||||||
Where("org_id = ?", orgID).
|
Where("org_id = ?", orgID).
|
||||||
Where("id = ?", id).
|
Where("id = ?", id.StringValue()).
|
||||||
Exec(ctx); err != nil {
|
Exec(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,13 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/SigNoz/signoz/pkg/errors"
|
"github.com/SigNoz/signoz/pkg/errors"
|
||||||
"github.com/SigNoz/signoz/pkg/http/render"
|
"github.com/SigNoz/signoz/pkg/http/render"
|
||||||
"github.com/SigNoz/signoz/pkg/types/alertmanagertypes"
|
"github.com/SigNoz/signoz/pkg/types/alertmanagertypes"
|
||||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||||
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -140,9 +140,9 @@ func (api *API) GetChannelByID(rw http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := strconv.Atoi(idString)
|
id, err := valuer.NewUUID(idString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
render.Error(rw, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "id is not a valid integer"))
|
render.Error(rw, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "id is not a valid uuid-v7"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,9 +177,9 @@ func (api *API) UpdateChannelByID(rw http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := strconv.Atoi(idString)
|
id, err := valuer.NewUUID(idString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
render.Error(rw, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "id is not a valid integer"))
|
render.Error(rw, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "id is not a valid uuid-v7"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,9 +227,9 @@ func (api *API) DeleteChannelByID(rw http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := strconv.Atoi(idString)
|
id, err := valuer.NewUUID(idString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
render.Error(rw, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "id is not a valid integer"))
|
render.Error(rw, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "id is not a valid uuid-v7"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/SigNoz/signoz/pkg/factory"
|
"github.com/SigNoz/signoz/pkg/factory"
|
||||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||||
"github.com/SigNoz/signoz/pkg/types/alertmanagertypes"
|
"github.com/SigNoz/signoz/pkg/types/alertmanagertypes"
|
||||||
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -269,11 +270,11 @@ func (provider *provider) ListAllChannels(ctx context.Context) ([]*alertmanagert
|
|||||||
return channels, nil
|
return channels, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *provider) GetChannelByID(ctx context.Context, orgID string, channelID int) (*alertmanagertypes.Channel, error) {
|
func (provider *provider) GetChannelByID(ctx context.Context, orgID string, channelID valuer.UUID) (*alertmanagertypes.Channel, error) {
|
||||||
return provider.configStore.GetChannelByID(ctx, orgID, channelID)
|
return provider.configStore.GetChannelByID(ctx, orgID, channelID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *provider) UpdateChannelByReceiverAndID(ctx context.Context, orgID string, receiver alertmanagertypes.Receiver, id int) error {
|
func (provider *provider) UpdateChannelByReceiverAndID(ctx context.Context, orgID string, receiver alertmanagertypes.Receiver, id valuer.UUID) error {
|
||||||
channel, err := provider.configStore.GetChannelByID(ctx, orgID, id)
|
channel, err := provider.configStore.GetChannelByID(ctx, orgID, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -378,7 +379,7 @@ func (provider *provider) CreateChannel(ctx context.Context, orgID string, recei
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *provider) DeleteChannelByID(ctx context.Context, orgID string, channelID int) error {
|
func (provider *provider) DeleteChannelByID(ctx context.Context, orgID string, channelID valuer.UUID) error {
|
||||||
channel, err := provider.configStore.GetChannelByID(ctx, orgID, channelID)
|
channel, err := provider.configStore.GetChannelByID(ctx, orgID, channelID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/SigNoz/signoz/pkg/factory"
|
"github.com/SigNoz/signoz/pkg/factory"
|
||||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||||
"github.com/SigNoz/signoz/pkg/types/alertmanagertypes"
|
"github.com/SigNoz/signoz/pkg/types/alertmanagertypes"
|
||||||
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
)
|
)
|
||||||
|
|
||||||
type provider struct {
|
type provider struct {
|
||||||
@ -99,11 +100,11 @@ func (provider *provider) ListAllChannels(ctx context.Context) ([]*alertmanagert
|
|||||||
return nil, errors.Newf(errors.TypeUnsupported, errors.CodeUnsupported, "not supported by provider signoz")
|
return nil, errors.Newf(errors.TypeUnsupported, errors.CodeUnsupported, "not supported by provider signoz")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *provider) GetChannelByID(ctx context.Context, orgID string, channelID int) (*alertmanagertypes.Channel, error) {
|
func (provider *provider) GetChannelByID(ctx context.Context, orgID string, channelID valuer.UUID) (*alertmanagertypes.Channel, error) {
|
||||||
return provider.configStore.GetChannelByID(ctx, orgID, channelID)
|
return provider.configStore.GetChannelByID(ctx, orgID, channelID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *provider) UpdateChannelByReceiverAndID(ctx context.Context, orgID string, receiver alertmanagertypes.Receiver, id int) error {
|
func (provider *provider) UpdateChannelByReceiverAndID(ctx context.Context, orgID string, receiver alertmanagertypes.Receiver, id valuer.UUID) error {
|
||||||
channel, err := provider.configStore.GetChannelByID(ctx, orgID, id)
|
channel, err := provider.configStore.GetChannelByID(ctx, orgID, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -127,7 +128,7 @@ func (provider *provider) UpdateChannelByReceiverAndID(ctx context.Context, orgI
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *provider) DeleteChannelByID(ctx context.Context, orgID string, channelID int) error {
|
func (provider *provider) DeleteChannelByID(ctx context.Context, orgID string, channelID valuer.UUID) error {
|
||||||
channel, err := provider.configStore.GetChannelByID(ctx, orgID, channelID)
|
channel, err := provider.configStore.GetChannelByID(ctx, orgID, channelID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -65,6 +65,7 @@ func NewSQLMigrationProviderFactories(sqlstore sqlstore.SQLStore) factory.NamedM
|
|||||||
sqlmigration.NewDropLicensesSitesFactory(sqlstore),
|
sqlmigration.NewDropLicensesSitesFactory(sqlstore),
|
||||||
sqlmigration.NewUpdateInvitesFactory(sqlstore),
|
sqlmigration.NewUpdateInvitesFactory(sqlstore),
|
||||||
sqlmigration.NewUpdatePatFactory(sqlstore),
|
sqlmigration.NewUpdatePatFactory(sqlstore),
|
||||||
|
sqlmigration.NewUpdateAlertmanagerFactory(sqlstore),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
277
pkg/sqlmigration/021_update_alertmanager.go
Normal file
277
pkg/sqlmigration/021_update_alertmanager.go
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
package sqlmigration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/SigNoz/signoz/pkg/factory"
|
||||||
|
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||||
|
"github.com/SigNoz/signoz/pkg/types"
|
||||||
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
|
"github.com/uptrace/bun"
|
||||||
|
"github.com/uptrace/bun/migrate"
|
||||||
|
)
|
||||||
|
|
||||||
|
type updateAlertmanager struct {
|
||||||
|
store sqlstore.SQLStore
|
||||||
|
}
|
||||||
|
|
||||||
|
type existingChannel struct {
|
||||||
|
bun.BaseModel `bun:"table:notification_channels"`
|
||||||
|
ID int `json:"id" bun:"id,pk,autoincrement"`
|
||||||
|
Name string `json:"name" bun:"name"`
|
||||||
|
Type string `json:"type" bun:"type"`
|
||||||
|
Data string `json:"data" bun:"data"`
|
||||||
|
CreatedAt time.Time `json:"created_at" bun:"created_at"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at" bun:"updated_at"`
|
||||||
|
OrgID string `json:"org_id" bun:"org_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type newChannel struct {
|
||||||
|
bun.BaseModel `bun:"table:notification_channel"`
|
||||||
|
types.Identifiable
|
||||||
|
types.TimeAuditable
|
||||||
|
Name string `json:"name" bun:"name"`
|
||||||
|
Type string `json:"type" bun:"type"`
|
||||||
|
Data string `json:"data" bun:"data"`
|
||||||
|
OrgID string `json:"org_id" bun:"org_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type existingAlertmanagerConfig struct {
|
||||||
|
bun.BaseModel `bun:"table:alertmanager_config"`
|
||||||
|
ID uint64 `bun:"id,pk,autoincrement"`
|
||||||
|
Config string `bun:"config,notnull,type:text"`
|
||||||
|
Hash string `bun:"hash,notnull,type:text"`
|
||||||
|
CreatedAt time.Time `bun:"created_at,notnull"`
|
||||||
|
UpdatedAt time.Time `bun:"updated_at,notnull"`
|
||||||
|
OrgID string `bun:"org_id,notnull,unique"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type newAlertmanagerConfig struct {
|
||||||
|
bun.BaseModel `bun:"table:alertmanager_config_new"`
|
||||||
|
types.Identifiable
|
||||||
|
types.TimeAuditable
|
||||||
|
Config string `bun:"config,notnull,type:text"`
|
||||||
|
Hash string `bun:"hash,notnull,type:text"`
|
||||||
|
OrgID string `bun:"org_id,notnull,unique"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type existingAlertmanagerState struct {
|
||||||
|
bun.BaseModel `bun:"table:alertmanager_state"`
|
||||||
|
ID uint64 `bun:"id,pk,autoincrement"`
|
||||||
|
Silences string `bun:"silences,nullzero,type:text"`
|
||||||
|
NFLog string `bun:"nflog,nullzero,type:text"`
|
||||||
|
CreatedAt time.Time `bun:"created_at,notnull"`
|
||||||
|
UpdatedAt time.Time `bun:"updated_at,notnull"`
|
||||||
|
OrgID string `bun:"org_id,notnull,unique"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type newAlertmanagerState struct {
|
||||||
|
bun.BaseModel `bun:"table:alertmanager_state_new"`
|
||||||
|
types.Identifiable
|
||||||
|
types.TimeAuditable
|
||||||
|
Silences string `bun:"silences,nullzero,type:text"`
|
||||||
|
NFLog string `bun:"nflog,nullzero,type:text"`
|
||||||
|
OrgID string `bun:"org_id,notnull,unique"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUpdateAlertmanagerFactory(sqlstore sqlstore.SQLStore) factory.ProviderFactory[SQLMigration, Config] {
|
||||||
|
return factory.
|
||||||
|
NewProviderFactory(
|
||||||
|
factory.MustNewName("update_alertmanager"),
|
||||||
|
func(ctx context.Context, ps factory.ProviderSettings, c Config) (SQLMigration, error) {
|
||||||
|
return newUpdateAlertmanager(ctx, ps, c, sqlstore)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func newUpdateAlertmanager(_ context.Context, _ factory.ProviderSettings, _ Config, store sqlstore.SQLStore) (SQLMigration, error) {
|
||||||
|
return &updateAlertmanager{store: store}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (migration *updateAlertmanager) Register(migrations *migrate.Migrations) error {
|
||||||
|
if err := migrations.
|
||||||
|
Register(migration.Up, migration.Down); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (migration *updateAlertmanager) Up(ctx context.Context, db *bun.DB) error {
|
||||||
|
tx, err := db.
|
||||||
|
BeginTx(ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer tx.Rollback()
|
||||||
|
|
||||||
|
err = migration.
|
||||||
|
store.
|
||||||
|
Dialect().
|
||||||
|
RenameTableAndModifyModel(ctx, tx, new(existingChannel), new(newChannel), func(ctx context.Context) error {
|
||||||
|
existingChannels := make([]*existingChannel, 0)
|
||||||
|
err = tx.
|
||||||
|
NewSelect().
|
||||||
|
Model(&existingChannels).
|
||||||
|
Scan(ctx)
|
||||||
|
if err != nil {
|
||||||
|
if err != sql.ErrNoRows {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil && len(existingChannels) > 0 {
|
||||||
|
newChannels := migration.
|
||||||
|
CopyOldChannelToNewChannel(existingChannels)
|
||||||
|
_, err = tx.
|
||||||
|
NewInsert().
|
||||||
|
Model(&newChannels).
|
||||||
|
Exec(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = migration.
|
||||||
|
store.
|
||||||
|
Dialect().
|
||||||
|
UpdatePrimaryKey(ctx, tx, new(existingAlertmanagerConfig), new(newAlertmanagerConfig), func(ctx context.Context) error {
|
||||||
|
existingAlertmanagerConfigs := make([]*existingAlertmanagerConfig, 0)
|
||||||
|
err = tx.
|
||||||
|
NewSelect().
|
||||||
|
Model(&existingAlertmanagerConfigs).
|
||||||
|
Scan(ctx)
|
||||||
|
if err != nil {
|
||||||
|
if err != sql.ErrNoRows {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil && len(existingAlertmanagerConfigs) > 0 {
|
||||||
|
newAlertmanagerConfigs := migration.
|
||||||
|
CopyOldConfigToNewConfig(existingAlertmanagerConfigs)
|
||||||
|
_, err = tx.
|
||||||
|
NewInsert().
|
||||||
|
Model(&newAlertmanagerConfigs).
|
||||||
|
Exec(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = migration.
|
||||||
|
store.
|
||||||
|
Dialect().
|
||||||
|
UpdatePrimaryKey(ctx, tx, new(existingAlertmanagerState), new(newAlertmanagerState), func(ctx context.Context) error {
|
||||||
|
existingAlertmanagerStates := make([]*existingAlertmanagerState, 0)
|
||||||
|
err = tx.
|
||||||
|
NewSelect().
|
||||||
|
Model(&existingAlertmanagerStates).
|
||||||
|
Scan(ctx)
|
||||||
|
if err != nil {
|
||||||
|
if err != sql.ErrNoRows {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil && len(existingAlertmanagerStates) > 0 {
|
||||||
|
newAlertmanagerStates := migration.
|
||||||
|
CopyOldStateToNewState(existingAlertmanagerStates)
|
||||||
|
_, err = tx.
|
||||||
|
NewInsert().
|
||||||
|
Model(&newAlertmanagerStates).
|
||||||
|
Exec(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (migration *updateAlertmanager) Down(context.Context, *bun.DB) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (migration *updateAlertmanager) CopyOldChannelToNewChannel(existingChannels []*existingChannel) []*newChannel {
|
||||||
|
newChannels := make([]*newChannel, 0)
|
||||||
|
for _, channel := range existingChannels {
|
||||||
|
newChannels = append(newChannels, &newChannel{
|
||||||
|
Identifiable: types.Identifiable{
|
||||||
|
ID: valuer.GenerateUUID(),
|
||||||
|
},
|
||||||
|
TimeAuditable: types.TimeAuditable{
|
||||||
|
CreatedAt: channel.CreatedAt,
|
||||||
|
UpdatedAt: channel.UpdatedAt,
|
||||||
|
},
|
||||||
|
Name: channel.Name,
|
||||||
|
Type: channel.Type,
|
||||||
|
Data: channel.Data,
|
||||||
|
OrgID: channel.OrgID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return newChannels
|
||||||
|
}
|
||||||
|
|
||||||
|
func (migration *updateAlertmanager) CopyOldConfigToNewConfig(existingAlertmanagerConfigs []*existingAlertmanagerConfig) []*newAlertmanagerConfig {
|
||||||
|
newAlertmanagerConfigs := make([]*newAlertmanagerConfig, 0)
|
||||||
|
for _, config := range existingAlertmanagerConfigs {
|
||||||
|
newAlertmanagerConfigs = append(newAlertmanagerConfigs, &newAlertmanagerConfig{
|
||||||
|
Identifiable: types.Identifiable{
|
||||||
|
ID: valuer.GenerateUUID(),
|
||||||
|
},
|
||||||
|
TimeAuditable: types.TimeAuditable{
|
||||||
|
CreatedAt: config.CreatedAt,
|
||||||
|
UpdatedAt: config.UpdatedAt,
|
||||||
|
},
|
||||||
|
Config: config.Config,
|
||||||
|
Hash: config.Hash,
|
||||||
|
OrgID: config.OrgID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return newAlertmanagerConfigs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (migration *updateAlertmanager) CopyOldStateToNewState(existingAlertmanagerStates []*existingAlertmanagerState) []*newAlertmanagerState {
|
||||||
|
newAlertmanagerStates := make([]*newAlertmanagerState, 0)
|
||||||
|
for _, state := range existingAlertmanagerStates {
|
||||||
|
newAlertmanagerStates = append(newAlertmanagerStates, &newAlertmanagerState{
|
||||||
|
Identifiable: types.Identifiable{
|
||||||
|
ID: valuer.GenerateUUID(),
|
||||||
|
},
|
||||||
|
TimeAuditable: types.TimeAuditable{
|
||||||
|
CreatedAt: state.CreatedAt,
|
||||||
|
UpdatedAt: state.UpdatedAt,
|
||||||
|
},
|
||||||
|
Silences: state.Silences,
|
||||||
|
NFLog: state.NFLog,
|
||||||
|
OrgID: state.OrgID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return newAlertmanagerStates
|
||||||
|
}
|
@ -8,6 +8,12 @@ import (
|
|||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
Identity = "id"
|
||||||
|
Integer = "INTEGER"
|
||||||
|
Text = "TEXT"
|
||||||
|
)
|
||||||
|
|
||||||
type dialect struct {
|
type dialect struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,3 +228,49 @@ func (dialect *dialect) AddNotNullDefaultToColumn(ctx context.Context, bun bun.I
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dialect *dialect) UpdatePrimaryKey(ctx context.Context, bun bun.IDB, oldModel interface{}, newModel interface{}, cb func(context.Context) error) error {
|
||||||
|
oldTableName := bun.Dialect().Tables().Get(reflect.TypeOf(oldModel)).Name
|
||||||
|
newTableName := bun.Dialect().Tables().Get(reflect.TypeOf(newModel)).Name
|
||||||
|
|
||||||
|
columnType, err := dialect.GetColumnType(ctx, bun, oldTableName, Identity)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if columnType == Text {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = bun.
|
||||||
|
NewCreateTable().
|
||||||
|
IfNotExists().
|
||||||
|
Model(newModel).
|
||||||
|
ForeignKey(`("org_id") REFERENCES "organizations" ("id")`).
|
||||||
|
Exec(ctx)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = cb(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = bun.
|
||||||
|
NewDropTable().
|
||||||
|
IfExists().
|
||||||
|
Model(oldModel).
|
||||||
|
Exec(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = bun.
|
||||||
|
ExecContext(ctx, fmt.Sprintf("ALTER TABLE %s RENAME TO %s", newTableName, oldTableName))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -44,4 +44,5 @@ type SQLDialect interface {
|
|||||||
ColumnExists(context.Context, bun.IDB, string, string) (bool, error)
|
ColumnExists(context.Context, bun.IDB, string, string) (bool, error)
|
||||||
RenameColumn(context.Context, bun.IDB, string, string, string) (bool, error)
|
RenameColumn(context.Context, bun.IDB, string, string, string) (bool, error)
|
||||||
RenameTableAndModifyModel(context.Context, bun.IDB, interface{}, interface{}, func(context.Context) error) error
|
RenameTableAndModifyModel(context.Context, bun.IDB, interface{}, interface{}, func(context.Context) error) error
|
||||||
|
UpdatePrimaryKey(context.Context, bun.IDB, interface{}, interface{}, func(context.Context) error) error
|
||||||
}
|
}
|
||||||
|
@ -36,3 +36,11 @@ func (dialect *dialect) RenameTableAndModifyModel(ctx context.Context, bun bun.I
|
|||||||
func (dialect *dialect) AddNotNullDefaultToColumn(ctx context.Context, bun bun.IDB, table string, column, columnType, defaultValue string) error {
|
func (dialect *dialect) AddNotNullDefaultToColumn(ctx context.Context, bun bun.IDB, table string, column, columnType, defaultValue string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dialect *dialect) UpdatePrimaryKey(ctx context.Context, bun bun.IDB, oldModel interface{}, newModel interface{}, cb func(context.Context) error) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dialect *dialect) IndexExists(ctx context.Context, bun bun.IDB, table string, index string) (bool, error) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
@ -7,6 +7,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/SigNoz/signoz/pkg/errors"
|
"github.com/SigNoz/signoz/pkg/errors"
|
||||||
|
"github.com/SigNoz/signoz/pkg/types"
|
||||||
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
"github.com/prometheus/alertmanager/config"
|
"github.com/prometheus/alertmanager/config"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
@ -27,15 +29,14 @@ type GettableChannels = []*Channel
|
|||||||
|
|
||||||
// Channel represents a single receiver of the alertmanager config.
|
// Channel represents a single receiver of the alertmanager config.
|
||||||
type Channel struct {
|
type Channel struct {
|
||||||
bun.BaseModel `bun:"table:notification_channels"`
|
bun.BaseModel `bun:"table:notification_channel"`
|
||||||
|
|
||||||
ID int `json:"id" bun:"id,pk,autoincrement"`
|
types.Identifiable
|
||||||
Name string `json:"name" bun:"name"`
|
types.TimeAuditable
|
||||||
Type string `json:"type" bun:"type"`
|
Name string `json:"name" bun:"name"`
|
||||||
Data string `json:"data" bun:"data"`
|
Type string `json:"type" bun:"type"`
|
||||||
CreatedAt time.Time `json:"created_at" bun:"created_at"`
|
Data string `json:"data" bun:"data"`
|
||||||
UpdatedAt time.Time `json:"updated_at" bun:"updated_at"`
|
OrgID string `json:"org_id" bun:"org_id"`
|
||||||
OrgID string `json:"org_id" bun:"org_id"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewChannelFromReceiver creates a new Channel from a Receiver.
|
// NewChannelFromReceiver creates a new Channel from a Receiver.
|
||||||
@ -47,10 +48,15 @@ func NewChannelFromReceiver(receiver config.Receiver, orgID string) *Channel {
|
|||||||
|
|
||||||
// Initialize channel with common fields
|
// Initialize channel with common fields
|
||||||
channel := Channel{
|
channel := Channel{
|
||||||
Name: receiver.Name,
|
Identifiable: types.Identifiable{
|
||||||
CreatedAt: time.Now(),
|
ID: valuer.GenerateUUID(),
|
||||||
UpdatedAt: time.Now(),
|
},
|
||||||
OrgID: orgID,
|
TimeAuditable: types.TimeAuditable{
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
},
|
||||||
|
Name: receiver.Name,
|
||||||
|
OrgID: orgID,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use reflection to examine receiver struct fields
|
// Use reflection to examine receiver struct fields
|
||||||
@ -120,14 +126,14 @@ func NewConfigFromChannels(globalConfig GlobalConfig, routeConfig RouteConfig, c
|
|||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetChannelByID(channels Channels, id int) (int, *Channel, error) {
|
func GetChannelByID(channels Channels, id valuer.UUID) (int, *Channel, error) {
|
||||||
for i, channel := range channels {
|
for i, channel := range channels {
|
||||||
if channel.ID == id {
|
if channel.ID == id {
|
||||||
return i, channel, nil
|
return i, channel, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0, nil, errors.Newf(errors.TypeNotFound, ErrCodeAlertmanagerChannelNotFound, "cannot find channel with id %d", id)
|
return 0, nil, errors.Newf(errors.TypeNotFound, ErrCodeAlertmanagerChannelNotFound, "cannot find channel with id %s", id.StringValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetChannelByName(channels Channels, name string) (int, *Channel, error) {
|
func GetChannelByName(channels Channels, name string) (int, *Channel, error) {
|
||||||
@ -143,7 +149,7 @@ func GetChannelByName(channels Channels, name string) (int, *Channel, error) {
|
|||||||
func (c *Channel) Update(receiver Receiver) error {
|
func (c *Channel) Update(receiver Receiver) error {
|
||||||
channel := NewChannelFromReceiver(receiver, c.OrgID)
|
channel := NewChannelFromReceiver(receiver, c.OrgID)
|
||||||
if channel == nil {
|
if channel == nil {
|
||||||
return errors.Newf(errors.TypeInvalidInput, ErrCodeAlertmanagerChannelNotFound, "cannot find channel with id %d", c.ID)
|
return errors.Newf(errors.TypeInvalidInput, ErrCodeAlertmanagerChannelNotFound, "cannot find channel with id %s", c.ID.StringValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Name != channel.Name {
|
if c.Name != channel.Name {
|
||||||
|
@ -10,6 +10,8 @@ import (
|
|||||||
|
|
||||||
"dario.cat/mergo"
|
"dario.cat/mergo"
|
||||||
"github.com/SigNoz/signoz/pkg/errors"
|
"github.com/SigNoz/signoz/pkg/errors"
|
||||||
|
"github.com/SigNoz/signoz/pkg/types"
|
||||||
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
"github.com/prometheus/alertmanager/config"
|
"github.com/prometheus/alertmanager/config"
|
||||||
commoncfg "github.com/prometheus/common/config"
|
commoncfg "github.com/prometheus/common/config"
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
@ -41,12 +43,11 @@ type RouteConfig struct {
|
|||||||
type StoreableConfig struct {
|
type StoreableConfig struct {
|
||||||
bun.BaseModel `bun:"table:alertmanager_config"`
|
bun.BaseModel `bun:"table:alertmanager_config"`
|
||||||
|
|
||||||
ID uint64 `bun:"id,pk,autoincrement"`
|
types.Identifiable
|
||||||
Config string `bun:"config"`
|
types.TimeAuditable
|
||||||
Hash string `bun:"hash"`
|
Config string `bun:"config"`
|
||||||
CreatedAt time.Time `bun:"created_at"`
|
Hash string `bun:"hash"`
|
||||||
UpdatedAt time.Time `bun:"updated_at"`
|
OrgID string `bun:"org_id"`
|
||||||
OrgID string `bun:"org_id"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config is the type for the entire alertmanager configuration
|
// Config is the type for the entire alertmanager configuration
|
||||||
@ -63,11 +64,16 @@ func NewConfig(c *config.Config, orgID string) *Config {
|
|||||||
return &Config{
|
return &Config{
|
||||||
alertmanagerConfig: c,
|
alertmanagerConfig: c,
|
||||||
storeableConfig: &StoreableConfig{
|
storeableConfig: &StoreableConfig{
|
||||||
Config: raw,
|
Identifiable: types.Identifiable{
|
||||||
Hash: fmt.Sprintf("%x", newConfigHash(raw)),
|
ID: valuer.GenerateUUID(),
|
||||||
CreatedAt: time.Now(),
|
},
|
||||||
UpdatedAt: time.Now(),
|
TimeAuditable: types.TimeAuditable{
|
||||||
OrgID: orgID,
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
},
|
||||||
|
Config: raw,
|
||||||
|
Hash: fmt.Sprintf("%x", newConfigHash(raw)),
|
||||||
|
OrgID: orgID,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -370,13 +376,13 @@ type ConfigStore interface {
|
|||||||
CreateChannel(context.Context, *Channel, ...StoreOption) error
|
CreateChannel(context.Context, *Channel, ...StoreOption) error
|
||||||
|
|
||||||
// GetChannelByID returns the channel for the given id.
|
// GetChannelByID returns the channel for the given id.
|
||||||
GetChannelByID(context.Context, string, int) (*Channel, error)
|
GetChannelByID(context.Context, string, valuer.UUID) (*Channel, error)
|
||||||
|
|
||||||
// UpdateChannel updates a channel.
|
// UpdateChannel updates a channel.
|
||||||
UpdateChannel(context.Context, string, *Channel, ...StoreOption) error
|
UpdateChannel(context.Context, string, *Channel, ...StoreOption) error
|
||||||
|
|
||||||
// DeleteChannelByID deletes a channel.
|
// DeleteChannelByID deletes a channel.
|
||||||
DeleteChannelByID(context.Context, string, int, ...StoreOption) error
|
DeleteChannelByID(context.Context, string, valuer.UUID, ...StoreOption) error
|
||||||
|
|
||||||
// ListChannels returns the list of channels.
|
// ListChannels returns the list of channels.
|
||||||
ListChannels(context.Context, string) ([]*Channel, error)
|
ListChannels(context.Context, string) ([]*Channel, error)
|
||||||
|
@ -6,6 +6,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/SigNoz/signoz/pkg/errors"
|
"github.com/SigNoz/signoz/pkg/errors"
|
||||||
|
"github.com/SigNoz/signoz/pkg/types"
|
||||||
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
"github.com/prometheus/alertmanager/cluster"
|
"github.com/prometheus/alertmanager/cluster"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
@ -28,19 +30,23 @@ var (
|
|||||||
type StoreableState struct {
|
type StoreableState struct {
|
||||||
bun.BaseModel `bun:"table:alertmanager_state"`
|
bun.BaseModel `bun:"table:alertmanager_state"`
|
||||||
|
|
||||||
ID uint64 `bun:"id,pk,autoincrement"`
|
types.Identifiable
|
||||||
Silences string `bun:"silences,nullzero"`
|
types.TimeAuditable
|
||||||
NFLog string `bun:"nflog,nullzero"`
|
Silences string `bun:"silences,nullzero"`
|
||||||
CreatedAt time.Time `bun:"created_at"`
|
NFLog string `bun:"nflog,nullzero"`
|
||||||
UpdatedAt time.Time `bun:"updated_at"`
|
OrgID string `bun:"org_id"`
|
||||||
OrgID string `bun:"org_id"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStoreableState(orgID string) *StoreableState {
|
func NewStoreableState(orgID string) *StoreableState {
|
||||||
return &StoreableState{
|
return &StoreableState{
|
||||||
OrgID: orgID,
|
Identifiable: types.Identifiable{
|
||||||
CreatedAt: time.Now(),
|
ID: valuer.GenerateUUID(),
|
||||||
UpdatedAt: time.Now(),
|
},
|
||||||
|
TimeAuditable: types.TimeAuditable{
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
},
|
||||||
|
OrgID: orgID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user