13 - Local Testing
With CI running, let's test the plugin locally using the formae CLI. This lets you verify your plugin works end-to-end before deploying it.
Install the Plugin
Build and install the plugin to your local formae plugins directory:
make install
This installs the plugin to ~/.pel/formae/plugins/sftp/v0.1.0/.
Start SFTP Server
Start the test SFTP server:
docker run -d --name sftp-test -p 2222:22 atmoz/sftp testuser:testpass:::upload
Initialize a Test Project
Use formae project init to scaffold a new project that uses your plugin. Since your plugin's PKL schema hasn't been published to the formae package registry yet, use the @local suffix to resolve it from your local installation:
mkdir sftp-test-project && cd sftp-test-project
formae project init --include sftp@local
The @local suffix tells formae to resolve the package from your local plugin directory (~/.pel/formae/plugins/) instead of the package registry at hub.platform.engineering.
This creates a PklProject file with your plugin configured as a local dependency:
amends "pkl:Project"
dependencies {
["formae"] {
uri = "package://hub.platform.engineering/plugins/pkl/schema/pkl/formae/formae@0.80.0"
}
// Local plugin resolved from ~/.pel/formae/plugins/SFTP/v0.1.0/schema/pkl/
["sftp"] = import("/home/you/.pel/formae/plugins/SFTP/v0.1.0/schema/pkl/PklProject")
}
The formae core dependency always comes from the package registry, while your plugin (marked with @local) is resolved from the local installation directory.
You can mix published and local packages. For example, if your plugin depends on AWS resources for testing:
formae project init --include aws --include sftp@local
This resolves aws from the registry and sftp from your local installation.
Create a Test Forma
Edit the generated main.pkl to test your plugin:
amends "@formae/forma.pkl"
import "@formae/formae.pkl"
import "@sftp/sftp.pkl"
forma {
new formae.Stack {
label = "local-test"
description = "Local testing stack"
}
new formae.Target {
label = "sftp-local"
config = new sftp.Config {
url = "sftp://localhost:2222"
}
}
new sftp.File {
label = "hello"
path = "/upload/hello.txt"
content = "Hello from formae!"
permissions = "0644"
}
}
Start the Agent
In a separate terminal, start the formae agent:
SFTP_USERNAME=testuser SFTP_PASSWORD=testpass formae agent start
The agent discovers your plugin and starts it. You should see the following message in the logs:
Plugin registered: namespace=SFTP resources=1
Apply the Forma
With the agent running, apply your forma:
formae apply --mode reconcile main.pkl
Command will
├── create target sftp-local
└── create resource hello
├── of type SFTP::Files::File
└── in stack local-test
This operation will create 1 target(s) and create 1 resource(s).
Do you want to continue? (Y): Y
┌──────────────┬─────────┬─────────┬────────┬─────────┬──────┐
│ ID │ Command │ Status │ Change │ Success │ Fail │
├──────────────┼─────────┼─────────┼────────┼─────────┼──────┤
│ 38jmr9w3J... │ apply │ Success │ 2 │ 2 │ 0 │
└──────────────┴─────────┴─────────┴────────┴─────────┴──────┘
Verify the Resource
Check that the file was created:
formae inventory resources --query="stack:local-test"
┌───────────────────┬────────────┬───────────────────┬───────┐
│ NativeID │ Stack │ Type │ Label │
├───────────────────┼────────────┼───────────────────┼───────┤
│ /upload/hello.txt │ local-test │ SFTP::Files::File │ hello │
└───────────────────┴────────────┴───────────────────┴───────┘
Or connect to the SFTP server directly:
sshpass -p testpass sftp -P 2222 testuser@localhost
sftp> ls /upload/
hello.txt
sftp> cat /upload/hello.txt
Hello from formae!
Clean Up
Destroy the resources by passing the same forma file:
formae destroy --watch main.pkl
Stop the test server:
docker rm -f sftp-test
Next: 14 - Observability - Logging and metrics for plugins