Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
182cc7c
update e2e test, change script
htemelski-redis Sep 30, 2025
460ea94
update script and tests
htemelski-redis Sep 30, 2025
4287b8b
fixed bdbid parsing
htemelski-redis Sep 30, 2025
a6133b3
disabled majority of tests, swapped event order
htemelski-redis Oct 2, 2025
1fdbeb3
change the config tag
htemelski-redis Oct 2, 2025
aa1b3b9
revert test order
htemelski-redis Oct 2, 2025
36ad014
fix typo
htemelski-redis Oct 2, 2025
23ee78a
reenable all e2e tests
htemelski-redis Oct 2, 2025
7b098fa
change the clonfig flag key for all e2e tests
htemelski-redis Oct 2, 2025
72cf032
improve logging for debug purposes of tests
ndyakov Oct 3, 2025
75ae204
longer deadline for FI in CI
ndyakov Oct 3, 2025
87670b2
increase waiting for notifications
ndyakov Oct 3, 2025
113edc5
extend tests
ndyakov Oct 3, 2025
ebfb7da
dont fail on flaky third client
ndyakov Oct 3, 2025
ae9f063
fi new params
ndyakov Oct 3, 2025
0ee3a8b
fix test build
ndyakov Oct 6, 2025
61998d5
more time for migrating
ndyakov Oct 6, 2025
0c8434c
first wait for FI action, then assert notification
ndyakov Oct 6, 2025
d8d55f9
fix test build
ndyakov Oct 6, 2025
93ef6cc
fix tests
ndyakov Oct 6, 2025
3699acf
fix tests
ndyakov Oct 6, 2025
012d566
change output
ndyakov Oct 6, 2025
560f0b7
global print logs for tests
ndyakov Oct 6, 2025
761daaf
better output
ndyakov Oct 6, 2025
bbd7b8d
fix error format
ndyakov Oct 6, 2025
e27d232
maybe the notification is already received
ndyakov Oct 6, 2025
7329e31
second and third client fix
ndyakov Oct 6, 2025
1adb576
print output if failed
ndyakov Oct 6, 2025
9ed6e2e
better second and third client checks
ndyakov Oct 6, 2025
f0adb97
output action data if notification is not received
ndyakov Oct 6, 2025
db17aa7
stop command runner
ndyakov Oct 6, 2025
bf3870d
database create / delete actions
ndyakov Oct 7, 2025
0d4212b
database create / delete actions used in tests
ndyakov Oct 7, 2025
820a33d
fix import
ndyakov Oct 7, 2025
37a7f8d
remove example
ndyakov Oct 7, 2025
13c5092
remove unused var
ndyakov Oct 7, 2025
c74156f
use different port than the one in env
ndyakov Oct 7, 2025
f1a4f46
wait for action to get the response
ndyakov Oct 7, 2025
ecd679b
fix output
ndyakov Oct 7, 2025
38f7b5e
fix create db config
ndyakov Oct 7, 2025
37c8c95
fix create db config
ndyakov Oct 7, 2025
d89e3f4
use new database for client
ndyakov Oct 7, 2025
8b1b8b6
fix create db config
ndyakov Oct 7, 2025
dbe717b
db per scenario
ndyakov Oct 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
363 changes: 363 additions & 0 deletions maintnotifications/e2e/DATABASE_MANAGEMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,363 @@
# Database Management with Fault Injector

This document describes how to use the fault injector's database management endpoints to create and delete Redis databases during E2E testing.

## Overview

The fault injector now supports two new endpoints for database management:

1. **CREATE_DATABASE** - Create a new Redis database with custom configuration
2. **DELETE_DATABASE** - Delete an existing Redis database

These endpoints are useful for E2E tests that need to dynamically create and destroy databases as part of their test scenarios.

## Action Types

### CREATE_DATABASE

Creates a new Redis database with the specified configuration.

**Parameters:**
- `cluster_index` (int): The index of the cluster where the database should be created
- `database_config` (object): The database configuration (see structure below)

**Raises:**
- `CreateDatabaseException`: When database creation fails

### DELETE_DATABASE

Deletes an existing Redis database.

**Parameters:**
- `cluster_index` (int): The index of the cluster containing the database
- `bdb_id` (int): The database ID to delete

**Raises:**
- `DeleteDatabaseException`: When database deletion fails

## Database Configuration Structure

The `database_config` object supports the following fields:

```go
type DatabaseConfig struct {
Name string `json:"name"`
Port int `json:"port"`
MemorySize int64 `json:"memory_size"`
Replication bool `json:"replication"`
EvictionPolicy string `json:"eviction_policy"`
Sharding bool `json:"sharding"`
AutoUpgrade bool `json:"auto_upgrade"`
ShardsCount int `json:"shards_count"`
ModuleList []DatabaseModule `json:"module_list,omitempty"`
OSSCluster bool `json:"oss_cluster"`
OSSClusterAPIPreferredIPType string `json:"oss_cluster_api_preferred_ip_type,omitempty"`
ProxyPolicy string `json:"proxy_policy,omitempty"`
ShardsPlacement string `json:"shards_placement,omitempty"`
ShardKeyRegex []ShardKeyRegexPattern `json:"shard_key_regex,omitempty"`
}

type DatabaseModule struct {
ModuleArgs string `json:"module_args"`
ModuleName string `json:"module_name"`
}

type ShardKeyRegexPattern struct {
Regex string `json:"regex"`
}
```

### Example Configuration

#### Simple Database

```json
{
"name": "simple-db",
"port": 12000,
"memory_size": 268435456,
"replication": false,
"eviction_policy": "noeviction",
"sharding": false,
"auto_upgrade": true,
"shards_count": 1,
"oss_cluster": false
}
```

#### Clustered Database with Modules

```json
{
"name": "ioredis-cluster",
"port": 11112,
"memory_size": 1273741824,
"replication": true,
"eviction_policy": "noeviction",
"sharding": true,
"auto_upgrade": true,
"shards_count": 3,
"module_list": [
{
"module_args": "",
"module_name": "ReJSON"
},
{
"module_args": "",
"module_name": "search"
},
{
"module_args": "",
"module_name": "timeseries"
},
{
"module_args": "",
"module_name": "bf"
}
],
"oss_cluster": true,
"oss_cluster_api_preferred_ip_type": "external",
"proxy_policy": "all-master-shards",
"shards_placement": "sparse",
"shard_key_regex": [
{
"regex": ".*\\{(?<tag>.*)\\}.*"
},
{
"regex": "(?<tag>.*)"
}
]
}
```

## Usage Examples

### Example 1: Create a Simple Database

```go
ctx := context.Background()
faultInjector := NewFaultInjectorClient("http://127.0.0.1:20324")

dbConfig := DatabaseConfig{
Name: "test-db",
Port: 12000,
MemorySize: 268435456, // 256MB
Replication: false,
EvictionPolicy: "noeviction",
Sharding: false,
AutoUpgrade: true,
ShardsCount: 1,
OSSCluster: false,
}

resp, err := faultInjector.CreateDatabase(ctx, 0, dbConfig)
if err != nil {
log.Fatalf("Failed to create database: %v", err)
}

// Wait for creation to complete
status, err := faultInjector.WaitForAction(ctx, resp.ActionID,
WithMaxWaitTime(5*time.Minute))
if err != nil {
log.Fatalf("Failed to wait for action: %v", err)
}

if status.Status == StatusSuccess {
log.Println("Database created successfully!")
}
```

### Example 2: Create a Database with Modules

```go
dbConfig := DatabaseConfig{
Name: "modules-db",
Port: 12001,
MemorySize: 536870912, // 512MB
Replication: true,
EvictionPolicy: "noeviction",
Sharding: true,
AutoUpgrade: true,
ShardsCount: 3,
ModuleList: []DatabaseModule{
{ModuleArgs: "", ModuleName: "ReJSON"},
{ModuleArgs: "", ModuleName: "search"},
},
OSSCluster: true,
OSSClusterAPIPreferredIPType: "external",
ProxyPolicy: "all-master-shards",
ShardsPlacement: "sparse",
}

resp, err := faultInjector.CreateDatabase(ctx, 0, dbConfig)
// ... handle response
```

### Example 3: Create Database Using a Map

```go
dbConfigMap := map[string]interface{}{
"name": "map-db",
"port": 12002,
"memory_size": 268435456,
"replication": false,
"eviction_policy": "volatile-lru",
"sharding": false,
"auto_upgrade": true,
"shards_count": 1,
"oss_cluster": false,
}

resp, err := faultInjector.CreateDatabaseFromMap(ctx, 0, dbConfigMap)
// ... handle response
```

### Example 4: Delete a Database

```go
clusterIndex := 0
bdbID := 1

resp, err := faultInjector.DeleteDatabase(ctx, clusterIndex, bdbID)
if err != nil {
log.Fatalf("Failed to delete database: %v", err)
}

status, err := faultInjector.WaitForAction(ctx, resp.ActionID,
WithMaxWaitTime(2*time.Minute))
if err != nil {
log.Fatalf("Failed to wait for action: %v", err)
}

if status.Status == StatusSuccess {
log.Println("Database deleted successfully!")
}
```

### Example 5: Complete Lifecycle (Create and Delete)

```go
// Create database
dbConfig := DatabaseConfig{
Name: "temp-db",
Port: 13000,
MemorySize: 268435456,
Replication: false,
EvictionPolicy: "noeviction",
Sharding: false,
AutoUpgrade: true,
ShardsCount: 1,
OSSCluster: false,
}

createResp, err := faultInjector.CreateDatabase(ctx, 0, dbConfig)
if err != nil {
log.Fatalf("Failed to create database: %v", err)
}

createStatus, err := faultInjector.WaitForAction(ctx, createResp.ActionID,
WithMaxWaitTime(5*time.Minute))
if err != nil || createStatus.Status != StatusSuccess {
log.Fatalf("Database creation failed")
}

// Extract bdb_id from output
var bdbID int
if id, ok := createStatus.Output["bdb_id"].(float64); ok {
bdbID = int(id)
}

// Use the database for testing...
time.Sleep(10 * time.Second)

// Delete the database
deleteResp, err := faultInjector.DeleteDatabase(ctx, 0, bdbID)
if err != nil {
log.Fatalf("Failed to delete database: %v", err)
}

deleteStatus, err := faultInjector.WaitForAction(ctx, deleteResp.ActionID,
WithMaxWaitTime(2*time.Minute))
if err != nil || deleteStatus.Status != StatusSuccess {
log.Fatalf("Database deletion failed")
}

log.Println("Database lifecycle completed successfully!")
```

## Available Methods

The `FaultInjectorClient` provides the following methods for database management:

### CreateDatabase

```go
func (c *FaultInjectorClient) CreateDatabase(
ctx context.Context,
clusterIndex int,
databaseConfig DatabaseConfig,
) (*ActionResponse, error)
```

Creates a new database using a structured `DatabaseConfig` object.

### CreateDatabaseFromMap

```go
func (c *FaultInjectorClient) CreateDatabaseFromMap(
ctx context.Context,
clusterIndex int,
databaseConfig map[string]interface{},
) (*ActionResponse, error)
```

Creates a new database using a flexible map configuration. Useful when you need to pass custom or dynamic configurations.

### DeleteDatabase

```go
func (c *FaultInjectorClient) DeleteDatabase(
ctx context.Context,
clusterIndex int,
bdbID int,
) (*ActionResponse, error)
```

Deletes an existing database by its ID.

## Testing

To run the database management E2E tests:

```bash
# Run all database management tests
go test -tags=e2e -v ./maintnotifications/e2e/ -run TestDatabase

# Run specific test
go test -tags=e2e -v ./maintnotifications/e2e/ -run TestDatabaseLifecycle
```

## Notes

- Database creation can take several minutes depending on the configuration
- Always use `WaitForAction` to ensure the operation completes before proceeding
- The `bdb_id` returned in the creation output should be used for deletion
- Deleting a non-existent database will result in a failed action status
- Memory sizes are specified in bytes (e.g., 268435456 = 256MB)
- Port numbers should be unique and not conflict with existing databases

## Common Eviction Policies

- `noeviction` - Return errors when memory limit is reached
- `allkeys-lru` - Evict any key using LRU algorithm
- `volatile-lru` - Evict keys with TTL using LRU algorithm
- `allkeys-random` - Evict random keys
- `volatile-random` - Evict random keys with TTL
- `volatile-ttl` - Evict keys with TTL, shortest TTL first

## Common Proxy Policies

- `all-master-shards` - Route to all master shards
- `all-nodes` - Route to all nodes
- `single-shard` - Route to a single shard

Loading
Loading