confiflow

package module
v0.0.0-...-b7da0db Latest Latest
Warning

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

Go to latest
Published: Mar 6, 2025 License: MIT Imports: 22 Imported by: 0

README

ConfiFlow

ConfiFlow is a flexible, multi-source configuration management library for Go applications. It provides a unified interface for accessing configuration data from various sources like files, environment variables, Git repositories, and Consul.

Features

  • Multiple Sources: Load configuration from files, Git, Consul, environment variables, and more
  • Dynamic Updates: Watch for configuration changes and get notified automatically
  • Structured Data: Access specific values within JSON and YAML configurations
  • Template Support: Render configuration templates with variables
  • Schema Validation: Validate configurations against JSON schemas
  • Configuration Merging: Combine multiple configurations into a unified view
  • Caching: Improve performance with an optional caching layer
  • FIPS Compliance: FIPS 140-2 compliant mode for security-sensitive applications

Installation

go get github.com/Michi01/ConfiFlow

Usage

Here's a comprehensive example demonstrating the usage of ConfiFlow:

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/Michi01/ConfiFlow"
)

func main() {
	// Create a new client
	client := confiflow.NewClient(
		confiflow.WithCacheEnabled(true),
		confiflow.WithDefaultProvider("file"),
	)
	defer client.Close()

	// Register default providers
	client.RegisterDefaultProviders()

	// Add a file provider
	client.AddSource(confiflow.Source{
		Type:     "file",
		Location: "./configs",
	})

	// Access a file
	ctx := context.Background()
	data, err := client.Get(ctx, "file:app.json")
	if err != nil {
		log.Fatalf("Failed to get config: %v", err)
	}
	fmt.Println(string(data))

	// Access a specific value in a structured configuration
	value, err := client.GetValue(ctx, "file:app.json#/database/host")
	if err != nil {
		log.Fatalf("Failed to get value: %v", err)
	}
	fmt.Println("Database host:", value)

	// Watch for configuration changes
	watchChan, err := client.Watch(ctx, "file:app.json")
	if err != nil {
		log.Fatalf("Failed to watch config: %v", err)
	}

	// Monitor for changes
	go func() {
		for {
			<-watchChan
			fmt.Println("Configuration changed!")
		}
	}()

	// Add a Consul provider
	client.AddSource(confiflow.Source{
		Type:     "consul",
		Location: "localhost:8500",
		Options: map[string]string{
			"prefix": "myapp/config",
			"token":  "consul-token",
		},
	})

	// Access a key from Consul
	data, err = client.Get(ctx, "consul:database")
	if err != nil {
		log.Fatalf("Failed to get Consul data: %v", err)
	}

	// Watch and unmarshal configuration
	var config AppConfig
	err = client.WatchAndUnmarshal(ctx, "file:app.json", &config, func() {
		fmt.Println("Config updated, new log level:", config.LogLevel)
	})
	if err != nil {
		log.Fatalf("Failed to watch and unmarshal: %v", err)
	}

	// Merge configurations
	mergeOpts := confiflow.MergeOptions{
		Strategy:      "deep",
		ArrayMerge:    "append",
		IgnoreMissing: true,
	}

	merged, err := client.MergeConfigs(ctx, []string{
		"file:default.json",
		"file:environment.json",
		"file:local.json",
	}, mergeOpts)
	if err != nil {
		log.Fatalf("Failed to merge configs: %v", err)
	}
	fmt.Println("Merged config:", string(merged))

	// Render template
	templateOpts := confiflow.TemplateOptions{
		IncludeEnv: true,
		CustomValues: map[string]interface{}{
			"version": "1.0.0",
		},
	}

	rendered, err := client.RenderTemplate(ctx, "file:templates/app.yaml.tmpl", templateOpts)
	if err != nil {
		log.Fatalf("Failed to render template: %v", err)
	}
	fmt.Println("Rendered template:", string(rendered))

	// Validate configuration
	valid, errors, err := client.ValidateConfig(ctx, "file:app.json", "file:schemas/app.schema.json")
	if err != nil {
		log.Fatalf("Failed to validate config: %v", err)
	}
	if !valid {
		for _, errMsg := range errors {
			fmt.Println("Validation error:", errMsg)
		}
	}

	// Create an HTTP server for the configuration API
	server, err := client.NewHTTPServer(":8080",
		confiflow.WithAuthToken("secure-token"),
		confiflow.WithTLS("cert.pem", "key.pem"),
	)
	if err != nil {
		log.Fatalf("Failed to create HTTP server: %v", err)
	}

	// Start the server
	go server.Start()

	// Wait for exit
	select {}
}

Configuration File

ConfiFlow can be configured using a JSON configuration file. Here's an example:

{
  "refreshInterval": "1m",
  "cacheEnabled": true,
  "cacheExpiration": "5m",
  "cacheCleanup": "10m",
  "defaultProvider": "file",
  "fipsMode": false,
  "sources": [
    {
      "name": "local",
      "type": "file",
      "location": "./configs"
    },
    {
      "name": "remote",
      "type": "git",
      "location": "https://github.com/username/repo.git",
      "options": {
        "branch": "main",
        "auth": "token",
        "token": "your-personal-access-token"
      }
    },
    {
      "name": "kvstore",
      "type": "consul",
      "location": "localhost:8500",
      "options": {
        "prefix": "myapp/config"
      }
    }
  ]
}

To load the client configuration from a file:

// Load client from config file
client, err := confiflow.ConfigFromFile(ctx, "confiflow.json")
if err != nil {
	log.Fatalf("Failed to load config: %v", err)
}

Documentation

For detailed documentation on all features and options, please refer to the GoDoc page.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

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

Client is the main ConfiFlow client

func ConfigFromFile

func ConfigFromFile(ctx context.Context, configPath string) (*Client, error)

ConfigFromFile initializes a client from a configuration file

func NewClient

func NewClient(opts ...Option) *Client

NewClient creates a new ConfiFlow client with the given options

func (*Client) AddEncryptionProvider

func (c *Client) AddEncryptionProvider(provider EncryptionProvider)

AddEncryptionProvider adds an encryption provider to the client

func (*Client) AddSource

func (c *Client) AddSource(source Source) error

AddSource adds a configuration source and creates a provider for it

func (*Client) AddSources

func (c *Client) AddSources(sources []Source) error

AddSources adds multiple configuration sources

func (*Client) Close

func (c *Client) Close() error

Close closes all providers and releases resources

func (*Client) CreateProvider

func (c *Client) CreateProvider(sourceURI string) (providers.Provider, error)

CreateProvider creates a provider instance from a source string Format: provider://location?param1=value1¶m2=value2

func (*Client) DecryptValue

func (c *Client) DecryptValue(ctx context.Context, encryptedValue string) (string, error)

DecryptValue decrypts an encrypted value

func (*Client) EncryptValue

func (c *Client) EncryptValue(ctx context.Context, value string, providerType string, keyID string) (string, error)

EncryptValue encrypts a value using the specified provider and key ID

func (*Client) Exists

func (c *Client) Exists(ctx context.Context, configPath string) bool

Exists checks if a configuration path exists

func (*Client) GenerateSecretKey

func (c *Client) GenerateSecretKey(length int) ([]byte, error)

GenerateSecretKey generates a new random secret key

func (*Client) Get

func (c *Client) Get(ctx context.Context, configPath string) ([]byte, error)

Get retrieves a configuration value

func (*Client) GetMultiple

func (c *Client) GetMultiple(ctx context.Context, configPaths []string) (map[string][]byte, error)

GetMultiple retrieves multiple configurations in parallel

func (*Client) GetSecurely

func (c *Client) GetSecurely(ctx context.Context, configPath string) ([]byte, error)

GetSecurely retrieves a configuration value and automatically decrypts any encrypted values

func (*Client) GetValue

func (c *Client) GetValue(ctx context.Context, valuePath string) (interface{}, error)

GetValue retrieves a specific value from a structured configuration

func (*Client) LoadProviders

func (c *Client) LoadProviders(ctx context.Context, configPath string) error

LoadProviders loads a list of providers defined in a configuration file

func (*Client) MergeConfigs

func (c *Client) MergeConfigs(ctx context.Context, paths []string, options MergeOptions) (interface{}, error)

MergeConfigs merges multiple configuration files into a single structure

func (*Client) NewEnvProvider

func (c *Client) NewEnvProvider(prefix string, delimiter string)

NewEnvProvider creates a provider that loads configurations from environment variables

func (*Client) NewFileProvider

func (c *Client) NewFileProvider(name, directory string) (providers.Provider, error)

func (*Client) NewKMSEncryptionProvider

func (c *Client) NewKMSEncryptionProvider(keyID string, region string) error

NewKMSEncryptionProvider creates a new AWS KMS encryption provider

func (*Client) NewLocalEncryptionProvider

func (c *Client) NewLocalEncryptionProvider(keyID string, key []byte) error

NewLocalEncryptionProvider creates a new local encryption provider

func (*Client) Refresh

func (c *Client) Refresh(ctx context.Context, configPath string) error

Refresh forces a refresh of the cached configuration

func (*Client) RefreshAll

func (c *Client) RefreshAll(ctx context.Context)

RefreshAll forces a refresh of all cached configurations

func (*Client) RegisterDefaultProviders

func (c *Client) RegisterDefaultProviders()

RegisterDefaultProviders registers all default provider factories

func (*Client) RegisterProvider

func (c *Client) RegisterProvider(name string, provider providers.Provider)

RegisterProvider registers a configuration provider

func (*Client) RegisterProviderFactory

func (c *Client) RegisterProviderFactory(providerType string, factory providers.ProviderFactory)

RegisterProviderFactory registers a factory function for creating providers

func (*Client) RenderTemplate

func (c *Client) RenderTemplate(ctx context.Context, templatePath string, options TemplateOptions) ([]byte, error)

RenderTemplate renders a configuration template

func (*Client) Unmarshal

func (c *Client) Unmarshal(ctx context.Context, configPath string, target interface{}) error

Unmarshal parses a configuration file into a target struct

func (*Client) ValidateConfig

func (c *Client) ValidateConfig(ctx context.Context, configPath, schemaPath string) (bool, []string, error)

ValidateConfig validates a configuration against a JSON schema

func (*Client) WaitForExists

func (c *Client) WaitForExists(ctx context.Context, configPath string, timeout time.Duration) error

WaitForExists waits for a configuration to exist with timeout

func (*Client) Watch

func (c *Client) Watch(ctx context.Context, configPath string) (<-chan struct{}, error)

Watch starts watching a configuration path for changes

func (*Client) WatchAndUnmarshal

func (c *Client) WatchAndUnmarshal(ctx context.Context, configPath string, target interface{}, onChange func()) error

WatchAndUnmarshal watches a configuration and updates the target when it changes

type Config

type Config struct {
	RefreshInterval time.Duration
	CacheEnabled    bool
	CacheExpiration time.Duration
	CacheCleanup    time.Duration
	CacheSize       int
	TLSConfig       *tls.Config
	DefaultProvider string
	FIPSMode        bool
}

Config represents the configuration of the ConfiFlow client

type EncryptionProvider

type EncryptionProvider = crypto.EncryptionProvider

EncryptionProvider represents an interface for encrypting and decrypting data

type EnvConfig

type EnvConfig struct {
	Prefix    string
	Delimiter string
}

EnvConfig represents a configuration loaded from environment variables

type MergeOptions

type MergeOptions struct {
	Strategy      string // "deep" or "shallow"
	ArrayMerge    string // "replace" or "append"
	IgnoreMissing bool   // Skip configs that are not found
}

MergeOptions configures the merging behavior

type Option

type Option func(*Config)

Option defines a configuration option for ConfiFlow

func WithCacheCleanup

func WithCacheCleanup(duration time.Duration) Option

WithCacheCleanup sets the cache cleanup interval

func WithCacheEnabled

func WithCacheEnabled(enabled bool) Option

WithCacheEnabled enables or disables caching

func WithCacheExpiration

func WithCacheExpiration(duration time.Duration) Option

WithCacheExpiration sets the cache item expiration duration

func WithCacheSize

func WithCacheSize(size int) Option

WithCacheSize sets the maximum number of items in the cache

func WithDefaultProvider

func WithDefaultProvider(providerName string) Option

WithDefaultProvider sets the default provider to use

func WithFIPSMode

func WithFIPSMode(enabled bool) Option

WithFIPSMode enables FIPS 140-2 compliant mode

func WithRefreshInterval

func WithRefreshInterval(interval time.Duration) Option

WithRefreshInterval sets the interval for polling configuration sources

func WithTLSConfig

func WithTLSConfig(tlsConfig *tls.Config) Option

WithTLSConfig sets custom TLS configuration

type Source

type Source struct {
	Type     string
	Location string
	Options  map[string]string
}

Source represents a configuration source

type TemplateOptions

type TemplateOptions struct {
	Delimiters   []string               // Template delimiters (default: "{{", "}}")
	CustomFuncs  template.FuncMap       // Custom template functions
	IncludeEnv   bool                   // Include environment variables
	CustomValues map[string]interface{} // Custom values to use in templates
}

TemplateOptions configures template rendering behavior

Directories

Path Synopsis
cmd
confiflow command
internal
git

Jump to

Keyboard shortcuts

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