Skip to content

Commit

Permalink
Add api end point to print the current database state in VTOrc (#15485)
Browse files Browse the repository at this point in the history
Signed-off-by: Manan Gupta <[email protected]>
  • Loading branch information
GuptaManan100 authored Mar 28, 2024
1 parent 8850e8e commit 2078d62
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 2 deletions.
18 changes: 18 additions & 0 deletions go/test/endtoend/vtorc/api/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,24 @@ func TestAPIEndpoints(t *testing.T) {
return response != "null"
})

t.Run("Database State", func(t *testing.T) {
// Get database state
status, resp, err := utils.MakeAPICall(t, vtorc, "/api/database-state")
require.NoError(t, err)
assert.Equal(t, 200, status)
assert.Contains(t, resp, `"alias": "zone1-0000000101"`)
assert.Contains(t, resp, `{
"TableName": "vitess_keyspace",
"Rows": [
{
"durability_policy": "none",
"keyspace": "ks",
"keyspace_type": "0"
}
]
},`)
})

t.Run("Disable Recoveries API", func(t *testing.T) {
// Disable recoveries of VTOrc
status, resp, err := utils.MakeAPICall(t, vtorc, "/api/disable-global-recoveries")
Expand Down
2 changes: 1 addition & 1 deletion go/vt/external/golib/sqlutils/sqlutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ type RowMap map[string]CellData
// CellData is the result of a single (atomic) column in a single row
type CellData sql.NullString

func (this *CellData) MarshalJSON() ([]byte, error) {
func (this CellData) MarshalJSON() ([]byte, error) {
if this.Valid {
return json.Marshal(this.String)
} else {
Expand Down
22 changes: 22 additions & 0 deletions go/vt/vtorc/db/generate_base.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,28 @@

package db

var TableNames = []string{
"database_instance",
"audit",
"active_node",
"node_health",
"topology_recovery",
"database_instance_topology_history",
"candidate_database_instance",
"topology_failure_detection",
"blocked_topology_recovery",
"database_instance_last_analysis",
"database_instance_analysis_changelog",
"node_health_history",
"vtorc_db_deployments",
"global_recovery_disable",
"topology_recovery_steps",
"database_instance_stale_binlog_coordinates",
"vitess_tablet",
"vitess_keyspace",
"vitess_shard",
}

// vtorcBackend is a list of SQL statements required to build the vtorc backend
var vtorcBackend = []string{
`
Expand Down
30 changes: 30 additions & 0 deletions go/vt/vtorc/inst/instance_dao.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package inst

import (
"encoding/json"
"errors"
"fmt"
"regexp"
Expand Down Expand Up @@ -1210,3 +1211,32 @@ func ExpireStaleInstanceBinlogCoordinates() error {
}
return ExecDBWriteFunc(writeFunc)
}

// GetDatabaseState takes the snapshot of the database and returns it.
func GetDatabaseState() (string, error) {
type tableState struct {
TableName string
Rows []sqlutils.RowMap
}

var dbState []tableState
for _, tableName := range db.TableNames {
ts := tableState{
TableName: tableName,
}
err := db.QueryVTOrc("select * from "+tableName, nil, func(rowMap sqlutils.RowMap) error {
ts.Rows = append(ts.Rows, rowMap)
return nil
})
if err != nil {
return "", err
}
dbState = append(dbState, ts)
}
jsonData, err := json.MarshalIndent(dbState, "", "\t")
if err != nil {
return "", err
}

return string(jsonData), nil
}
16 changes: 16 additions & 0 deletions go/vt/vtorc/inst/instance_dao_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -746,3 +746,19 @@ func waitForCacheInitialization() {
time.Sleep(100 * time.Millisecond)
}
}

func TestGetDatabaseState(t *testing.T) {
// Clear the database after the test. The easiest way to do that is to run all the initialization commands again.
defer func() {
db.ClearVTOrcDatabase()
}()

for _, query := range initialSQL {
_, err := db.ExecVTOrc(query)
require.NoError(t, err)
}

ds, err := GetDatabaseState()
require.NoError(t, err)
require.Contains(t, ds, `"alias": "zone1-0000000112"`)
}
16 changes: 15 additions & 1 deletion go/vt/vtorc/server/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const (
disableGlobalRecoveriesAPI = "/api/disable-global-recoveries"
enableGlobalRecoveriesAPI = "/api/enable-global-recoveries"
replicationAnalysisAPI = "/api/replication-analysis"
databaseStateAPI = "/api/database-state"
healthAPI = "/debug/health"
AggregatedDiscoveryMetricsAPI = "/api/aggregated-discovery-metrics"

Expand All @@ -60,6 +61,7 @@ var (
disableGlobalRecoveriesAPI,
enableGlobalRecoveriesAPI,
replicationAnalysisAPI,
databaseStateAPI,
healthAPI,
AggregatedDiscoveryMetricsAPI,
}
Expand All @@ -86,6 +88,8 @@ func (v *vtorcAPI) ServeHTTP(response http.ResponseWriter, request *http.Request
errantGTIDsAPIHandler(response, request)
case replicationAnalysisAPI:
replicationAnalysisAPIHandler(response, request)
case databaseStateAPI:
databaseStateAPIHandler(response)
case AggregatedDiscoveryMetricsAPI:
AggregatedDiscoveryMetricsAPIHandler(response, request)
default:
Expand All @@ -104,7 +108,7 @@ func getACLPermissionLevelForAPI(apiEndpoint string) string {
return acl.ADMIN
case replicationAnalysisAPI:
return acl.MONITORING
case healthAPI:
case healthAPI, databaseStateAPI:
return acl.MONITORING
}
return acl.ADMIN
Expand Down Expand Up @@ -166,6 +170,16 @@ func errantGTIDsAPIHandler(response http.ResponseWriter, request *http.Request)
returnAsJSON(response, http.StatusOK, instances)
}

// databaseStateAPIHandler is the handler for the databaseStateAPI endpoint
func databaseStateAPIHandler(response http.ResponseWriter) {
ds, err := inst.GetDatabaseState()
if err != nil {
http.Error(response, err.Error(), http.StatusInternalServerError)
return
}
writePlainTextResponse(response, ds, http.StatusOK)
}

// AggregatedDiscoveryMetricsAPIHandler is the handler for the discovery metrics endpoint
func AggregatedDiscoveryMetricsAPIHandler(response http.ResponseWriter, request *http.Request) {
// return metrics for last x seconds
Expand Down

0 comments on commit 2078d62

Please sign in to comment.