/** * Value Extractor Tests */ import { afterEach, beforeEach, describe, expect, test } from 'bun:test'; import { existsSync } from 'node:fs'; import { mkdir, rm, writeFile } from 'node:fs/promises'; import { compareExtractedValues, extractAnsibleValues, extractTerraformValues, } from './value-extractor'; const TEST_DIR = './test-value-extractor-temp'; describe('Value Extractor', () => { beforeEach(async () => { if (existsSync(TEST_DIR)) { await rm(TEST_DIR, { recursive: true }); } await mkdir(TEST_DIR, { recursive: true }); }); afterEach(async () => { if (existsSync(TEST_DIR)) { await rm(TEST_DIR, { recursive: true }); } }); describe('extractTerraformValues', () => { test('should extract all terraform values correctly', async () => { const terraformContent = ` resource "proxmox_lxc" "homebridge" { target_node = var.node_name vmid = 2110 hostname = "iot" ostemplate = var.lxc_template_id cores = 2 memory = 1024 network { name = "eth0" bridge = "vmbr0" tag = 192 ip = "192.168.0.110/24" gw = "192.168.0.254" } rootfs { storage = "datacenter" size = "20G" } } `; const terraformPath = `${TEST_DIR}/main.tf`; await writeFile(terraformPath, terraformContent); const values = await extractTerraformValues(terraformPath); expect(values.vmid).toBe(2110); expect(values.hostname).toBe('iot'); expect(values.ip).toBe('192.168.0.110/24'); expect(values.gateway).toBe('192.168.0.254'); expect(values.vlan).toBe(192); expect(values.cores).toBe(2); expect(values.memory).toBe(1024); expect(values.storage).toBe('datacenter'); expect(values.rootfs_size).toBe('20G'); }); test('should handle missing values gracefully', async () => { const terraformContent = ` resource "proxmox_lxc" "homebridge" { vmid = 2110 hostname = "iot" } `; const terraformPath = `${TEST_DIR}/main.tf`; await writeFile(terraformPath, terraformContent); const values = await extractTerraformValues(terraformPath); expect(values.vmid).toBe(2110); expect(values.hostname).toBe('iot'); expect(values.ip).toBeUndefined(); expect(values.cores).toBeUndefined(); }); }); describe('extractAnsibleValues', () => { test('should extract all ansible values correctly', async () => { // Create proper inventory structure await mkdir(`${TEST_DIR}/ansible/inventory/group_vars`, { recursive: true }); // Create group_vars/all.yml with system config (not a playbook) const groupVarsContent = `--- # System-wide variables available to all hosts dns_primary: 192.168.0.1 dns_fallback: 8.8.8.8 1.1.1.1 routing_internal_gateway: 192.168.0.254 `; await writeFile(`${TEST_DIR}/ansible/inventory/group_vars/all.yml`, groupVarsContent); const values = await extractAnsibleValues(`${TEST_DIR}/ansible`); expect(values.dns_primary).toBe('192.168.0.1'); expect(values.dns_fallback).toBe('8.8.8.8 1.1.1.1'); expect(values.gateway).toBe('192.168.0.254'); }); }); describe('compareExtractedValues', () => { test('should pass when all values match', async () => { // Setup test files await mkdir(`${TEST_DIR}/terraform`, { recursive: true }); await mkdir(`${TEST_DIR}/ansible/inventory/group_vars`, { recursive: true }); const terraformContent = ` resource "proxmox_lxc" "homebridge" { vmid = 2110 hostname = "iot" cores = 1 memory = 1024 network { tag = 192 ip = "192.168.0.110/24" gw = "192.168.0.254" } rootfs { storage = "datacenter" size = "20G" } } `; const groupVarsContent = `--- # System-wide variables available to all hosts dns_primary: 192.168.0.1 dns_fallback: 8.8.8.8 1.1.1.1 routing_internal_gateway: 192.168.0.254 `; await writeFile(`${TEST_DIR}/terraform/main.tf`, terraformContent); await writeFile(`${TEST_DIR}/ansible/inventory/group_vars/all.yml`, groupVarsContent); const expectedValues = { terraform: { vmid: 2110, hostname: 'iot', ip: '192.168.0.110/24', gateway: '192.168.0.254', vlan: 192, cores: 1, memory: 1024, storage: 'datacenter', rootfs_size: '20G', }, ansible: { dns_primary: '192.168.0.1', dns_fallback: '8.8.8.8 1.1.1.1', gateway: '192.168.0.254', }, }; const result = await compareExtractedValues(TEST_DIR, expectedValues); expect(result.pass).toBe(true); expect(result.mismatches).toHaveLength(0); }); test('should detect mismatches when values differ', async () => { // Setup test files with wrong values await mkdir(`${TEST_DIR}/terraform`, { recursive: true }); await mkdir(`${TEST_DIR}/ansible/inventory/group_vars`, { recursive: true }); const terraformContent = ` resource "proxmox_lxc" "homebridge" { vmid = 9999 hostname = "wrong-host" cores = 1 } `; const groupVarsContent = `--- # System-wide variables with wrong values dns_primary: 1.1.1.1 `; await writeFile(`${TEST_DIR}/terraform/main.tf`, terraformContent); await writeFile(`${TEST_DIR}/ansible/inventory/group_vars/all.yml`, groupVarsContent); const expectedValues = { terraform: { vmid: 2110, hostname: 'iot', cores: 1, }, ansible: { dns_primary: '192.168.0.1', }, }; const result = await compareExtractedValues(TEST_DIR, expectedValues); expect(result.pass).toBe(false); expect(result.mismatches).toHaveLength(3); // Check specific mismatches const vmidMismatch = result.mismatches.find((m) => m.path === 'terraform.vmid'); expect(vmidMismatch).toBeDefined(); expect(vmidMismatch?.expected).toBe(2110); expect(vmidMismatch?.actual).toBe(9999); const hostnameMismatch = result.mismatches.find((m) => m.path === 'terraform.hostname'); expect(hostnameMismatch).toBeDefined(); expect(hostnameMismatch?.expected).toBe('iot'); expect(hostnameMismatch?.actual).toBe('wrong-host'); const dnsMismatch = result.mismatches.find((m) => m.path === 'ansible.dns_primary'); expect(dnsMismatch).toBeDefined(); expect(dnsMismatch?.expected).toBe('192.168.0.1'); expect(dnsMismatch?.actual).toBe('1.1.1.1'); }); }); });