coolify/tests/Unit/Rules/ValidCloudInitYamlTest.php
Andras Bacsai d93a13eeee feat: add YAML validation for cloud-init scripts
Add ValidCloudInitYaml validation rule to ensure cloud-init scripts
are properly formatted before saving. The validator supports:
- Cloud-config YAML (with or without #cloud-config header)
- Bash scripts (starting with #!)
- Empty/null values (optional field)

Uses Symfony YAML parser to validate YAML syntax and provides
detailed error messages when validation fails.

Added comprehensive unit tests covering:
- Valid cloud-config with/without header
- Valid bash scripts
- Invalid YAML syntax detection
- Complex multi-section cloud-config

Applied validation to:
- ByHetzner component (server creation)
- CloudInitScriptForm component (script management)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 13:56:55 +02:00

174 lines
3.4 KiB
PHP

<?php
use App\Rules\ValidCloudInitYaml;
it('accepts valid cloud-config YAML with header', function () {
$rule = new ValidCloudInitYaml;
$valid = true;
$script = <<<'YAML'
#cloud-config
users:
- name: demo
groups: sudo
shell: /bin/bash
packages:
- nginx
- git
runcmd:
- echo "Hello World"
YAML;
$rule->validate('script', $script, function ($message) use (&$valid) {
$valid = false;
});
expect($valid)->toBeTrue();
});
it('accepts valid cloud-config YAML without header', function () {
$rule = new ValidCloudInitYaml;
$valid = true;
$script = <<<'YAML'
users:
- name: demo
groups: sudo
packages:
- nginx
YAML;
$rule->validate('script', $script, function ($message) use (&$valid) {
$valid = false;
});
expect($valid)->toBeTrue();
});
it('accepts valid bash script with shebang', function () {
$rule = new ValidCloudInitYaml;
$valid = true;
$script = <<<'BASH'
#!/bin/bash
apt update
apt install -y nginx
systemctl start nginx
BASH;
$rule->validate('script', $script, function ($message) use (&$valid) {
$valid = false;
});
expect($valid)->toBeTrue();
});
it('accepts empty or null script', function () {
$rule = new ValidCloudInitYaml;
$valid = true;
$rule->validate('script', '', function ($message) use (&$valid) {
$valid = false;
});
expect($valid)->toBeTrue();
$rule->validate('script', null, function ($message) use (&$valid) {
$valid = false;
});
expect($valid)->toBeTrue();
});
it('rejects invalid YAML format', function () {
$rule = new ValidCloudInitYaml;
$valid = true;
$errorMessage = '';
$script = <<<'YAML'
#cloud-config
users:
- name: demo
groups: sudo
invalid_indentation
packages:
- nginx
YAML;
$rule->validate('script', $script, function ($message) use (&$valid, &$errorMessage) {
$valid = false;
$errorMessage = $message;
});
expect($valid)->toBeFalse();
expect($errorMessage)->toContain('YAML');
});
it('rejects script that is neither bash nor valid YAML', function () {
$rule = new ValidCloudInitYaml;
$valid = true;
$errorMessage = '';
$script = <<<'INVALID'
this is not valid YAML
and has invalid indentation:
- item
without proper structure {
INVALID;
$rule->validate('script', $script, function ($message) use (&$valid, &$errorMessage) {
$valid = false;
$errorMessage = $message;
});
expect($valid)->toBeFalse();
expect($errorMessage)->toContain('bash script');
});
it('accepts complex cloud-config with multiple sections', function () {
$rule = new ValidCloudInitYaml;
$valid = true;
$script = <<<'YAML'
#cloud-config
users:
- name: coolify
groups: sudo, docker
shell: /bin/bash
sudo: ['ALL=(ALL) NOPASSWD:ALL']
ssh_authorized_keys:
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQ...
packages:
- docker.io
- docker-compose
- git
- curl
package_update: true
package_upgrade: true
runcmd:
- systemctl enable docker
- systemctl start docker
- usermod -aG docker coolify
- echo "Server setup complete"
write_files:
- path: /etc/docker/daemon.json
content: |
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
YAML;
$rule->validate('script', $script, function ($message) use (&$valid) {
$valid = false;
});
expect($valid)->toBeTrue();
});