config

package
v0.0.5 Latest Latest
Warning

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

Go to latest
Published: Nov 15, 2025 License: MIT Imports: 7 Imported by: 0

README

Config Manager

This package provides a simple way to load configuration and secrets into your application using viper. It supports merging multiple config files and reading secrets from either a file or Google Secret Manager (GSM).

Overview

  • Load config from one or more files in a directory.
  • Choose a top-level key to unmarshal from (e.g. Config).
  • Read secrets from a file path or GSM, controlled via environment variables.

Environment Variables

  • CONFIG_FILE_PATH: Directory containing your config files (e.g. ./config or ./config/test).
  • SECRET_FILE_PATH: Full path to the secret file (e.g. ./config/secret.json).
  • SECRET_GSM_PROJECT_ID: GSM project ID when using GSM.

Config File Layout

You can split config across multiple files. Each file should have a top-level key that matches the key you pass to the manager (commonly Config).

Example directory structure:

config/
  config.json
  app.json

Example file contents:

config/config.json

{
  "Config": {
    "Environment": "dev"
  }
}

config/app.json

{
  "Config": {
    "AppEnv": "test"
  }
}

Quick Start (Load Config)

package main

import (
    "context"
    gdkconfig "github.com/aidapedia/gdk/config"
)

// Define your target struct that matches the JSON inside the top-level key.
type AppConfig struct {
    Environment string
    AppEnv      string
}

func main() {
    // Ensure environment variable points to the directory with your config files.
    // e.g. os.Setenv("CONFIG_FILE_PATH", "./config")

    cfg := AppConfig{}

    // file names are specified WITHOUT extensions and must exist under CONFIG_FILE_PATH.
    // key is the top-level JSON key inside each file (e.g. "Config").
    m := gdkconfig.NewManager(Option{
				TargetStore: &cfg,
				FileName:    []string{"config", "app"},
				ConfigKey:   "AppConfig",
			})

    if err := m.SetConfig(context.Background()); err != nil {
        panic(err)
    }

    // Get your config imediately
    _ = cfg
}
Notes
  • Pass your target struct pointer (cfg) as the first argument to NewManager.
  • The manager will MergeInConfig() for each file name provided and UnmarshalKey(key, &store).
  • If you want to unmarshal the whole file, put your fields under a common top-level key and use that key.

Load Secrets

You can also load secrets using the manager or the secret package directly.

Secrets via Manager (File)
package main

import (
    "context"
    gdkconfig "github.com/aidapedia/gdk/config"
)

type Secrets struct {
    APIKey string
    Token  string
}

func main() {
    // SECRET_FILE_PATH must be set to the full file path, e.g. ./config/secret.json
    // e.g. os.Setenv("SECRET_FILE_PATH", "./config/secret.json")

    sec := &Secrets{}
    m := gdkconfig.NewManager(nil, gdkconfig.SecretTypeFile, nil, "")

    // Internally, SetSecretStore reads SECRET_FILE_PATH and fills m.secretStore.
    // To use it, set m.secretStore to your target type first.
    // (Do this inside the same package or provide a wrapper that sets it.)
}
Secrets via secret.File (Direct)

If you prefer to load secrets directly:

package main

import (
    "context"
    "github.com/aidapedia/gdk/config/secret"
)

type Secrets struct {
    ServiceName string
}

func main() {
    // Provide the full path to the secret file.
    // If your file is in a directory, include the directory in the path.
    s := secret.NewSecretFile("config/secret.json")

    var sec Secrets
    if err := s.GetSecret(context.Background(), &sec); err != nil {
        panic(err)
    }
}

Example config/secret.json:

{
  "ServiceName": "example-service"
}

Troubleshooting

  • "CONFIG_FILE_PATH environment variable is not set": Set CONFIG_FILE_PATH to the directory that contains your config files.
  • "Failed to get secret: open : no such file or directory": Ensure you pass the full relative/absolute path to the secret file (secret.NewSecretFile("config/secret.json")) or set SECRET_FILE_PATH correctly.
  • Using relative paths: Paths are resolved from the process working directory. In tests inside config, setting CONFIG_FILE_PATH to "test" reads from config/test.

Testing Example

The repository includes tests under config/test/ demonstrating multi-file merge with the Config key:

  • config/test/config.json sets Environment.
  • config/test/app.json sets AppEnv.
  • The test sets CONFIG_FILE_PATH to "test" and uses file names []string{"config", "app"}.

This pattern lets you compose configuration cleanly across files and environments.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Manager added in v0.0.3

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

func New added in v0.0.3

func New(opt Option) *Manager

func (*Manager) SetConfig added in v0.0.3

func (m *Manager) SetConfig(ctx context.Context) error

SetConfig sets the config value store.

func (*Manager) SetSecretStore added in v0.0.3

func (m *Manager) SetSecretStore(ctx context.Context) error

SetSecretStore sets the secret value store.

type Option added in v0.0.3

type Option struct {
	TargetStore interface{}
	ConfigKey   string
	FileName    []string

	WithSecret   SecretType
	TargetSecret interface{}
}

func (*Option) Validate added in v0.0.3

func (o *Option) Validate() error

type SecretType added in v0.0.3

type SecretType string
const (
	SecretTypeFile SecretType = "file"
	SecretTypeGSM  SecretType = "gsm"
)

SecretType is the type of secret to use. We will implement the following secret types: - file: read secret from a file - gsm: read secret from Google Secret Manager

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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