github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/internal/status/options.go (about)

     1  // Copyright 2016, 2024 The TrueBlocks Authors. All rights reserved.
     2  // Use of this source code is governed by a license that can
     3  // be found in the LICENSE file.
     4  /*
     5   * Parts of this file were auto generated. Edit only those parts of
     6   * the code inside of 'EXISTING_CODE' tags.
     7   */
     8  
     9  package statusPkg
    10  
    11  import (
    12  	// EXISTING_CODE
    13  	"encoding/json"
    14  	"io"
    15  	"net/http"
    16  	"net/url"
    17  	"strings"
    18  
    19  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/internal/globals"
    20  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/base"
    21  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/caps"
    22  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/logger"
    23  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/rpc"
    24  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/validate"
    25  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/walk"
    26  	// EXISTING_CODE
    27  )
    28  
    29  // StatusOptions provides all command options for the chifra status command.
    30  type StatusOptions struct {
    31  	Modes       []string              `json:"modes,omitempty"`       // The (optional) name of the binary cache to report on, terse otherwise
    32  	Diagnose    bool                  `json:"diagnose,omitempty"`    // Same as the default but with additional diagnostics
    33  	FirstRecord uint64                `json:"firstRecord,omitempty"` // The first record to process
    34  	MaxRecords  uint64                `json:"maxRecords,omitempty"`  // The maximum number of records to process
    35  	Chains      bool                  `json:"chains,omitempty"`      // Include a list of chain configurations in the output
    36  	Healthcheck bool                  `json:"healthcheck,omitempty"` // An alias for the diagnose endpoint
    37  	Globals     globals.GlobalOptions `json:"globals,omitempty"`     // The global options
    38  	Conn        *rpc.Connection       `json:"conn,omitempty"`        // The connection to the RPC server
    39  	BadFlag     error                 `json:"badFlag,omitempty"`     // An error flag if needed
    40  	// EXISTING_CODE
    41  	ModeTypes []walk.CacheType `json:"-"`
    42  	// EXISTING_CODE
    43  }
    44  
    45  var defaultStatusOptions = StatusOptions{
    46  	MaxRecords: 10000,
    47  }
    48  
    49  // testLog is used only during testing to export the options for this test case.
    50  func (opts *StatusOptions) testLog() {
    51  	logger.TestLog(len(opts.Modes) > 0, "Modes: ", opts.Modes)
    52  	logger.TestLog(opts.Diagnose, "Diagnose: ", opts.Diagnose)
    53  	logger.TestLog(opts.FirstRecord != 0, "FirstRecord: ", opts.FirstRecord)
    54  	logger.TestLog(opts.MaxRecords != 10000, "MaxRecords: ", opts.MaxRecords)
    55  	logger.TestLog(opts.Chains, "Chains: ", opts.Chains)
    56  	logger.TestLog(opts.Healthcheck, "Healthcheck: ", opts.Healthcheck)
    57  	opts.Conn.TestLog(opts.getCaches())
    58  	opts.Globals.TestLog()
    59  }
    60  
    61  // String implements the Stringer interface
    62  func (opts *StatusOptions) String() string {
    63  	b, _ := json.MarshalIndent(opts, "", "  ")
    64  	return string(b)
    65  }
    66  
    67  // statusFinishParseApi finishes the parsing for server invocations. Returns a new StatusOptions.
    68  func statusFinishParseApi(w http.ResponseWriter, r *http.Request) *StatusOptions {
    69  	values := r.URL.Query()
    70  	if r.Header.Get("User-Agent") == "testRunner" {
    71  		values.Set("testRunner", "true")
    72  	}
    73  	return StatusFinishParseInternal(w, values)
    74  }
    75  
    76  func StatusFinishParseInternal(w io.Writer, values url.Values) *StatusOptions {
    77  	copy := defaultStatusOptions
    78  	copy.Globals.Caps = getCaps()
    79  	opts := &copy
    80  	opts.MaxRecords = 10000
    81  	for key, value := range values {
    82  		switch key {
    83  		case "modes":
    84  			for _, val := range value {
    85  				s := strings.Split(val, " ") // may contain space separated items
    86  				opts.Modes = append(opts.Modes, s...)
    87  			}
    88  		case "diagnose":
    89  			opts.Diagnose = true
    90  		case "firstRecord":
    91  			opts.FirstRecord = base.MustParseUint64(value[0])
    92  		case "maxRecords":
    93  			opts.MaxRecords = base.MustParseUint64(value[0])
    94  		case "chains":
    95  			opts.Chains = true
    96  		case "healthcheck":
    97  			opts.Healthcheck = true
    98  		default:
    99  			if !copy.Globals.Caps.HasKey(key) {
   100  				err := validate.Usage("Invalid key ({0}) in {1} route.", key, "status")
   101  				if opts.BadFlag == nil || opts.BadFlag.Error() > err.Error() {
   102  					opts.BadFlag = err
   103  				}
   104  			}
   105  		}
   106  	}
   107  	opts.Conn = opts.Globals.FinishParseApi(w, values, opts.getCaches())
   108  
   109  	// EXISTING_CODE
   110  	if len(opts.Modes) == 0 && opts.Globals.Verbose {
   111  		opts.Modes = append(opts.Modes, "some")
   112  	}
   113  	opts.ModeTypes = walk.CacheTypesFromStringSlice(opts.Modes)
   114  	// EXISTING_CODE
   115  	if !opts.Diagnose {
   116  		opts.Diagnose = opts.Healthcheck // alias
   117  		opts.Healthcheck = false
   118  	}
   119  
   120  	return opts
   121  }
   122  
   123  // statusFinishParse finishes the parsing for command line invocations. Returns a new StatusOptions.
   124  func statusFinishParse(args []string) *StatusOptions {
   125  	// remove duplicates from args if any (not needed in api mode because the server does it).
   126  	dedup := map[string]int{}
   127  	if len(args) > 0 {
   128  		tmp := []string{}
   129  		for _, arg := range args {
   130  			if value := dedup[arg]; value == 0 {
   131  				tmp = append(tmp, arg)
   132  			}
   133  			dedup[arg]++
   134  		}
   135  		args = tmp
   136  	}
   137  
   138  	defFmt := "txt"
   139  	opts := GetOptions()
   140  	opts.Conn = opts.Globals.FinishParse(args, opts.getCaches())
   141  
   142  	// EXISTING_CODE
   143  	opts.Modes = append(opts.Modes, args...)
   144  	if len(opts.Modes) == 0 && opts.Globals.Verbose {
   145  		opts.Modes = append(opts.Modes, "some")
   146  	}
   147  	opts.ModeTypes = walk.CacheTypesFromStringSlice(opts.Modes)
   148  	if len(opts.Modes) > 0 {
   149  		defFmt = "json"
   150  	}
   151  	// EXISTING_CODE
   152  	if !opts.Diagnose {
   153  		opts.Diagnose = opts.Healthcheck // alias
   154  		opts.Healthcheck = false
   155  	}
   156  	if len(opts.Globals.Format) == 0 || opts.Globals.Format == "none" {
   157  		opts.Globals.Format = defFmt
   158  	}
   159  
   160  	return opts
   161  }
   162  
   163  func GetOptions() *StatusOptions {
   164  	// EXISTING_CODE
   165  	// EXISTING_CODE
   166  	return &defaultStatusOptions
   167  }
   168  
   169  func getCaps() caps.Capability {
   170  	var capabilities caps.Capability // capabilities for chifra status
   171  	capabilities = capabilities.Add(caps.Default)
   172  	// EXISTING_CODE
   173  	// EXISTING_CODE
   174  	return capabilities
   175  }
   176  
   177  func ResetOptions(testMode bool) {
   178  	// We want to keep writer between command file calls
   179  	w := GetOptions().Globals.Writer
   180  	opts := StatusOptions{}
   181  	globals.SetDefaults(&opts.Globals)
   182  	opts.Globals.TestMode = testMode
   183  	opts.Globals.Writer = w
   184  	opts.Globals.Caps = getCaps()
   185  	opts.MaxRecords = 10000
   186  	defaultStatusOptions = opts
   187  }
   188  
   189  func (opts *StatusOptions) getCaches() (caches map[walk.CacheType]bool) {
   190  	// EXISTING_CODE
   191  	// EXISTING_CODE
   192  	return
   193  }
   194  
   195  // EXISTING_CODE
   196  // EXISTING_CODE