mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-07-29 13:41:58 +08:00

* feat: cloud service integrations: get model and repo interface started * feat: cloud service integrations: flesh out more of cloud services model * feat: cloud integrations: reorganize things a little * feat: cloud integrations: get svc controller started * feat: cloud integrations: add stubs for EC2 and RDS postgres services * feat: cloud integrations: add validation for listing and getting available svcs and some cleanup * feat: cloud integrations: refactor helpers in existing integrations code for reuse * feat: cloud integrations: parsing of cloud service definitions * feat: cloud integrations: impl for getCloudProviderService * feat: cloud integrations: some reorganization * feat: cloud integrations: some more cleanup * feat: cloud integrations: add validation for listing available cloud provider services * feat: cloud integrations: API endpoint for listing available cloud provider services * feat: cloud integrations: add validation for getting details of a particular service * feat: cloud integrations: API endpoint for getting details of a service * feat: cloud integrations: add controller validation for configuring cloud services * feat: cloud integrations: get serviceConfigRepo started * feat: cloud integrations: service config in service list summaries when queried for cloud account id * feat: cloud integrations: only a supported service for a connected cloud account can be configured * feat: cloud integrations: add validation for configuring services via the API * feat: cloud integrations: API for configuring services * feat: cloud integrations: some cleanup * feat: cloud integrations: fix broken test --------- Co-authored-by: Srikanth Chekuri <srikanth.chekuri92@gmail.com>
199 lines
4.2 KiB
Go
199 lines
4.2 KiB
Go
package cloudintegrations
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"fmt"
|
|
|
|
"github.com/jmoiron/sqlx"
|
|
"go.signoz.io/signoz/pkg/query-service/model"
|
|
)
|
|
|
|
type serviceConfigRepository interface {
|
|
get(
|
|
ctx context.Context,
|
|
cloudProvider string,
|
|
cloudAccountId string,
|
|
serviceId string,
|
|
) (*CloudServiceConfig, *model.ApiError)
|
|
|
|
upsert(
|
|
ctx context.Context,
|
|
cloudProvider string,
|
|
cloudAccountId string,
|
|
serviceId string,
|
|
config CloudServiceConfig,
|
|
) (*CloudServiceConfig, *model.ApiError)
|
|
|
|
getAllForAccount(
|
|
ctx context.Context,
|
|
cloudProvider string,
|
|
cloudAccountId string,
|
|
) (
|
|
configsBySvcId map[string]*CloudServiceConfig,
|
|
apiErr *model.ApiError,
|
|
)
|
|
}
|
|
|
|
func newServiceConfigRepository(db *sqlx.DB) (
|
|
*serviceConfigSQLRepository, error,
|
|
) {
|
|
|
|
if err := initServiceConfigSqliteDBIfNeeded(db); err != nil {
|
|
return nil, fmt.Errorf(
|
|
"could not init sqlite DB for cloudintegrations service configs: %w", err,
|
|
)
|
|
}
|
|
|
|
return &serviceConfigSQLRepository{
|
|
db: db,
|
|
}, nil
|
|
}
|
|
|
|
func initServiceConfigSqliteDBIfNeeded(db *sqlx.DB) error {
|
|
|
|
if db == nil {
|
|
return fmt.Errorf("db is required")
|
|
}
|
|
|
|
createTableStatement := `
|
|
CREATE TABLE IF NOT EXISTS cloud_integrations_service_configs(
|
|
cloud_provider TEXT NOT NULL,
|
|
cloud_account_id TEXT NOT NULL,
|
|
service_id TEXT NOT NULL,
|
|
config_json TEXT,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
UNIQUE(cloud_provider, cloud_account_id, service_id)
|
|
)
|
|
`
|
|
_, err := db.Exec(createTableStatement)
|
|
if err != nil {
|
|
return fmt.Errorf(
|
|
"could not ensure cloud provider service configs schema in sqlite DB: %w", err,
|
|
)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type serviceConfigSQLRepository struct {
|
|
db *sqlx.DB
|
|
}
|
|
|
|
func (r *serviceConfigSQLRepository) get(
|
|
ctx context.Context,
|
|
cloudProvider string,
|
|
cloudAccountId string,
|
|
serviceId string,
|
|
) (*CloudServiceConfig, *model.ApiError) {
|
|
|
|
var result CloudServiceConfig
|
|
|
|
err := r.db.GetContext(
|
|
ctx, &result, `
|
|
select
|
|
config_json
|
|
from cloud_integrations_service_configs
|
|
where
|
|
cloud_provider=$1
|
|
and cloud_account_id=$2
|
|
and service_id=$3
|
|
`,
|
|
cloudProvider, cloudAccountId, serviceId,
|
|
)
|
|
|
|
if err == sql.ErrNoRows {
|
|
return nil, model.NotFoundError(fmt.Errorf(
|
|
"couldn't find %s %s config for %s",
|
|
cloudProvider, serviceId, cloudAccountId,
|
|
))
|
|
|
|
} else if err != nil {
|
|
return nil, model.InternalError(fmt.Errorf(
|
|
"couldn't query cloud service config: %w", err,
|
|
))
|
|
}
|
|
|
|
return &result, nil
|
|
|
|
}
|
|
|
|
func (r *serviceConfigSQLRepository) upsert(
|
|
ctx context.Context,
|
|
cloudProvider string,
|
|
cloudAccountId string,
|
|
serviceId string,
|
|
config CloudServiceConfig,
|
|
) (*CloudServiceConfig, *model.ApiError) {
|
|
|
|
query := `
|
|
INSERT INTO cloud_integrations_service_configs (
|
|
cloud_provider,
|
|
cloud_account_id,
|
|
service_id,
|
|
config_json
|
|
) values ($1, $2, $3, $4)
|
|
on conflict(cloud_provider, cloud_account_id, service_id)
|
|
do update set config_json=excluded.config_json
|
|
`
|
|
_, dbErr := r.db.ExecContext(
|
|
ctx, query,
|
|
cloudProvider, cloudAccountId, serviceId, &config,
|
|
)
|
|
if dbErr != nil {
|
|
return nil, model.InternalError(fmt.Errorf(
|
|
"could not upsert cloud service config: %w", dbErr,
|
|
))
|
|
}
|
|
|
|
upsertedConfig, apiErr := r.get(ctx, cloudProvider, cloudAccountId, serviceId)
|
|
if apiErr != nil {
|
|
return nil, model.InternalError(fmt.Errorf(
|
|
"couldn't fetch upserted service config: %w", apiErr.ToError(),
|
|
))
|
|
}
|
|
|
|
return upsertedConfig, nil
|
|
|
|
}
|
|
|
|
func (r *serviceConfigSQLRepository) getAllForAccount(
|
|
ctx context.Context,
|
|
cloudProvider string,
|
|
cloudAccountId string,
|
|
) (map[string]*CloudServiceConfig, *model.ApiError) {
|
|
|
|
type ScannedServiceConfigRecord struct {
|
|
ServiceId string `db:"service_id"`
|
|
Config CloudServiceConfig `db:"config_json"`
|
|
}
|
|
|
|
records := []ScannedServiceConfigRecord{}
|
|
|
|
err := r.db.SelectContext(
|
|
ctx, &records, `
|
|
select
|
|
service_id,
|
|
config_json
|
|
from cloud_integrations_service_configs
|
|
where
|
|
cloud_provider=$1
|
|
and cloud_account_id=$2
|
|
`,
|
|
cloudProvider, cloudAccountId,
|
|
)
|
|
if err != nil {
|
|
return nil, model.InternalError(fmt.Errorf(
|
|
"could not query service configs from db: %w", err,
|
|
))
|
|
}
|
|
|
|
result := map[string]*CloudServiceConfig{}
|
|
|
|
for _, r := range records {
|
|
result[r.ServiceId] = &r.Config
|
|
}
|
|
|
|
return result, nil
|
|
}
|