ccconfig

package
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Dec 18, 2025 License: MIT Imports: 6 Imported by: 3

README

ccConfig Interface

The ccConfig package provides a simple yet flexible configuration management system for the ClusterCockpit ecosystem. It allows components to load JSON configuration files with support for both inline configurations and external file references.

Features

  • Simple API: Just two main functions - Init() to load and GetPackageConfig() to retrieve
  • File References: Support for splitting configuration across multiple files
  • Flexible Structure: Organize config by component/package
  • Helper Functions: Check for existence, list keys, and reset configuration
  • Zero Dependencies: Uses only standard library (plus ccLogger)

Configuration File Structure

All configuration files follow this JSON structure:

{
    "main": {
        "interval": "10s",
        "debug": true
    },
    "database": {
        "host": "localhost",
        "port": 5432
    },
    "sinks-file": "./sinks.json"
}

Each top-level key represents a configuration section that can be retrieved independently.

File References

Keys ending with -file are treated specially. The value should be a string path to an external JSON file:

{
    "receivers-file": "./receivers.json",
    "sinks-file": "./sinks.json",
    "main": {
        "interval": "10s"
    }
}

In the example above:

  • receivers.json content will be available via GetPackageConfig("receivers")
  • sinks.json content will be available via GetPackageConfig("sinks")
  • The inline main config is available via GetPackageConfig("main")

API Reference

Init(filename string)

Initializes the configuration system by loading a JSON configuration file.

ccconfig.Init("./config.json")

Behavior:

  • If the file doesn't exist, continues with empty configuration
  • If the file is invalid JSON, terminates with fatal error
  • Processes all -file references and loads external files
GetPackageConfig(key string) json.RawMessage

Retrieves raw JSON configuration for a specific key.

rawConfig := ccconfig.GetPackageConfig("database")
if rawConfig == nil {
    log.Fatal("database config not found")
}

var dbConfig DatabaseConfig
if err := json.Unmarshal(rawConfig, &dbConfig); err != nil {
    log.Fatalf("invalid config: %v", err)
}

Returns:

  • json.RawMessage containing the configuration data
  • nil if the key doesn't exist (also logs an info message)
HasKey(key string) bool

Checks whether a configuration key exists.

if ccconfig.HasKey("optional-metrics") {
    config := ccconfig.GetPackageConfig("optional-metrics")
    // ... use config
}
GetKeys() []string

Returns all available configuration keys.

keys := ccconfig.GetKeys()
for _, key := range keys {
    fmt.Printf("Config section: %s\n", key)
}
Reset()

Clears all loaded configuration. Useful for testing.

ccconfig.Reset()
ccconfig.Init("test-config.json")

Usage Example

package main

import (
    "encoding/json"
    "log"
    ccconfig "github.com/ClusterCockpit/cc-lib/ccConfig"
)

type AppConfig struct {
    Interval string `json:"interval"`
    Debug    bool   `json:"debug"`
    Workers  int    `json:"workers"`
}

func main() {
    // Initialize configuration
    ccconfig.Init("./config.json")

    // Check if configuration exists
    if !ccconfig.HasKey("myapp") {
        log.Fatal("myapp configuration section not found")
    }

    // Retrieve and parse configuration
    rawConfig := ccconfig.GetPackageConfig("myapp")
    var config AppConfig
    if err := json.Unmarshal(rawConfig, &config); err != nil {
        log.Fatalf("failed to parse config: %v", err)
    }

    // Use configuration
    log.Printf("Starting with %d workers, interval: %s", 
               config.Workers, config.Interval)
}

Best Practices

1. Always Check for nil
rawConfig := ccconfig.GetPackageConfig("component")
if rawConfig == nil {
    // Handle missing configuration appropriately
    log.Fatal("required configuration not found")
}
2. Use Struct Tags for JSON
type Config struct {
    Interval string `json:"interval"`
    Enabled  bool   `json:"enabled"`
    // Use omitempty for optional fields
    OptionalField string `json:"optional_field,omitempty"`
}
3. Organize Configuration by Component

Split large configurations into separate files:

{
    "main": { ... },
    "receivers-file": "./receivers.json",
    "sinks-file": "./sinks.json",
    "collectors-file": "./collectors.json"
}
4. Validate After Loading
var config AppConfig
if err := json.Unmarshal(rawConfig, &config); err != nil {
    log.Fatalf("invalid config: %v", err)
}

// Validate configuration values
if config.Interval == "" {
    log.Fatal("interval must be specified")
}
if config.Workers < 1 {
    log.Fatal("workers must be at least 1")
}
5. Use Reset() in Tests
func TestMyComponent(t *testing.T) {
    ccconfig.Reset() // Clear any previous config
    ccconfig.Init("./testdata/test-config.json")
    
    // ... your tests
}

Troubleshooting

Configuration Not Found

Problem: GetPackageConfig() returns nil

Solutions:

  1. Check that Init() was called with the correct file path
  2. Verify the key name matches exactly (case-sensitive)
  3. For file references, ensure the -file suffix is in the config, not in your retrieval key
  4. Use GetKeys() to see all available keys
// Debug: Print all available keys
keys := ccconfig.GetKeys()
fmt.Printf("Available keys: %v\n", keys)
Invalid JSON Error

Problem: Fatal error during Init() about invalid JSON

Solutions:

  1. Validate your JSON with a linter (e.g., jq . < config.json)
  2. Check for trailing commas (not allowed in JSON)
  3. Ensure all strings use double quotes, not single quotes
  4. Verify file encoding is UTF-8
File Reference Not Loading

Problem: External file referenced via -file suffix not loading

Solutions:

  1. Check file path is relative to the current working directory
  2. Verify file exists and is readable
  3. Ensure the referenced file contains valid JSON
  4. Check logs for error messages from ccLogger
Unmarshal Errors

Problem: json.Unmarshal() fails when parsing retrieved config

Solutions:

  1. Ensure struct field types match JSON types
  2. Use JSON tags that match your config keys exactly
  3. Make sure struct fields are exported (start with capital letter)
  4. Enable debug logging to see the raw JSON being parsed
rawConfig := ccconfig.GetPackageConfig("myapp")
fmt.Printf("Raw config: %s\n", string(rawConfig)) // Debug print

Implementation Notes

  • Configuration is stored in a global map after initialization
  • The package does not support hot-reloading (requires restart to pick up changes)
  • File references are resolved at initialization time
  • Missing config files (os.IsNotExist) are silently ignored, other errors are fatal
  • The package is not thread-safe - ensure Init() is called before concurrent access

Documentation

Overview

Package ccconfig provides a simple configuration management system for the ClusterCockpit ecosystem.

The package supports loading JSON configuration files with a flexible structure that allows both inline configuration and external file references. Configuration sections can be accessed by key, enabling modular configuration management across different components.

Configuration File Structure

Configuration files should follow this JSON structure:

{
    "main": {
        // Main configuration for the component
    },
    "foo": {
        // Configuration for sub-component 'foo'
    },
    "bar-file": "path/to/bar.json"
}

File References

Keys ending with "-file" are treated as file references. The value should be a string path to an external JSON file. The referenced file's content will be loaded and stored under the key prefix (without "-file" suffix).

For example, "sinks-file": "sinks.json" will load the content of sinks.json and make it available via GetPackageConfig("sinks").

Usage Example

package main

import (
    "encoding/json"
    "log"
    ccconfig "github.com/ClusterCockpit/cc-lib/ccConfig"
)

type AppConfig struct {
    Interval string `json:"interval"`
    Debug    bool   `json:"debug"`
}

func main() {
    // Initialize with config file
    ccconfig.Init("config.json")

    // Get configuration for your package
    rawConfig := ccconfig.GetPackageConfig("myapp")
    if rawConfig == nil {
        log.Fatal("myapp configuration not found")
    }

    // Unmarshal into your config struct
    var config AppConfig
    if err := json.Unmarshal(rawConfig, &config); err != nil {
        log.Fatalf("failed to parse config: %v", err)
    }

    // Use the configuration
    log.Printf("Running with interval: %s", config.Interval)
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GetKeys added in v0.11.0

func GetKeys() []string

GetKeys returns a list of all available configuration keys. This can be useful for debugging or for components that need to discover what configuration sections are available.

Returns:

  • A slice of strings containing all configuration keys

Example:

keys := ccconfig.GetKeys()
for _, key := range keys {
    fmt.Printf("Found config section: %s\n", key)
}

func GetPackageConfig

func GetPackageConfig(key string) json.RawMessage

GetPackageConfig retrieves the raw JSON configuration for a given key. It returns the configuration as json.RawMessage which can then be unmarshaled into the appropriate structure.

If the key does not exist, it logs an informational message and returns nil. Callers should check for nil before attempting to unmarshal the result.

Parameters:

  • key: The configuration key to retrieve

Returns:

  • json.RawMessage containing the configuration data, or nil if the key doesn't exist

Example:

rawConfig := ccconfig.GetPackageConfig("database")
if rawConfig != nil {
    var dbConfig DatabaseConfig
    json.Unmarshal(rawConfig, &dbConfig)
}

func HasKey added in v0.11.0

func HasKey(key string) bool

HasKey checks whether a configuration key exists. This can be used to determine if a component's configuration was loaded before attempting to retrieve it.

Parameters:

  • key: The configuration key to check

Returns:

  • true if the key exists, false otherwise

Example:

if ccconfig.HasKey("optional-feature") {
    config := ccconfig.GetPackageConfig("optional-feature")
    // ... use config
}

func Init

func Init(filename string)

Init initializes the configuration system by loading and parsing a JSON configuration file. It reads the specified file and processes all configuration sections. Keys ending with "-file" are treated as references to external files, which are loaded and stored under the base key name.

If the file does not exist, Init will silently continue with an empty configuration. Other errors (permission denied, invalid JSON, etc.) will cause the program to terminate with a fatal error message.

Parameters:

  • filename: Path to the main JSON configuration file

Example:

ccconfig.Init("./config.json")

func Reset added in v0.11.0

func Reset()

Reset clears all loaded configuration data. This is primarily useful for testing scenarios where you need to reload or clear configuration between test cases.

Example:

ccconfig.Reset()
ccconfig.Init("test-config.json")

Types

This section is empty.

Jump to

Keyboard shortcuts

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