npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@celilo/terraform-fake

v0.3.1

Published

Fake infrastructure backends you can point a real Terraform provider at. Ships a Proxmox /api2/json fake built from an observed provider lifecycle — including the response types that panic telmate/proxmox if you get them wrong — with provisioning left to

Downloads

572

Readme

@celilo/terraform-fake

A fake Proxmox API you can point a real Terraform provider at.

Not a mock that returns 200 OK. It holds state, so a terraform apply creates something, a second apply reports no changes, and a destroy removes it — which is the part that actually catches bugs, because a fake that always says yes lets a broken plan look like a working one.

bun add -d @celilo/terraform-fake     # or npm / pnpm

Why this exists

Testing Terraform against a real hypervisor is slow, expensive, and hard to get into a known state. Testing it against nothing at all is the usual alternative, and it means the provider interaction — the part most likely to break — is the one part never exercised.

The endpoint list here is not a reading of the Proxmox API docs. It is what telmate/proxmox and one production consumer were observed to call across a full create → re-apply → destroy cycle, captured by pointing the real provider at a logging server and implementing whatever it asked for next.

Usage

import { createProxmoxFake } from '@celilo/terraform-fake';

const fake = createProxmoxFake({
  tls: { key: myKeyPem, cert: myCertPem },   // self-signed is fine
  nodes: [{ name: 'pve1', cores: 8, memoryBytes: 16 * 1024 ** 3, diskBytes: 500 * 1024 ** 3 }],
});

const port = await fake.listen(8006);
// ... run terraform against https://127.0.0.1:8006/api2/json ...
await fake.close();

Point Terraform at it:

provider "proxmox" {
  pm_api_url          = "https://127.0.0.1:8006/api2/json"
  pm_api_token_id     = "you@pve!testing"
  pm_api_token_secret = "any-value"
  pm_tls_insecure     = true          # the cert is self-signed
}

The token's user does not need to exist in any config you write — the fake reports whoever your token says you are.

Making the guests real

By default nothing is provisioned: the fake is bookkeeping, which is all you need to exercise a provider. If you want a create to produce an actual machine — a container, a VM, a process — supply a provisioner:

const fake = createProxmoxFake({
  tls,
  provisioner: {
    async createGuest(guest) {
      // guest.vmid, guest.hostname, guest.config (the raw create parameters,
      // including net0 with the address Terraform asked for)
      await startSomethingReal(guest);
    },
    async destroyGuest(guest) {
      await removeIt(guest.vmid);
    },
  },
});

This seam is deliberate. Everything environment-specific — Docker, networks, SSH keys, naming conventions — belongs to you, not to this package.

Asserting on what happened

fake.state is the state store, so a test can check what a plan actually did:

const guest = fake.state.findGuest(203);
expect(guest?.config.net0).toContain('ip=10.0.20.13/24');

Things that will bite you if you build this yourself

Each of these was found by a provider crash, and each is handled here.

The config read-back must be re-typed. A create arrives form-encoded, so every value is a string. Echo it back and the provider panics — it type-asserts without the comma-ok form, so a mismatch takes down the plugin rather than producing an error:

panic: interface conversion: interface {} is string, not float64

cpulimit is the trap. The obvious repair — coerce anything numeric-looking — panics the other way, because cpulimit is semantically a number and read as a string. The exact field list lives in config-types.ts.

/cluster/resources must honour ?type=. The provider fetches ?type=vm and then reads vmid as a float on every row returned. A node row has no vmid, so answering an unfiltered list crashes it.

State must outlive a single apply. Restart the fake between applies and its guests vanish, so the provider concludes the resource was deleted and recreates it. Correct provider behaviour; a badly misleading test.

The first call is /access/users. Not /version. A fake that omits it fails before doing anything, with an error naming neither.

Scope

Supported: the proxmox_lxc lifecycle (create, read, update, delete, start, stop), cluster resources, nodes, storage, tasks, access and pools.

proxmox_vm_qemu is supported for clone-from-template, which is the only way a VM gets created in practice: create and destroy are clean, and a re-apply has two known residual diffs (disk.format and a synthesized startup_shutdown block) that are provider-schema artifacts rather than read-back errors.

It did have its own type map and its own cpulimit-shaped surprise, exactly as predicted: agent reads as a STRING even though its value is 1, because Proxmox packs options into it. Coercing it panics in config__qemu__guestagent.go the same way not coercing cores panics in config__qemu__cpu.go.

Two more VM-only behaviours worth knowing if you build this yourself:

  • A VM's address is discovered through the guest agent (/agent/network-get-interfaces), not from net0. The provider polls it after start and blocks until it answers.
  • Proxmox reads disks back differently than they are written. local-lvm:20 on the way in is an allocation request; on the way out it is local-lvm:vm-9200-disk-0,size=20G. Echo the request form and the provider reads a 20GB disk as 0T and proposes a change on every plan.

Verified against telmate/[email protected] and Terraform 1.7.1. Newer provider versions may assert different types — re-extract rather than assume.

License

MIT