# π§ Amalgam
**Generate type-safe [Nickel](https://nickel-lang.org) configurations from any schema source**
Amalgam transforms Kubernetes CRDs, OpenAPI schemas, and other type definitions into strongly-typed Nickel configuration language, enabling type-safe infrastructure as code with automatic validation and completion.
## π― Why Nickel?
[Nickel](https://nickel-lang.org) is a powerful configuration language that offers:
- **Gradual Typing** - Mix static types with dynamic code as needed
- **Contracts** - Runtime validation with custom predicates
- **Merging** - Powerful record merging and extension
- **Functions** - First-class functions for abstraction
- **Correctness** - Designed to prevent configuration errors
Amalgam bridges the gap between existing schemas (K8s CRDs, OpenAPI) and Nickel's type system, giving you the best of both worlds: auto-generated types from authoritative sources with Nickel's powerful configuration capabilities.
## β¨ Features
- π¦ **Import Kubernetes CRDs** - Convert CRDs to strongly-typed [Nickel](https://nickel-lang.org) configurations
- π **Smart Import Resolution** - Automatically resolves K8s type references with proper imports
- π **Package Generation** - Creates organized package structures from multiple CRDs
- π **Extensible Architecture** - Plugin-based resolver system for adding new type mappings
- π **GitHub Integration** - Fetch CRDs directly from GitHub repositories
## π₯ Installation
```bash
# Clone the repository
git clone https://github.com/seryl/amalgam
cd amalgam
# Build with Cargo
cargo build --release
# Install locally
cargo install --path crates/amalgam-cli
```
## π Quick Start
### Import a Single CRD
```bash
# Import from a local file
amalgam import crd --file my-crd.yaml --output my-crd.ncl
# Import from a URL
amalgam import url --url https://raw.githubusercontent.com/example/repo/main/crd.yaml --output output/
```
### Import Crossplane CRDs
```bash
# Fetch all Crossplane CRDs and generate a Nickel package
amalgam import url \
--url https://github.com/crossplane/crossplane/tree/main/cluster/crds \
--output crossplane-types/
```
This generates a structured Nickel package:
```
crossplane-types/
βββ mod.ncl # Main module
βββ apiextensions.crossplane.io/
β βββ mod.ncl # Group module
β βββ v1/
β β βββ mod.ncl # Version module
β β βββ composition.ncl # Type definitions
β β βββ compositeresourcedefinition.ncl
β βββ v1beta1/
β βββ ...
βββ pkg.crossplane.io/
βββ ...
```
## π Generated Nickel Output Example
Amalgam automatically resolves Kubernetes type references and generates clean [Nickel](https://nickel-lang.org) code:
```nickel
# Module: composition.apiextensions.crossplane.io
let k8s_io_v1 = import "../../k8s_io/v1/objectmeta.ncl" in
{
Composition = {
apiVersion | optional | String,
kind | optional | String,
metadata | optional | k8s_io_v1.ObjectMeta,
spec | optional | {
compositeTypeRef | {
apiVersion | String,
kind | String,
},
# ... more fields
},
},
}
```
## π― Key Features Explained
### Import Resolution
The tool intelligently detects and resolves Kubernetes type references:
- **Detects**: `io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta`
- **Generates Import**: `let k8s_io_v1 = import "../../k8s_io/v1/objectmeta.ncl" in`
- **Resolves Reference**: `k8s_io_v1.ObjectMeta`
### Extensible Resolver System
Add custom type resolvers using the plugin architecture:
```rust
pub trait ReferenceResolver: Send + Sync {
fn can_resolve(&self, reference: &str) -> bool;
fn resolve(&self, reference: &str, imports: &[Import], context: &ResolutionContext) -> Option<Resolution>;
fn name(&self) -> &str;
}
```
Built-in resolvers:
- `KubernetesResolver` - Handles K8s API types
- `LocalTypeResolver` - Resolves local type references
- Easy to add custom resolvers for other type systems
## π» CLI Commands
### Main Commands
- `import` - Import types from various sources
- `crd` - Import from a CRD file
- `url` - Import from URL (GitHub, raw files)
- `open-api` - Import from OpenAPI spec
- `k8s` - Import from Kubernetes cluster (planned)
- `generate` - Generate code from IR
- `convert` - Convert between formats
- `vendor` - Manage vendored packages
### Options
- `-v, --verbose` - Enable verbose output
- `-d, --debug` - Enable debug output with detailed tracing
## ποΈ Architecture
```
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β amalgam CLI β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Schema Pipeline β
β ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ β
β β CRD β β OpenAPI β β Go β β Protobuf β β
β β Parser β β Parser β β AST β β Parser β β
β ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Intermediate Representation (IR) β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Unified Type System (Algebraic Types) β β
β β - Sum Types (Enums/Unions) β β
β β - Product Types (Structs/Records) β β
β β - Contracts & Refinement Types β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Code Generation β
β ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ β
β β Nickel β β Go β β CUE β β WASM β β
β βGenerator β βGenerator β βGenerator β β Module β β
β ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
```
## π Project Structure
```
amalgam/
βββ Cargo.toml # Workspace definition
βββ crates/
β βββ amalgam-core/ # Core IR and type system
β βββ amalgam-parser/ # Schema parsers (CRD, OpenAPI)
β βββ amalgam-codegen/ # Code generators with resolver system
β βββ amalgam-cli/ # Command-line interface
βββ examples/ # Example configurations
βββ tests/ # Integration tests
```
## π‘ Use Cases
### Kubernetes Configuration Management
Generate type-safe [Nickel](https://nickel-lang.org) configurations from your CRDs:
```bash
# Import your custom CRDs
amalgam import crd --file my-operator-crd.yaml --output types/
# Use in Nickel configurations
let types = import "types/my-operator.ncl" in
let config = {
apiVersion = "example.io/v1",
kind = "MyResource",
metadata = {
name = "example",
},
spec = types.MyResourceSpec & {
# Type-safe configuration with auto-completion
replicas = 3,
# ...
}
}
```
### CrossPlane Composition
Type-safe CrossPlane compositions in Nickel with full IDE support:
```nickel
let crossplane = import "crossplane-types/mod.ncl" in
let composition = crossplane.apiextensions.v1.Composition & {
metadata.name = "my-composition",
spec = {
compositeTypeRef = {
apiVersion = "example.io/v1",
kind = "XDatabase",
},
# Full type checking and validation
}
}
```
## π οΈ Development
### Building
```bash
# Build all crates
cargo build --workspace
# Run tests
cargo test --workspace
# Run with debug logging
cargo run -- --debug import crd --file test.yaml
```
### Testing
The project includes comprehensive test coverage:
- Unit tests for type resolution and parsing
- Integration tests with real CRDs
- Snapshot tests for generated output
- Property-based tests for round-trip conversions
```bash
# Run all tests
cargo test
# Run specific test suite
cargo test --package amalgam-parser
# Update snapshots
cargo test -- --ignored
```
## π€ Contributing
Contributions are welcome! Areas of interest:
- [ ] Additional schema parsers (Protobuf, GraphQL)
- [ ] More code generators (TypeScript, Python)
- [ ] Kubernetes cluster integration
- [ ] Enhanced type inference
- [ ] IDE plugins for generated types
## π License
This project is licensed under the **Apache License 2.0** - see the [LICENSE](LICENSE) file for details.
### Why Apache 2.0?
- β
**Enterprise-friendly** - Widely accepted in corporate environments
- β
**Patent protection** - Includes express patent grants
- β
**Commercial-ready** - Allows building proprietary products and services
- β
**Contribution clarity** - Clear terms for contributions
## π Acknowledgments
- **Generates code for [Nickel](https://nickel-lang.org/)** - A powerful configuration language with contracts and gradual typing
- Inspired by [CUE](https://cuelang.org/) and its approach to configuration
- Uses patterns from [dhall-kubernetes](https://github.com/dhall-lang/dhall-kubernetes)