From 4020f454e13e16afcb81dad9857992ea9bf84a99 Mon Sep 17 00:00:00 2001 From: spmfox Date: Wed, 7 Jun 2023 00:29:18 -0400 Subject: Initial commit --- src/app.jsx | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/manifest.json | 8 +++ 2 files changed, 205 insertions(+) create mode 100644 src/app.jsx create mode 100644 src/manifest.json (limited to 'src') diff --git a/src/app.jsx b/src/app.jsx new file mode 100644 index 0000000..b1a2825 --- /dev/null +++ b/src/app.jsx @@ -0,0 +1,197 @@ +/* + * This file is part of Cockpit. + * + * Copyright (C) 2017 Red Hat, Inc. + * + * Cockpit is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * Cockpit is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Cockpit; If not, see . + */ + +import cockpit from 'cockpit'; +import React from 'react'; +import { Card, CardBody, CardTitle } from '@patternfly/react-core/dist/esm/components/Card/index.js'; + +const _ = cockpit.gettext; + +export class Application extends React.Component { + constructor() { + super(); + this.state = { + playbookFolder: '/opt/playbooks', + imageList: [], + }; + } + + componentDidMount() { + const populatePlaybookList = () => { + const playbookDropdown = document.getElementById('playbook'); + const command = `ls ${this.state.playbookFolder} |grep -e .yml -e .yaml`; + + const process = cockpit.spawn(['bash', '-c', command], { superuser: 'require', err: 'message' }); + + process.done((data) => { + const playbooks = data.split('\n'); + + playbookDropdown.innerHTML = ''; + + playbooks.forEach(function (playbook) { + if (playbook !== '') { + const option = document.createElement('option'); + option.value = playbook; + option.textContent = playbook; + playbookDropdown.appendChild(option); + } + }); + }); + + process.fail(function (error) { + console.error('Error fetching playbooks:', error); + }); + }; + + const populateImageList = () => { + const imageNameDropdown = document.getElementById('image-name'); + const command = 'podman image list --filter label=ansible_execution_environment --noheading --format "table {{.Repository}}"'; + + const process = cockpit.spawn(['bash', '-c', command], { superuser: 'require', err: 'message' }); + + process.done((data) => { + const images = data.split('\n'); + + this.setState({ imageList: images.filter((image) => image !== '') }); + + imageNameDropdown.innerHTML = ''; + + images.forEach(function (image) { + if (image !== '') { + const option = document.createElement('option'); + option.value = image; + option.textContent = image; + imageNameDropdown.appendChild(option); + } + }); + }); + + process.fail(function (error) { + console.error('Error fetching images:', error); + }); + }; + + const executePlaybook = (playbook, extraArgs) => { + const runInContainer = document.getElementById('run-in-container').checked; + const imageName = document.getElementById('image-name').value; + const playbookFolder = this.state.playbookFolder; + + let command = ''; + + if (runInContainer) { + command = `podman container runlabel ansible_execution_environment ${imageName} "${playbookFolder}/${playbook} ${extraArgs}"`; + } else { + command = `systemd-run --quiet --scope ansible-playbook ${playbookFolder}/${playbook} ${extraArgs}`; + } + + const outputElement = document.getElementById('output'); + outputElement.innerHTML = ''; + + const process = cockpit.spawn(['bash', '-c', command], { superuser: 'require', err: 'message' }); + + process.done(function () { + console.log('Playbook execution complete'); + }); + + process.fail(function (error) { + console.error('Error executing playbook:', error); + outputElement.textContent += 'Error executing playbook: ' + error; + }); + + process.stream(function (data) { + outputElement.innerHTML += data; + }); + }; + + document.getElementById('ansible-form').addEventListener('submit', function (event) { + event.preventDefault(); + + const selectedPlaybook = document.getElementById('playbook').value; + const extraArgs = document.getElementById('extra-args').value; + + if (selectedPlaybook !== '') { + executePlaybook(selectedPlaybook, extraArgs); + } + }); + + document.getElementById('load-playbooks-btn').addEventListener('click', () => { + const newPlaybookFolder = document.getElementById('playbook-folder').value; + this.setState({ playbookFolder: newPlaybookFolder }, () => { + populatePlaybookList(); + }); + }); + + populatePlaybookList(); + populateImageList(); + } + + render() { + return ( +
+ + Run Ansible Playbook + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + +
+
+
+ + Output + +

+          
+
+
+ ); + } +} diff --git a/src/manifest.json b/src/manifest.json new file mode 100644 index 0000000..f3f2b9a --- /dev/null +++ b/src/manifest.json @@ -0,0 +1,8 @@ +{ + "tools": { + "index": { + "label": "Ansible Playbooks" + } + } +} + -- cgit