03 - Target Configuration
This section explains how plugins receive target configuration.
What is a Target?
A target uniquely identifies a deployment location for your infrastructure. Think of it as "where" your resources live:
- For AWS: a region like
us-east-1 - For Kubernetes: a cluster endpoint
- For SFTP: a server URL like
sftp://files.example.com:22
Targets are stored in formae's database in plaintext, so they must never contain secrets. The target identifies the location; credentials are provided separately.
Target vs Credentials
| Target | Credentials | |
|---|---|---|
| Purpose | Identifies deployment location | Authenticates to the location |
| Storage | Plaintext in database | Environment variables / secrets |
| Example (SFTP) | sftp://files.example.com:22 |
Username, password |
| Example (AWS) | us-east-1 |
Access key, secret key |
Target Configuration in Requests
Every request to your plugin includes a TargetConfig field:
type CreateRequest struct {
ResourceType string
Properties json.RawMessage
TargetConfig json.RawMessage // <-- Target configuration (no secrets!)
}
Define the Target Config Type
For our SFTP plugin, the target is just the server URL. Add this to sftp.go:
// TargetConfig holds SFTP target settings.
// Contains only the deployment location, NOT credentials.
type TargetConfig struct {
URL string `json:"url"` // sftp://host:port
}
func parseTargetConfig(data json.RawMessage) (*TargetConfig, error) {
var cfg TargetConfig
if err := json.Unmarshal(data, &cfg); err != nil {
return nil, fmt.Errorf("invalid target config: %w", err)
}
if cfg.URL == "" {
return nil, fmt.Errorf("target config missing 'url'")
}
return &cfg, nil
}
func parseURL(sftpURL string) (host string, port string, err error) {
u, err := url.Parse(sftpURL)
if err != nil {
return "", "", fmt.Errorf("invalid URL: %w", err)
}
if u.Scheme != "sftp" {
return "", "", fmt.Errorf("expected sftp:// URL, got %s://", u.Scheme)
}
host = u.Hostname()
port = u.Port()
if port == "" {
port = "22"
}
return host, port, nil
}
Update sftp.go
Add the target configuration and credentials code. Update the imports and add the helper functions:
package main
import (
"context"
"encoding/json"
"errors"
"fmt"
"net/url"
"os"
"github.com/platform-engineering-labs/formae/pkg/plugin"
"github.com/platform-engineering-labs/formae/pkg/plugin/resource"
)
// TargetConfig holds SFTP target settings.
// Contains only the deployment location, NOT credentials.
type TargetConfig struct {
URL string `json:"url"` // sftp://host:port
}
func parseTargetConfig(data json.RawMessage) (*TargetConfig, error) {
var cfg TargetConfig
if err := json.Unmarshal(data, &cfg); err != nil {
return nil, fmt.Errorf("invalid target config: %w", err)
}
if cfg.URL == "" {
return nil, fmt.Errorf("target config missing 'url'")
}
return &cfg, nil
}
func parseURL(sftpURL string) (host string, port string, err error) {
u, err := url.Parse(sftpURL)
if err != nil {
return "", "", fmt.Errorf("invalid URL: %w", err)
}
if u.Scheme != "sftp" {
return "", "", fmt.Errorf("expected sftp:// URL, got %s://", u.Scheme)
}
host = u.Hostname()
port = u.Port()
if port == "" {
port = "22"
}
return host, port, nil
}
func getCredentials() (username, password string, err error) {
username = os.Getenv("SFTP_USERNAME")
password = os.Getenv("SFTP_PASSWORD")
if username == "" || password == "" {
return "", "", fmt.Errorf("SFTP_USERNAME and SFTP_PASSWORD must be set")
}
return username, password, nil
}
// ... rest of Plugin implementation
Verify
To verify that the target configuration code compiles correctly:
cd formae-plugin-sftp
make build