Skip to content

Commit

Permalink
Allow Viewing of Disabled Params (#902)
Browse files Browse the repository at this point in the history
* Allow Viewing of Disabled Params

Resolves #3583

Add a new subcommand "algorand-indexer api-config" to show current
config

* Mod file

* PR comments

* PR comments
  • Loading branch information
AlgoStephenAkiki authored Mar 1, 2022
1 parent 8d85bf4 commit 8b58e4b
Show file tree
Hide file tree
Showing 7 changed files with 214 additions and 5 deletions.
44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,50 @@ When `--token your-token` is provided, an authentication header is required. For
~$ curl localhost:8980/transactions -H "X-Indexer-API-Token: your-token"
```

## Disabling Parameters

The Indexer has the ability to selectively enable or disable parameters for endpoints. Disabling a "required" parameter will result in the entire endpoint being disabled while disabling an "optional" parameter will cause an error to be returned only if the parameter is provided.

### Viewing the Current Configuration

The Indexer has a default set of disabled parameters. To view the disabled parameters issue:
```
~$ algorand-indexer api-config
```

This will output ONLY the disabled parameters in a YAML configuration. To view all parameters (both enabled and disabled) issue:

```
~$ algorand-indexer api-config --all
```

### Interpreting The Configuration

Below is a snippet of the output from `algorand-indexer api-config`:

```
/v2/accounts:
optional:
- currency-greater-than: disabled
- currency-less-than: disabled
/v2/assets/{asset-id}/transactions:
optional:
- note-prefix: disabled
- tx-type: disabled
- sig-type: disabled
- before-time: disabled
- after-time: disabled
- currency-greater-than: disabled
- currency-less-than: disabled
- address-role: disabled
- exclude-close-to: disabled
- rekey-to: disabled
required:
- asset-id: disabled
```

Seeing this we know that the `/v2/accounts` endpoint will return an error if either `currency-greater-than` or `currency-less-than` is provided. Additionally, because a "required" parameter is provided for `/v2/assets/{asset-id}/transactions` then we know this entire endpoint is disabled. The optional parameters are provided so that you can understand what else is disabled if you enable all "required" parameters.

## Metrics

The `/metrics` endpoint is configured with the `--metrics-mode` option and configures if and how [Prometheus](https://prometheus.io/) formatted metrics are generated.
Expand Down
95 changes: 95 additions & 0 deletions api/disabled_parameters.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,103 @@ import (

"github.com/getkin/kin-openapi/openapi3"
"github.com/labstack/echo/v4"
"gopkg.in/yaml.v3"
)

// DisplayDisabledMap is a struct that contains the necessary information
// to output the current config to the screen
type DisplayDisabledMap struct {
// A complicated map but necessary to output the correct YAML.
// This is supposed to represent a data structure with a similar YAML
// representation:
// /v2/accounts/{account-id}:
// required:
// - account-id : enabled
// /v2/accounts:
// optional:
// - auth-addr : enabled
// - next: disabled
Data map[string]map[string][]map[string]string
}

func (ddm *DisplayDisabledMap) String() (string, error) {

if len(ddm.Data) == 0 {
return "", nil
}

bytes, err := yaml.Marshal(ddm.Data)
if err != nil {
return "", err
}

return string(bytes), nil
}

func makeDisplayDisabledMap() *DisplayDisabledMap {
return &DisplayDisabledMap{
Data: make(map[string]map[string][]map[string]string),
}
}

func (ddm *DisplayDisabledMap) addEntry(restPath string, requiredOrOptional string, entryName string, status string) {
if ddm.Data == nil {
ddm.Data = make(map[string]map[string][]map[string]string)
}

if ddm.Data[restPath] == nil {
ddm.Data[restPath] = make(map[string][]map[string]string)
}

mapEntry := map[string]string{entryName: status}

ddm.Data[restPath][requiredOrOptional] = append(ddm.Data[restPath][requiredOrOptional], mapEntry)
}

// MakeDisplayDisabledMapFromConfig will make a DisplayDisabledMap that takes into account the DisabledMapConfig.
// If limited is set to true, then only disabled parameters will be added to the DisplayDisabledMap
func MakeDisplayDisabledMapFromConfig(swag *openapi3.Swagger, mapConfig *DisabledMapConfig, limited bool) *DisplayDisabledMap {

rval := makeDisplayDisabledMap()
for restPath, item := range swag.Paths {

for opName, opItem := range item.Operations() {

for _, pref := range opItem.Parameters {

paramName := pref.Value.Name

parameterIsDisabled := mapConfig.isDisabled(restPath, opName, paramName)
// If we are limited, then don't bother with enabled parameters
if !parameterIsDisabled && limited {
// If the parameter is not disabled, then we don't need
// to do anything
continue
}

var statusStr string

if parameterIsDisabled {
statusStr = "disabled"
} else {
statusStr = "enabled"
}

if pref.Value.Required {
rval.addEntry(restPath, "required", paramName, statusStr)
} else {
// If the optional parameter is disabled, add it to the map
rval.addEntry(restPath, "optional", paramName, statusStr)
}
}

}

}

return rval
}

// EndpointConfig is a data structure that contains whether the
// endpoint is disabled (with a boolean) as well as a set that
// contains disabled optional parameters. The disabled optional parameter
Expand Down
9 changes: 4 additions & 5 deletions api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ type ExtraOptions struct {

// ReadTimeout is the maximum duration for reading the entire request, including the body.
ReadTimeout time.Duration

// DisabledMapConfig is the disabled map configuration that is being used by the server
DisabledMapConfig *DisabledMapConfig
}

func (e ExtraOptions) handlerTimeout() time.Duration {
Expand Down Expand Up @@ -83,11 +86,7 @@ func Serve(ctx context.Context, serveAddr string, db idb.IndexerDb, fetcherError
log.Fatal(err)
}

// TODO enable this when command line options allows for disabling/enabling overrides
//disabledMapConfig := GetDefaultDisabledMapConfigForPostgres()
disabledMapConfig := MakeDisabledMapConfig()

disabledMap, err := MakeDisabledMapFromOA3(swag, disabledMapConfig)
disabledMap, err := MakeDisabledMapFromOA3(swag, options.DisabledMapConfig)
if err != nil {
log.Fatal(err)
}
Expand Down
63 changes: 63 additions & 0 deletions cmd/algorand-indexer/api_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package main

import (
"fmt"
"os"

"github.com/spf13/cobra"

"github.com/algorand/indexer/api"
"github.com/algorand/indexer/api/generated/v2"
"github.com/algorand/indexer/config"
)

var (
showAllDisabled bool
)

var apiConfigCmd = &cobra.Command{
Use: "api-config",
Short: "dump api configuration",
Long: "dump api configuration",
//Args:
Run: func(cmd *cobra.Command, args []string) {
var err error
config.BindFlags(cmd)
err = configureLogger()
if err != nil {
fmt.Fprintf(os.Stderr, "failed to configure logger: %v", err)
os.Exit(1)
}
swag, err := generated.GetSwagger()

if err != nil {
fmt.Fprintf(os.Stderr, "failed to get swagger: %v", err)
os.Exit(1)
}

options := makeOptions()

var displayDisabledMapConfig *api.DisplayDisabledMap
// Show a limited subset
if !showAllDisabled {
displayDisabledMapConfig = api.MakeDisplayDisabledMapFromConfig(swag, options.DisabledMapConfig, true)
} else {
displayDisabledMapConfig = api.MakeDisplayDisabledMapFromConfig(swag, options.DisabledMapConfig, false)
}

output, err := displayDisabledMapConfig.String()

if err != nil {
fmt.Fprintf(os.Stderr, "failed to output yaml: %v", err)
os.Exit(1)
}

fmt.Fprint(os.Stdout, output)
os.Exit(0)

},
}

func init() {
apiConfigCmd.Flags().BoolVar(&showAllDisabled, "all", false, "show all api config parameters, enabled and disabled")
}
6 changes: 6 additions & 0 deletions cmd/algorand-indexer/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,12 @@ func makeOptions() (options api.ExtraOptions) {
options.WriteTimeout = writeTimeout
options.ReadTimeout = readTimeout

// TODO enable this when command line options allows for disabling/enabling overrides
//disabledMapConfig := api.GetDefaultDisabledMapConfigForPostgres()
disabledMapConfig := api.MakeDisabledMapConfig()

options.DisabledMapConfig = disabledMapConfig

return
}

Expand Down
1 change: 1 addition & 0 deletions cmd/algorand-indexer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ func init() {
rootCmd.AddCommand(importCmd)
importCmd.Hidden = true
rootCmd.AddCommand(daemonCmd)
rootCmd.AddCommand(apiConfigCmd)

// Not applied globally to avoid adding to utility commands.
addFlags := func(cmd *cobra.Command) {
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ require (
github.com/vektra/mockery v1.1.2 // indirect
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
golang.org/x/tools v0.1.9 // indirect
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
)

0 comments on commit 8b58e4b

Please sign in to comment.