Skip to content

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