Plugin Developer Guide
Plugin Developer Guide
Overview
Rundeck plugins allow you to extend Rundeck's functionality by adding new capabilities for job execution, notifications, logging, resource discovery, and more. This guide will help you develop custom plugins to meet your specific automation needs.
Plugin Types Available:
- Node Steps - Execute actions on remote nodes
- Workflow Steps - Execute workflow-level orchestration
- Node Executors - Define how to execute commands on nodes
- File Copiers - Define how to copy files to nodes
- Resource Model Sources - Provide node inventory from external systems
- Notifications - Send notifications on job events
- Log Filters - Transform or capture log output
- Storage Plugins - Store key/password data in external systems
- And many more...
Choosing Your Plugin Development Approach
Rundeck supports three different methods for developing plugins, each with its own strengths and use cases.
Quick Comparison
| Feature | Java Plugins | Script Plugins | Groovy Plugins |
|---|---|---|---|
| Development Language | Java | Any scripting language | Groovy |
| Best For | Complex logic, performance | Quick prototypes, shell commands | Medium complexity |
| Learning Curve | Higher | Lower | Medium |
| Available Plugin Types | All types | Most types | Notification, Logging |
| IDE Support | Excellent | N/A | Good |
| Distribution | JAR file | ZIP file | ZIP file |
| Dependencies | Maven/Gradle | System dependencies | Groovy libraries |
| Performance | Best | Good | Good |
When to Use Java Plugins
Choose Java when you need:
- Maximum performance and efficiency
- Complex business logic or algorithms
- Integration with Java libraries or frameworks
- Type safety and compile-time error checking
- Full access to Rundeck's internal APIs
- Professional IDE support and debugging
Common Use Cases:
- Complex workflow orchestration
- Integration with enterprise systems (APIs, databases)
- Custom authentication or authorization
- Performance-critical operations
- Plugins that will be widely distributed
Get Started: Java Plugin Development Guide
When to Use Script Plugins
Choose Script plugins when you:
- Want to prototype quickly
- Already have working shell/Python/Ruby scripts
- Need simple command execution or file operations
- Want minimal setup and configuration
- Prefer not to set up a Java development environment
Common Use Cases:
- Wrapping existing scripts or command-line tools
- Simple file operations or system commands
- Quick automation tasks
- Prototyping before developing a Java plugin
- Environment-specific customizations
Get Started: Script Plugin Development Guide
When to Use Groovy Plugins
Choose Groovy when you need:
- Dynamic scripting capabilities with Java ecosystem access
- Notification or logging functionality
- Balance between script flexibility and Java power
- Ability to use Java libraries without full Java setup
Limitations:
- Currently only supports Notification and Logging plugin types
Get Started: Groovy Plugin Development Guide
Decision Tree
Need a plugin? Start here:
│
├─ Is it for Notifications or Logging only?
│ ├─ Yes → Use Groovy or Java plugins
│ └─ No → Continue...
│
├─ Do you have existing shell/Python/Ruby scripts?
│ ├─ Yes → Start with Script plugins
│ └─ No → Continue...
│
├─ Need maximum performance or complex logic?
│ ├─ Yes → Use Java plugins
│ └─ No → Continue...
│
├─ Comfortable with Java development?
│ ├─ Yes → Use Java plugins (most flexible)
│ └─ No → Use Script plugins (easiest to start)
Getting Started Steps
1. Identify Your Plugin Type
Determine which plugin service type you need to implement based on what you want to extend in Rundeck.
2. Choose Your Development Method
Based on your requirements, select Java, Script, or Groovy plugins.
3. Set Up Your Development Environment
For Java Plugins:
- Install JDK 11 or later
- Set up Maven or Gradle
- Add Rundeck dependencies
- Configure your IDE
For Script Plugins:
- Install your scripting language runtime
- Create plugin directory structure
- Write your script
- Create plugin metadata
For Groovy Plugins:
- Install Groovy runtime
- Create plugin directory structure
- Write your Groovy script
- Create plugin metadata
4. Develop and Test
Follow the specific guide for your chosen method:
5. Package and Deploy
- Java: Build JAR file with proper manifest
- Script/Groovy: Create ZIP file with metadata
- Deploy to Rundeck's
libextdirectory - Restart Rundeck or use dynamic plugin loading (if enabled)
Available Plugin Types
Rundeck supports many different types of plugins. Each type serves a specific purpose in the automation workflow:
Job Execution Plugins
- Node Steps - Execute once per target node
- Workflow Steps - Execute once per job invocation
- Node Executors - Control how commands execute on nodes
- File Copiers - Control how files are copied to nodes
Resource Discovery
- Resource Model Sources - Provide node inventory data
- Resource Format Parsers - Parse resource data formats
- Resource Format Generators - Generate resource data formats
Logging and Output
- Log Filters - Transform or capture log output
- Logging Plugins - Stream logs to external systems
- Content Converters - Render log output as HTML/Markdown
Notifications and Events
- Notification Plugins - Send notifications on job events
- Webhook Plugins - Receive and process webhooks
- Audit Event Listeners - Respond to audit events
Security and Storage
- Storage Plugins - Store keys/passwords in external systems
- Storage Converter Plugins - Encrypt/decrypt stored data
- User Group Source Plugins - Integrate with authentication systems
Orchestration and Control
- Orchestrator Plugins - Control node execution order
- Workflow Strategy Plugins - Define custom workflow execution patterns
Configuration and Options
- Option Values Plugins - Provide dynamic option values
- File Upload Plugins - Handle file uploads for job options
Lifecycle Plugins
- Execution Lifecycle Plugins - Hook into execution lifecycle events
- Job Lifecycle Plugins - Hook into job definition lifecycle
User Interface
- UI Plugins - Add custom UI components
Common Plugin Development Topics
Configuration Properties
Learn how to define configuration properties for your plugin:
- Plugin Properties Reference - Property types, scopes, and rendering options
- Property Annotations (Java plugins)
- Plugin Metadata (Script/Groovy plugins)
Localization and Icons
Make your plugin user-friendly:
- Plugin Localization - Translate plugin UI text
- Plugin Icons - Add custom icons
Plugin Groups
Organize related plugins:
- Plugin Groups - Group related plugins in the UI
Plugin Development Best Practices
Performance and Scale Considerations
Your Plugin Will Be Used at Scale
Plugins that work fine in development can cause serious performance issues in production environments with thousands of jobs and executions. You are responsible for ensuring your plugin performs efficiently.
Why Performance Matters
Rundeck environments vary dramatically in size:
- Small: 10-100 jobs, hundreds of executions
- Medium: 100-1,000 jobs, thousands of executions
- Large: 1,000-5,000 jobs, tens of thousands of executions
- Enterprise: 10,000+ jobs, millions of executions
A plugin that works perfectly with 50 jobs may bring Rundeck to its knees with 5,000 jobs.
Common Performance Pitfalls
1. Unbounded Queries
// BAD - Loads all executions in memory
List<Execution> allExecutions = executionService.getAllExecutions(project);
// GOOD - Page results, process in batches
int pageSize = 100;
for (int offset = 0; offset < totalCount; offset += pageSize) {
List<Execution> batch = executionService.getExecutions(project, pageSize, offset);
processBatch(batch);
}
2. N+1 Query Problems
// BAD - Separate query for each job
for (Job job : jobs) {
List<Execution> executions = getExecutionsForJob(job.id); // Query per job!
process(job, executions);
}
// GOOD - Single batched query
List<Execution> allExecutions = getExecutionsForJobs(jobIds);
Map<String, List<Execution>> executionsByJob = groupByJobId(allExecutions);
for (Job job : jobs) {
process(job, executionsByJob.get(job.id));
}
3. Inefficient Loops
// BAD - Rebuilds list on every iteration
List<String> results = new ArrayList<>();
for (Node node : nodes) {
results = Stream.concat(results.stream(), processNode(node).stream())
.collect(Collectors.toList()); // Rebuilding entire list each time!
}
// GOOD - Add to existing list
List<String> results = new ArrayList<>();
for (Node node : nodes) {
results.addAll(processNode(node)); // Simple append
}
4. Holding Resources Too Long
// BAD - Connection held for entire operation
Connection conn = getConnection();
for (int i = 0; i < 10000; i++) {
processRecord(conn, i); // Connection held during all processing
}
conn.close();
// GOOD - Use connection only when needed
for (int i = 0; i < 10000; i++) {
processRecord(i); // Processing happens without connection
}
// Connection auto-closed by try-with-resources when actually used
5. Excessive Logging
// BAD - Logs in tight loop
for (Execution exec : executions) {
logger.debug("Processing execution: " + exec.getId() + " details: " + exec.toString());
}
// GOOD - Log summaries
logger.debug("Processing {} executions", executions.size());
if (logger.isTraceEnabled()) {
executions.forEach(e -> logger.trace("Execution: {}", e.getId()));
}
Performance Testing
Test with realistic data:
# Generate test data at scale
# Create 1000 jobs
for i in {1..1000}; do
rd jobs create -p TestProject -n "TestJob$i" ...
done
# Generate execution history
# Run jobs repeatedly to simulate real usage
Monitor during testing:
- CPU usage (server and client)
- Memory usage (heap, GC frequency)
- Response times
- Database query counts
- Thread pool utilization
- Log file growth
Tools:
- JProfiler / YourKit for Java profiling
- Chrome DevTools for UI plugin performance
- Rundeck's metrics endpoints (
/metrics) - Database slow query logs
Plugin-Specific Considerations
Node Step / Workflow Step Plugins:
- May execute thousands of times per job
- Keep execution logic lightweight
- Cache expensive operations (API calls, file reads)
- Use connection pooling for external services
Notification Plugins:
- May fire for every execution (high volume)
- Implement rate limiting for external services
- Queue and batch notifications when possible
- Handle failures gracefully (don't block execution completion)
Resource Model Source Plugins:
- May manage thousands of nodes
- Cache node data appropriately
- Implement efficient filtering
- Stream results instead of loading all in memory
UI Plugins:
- API calls multiply across all users
- Cache aggressively in browser
- Limit auto-refresh frequency
- Use Web Workers for heavy processing
- See UI Plugins Performance for details
Option Values Plugins:
- May be called frequently as users configure jobs
- Cache API results
- Implement timeouts
- Return reasonable result set sizes (< 1000 values)
Performance Checklist
Before releasing your plugin:
- [ ] Test with production-scale data (not just 10 test jobs)
- [ ] Implement pagination for large result sets
- [ ] Cache expensive operations appropriately
- [ ] Use efficient data structures (avoid repeated list rebuilding)
- [ ] Implement timeouts for external calls
- [ ] Handle large volumes gracefully (batching, streaming)
- [ ] Add configurable limits (max results, max retries, timeouts)
- [ ] Monitor resource usage (memory, CPU, connections)
- [ ] Log at appropriate levels (not debug in production)
- [ ] Profile your code under load
- [ ] Document performance characteristics in README
- [ ] Document recommended environment sizes/limits
When Performance Issues Arise
If users report performance problems:
Ask for environment details
- How many jobs?
- How many executions?
- How many nodes?
- Rundeck version and configuration
Reproduce at scale
- Generate test data matching user's environment
- Use profiling tools to identify bottlenecks
Optimize incrementally
- Fix the biggest bottleneck first
- Measure improvement after each change
- Test at scale again
Document limitations
- Update README with tested scale limits
- Provide configuration recommendations
- Warn about known performance characteristics
Security Considerations
Credentials and Secrets:
- Use Rundeck's Key Storage for sensitive data
- Never log credentials or secrets
- Use secure credential types (
@PluginPropertywithrenderingOptions)
Input Validation:
- Validate all user inputs
- Sanitize data before executing commands
- Prevent injection attacks (command, SQL, script)
External Connections:
- Validate SSL/TLS certificates
- Use secure protocols (HTTPS, SSH)
- Implement timeouts to prevent hanging
- Handle connection failures gracefully
Error Messages:
- Don't expose sensitive information in errors
- Log detailed errors server-side
- Show generic errors to users
Additional Resources
Tools and Utilities
- Plugin Bootstrap Tool - Generate complete plugin projects in seconds (RECOMMENDED)
- Supports Java, Script, and UI plugins
- Creates project structure, build files, template code, and tests
- Get started immediately with working plugin scaffold
- Password Utility - Encrypt passwords for configuration
- Rundeck Plugin Archetype - Maven archetype for Java plugins
API Documentation
- API Reference - REST API documentation
- Java API Documentation - JavaDoc for core classes
Community and Support
- Plugin Repository - Browse and download community plugins
- GitHub Discussions - Ask questions and share knowledge
- Rundeck Slack - Chat with the community
Next Steps
- Choose your approach: Review the comparison table above
- Use the Plugin Bootstrap Tool (Recommended): Generate a complete plugin project instantly
- See Plugin Bootstrap Tool for commands and examples
- Saves hours of setup time
- Read the specific guide:
- Select a plugin type: Pick from the available types
- Start developing: Implement your plugin logic in the generated scaffold
- Test and deploy: Build, test, and deploy to Rundeck
Quick Start
The fastest way to start: Use the Plugin Bootstrap Tool to generate your project, then follow the specific guide for your chosen approach.
Good luck with your plugin development! If you have questions, reach out to the Rundeck community.