Account-Level Object Architecture

Overview

The Account-Level Object Architecture is a new pattern in Liquibase that enables discovery and management of Snowflake account-level objects like warehouses, resource monitors, integrations, and network policies. This is the first implementation of this pattern in Liquibase.

Key Components

1. AccountSnowflake Object (AccountSnowflake.java)

The AccountSnowflake class serves as the top-level container for all account-level objects:

  • Extends: AbstractDatabaseObject

  • Purpose: Container for account-level objects that exist at the account scope

  • Key Features:

  • Stores child objects in internal collection (accountObjects)

  • Exposes children via serialization attributes for YAML/JSON output

  • Provides typed accessors (e.g., getWarehouses())

Serialization Pattern

The key innovation is using Liquibase's attribute-based serialization:

// Store warehouses as attribute for serialization
setAttribute("warehouses", warehouseList);

This ensures warehouses appear in snapshot output under the account:

accountSnowflake:
  warehouses:
    - liquibase.ext.snowflake.database.object.WarehouseSnowflake#COMPUTE_WH
    - liquibase.ext.snowflake.database.object.WarehouseSnowflake#INT_DB_TEST_WH

2. StandaloneWarehouseSnapshotGenerator

The snapshot generator implements the discovery pattern:

  • Priority: 150 (higher than other generators)

  • Scope: Handles both WarehouseSnowflake and AccountSnowflake objects

  • Discovery: Uses SHOW WAREHOUSES SQL command

  • Integration: Populates AccountSnowflake objects with discovered warehouses

Key Methods

@Override
public Class<? extends DatabaseObject>[] addsTo() {
    return new Class[] { AccountSnowflake.class };
}

@Override
protected DatabaseObject snapshotObject(DatabaseObject example, DatabaseSnapshot snapshot) {
    // Discover warehouses and add to AccountSnowflake
}

3. Core Liquibase Integration

The architecture requires core Liquibase modifications:

  • Extension Point: discoverRootLevelExtensionObjects() in snapshot framework

  • Object Registration: AccountSnowflake and WarehouseSnowflake in service files

  • Type Discovery: Framework discovers account-level objects alongside traditional schema objects

Discovery Flow

  1. Initialization: Liquibase snapshot framework starts

  2. Root Object Discovery: Core calls discoverRootLevelExtensionObjects()

  3. Account Discovery: StandaloneWarehouseSnapshotGenerator discovers AccountSnowflake

  4. Warehouse Population: Generator executes SHOW WAREHOUSES and populates account

  5. Serialization: Account object exposes warehouses via setAttribute("warehouses", ...)

  6. Output: Warehouses appear nested under account in YAML/JSON

Object Hierarchy

AccountSnowflake (account-level container)
├── WarehouseSnowflake (compute clusters)
├── ResourceMonitorSnowflake (future: usage controls)
├── IntegrationSnowflake (future: external connections)
└── NetworkPolicySnowflake (future: IP access controls)

Configuration

Service Registration

Objects must be registered in META-INF/services/liquibase.structure.DatabaseObject:

liquibase.ext.snowflake.database.object.AccountSnowflake
liquibase.ext.snowflake.database.object.WarehouseSnowflake

Generators in META-INF/services/liquibase.snapshot.SnapshotGenerator:

liquibase.ext.snowflake.snapshot.StandaloneWarehouseSnapshotGenerator

Snapshot Control

The framework automatically includes account-level objects in snapshot types:

snapshotControl:
  includedType:
    - liquibase.ext.snowflake.database.object.AccountSnowflake
    - liquibase.ext.snowflake.database.object.WarehouseSnowflake

Technical Implementation Details

Container Pattern

Unlike traditional schema-level objects (Tables, Columns), account-level objects use a container pattern:

  1. Parent Object: AccountSnowflake acts as container

  2. Child Objects: WarehouseSnowflake objects stored in parent

  3. Serialization: Children exposed via parent's attributes

Priority System

Generator priorities ensure correct processing order:

  • Account Generator: Priority 150 (high)

  • Schema Generators: Lower priorities

  • Result: Account objects processed before schema objects

Database Connection

Account-level discovery requires appropriate Snowflake privileges:

  • Warehouse Discovery: SHOW WAREHOUSES privilege

  • Connection Scope: Account-level connection (not schema-specific)

Usage Examples

Snapshot Command

liquibase snapshot --snapshot-format=yaml

Expected Output

objects:
  liquibase.ext.snowflake.database.object.AccountSnowflake:
    - accountSnowflake:
        warehouses:
          - liquibase.ext.snowflake.database.object.WarehouseSnowflake#COMPUTE_WH
          - liquibase.ext.snowflake.database.object.WarehouseSnowflake#INT_DB_TEST_WH

Extension Points

Adding New Account-Level Objects

  1. Create object class extending AbstractDatabaseObject

  2. Add typed accessor to AccountSnowflake (e.g., getResourceMonitors())

  3. Update generator to discover new object type

  4. Register in service files

Custom Discovery Logic

Override discovery methods in generator:

private Collection<NewAccountObject> discoverNewObjects(Database database) {
    // Custom SHOW command or API call
}

Testing

Integration Tests

Test framework validates:

  • Object discovery and population

  • Serialization correctness

  • Generator priority handling

  • Database connection requirements

User Acceptance Tests

End-to-end validation:

  • Snapshot generation includes account objects

  • YAML/JSON output structure correct

  • All warehouse properties captured

Troubleshooting

Common Issues

  1. Empty Account Objects: Ensure setAttribute() called after populating

  2. Missing Warehouses: Check Snowflake privileges and connection

  3. Serialization Problems: Verify attribute naming and types

Debug Output

Enable debug logging to trace:

  • Generator priority selection

  • Object discovery process

  • Serialization attribute updates

  • Framework integration points

Future Enhancements

  1. Resource Monitor Support: Add ResourceMonitorSnowflake objects

  2. Integration Objects: External service connections

  3. Network Policies: IP-based access controls

  4. User and Role Management: Account-level security objects

This architecture provides a foundation for comprehensive Snowflake account management through Liquibase.