Documentation

Overview

    Package config provides functionality for working with configuration files and command line arguments to a Granitic application.

    Grantic uses JSON files to store component definitions (declarations of, and relationships between, components to run in the IoC container) and configuration (variables used by IoC components that may vary between environments and settings for Grantic's built-in facilities). A definition of the use and syntax of these files are outside of the scope of a GoDoc page, but are described in detail at https://granitic.io/ref/component-definition-files and https://granitic.io/ref/configuration-files

    This package defines functionality for loading a JSON file (from a filesystem or via HTTP) and merging multiple files into a single view. This is a key concept in Granitic.

    Given a folder of configuration files called conf:

    conf/x.json
    conf/sub/a.json
    conf/sub/b.json
    

    starting a Grantic application with:

    -c http://example.com/base.json,conf,http://example.com/myinstance.json
    

    The following will take place. Firstly the files would be expanded into a flat list of paths/URIs

    http://example.com/base.json
    conf/sub/a.json
    conf/sub/b.json
    conf/x.json
    http://example.com/myinstance.json
    

    The the files will be merged together from left, using the the first file as a base. In this example, http://example.com/base.json and conf/sub/a.json will be merged together, then result of that merge will be merged with conf/sub/b.json and so on.

    For named fields (in a JSON object/map), the process of merging is fairly obvious. When merging files A and B, a field that is defined in both files will have the value of the field used in file B in the merged output. For example,

    a.json
    
    {
    	"database": {
    		"host": "localhost",
    		"port": 3306,
    		"flags": ["a", "b", "c"]
    	}
    }
    

    and

    b.json
    
    {
    	"database": {
    		"host": "remotehost",
    		"flags": ["d"]
    	}
    }
    

    woud merge to:

    {
    	"database": {
    		"host": "remotehost",
    		"port": 3306,
    		"flags": ["d"]
    	}
    }
    

    The merging of configuration files occurs exactly above, but when component definition files are merged, arrays are joined, not overwritten. For example:

    { "methods": ["GET"] }
    

    merged with;

    { "methods": ["POST"] }
    

    would result in:

    { "methods": ["GET", "POST"] }
    

    Another core concept used by the types in this package is a config path. This is the absolute path to field in the eventual merged configuration file with a dot-delimited notation. E.g "database.host".

    Index

    Constants

    View Source
    const (
    	Unset       = -2
    	JSONUnknown = -1
    	JSONString  = 1
    	JSONArray   = 2
    	JSONMap     = 3
    	JSONBool    = 4
    )

      Used by code that needs to know what type of JSON data structure resides at a particular path before operating on it.

      View Source
      const JSONPathSeparator string = "."

        JSONPathSeparator is the character used to delimit paths to config values.

        Variables

        This section is empty.

        Functions

        func ExpandToFilesAndURLs

        func ExpandToFilesAndURLs(paths []string) ([]string, error)

          ExpandToFilesAndURLs takes a slice that may be a mixture of URLs, file paths and directory paths and returns a list of URLs and file paths, recursively expanding any non-empty directories into a list of files. Returns an error if there is a problem traversing directories of if any of the supplied file paths does not exist.

          func FileListFromPath

          func FileListFromPath(path string) ([]string, error)

            FileListFromPath takes a string that could represent a path to a directory or a path to a file and returns a list of file paths. If the path is to directory, any files in that directory are included in the result. Any sub-directories are recursively entered.

            func FindJSONFilesInDir

            func FindJSONFilesInDir(dirPath string) ([]string, error)

              FindJSONFilesInDir finds all files with a .json extension in the supplied directory path, recursively checking sub-directories. Note that each directory's contents are examined and added to the list of files lexicographically, so any files in a sub-directory 'b' would appear in the resulting list of files before 'c.json'

              func JSONType

              func JSONType(value interface{}) int

                JSONType determines the apparent JSONType of the supplied Go interface.

                func WriteJSONConfig

                func WriteJSONConfig(a *Accessor, f string) error

                  WriteJSONConfig writes the contents of a config.Accessor to a file

                  Types

                  type Accessor

                  type Accessor struct {
                  	// The merged JSON configuration in object form.
                  	JSONData map[string]interface{}
                  
                  	// Logger used by Granitic framework components. Automatically injected.
                  	FrameworkLogger logging.Logger
                  }

                    A Accessor provides access to a merged view of configuration files during the initialisation and configuration of the Granitic IoC container.

                    func (*Accessor) Array

                    func (ac *Accessor) Array(path string) ([]interface{}, error)

                      Array returns the value of an array of JSON obects at the supplied path. Caution should be used when calling this method as behaviour is undefined for JSON arrays of JSON types other than object.

                      func (*Accessor) BoolVal

                      func (ac *Accessor) BoolVal(path string) (bool, error)

                        BoolVal returns the bool value of the JSON bool at the supplied path. An error will be returned if the value is not a JSON bool. Note this method only suports the JSON definition of bools (true, false) not the Go definition (true, false, 1, 0 etc).

                        func (*Accessor) Float64Val

                        func (ac *Accessor) Float64Val(path string) (float64, error)

                          Float64Val returns the float64 value of the JSON number at the supplied path. An error will be returned if the value is not a JSON number.

                          func (*Accessor) Flush

                          func (ac *Accessor) Flush()

                            Flush removes internal references to the (potentially very large) merged JSON data so the associated memory can be recovered during the next garbage collection.

                            func (*Accessor) IntVal

                            func (ac *Accessor) IntVal(path string) (int, error)

                              IntVal returns the int value of the JSON number at the supplied path. JSON numbers are internally represented by Go as a float64, so no error will be returned, but data might be lost if the JSON number does not actually represent an int. An error will be returned if the value is not a JSON number or cannot be converted to an int.

                              func (*Accessor) ObjectVal

                              func (ac *Accessor) ObjectVal(path string) (map[string]interface{}, error)

                                ObjectVal returns a map representing a JSON object or nil if the path does not exist of points to a null JSON value. An error is returned if the value cannot be interpreted as a JSON object.

                                func (*Accessor) PathExists

                                func (ac *Accessor) PathExists(path string) bool

                                  PathExists check to see whether the supplied dot-delimited path exists in the configuration and points to a non-null JSON value.

                                  func (*Accessor) Populate

                                  func (ac *Accessor) Populate(path string, target interface{}) error

                                    Populate sets the fields on the supplied target object using the JSON data at the supplied path. This is achieved using Go's json.Marshal to convert the data back into text JSON and then json.Unmarshal to unmarshal back into the target.

                                    func (*Accessor) SetField

                                    func (ac *Accessor) SetField(fieldName string, path string, target interface{}) error

                                      SetField takes a target Go interface and uses the data a the supplied path to populated the named field on the target. The target must be a pointer to a struct. The field must be a string, bool, int, float63, string[interface{}] map or a slice of one of those types. An eror will be returned if the target field, is missing, not settable or incompatible with the JSON value at the supplied path.

                                      func (*Accessor) StringVal

                                      func (ac *Accessor) StringVal(path string) (string, error)

                                        StringVal returns the string value of the JSON string at the supplied path. Does not convert other types to a string, so will return an error if the value is not a JSON string.

                                        func (*Accessor) Value

                                        func (ac *Accessor) Value(path string) interface{}

                                          Value returns the JSON value at the supplied path or nil if the path does not exist of points to a null JSON value.

                                          type ContentParser

                                          type ContentParser interface {
                                          	ParseInto(data []byte, target interface{}) error
                                          	Extensions() []string
                                          	ContentTypes() []string
                                          }

                                            A ContentParser can take a []byte of some structured file type (e.g. YAML, JSON() and convert into a map[string]interface{} representation

                                            type EmptyFileError

                                            type EmptyFileError struct {
                                            	Message string
                                            }

                                              EmptyFileError is a marker error to indicate that a config file was logically empty

                                              func (EmptyFileError) Error

                                              func (efe EmptyFileError) Error() string

                                                Error returns the message associated with this error

                                                type InitialSettings

                                                type InitialSettings struct {
                                                
                                                	// The level at which messages from Granitic components used before configuration files can be loaded (the initiator,
                                                	// logger, IoC container, JSON merger etc.) will be logged. As soon as configuration has been loaded, this value will
                                                	// be discarded in favour of LogLevels defined in that configuration.
                                                	FrameworkLogLevel logging.LogLevel
                                                
                                                	// Files, directories and URLs from which JSON configuration should be loaded and merged.
                                                	Configuration []string
                                                
                                                	// The time at which the application was started (to allow accurate timing of the IoC container start process).
                                                	StartTime time.Time
                                                
                                                	// An (optional) unique identifier for this instance of a Granitic application.
                                                	InstanceID string
                                                
                                                	// A base 64 serialised version of Granitic's built-in configuration files
                                                	BuiltInConfig *string
                                                
                                                	// Additional parsers to support config files in a format other than JSON
                                                	ConfigParsers []ContentParser
                                                
                                                	// Exit immediately after container has successfully started
                                                	DryRun bool
                                                
                                                	// Buffer messages and only log them when application logging has been configured
                                                	DeferBootstrapLogging bool
                                                
                                                	// A path to write the merged view of configuration to (then exit)
                                                	MergedConfigPath string
                                                
                                                	// Create a UUID and use it as the instance ID
                                                	GenerateInstanceUUID bool
                                                }

                                                  InitialSettings contains settings that are needed by Granitic before configuration files can be loaded and parsed. See package granitic for more information on how this is used when starting a Granitic application with command line arguments or supplying an instance of this struct programmatically.

                                                  func InitialSettingsFromEnvironment

                                                  func InitialSettingsFromEnvironment() *InitialSettings

                                                    InitialSettingsFromEnvironment builds an InitialSettings and populates it with defaults or the values of command line arguments if available.

                                                    type JSONContentParser

                                                    type JSONContentParser struct {
                                                    }

                                                      JSONContentParser supports the loading and parsing of JSON configuration and component definition files

                                                      func (*JSONContentParser) ContentTypes

                                                      func (jcp *JSONContentParser) ContentTypes() []string

                                                        ContentTypes returns the MIME media types/HTTP content-types that will be considered to represent JSON

                                                        func (*JSONContentParser) Extensions

                                                        func (jcp *JSONContentParser) Extensions() []string

                                                          Extensions returns the list of filename extensions (lowercase, without leading dot) that will be considered to be JSON files.

                                                          func (*JSONContentParser) ParseInto

                                                          func (jcp *JSONContentParser) ParseInto(data []byte, target interface{}) error

                                                            ParseInto takes a byte array that is assumed to be serialised JSON and attempts to parse that into the supplied target object

                                                            type JSONMerger

                                                            type JSONMerger struct {
                                                            	// Logger used by Granitic framework components. Automatically injected.
                                                            	Logger logging.Logger
                                                            
                                                            	// True if arrays should be joined when merging; false if the entire conetnts of the array should be overwritten.
                                                            	MergeArrays bool
                                                            
                                                            	DefaultParser ContentParser
                                                            	// contains filtered or unexported fields
                                                            }

                                                              A JSONMerger can merge a sequence of JSON configuration files (from a filesystem or HTTP URL) into a single view of configuration that will be used to configure Grantic's facilities and the user's IoC components. See the top of this page for a brief explanation of how merging works.

                                                              func NewJSONMergerWithDirectLogging

                                                              func NewJSONMergerWithDirectLogging(l logging.Logger, cp ContentParser) *JSONMerger

                                                                NewJSONMergerWithDirectLogging creates a JSONMerger that uses the supplied logger

                                                                func NewJSONMergerWithManagedLogging

                                                                func NewJSONMergerWithManagedLogging(flm *logging.ComponentLoggerManager, cp ContentParser) *JSONMerger

                                                                  NewJSONMergerWithManagedLogging creates a JSONMerger with a Logger managed by Granitic

                                                                  func (*JSONMerger) LoadAndMergeConfig

                                                                  func (jm *JSONMerger) LoadAndMergeConfig(files []string) (map[string]interface{}, error)

                                                                    LoadAndMergeConfig takes a list of file paths or URIs to JSON files and merges them into a single in-memory object representation. See the top of this page for a brief explanation of how merging works. Returns an error if a remote URI returned a 4xx or 5xx response code, a file or folder could not be accessed or if two files could not be merged dued to JSON parsing errors.

                                                                    func (*JSONMerger) LoadAndMergeConfigWithBase

                                                                    func (jm *JSONMerger) LoadAndMergeConfigWithBase(config map[string]interface{}, files []string) (map[string]interface{}, error)

                                                                      LoadAndMergeConfigWithBase takes a representation of a JSON file that has already been parsed and merges the contents of the supplied list of JSON files into that in-memory representation and returns the file merged version.

                                                                      func (*JSONMerger) RegisterContentParser

                                                                      func (jm *JSONMerger) RegisterContentParser(cp ContentParser)

                                                                        RegisterContentParser adds the supplied ContentParser to the set of parsers that might be eligible to parse a file/stream

                                                                        type MissingPathError

                                                                        type MissingPathError struct {
                                                                        	// contains filtered or unexported fields
                                                                        }

                                                                          MissingPathError indicates that the a problem was caused by there being no value at the supplied config path

                                                                          func (MissingPathError) Error

                                                                          func (mp MissingPathError) Error() string