github.com/yandex/pandora@v0.5.32/components/providers/scenario/config/config.go (about)

     1  package config
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/spf13/afero"
     8  	grpcgun "github.com/yandex/pandora/components/guns/grpc/scenario"
     9  	httpscenario "github.com/yandex/pandora/components/guns/http_scenario"
    10  	"github.com/yandex/pandora/components/providers/scenario/http/preprocessor"
    11  	"github.com/yandex/pandora/components/providers/scenario/vs"
    12  )
    13  
    14  // AmmoConfig is a config for dynamic converting from map[string]interface{}
    15  type AmmoConfig struct {
    16  	Locals          map[string]any
    17  	VariableSources []vs.VariableSource `config:"variable_sources"`
    18  	Requests        []RequestConfig
    19  	Calls           []CallConfig
    20  	Scenarios       []ScenarioConfig
    21  }
    22  
    23  // ScenarioConfig is a config for dynamic converting from map[string]interface{}
    24  type ScenarioConfig struct {
    25  	Name           string
    26  	Weight         int64
    27  	MinWaitingTime int64 `config:"min_waiting_time"`
    28  	Requests       []string
    29  }
    30  
    31  // RequestConfig is a config for dynamic converting from map[string]interface{}
    32  type RequestConfig struct {
    33  	Name           string
    34  	Method         string
    35  	Headers        map[string]string
    36  	Tag            string
    37  	Body           *string
    38  	URI            string
    39  	Preprocessor   *preprocessor.Preprocessor
    40  	Postprocessors []httpscenario.Postprocessor
    41  	Templater      httpscenario.Templater
    42  }
    43  
    44  type CallConfig struct {
    45  	Name           string
    46  	Tag            string
    47  	Call           string
    48  	Payload        string
    49  	Metadata       map[string]string
    50  	Preprocessors  []grpcgun.Preprocessor
    51  	Postprocessors []grpcgun.Postprocessor
    52  }
    53  
    54  func ReadAmmoConfig(fs afero.Fs, fileName string) (ammoCfg *AmmoConfig, err error) {
    55  	const op = "scenario.ReadAmmoConfig"
    56  
    57  	if fileName == "" {
    58  		return nil, fmt.Errorf("scenario provider config should contain non-empty 'file' field")
    59  	}
    60  	file, openErr := fs.Open(fileName)
    61  	if openErr != nil {
    62  		return nil, fmt.Errorf("%s %w", op, openErr)
    63  	}
    64  	defer func() {
    65  		closeErr := file.Close()
    66  		if closeErr != nil {
    67  			if err != nil {
    68  				err = fmt.Errorf("%s multiple errors faced: %w, with close err: %s", op, err, closeErr)
    69  			} else {
    70  				err = fmt.Errorf("%s, %w", op, closeErr)
    71  			}
    72  		}
    73  	}()
    74  	stat, statErr := file.Stat()
    75  	if statErr != nil {
    76  		err = fmt.Errorf("%s file.Stat() %w", op, err)
    77  		return
    78  	}
    79  	lowerName := strings.ToLower(stat.Name())
    80  	switch {
    81  	case strings.HasSuffix(lowerName, ".hcl"):
    82  		ammoHcl, parseErr := ParseHCLFile(file)
    83  		if parseErr != nil {
    84  			err = fmt.Errorf("%s ParseHCLFile %w", op, parseErr)
    85  			return
    86  		}
    87  		ammoCfg, err = ConvertHCLToAmmo(ammoHcl)
    88  	case strings.HasSuffix(lowerName, ".yaml") || strings.HasPrefix(lowerName, ".yml"):
    89  		ammoCfg, err = ParseAmmoConfig(file)
    90  	default:
    91  		err = fmt.Errorf("%s file extension should be .yaml or .yml", op)
    92  		return
    93  	}
    94  	if err != nil {
    95  		err = fmt.Errorf("%s ParseAmmoConfig %w", op, err)
    96  		return
    97  	}
    98  
    99  	return ammoCfg, nil
   100  }