Skip to main content

Overview

AccountFactory is a utility class that creates Account instances and populates them with credentials from various sources. It supports loading credentials from Vault, YAML files, or environment variables.

Class signature

public final class AccountFactory
Package: software.tnb.common.account

Methods

create(Class)

Creates an instance of the specified Account class and populates it with credentials from configured loaders.
public static <T extends Account> T create(Class<T> accountClass)
accountClass
Class<T>
required
The Account class to instantiate and populate
return
T
A new instance of the specified Account class with credentials loaded
Type parameters:
  • T - Account type that extends Account
Example:
// Create a Kafka account with credentials
KafkaAccount kafka = AccountFactory.create(KafkaAccount.class);

// Create an AWS account with credentials
AWSAccount aws = AccountFactory.create(AWSAccount.class);

defaultLoader()

Creates the default credentials loader chain based on available configuration. Loaders are checked in priority order:
  1. Vault (with token authentication)
  2. Vault (with AppRole authentication)
  3. YAML string from configuration
  4. YAML file from configuration
public static CredentialsLoader defaultLoader() throws Exception
return
CredentialsLoader
A DelegatingCredentialsLoader that tries each configured loader in sequence
Example:
CredentialsLoader loader = AccountFactory.defaultLoader();
// Loader is automatically used by create() method

setCredentialsLoader(CredentialsLoader)

Sets a custom credentials loader to override the default loading mechanism.
public static void setCredentialsLoader(CredentialsLoader loader)
loader
CredentialsLoader
required
The custom CredentialsLoader to use for loading account credentials
Example:
// Use a custom credentials loader
CredentialsLoader customLoader = new YamlCredentialsLoader(
    new File("/path/to/credentials.yaml")
);
AccountFactory.setCredentialsLoader(customLoader);

// All subsequent create() calls will use the custom loader
KafkaAccount kafka = AccountFactory.create(KafkaAccount.class);

Credentials loading mechanism

AccountFactory uses a flexible credentials loading system:

Loader priority

The default loader checks sources in this order:
  1. Vault with token - If test.credentials.vault.token is configured
  2. Vault with AppRole - If test.credentials.vault.role-id and test.credentials.vault.secret-id are configured
  3. YAML string - If test.credentials contains YAML content
  4. YAML file - If test.credentials.file points to a file

Credential IDs

For accounts implementing WithId, the factory resolves credential IDs hierarchically:
  • Walks up the class hierarchy
  • Collects IDs from each level that implements WithId
  • Uses the ID list to look up credentials
Accounts that don’t implement WithId are instantiated without credential loading.

Configuration

Configure credential sources using system properties or test configuration:
// Token authentication
System.setProperty("test.credentials.vault.address", "https://vault.example.com");
System.setProperty("test.credentials.vault.token", "s.xyz123");
System.setProperty("test.credentials.vault.path.pattern", "secret/data/%s");

// AppRole authentication
System.setProperty("test.credentials.vault.address", "https://vault.example.com");
System.setProperty("test.credentials.vault.role-id", "role-123");
System.setProperty("test.credentials.vault.secret-id", "secret-456");

Custom credentials loaders

You can implement custom credential loading logic:
public class CustomCredentialsLoader implements CredentialsLoader {
    
    @Override
    public <T extends Account> T get(List<String> credentialIds, Class<T> accountClass) {
        T account = createInstance(accountClass);
        
        // Load credentials from your custom source
        loadCredentials(account, credentialIds);
        
        return account;
    }
    
    private <T extends Account> void loadCredentials(T account, List<String> ids) {
        // Custom loading logic
    }
}

// Use the custom loader
AccountFactory.setCredentialsLoader(new CustomCredentialsLoader());

Built-in credential loaders

VaultCredentialsLoader

Loads credentials from HashiCorp Vault:
// Token authentication
VaultCredentialsLoader loader = new VaultCredentialsLoader(
    "https://vault.example.com",
    "secret/data/%s",
    "s.token123"
);

// AppRole authentication  
VaultCredentialsLoader loader = new VaultCredentialsLoader(
    "https://vault.example.com",
    "secret/data/%s",
    "role-id",
    "secret-id"
);

YamlCredentialsLoader

Loads credentials from YAML files or strings:
// From file
YamlCredentialsLoader loader = new YamlCredentialsLoader(
    new File("/path/to/credentials.yaml")
);

// From string
String yaml = "kafka:\n  bootstrap.servers: localhost:9092";
YamlCredentialsLoader loader = new YamlCredentialsLoader(yaml);

DelegatingCredentialsLoader

Tries multiple loaders in sequence:
List<CredentialsLoader> loaders = Arrays.asList(
    vaultLoader,
    yamlLoader,
    fallbackLoader
);
DelegatingCredentialsLoader loader = new DelegatingCredentialsLoader(loaders);

Error handling

AccountFactory handles errors as follows:
  • No credentials needed: Accounts without WithId are created without loading
  • Load failure: Throws test failure via fail() with detailed error message
  • Instantiation failure: Wraps exceptions in RuntimeException

Build docs developers (and LLMs) love