Skip to content
Merged

070 #21

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ BOLT_COMMAND_WHITELIST_ALLOW_ALL=false
BOLT_COMMAND_WHITELIST=["ls","pwd","whoami","uptime"]
BOLT_EXECUTION_TIMEOUT=300000

# Ansible integration (optional)
ANSIBLE_ENABLED=false
ANSIBLE_PROJECT_PATH=.
ANSIBLE_INVENTORY_PATH=inventory/hosts
ANSIBLE_EXECUTION_TIMEOUT=300000

# PuppetDB integration (optional)
PUPPETDB_ENABLED=false
PUPPETDB_SERVER_URL=
Expand Down
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</td>
<td>
<h3>Classic Infrastructures Command & Control Awesomeness</h3>
<p>Pabawi is a web frontend for infrastructure management, inventory and remote execution. It currently provides integrations with Puppet, Bolt, PuppetDB, and Hiera. It supports both Puppet Enterprise and Open Source Puppet / OpenVox. It provides a unified web interface for managing infrastructure, executing commands, viewing system information, and tracking operations across your entire environment.</p>
<p>Pabawi is a web frontend for infrastructure management, inventory and remote execution. It currently provides integrations with Puppet, Bolt, Ansible, PuppetDB, and Hiera. It supports both Puppet Enterprise and Open Source Puppet / OpenVox. It provides a unified web interface for managing infrastructure, executing commands, viewing system information, and tracking operations across your entire environment.</p>
</td>
</tr>
</table>
Expand All @@ -22,6 +22,7 @@
- [Screenshots](#screenshots)
- [Prerequisites](#prerequisites)
- [Bolt Integration](#bolt-integration)
- [Ansible Integration](#ansible-integration)
- [PuppetDB Integration](#puppetdb-integration)
- [PuppetServer Integration](#puppetserver-integration)
- [Hiera Integration](#hiera-integration)
Expand Down Expand Up @@ -126,6 +127,13 @@ To have an idea of Pabawi awesomeness, here some random screenshots
- Any required SSH keys used in Bolt configuration
- For details: [Bolt Setup](docs/integrations/bolt.md)

### Ansible Integration

- Ansible CLI installed (`ansible` and `ansible-playbook`)
- A valid local Ansible inventory file
- SSH (or configured Ansible transport) access to target nodes
- For details: [Ansible Setup](docs/integrations/ansible.md)

### PuppetDB Integration

- Network access to PuppetDB port 8081
Expand Down Expand Up @@ -201,7 +209,7 @@ For comprehensive Docker deployment instructions including all integrations, see

Pabawi uses a `.env` file for configuration. Use `backend/.env.example` as reference.

For detailed configuration options including Bolt, PuppetDB, PuppetServer, and Hiera integration settings, please refer to the [Configuration Guide](docs/configuration.md).
For detailed configuration options including Bolt, Ansible, PuppetDB, PuppetServer, and Hiera integration settings, please refer to the [Configuration Guide](docs/configuration.md).

For API details, see the [Integrations API Documentation](docs/integrations-api.md).

Expand All @@ -219,7 +227,7 @@ For details of the repository files and configurations check the [Repository Str

### Planned Features

- **Additional Integrations**: Ansible, Tiny Puppet
- **Additional Integrations**: Tiny Puppet
- **Additional Integrations (to evaluate)**: Terraform, AWS CLI, Azure CLI, Kubernetes, Choria, Icinga
- **Scheduled Executions**: Cron-like scheduling for recurring tasks
- **Custom Dashboards**: User-configurable dashboard widgets
Expand All @@ -229,6 +237,8 @@ For details of the repository files and configurations check the [Repository Str

### Version History

- **v0.7.0**: Ansible Integration. Used classed aware hiera lookups
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in version history description: "Used classed aware hiera lookups" should be "Class-aware Hiera lookups" or "Uses class-aware Hiera lookups".

Suggested change
- **v0.7.0**: Ansible Integration. Used classed aware hiera lookups
- **v0.7.0**: Ansible Integration. Uses class-aware Hiera lookups

Copilot uses AI. Check for mistakes.
- **v0.6.0**: Code consolidation and fixing
- **v0.5.0**: Report filtering, puppet run history visualization, enhanced expert mode with frontend logging
- **v0.4.0**: Hiera integration, puppetserver CA management removal, enhanced plugin architecture
- **v0.3.0**: Puppetserver integration, interface enhancements
Expand Down Expand Up @@ -262,6 +272,7 @@ This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENS
#### Integration Setup

- [Bolt Setup](docs/integrations/bolt.md) - Bolt configuration guide
- [Ansible Setup](docs/integrations/ansible.md) - Ansible configuration guide
- [Hiera Setup](docs/integrations/hiera.md) - Hiera configuration guide
- [PuppetDB Integration Setup](docs/integrations/puppetdb.md) - PuppetDB configuration guide
- [Puppetserver Setup](docs/integrations/puppetserver.md) - Puppetserver configuration guide
Expand Down
6 changes: 6 additions & 0 deletions backend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ BOLT_COMMAND_WHITELIST_ALLOW_ALL=false
BOLT_COMMAND_WHITELIST=["ls","pwd","whoami"]
BOLT_EXECUTION_TIMEOUT=300000

# Ansible integration configuration
# ANSIBLE_ENABLED=true
# ANSIBLE_PROJECT_PATH=/path/to/your/ansible/project
# ANSIBLE_INVENTORY_PATH=inventory/hosts
# ANSIBLE_EXECUTION_TIMEOUT=300000

# Logging configuration (v0.5.0+)
# LOG_LEVEL controls backend logging verbosity
# Options: error, warn, info, debug
Expand Down
2 changes: 1 addition & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "backend",
"version": "0.6.0",
"version": "0.7.0",
"description": "Backend API server for Pabawi",
"main": "dist/server.js",
"scripts": {
Expand Down
31 changes: 31 additions & 0 deletions backend/src/config/ConfigService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ export class ConfigService {
* Parse integrations configuration from environment variables
*/
private parseIntegrationsConfig(): {
ansible?: {
enabled: boolean;
projectPath: string;
inventoryPath?: string;
timeout?: number;
};
puppetdb?: {
enabled: boolean;
serverUrl: string;
Expand Down Expand Up @@ -106,6 +112,18 @@ export class ConfigService {
} {
const integrations: ReturnType<typeof this.parseIntegrationsConfig> = {};

// Parse Ansible configuration
if (process.env.ANSIBLE_ENABLED === "true") {
integrations.ansible = {
enabled: true,
projectPath: process.env.ANSIBLE_PROJECT_PATH ?? process.cwd(),
inventoryPath: process.env.ANSIBLE_INVENTORY_PATH,
timeout: process.env.ANSIBLE_EXECUTION_TIMEOUT
? parseInt(process.env.ANSIBLE_EXECUTION_TIMEOUT, 10)
: undefined,
};
}

// Parse PuppetDB configuration
if (process.env.PUPPETDB_ENABLED === "true") {
const serverUrl = process.env.PUPPETDB_SERVER_URL;
Expand Down Expand Up @@ -608,6 +626,19 @@ export class ConfigService {
return null;
}

/**
* Get Ansible configuration if enabled
*/
public getAnsibleConfig():
| (typeof this.config.integrations.ansible & { enabled: true })
| null {
const ansible = this.config.integrations.ansible;
if (ansible?.enabled) {
return ansible as typeof ansible & { enabled: true };
}
return null;
}

/**
* Get Puppetserver configuration if enabled
*/
Expand Down
13 changes: 13 additions & 0 deletions backend/src/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,18 @@ export const PuppetserverConfigSchema = z.object({

export type PuppetserverConfig = z.infer<typeof PuppetserverConfigSchema>;

/**
* Ansible integration configuration schema
*/
export const AnsibleConfigSchema = z.object({
enabled: z.boolean().default(false),
projectPath: z.string().default(process.cwd()),
inventoryPath: z.string().default("inventory/hosts"),
timeout: z.number().int().positive().default(300000),
});

export type AnsibleConfig = z.infer<typeof AnsibleConfigSchema>;

/**
* Hiera fact source configuration schema
*/
Expand Down Expand Up @@ -261,6 +273,7 @@ export type HieraConfig = z.infer<typeof HieraConfigSchema>;
* Integrations configuration schema
*/
export const IntegrationsConfigSchema = z.object({
ansible: AnsibleConfigSchema.optional(),
puppetdb: PuppetDBConfigSchema.optional(),
puppetserver: PuppetserverConfigSchema.optional(),
hiera: HieraConfigSchema.optional(),
Expand Down
14 changes: 12 additions & 2 deletions backend/src/database/ExecutionRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ interface DbRow {
re_execution_count: number | null;
stdout: string | null;
stderr: string | null;
execution_tool: string | null;
total?: number;
running?: number;
success?: number;
Expand All @@ -33,6 +34,8 @@ interface DbRow {
*/
export type ExecutionType = "command" | "task" | "facts" | "puppet" | "package";

export type ExecutionTool = "bolt" | "ansible";

/**
* Execution status
*/
Expand Down Expand Up @@ -74,6 +77,7 @@ export interface ExecutionRecord {
reExecutionCount?: number;
stdout?: string;
stderr?: string;
executionTool?: ExecutionTool;
}

/**
Expand Down Expand Up @@ -130,8 +134,8 @@ export class ExecutionRepository {
INSERT INTO executions (
id, type, target_nodes, action, parameters, status,
started_at, completed_at, results, error, command, expert_mode,
original_execution_id, re_execution_count, stdout, stderr
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
original_execution_id, re_execution_count, stdout, stderr, execution_tool
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`;

const params = [
Expand All @@ -151,6 +155,7 @@ export class ExecutionRepository {
record.reExecutionCount ?? 0,
record.stdout ?? null,
record.stderr ?? null,
record.executionTool ?? "bolt",
];

try {
Expand Down Expand Up @@ -181,6 +186,7 @@ export class ExecutionRepository {
"reExecutionCount",
"stdout",
"stderr",
"executionTool",
];
const updateFields: string[] = [];
const params: unknown[] = [];
Expand Down Expand Up @@ -474,6 +480,10 @@ export class ExecutionRepository {
reExecutionCount: row.re_execution_count ?? 0,
stdout: row.stdout ?? undefined,
stderr: row.stderr ?? undefined,
executionTool:
row.execution_tool === "ansible"
? "ansible"
: "bolt",
};
}

Expand Down
4 changes: 4 additions & 0 deletions backend/src/database/migrations.sql
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,7 @@ ALTER TABLE executions ADD COLUMN stdout TEXT;

-- Add stderr column if it doesn't exist
ALTER TABLE executions ADD COLUMN stderr TEXT;

-- Migration: Add execution_tool column to indicate which execution engine was used
-- Values: bolt, ansible
ALTER TABLE executions ADD COLUMN execution_tool TEXT DEFAULT 'bolt';
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The migration adds the execution_tool column without a CHECK constraint, while the schema.sql file (line 19) includes CHECK(execution_tool IN ('bolt', 'ansible')). This mismatch means that existing databases upgraded via migration won't have the constraint enforced, while fresh installations will. Consider adding the CHECK constraint in the migration as well: ALTER TABLE executions ADD COLUMN execution_tool TEXT DEFAULT 'bolt' CHECK(execution_tool IN ('bolt', 'ansible'));

Suggested change
ALTER TABLE executions ADD COLUMN execution_tool TEXT DEFAULT 'bolt';
ALTER TABLE executions ADD COLUMN execution_tool TEXT DEFAULT 'bolt' CHECK(execution_tool IN ('bolt', 'ansible'));

Copilot uses AI. Check for mistakes.
3 changes: 2 additions & 1 deletion backend/src/database/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ CREATE TABLE IF NOT EXISTS executions (
original_execution_id TEXT, -- Reference to original execution if this is a re-execution
re_execution_count INTEGER DEFAULT 0, -- Number of times this execution has been re-executed
stdout TEXT, -- Complete stdout output (stored when expert mode enabled)
stderr TEXT -- Complete stderr output (stored when expert mode enabled)
stderr TEXT, -- Complete stderr output (stored when expert mode enabled)
execution_tool TEXT DEFAULT 'bolt' CHECK(execution_tool IN ('bolt', 'ansible'))
);

-- Index Strategy:
Expand Down
2 changes: 1 addition & 1 deletion backend/src/integrations/IntegrationManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import type {
PluginRegistration,
Action,
} from "./types";
import type { Node, Facts, ExecutionResult } from "../bolt/types";
import type { Node, Facts, ExecutionResult } from "./bolt/types";
import { NodeLinkingService, type LinkedNode } from "./NodeLinkingService";
import { LoggerService } from "../services/LoggerService";

Expand Down
2 changes: 1 addition & 1 deletion backend/src/integrations/NodeLinkingService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* Implements the node linking strategy described in the design document.
*/

import type { Node } from "../bolt/types";
import type { Node } from "./bolt/types";
import type { IntegrationManager } from "./IntegrationManager";
import { LoggerService } from "../services/LoggerService";

Expand Down
Loading