config

package
v0.0.0-...-6b9c677 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 3, 2024 License: MIT Imports: 15 Imported by: 1

README

config

Architecture

  • Collector: One or multiple collectors that are reading configuration data from various sources
  • pkgs/controller/ConfigurationController: Kubernetes CRD controller. Collects and passes to DocumentStore
  • internal/config/DocumentStore: Keeps all collected document files
  • Provider: Provides a resolved, contextual configuration

Configuration structure

PFConfig is a Custom Resource Definition that has a .data section, just like in a kind: ConfigMap or in a kind: Secret.

The .data section is a key-value flat list with component prefixes. For example, when a jxscm component wants to retrieve its configuration it will get a map like {"token-secret-name": "some-secret", "token-secret-key": "token"}.

NOTICE: In the code the components are getting key-values without a prefix

---
apiVersion: pipelinesfeedback.keskad.pl/v1alpha1
kind: PFConfig
metadata:
    name: keskad-sample-1
spec:
    jobDiscovery: {}
data:
    # {component}.{key}: {value}
    
    # jxscm is a component name
    # In jxscm implementation then we use the ConfigurationProvider in a following way to retrieve all "jxscm" prefixed keys:
    # `jx.sc.Config.FetchContextual("jxscm", pipeline.GetNamespace(), pipeline)`
    
    jxscm.token-secret-name: "some-secret"
    jxscm.token-secret-key: "token"

Using ConfigurationProvider in a component

cfg := configurationProvider.FetchContextual("jxscm", pipeline.GetNamespace(), pipeline)

// token-secret-key => `jxscm.token-secret-key` from the configuration
// token.txt => a default value in case, when a user would not set anything in the configuration
println(cfg.GetOrDefault("token-secret-key", "token.txt"))

Implementing a collector

ConfigurationCollector interface lets you implement a configuration source that is fetching configuration files at application startup or at runtime, when a Pipeline is reconciled by the controller.

type ConfigurationCollector interface {
	contract.Pluggable
	CollectInitially() ([]*v1alpha1.PFConfig, error)
	CollectOnRequest(info contract.PipelineInfo) ([]*v1alpha1.PFConfig, error)
	SetLogger(logger logging.Logger)
}

It is up to you, how to read the data. It can be fetched via HTTP, parsed from YAML/JSON or whatever you implement. Most important thing is the output format which should be the v1alpha1.PFConfig object containing a key-value data section.

Cases:

  • .metadata.namespace not provided: Configuration will be global for Pipelines in all namespaces
  • .spec.jobDiscovery not provided: Configuration will be for all objects in a namespace or in all namespaces

Schema validation

SchemaValidator component is responsible for validation in two cases:

a) Configuration load time: Validate if user's configuration contains valid keys

ERRO[0005] cannot load configuration 'default/keskad-sample-1' coming from Kubernetes: cannot push PFConfig to IndexedDocumentStore: field 'dupa' is not a valid field for component 'jxscm'

b) Configuration value is read in code: Validate if the developer documented a configuration key used in code

FATA[0001] code contains undocumented configuration option: jxscm.progress-comment, please register it in schema so the users will be aware of it

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ConfigurationCollector

type ConfigurationCollector interface {
	contract.Pluggable
	CollectInitially() ([]*v1alpha1.PFConfig, error)
	CollectOnRequest(info contract.PipelineInfo) ([]*v1alpha1.PFConfig, error)
	SetLogger(logger *logging.InternalLogger)
}

type ConfigurationProvider

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

ConfigurationProvider is serving already collected configuration. Served configuration is already merged from various sources

func (*ConfigurationProvider) FetchContextual

func (cp *ConfigurationProvider) FetchContextual(component string, namespace string, pipeline contract.PipelineInfo) Data

FetchContextual is retrieving a final configuration in context of a given contract.PipelineInfo

func (*ConfigurationProvider) FetchFromFieldOrSecret

func (cp *ConfigurationProvider) FetchFromFieldOrSecret(ctx context.Context, data *Data, namespace string, fieldKey string, referenceKey string, referenceSecretNameKey string) (string, error)

FetchFromFieldOrSecret allows to use an inline secret from configuration file (if present), fallbacks to fetching a secret key from a Kubernetes secret

func (*ConfigurationProvider) FetchGlobal

func (cp *ConfigurationProvider) FetchGlobal(component string) Data

FetchGlobal is fetching a global configuration for given component (without a context of a Pipeline)

func (*ConfigurationProvider) FetchSecretKey

func (cp *ConfigurationProvider) FetchSecretKey(ctx context.Context, name string,
	namespace string, key string, cache bool) (string, error)

FetchSecretKey is fetching a key from .data section from a Kubernetes Secret, directly from the Cluster's API Use this method in pair with FetchContextual() to at first fetch the key name, then to fetch the secret key

type ConfigurationProviderInterface

type ConfigurationProviderInterface interface {
	FetchContextual(component string, namespace string, pipeline contract.PipelineInfo) Data
	FetchGlobal(component string) Data
	FetchSecretKey(ctx context.Context, name string, namespace string, key string, cache bool) (string, error)
	FetchFromFieldOrSecret(ctx context.Context, data *Data, namespace string, fieldKey string, referenceKey string, referenceSecretNameKey string) (string, error)
}

func NewConfigurationProvider

func NewConfigurationProvider(docStore config.IndexedDocumentStore, logger *logging.InternalLogger,
	client v1.CoreV1Interface, kvStore store.Operator, cfgSchema Validator) (ConfigurationProviderInterface, error)

NewConfigurationProvider is a constructor

type Data

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

func NewData

func NewData(componentName string, kv map[string]string, validator Validator, logger logging.FatalLogger) Data

func (*Data) Get

func (d *Data) Get(keyName string) string

Get retrieves a configuration value. For non-existing key it returns an empty string

func (*Data) GetOrDefault

func (d *Data) GetOrDefault(keyName string, defaultVal string) string

GetOrDefault retrieves a configuration value. For non-existing keys it returns a default value defined in `defaultVal` parameter

func (*Data) HasKey

func (d *Data) HasKey(keyName string) bool

type FakeCollector

type FakeCollector struct {
}

func (*FakeCollector) CanHandle

func (f *FakeCollector) CanHandle(adapterName string) bool

func (*FakeCollector) CollectInitially

func (f *FakeCollector) CollectInitially() ([]*v1alpha1.PFConfig, error)

func (*FakeCollector) CollectOnRequest

func (f *FakeCollector) CollectOnRequest(info contract.PipelineInfo) ([]*v1alpha1.PFConfig, error)

func (*FakeCollector) GetImplementationName

func (f *FakeCollector) GetImplementationName() string

func (*FakeCollector) InjectDependencies

func (f *FakeCollector) InjectDependencies(recorder record.EventRecorder, kubeconfig *rest.Config) error

func (*FakeCollector) SetLogger

func (f *FakeCollector) SetLogger(logger *logging.InternalLogger)

type LocalFileConfigurationCollector

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

func NewLocalFileConfigurationCollector

func NewLocalFileConfigurationCollector(logger *logging.InternalLogger, path string) *LocalFileConfigurationCollector

func (*LocalFileConfigurationCollector) CanHandle

func (lf *LocalFileConfigurationCollector) CanHandle(adapterName string) bool

func (*LocalFileConfigurationCollector) CollectInitially

func (lf *LocalFileConfigurationCollector) CollectInitially() ([]*v1alpha1.PFConfig, error)

CollectInitially is looking for a JSON file specified in CONFIG_PATH environment variable it falls back to "pipelines-feedback.json" local file path. If the file does not exist it is ignored.

func (*LocalFileConfigurationCollector) CollectOnRequest

CollectOnRequest is not implemented as the "local" does not allow dynamic resolution

func (*LocalFileConfigurationCollector) GetImplementationName

func (lf *LocalFileConfigurationCollector) GetImplementationName() string

func (*LocalFileConfigurationCollector) InjectDependencies

func (lf *LocalFileConfigurationCollector) InjectDependencies(recorder record.EventRecorder, kubeconfig *rest.Config) error

func (*LocalFileConfigurationCollector) SetLogger

type MultipleCollector

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

MultipleCollector is an "adapter of adapters" pattern that lets you use multiple configuration sources at a single time

func CreateMultipleCollector

func CreateMultipleCollector(collectors []ConfigurationCollector, logger *logging.InternalLogger) *MultipleCollector

func (*MultipleCollector) CanHandle

func (mc *MultipleCollector) CanHandle(adapterName string) bool

func (*MultipleCollector) CollectInitially

func (mc *MultipleCollector) CollectInitially() ([]*v1alpha1.PFConfig, error)

func (*MultipleCollector) CollectOnRequest

func (mc *MultipleCollector) CollectOnRequest(info contract.PipelineInfo) ([]*v1alpha1.PFConfig, error)

func (*MultipleCollector) GetImplementationName

func (mc *MultipleCollector) GetImplementationName() string

func (*MultipleCollector) SetLogger

func (mc *MultipleCollector) SetLogger(logger *logging.InternalLogger)

type Schema

type Schema struct {
	Name          string
	AllowedFields []string
}

type SchemaValidator

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

func (*SchemaValidator) Add

func (sm *SchemaValidator) Add(schema Schema)

func (*SchemaValidator) ValidateConfig

func (sm *SchemaValidator) ValidateConfig(data v1alpha1.Data) error

func (*SchemaValidator) ValidateRequestedEntry

func (sm *SchemaValidator) ValidateRequestedEntry(group string, key string) error

type Validator

type Validator interface {
	ValidateRequestedEntry(group string, key string) error
	ValidateConfig(data v1alpha1.Data) error
	Add(schema Schema)
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL