minikube/gui/operator.cpp

419 lines
13 KiB
C++
Raw Normal View History

#include "operator.h"
#include <QPushButton>
#include <QJsonObject>
#include <QJsonDocument>
#include <QStandardPaths>
Operator::Operator(AdvancedView *advancedView, BasicView *basicView, CommandRunner *commandRunner,
ErrorMessage *errorMessage, ProgressWindow *progressWindow, Tray *tray,
HyperKit *hyperKit, Updater *updater, QStackedWidget *stackedWidget,
QDialog *parent)
{
m_advancedView = advancedView;
m_basicView = basicView;
m_commandRunner = commandRunner;
m_errorMessage = errorMessage;
m_progressWindow = progressWindow;
m_tray = tray;
m_hyperKit = hyperKit;
m_updater = updater;
m_stackedWidget = stackedWidget;
m_parent = parent;
m_isBasicView = true;
dashboardProcess = NULL;
connect(m_basicView, &BasicView::start, this, &Operator::startMinikube);
connect(m_basicView, &BasicView::stop, this, &Operator::stopMinikube);
connect(m_basicView, &BasicView::pause, this, &Operator::pauseOrUnpauseMinikube);
connect(m_basicView, &BasicView::delete_, this, &Operator::deleteMinikube);
connect(m_basicView, &BasicView::refresh, this, &Operator::updateClusters);
2022-07-08 23:46:29 +00:00
connect(m_basicView, &BasicView::dockerEnv, this, &Operator::dockerEnv);
connect(m_basicView, &BasicView::ssh, this, &Operator::sshConsole);
connect(m_basicView, &BasicView::dashboard, this, &Operator::dashboardBrowser);
connect(m_basicView, &BasicView::advanced, this, &Operator::toAdvancedView);
connect(m_advancedView, &AdvancedView::start, this, &Operator::startMinikube);
connect(m_advancedView, &AdvancedView::stop, this, &Operator::stopMinikube);
connect(m_advancedView, &AdvancedView::pause, this, &Operator::pauseOrUnpauseMinikube);
connect(m_advancedView, &AdvancedView::delete_, this, &Operator::deleteMinikube);
connect(m_advancedView, &AdvancedView::refresh, this, &Operator::updateClusters);
2022-07-08 23:46:29 +00:00
connect(m_advancedView, &AdvancedView::dockerEnv, this, &Operator::dockerEnv);
connect(m_advancedView, &AdvancedView::ssh, this, &Operator::sshConsole);
connect(m_advancedView, &AdvancedView::dashboard, this, &Operator::dashboardBrowser);
connect(m_advancedView, &AdvancedView::basic, this, &Operator::toBasicView);
connect(m_advancedView, &AdvancedView::createCluster, this, &Operator::createCluster);
connect(m_advancedView->clusterListView, SIGNAL(clicked(QModelIndex)), this,
SLOT(updateButtons()));
connect(m_commandRunner, &CommandRunner::startingExecution, this, &Operator::commandStarting);
connect(m_commandRunner, &CommandRunner::executionEnded, this, &Operator::commandEnding);
connect(m_commandRunner, &CommandRunner::output, this, &Operator::commandOutput);
connect(m_commandRunner, &CommandRunner::error, this, &Operator::commandError);
connect(m_commandRunner, &CommandRunner::updatedClusters, this, &Operator::clustersReceived);
connect(m_commandRunner, &CommandRunner::startCommandStarting, this,
&Operator::startCommandStarting);
connect(m_progressWindow, &ProgressWindow::cancelled, this, &Operator::cancelCommand);
connect(m_tray, &Tray::restoreWindow, this, &Operator::restoreWindow);
connect(m_tray, &Tray::hideWindow, this, &Operator::hideWindow);
connect(m_tray, &Tray::start, this, &Operator::startMinikube);
connect(m_tray, &Tray::stop, this, &Operator::stopMinikube);
connect(m_tray, &Tray::pauseOrUnpause, this, &Operator::pauseOrUnpauseMinikube);
connect(m_hyperKit, &HyperKit::rerun, this, &Operator::createCluster);
updateClusters();
}
QStringList Operator::getCurrentClusterFlags()
{
return { "-p", selectedClusterName() };
}
void Operator::startMinikube()
{
m_commandRunner->startMinikube(getCurrentClusterFlags());
}
void Operator::stopMinikube()
{
m_commandRunner->stopMinikube(getCurrentClusterFlags());
}
void Operator::pauseOrUnpauseMinikube()
{
Cluster cluster = selectedCluster();
if (cluster.status() == "Paused") {
unpauseMinikube();
return;
}
pauseMinikube();
}
void Operator::pauseMinikube()
{
m_commandRunner->pauseMinikube(getCurrentClusterFlags());
}
void Operator::unpauseMinikube()
{
m_commandRunner->unpauseMinikube(getCurrentClusterFlags());
}
void Operator::deleteMinikube()
{
m_commandRunner->deleteMinikube(getCurrentClusterFlags());
}
void Operator::createCluster(QStringList args)
{
m_commandRunner->startMinikube(args);
}
void Operator::startCommandStarting()
{
commandStarting();
m_progressWindow->setText("Starting...");
m_progressWindow->show();
}
void Operator::commandStarting()
{
m_advancedView->showLoading();
m_tray->disableActions();
m_parent->setCursor(Qt::WaitCursor);
disableButtons();
}
void Operator::disableButtons()
{
if (m_isBasicView) {
m_basicView->disableButtons();
} else {
m_advancedView->disableButtons();
}
}
void Operator::commandEnding()
{
m_progressWindow->done();
updateClusters();
}
void Operator::toAdvancedView()
{
m_isBasicView = false;
m_stackedWidget->setCurrentIndex(1);
m_parent->resize(670, 400);
updateButtons();
}
void Operator::toBasicView()
{
m_isBasicView = true;
m_stackedWidget->setCurrentIndex(0);
2022-07-08 23:46:29 +00:00
m_parent->resize(200, 300);
updateButtons();
}
void Operator::updateClusters()
{
m_commandRunner->requestClusters();
}
void Operator::clustersReceived(ClusterList clusterList)
{
m_clusterList = clusterList;
m_advancedView->updateClustersTable(m_clusterList);
updateButtons();
m_advancedView->hideLoading();
m_parent->unsetCursor();
m_updater->checkForUpdates();
}
void Operator::updateButtons()
{
Cluster cluster = selectedCluster();
if (m_isBasicView) {
m_basicView->update(cluster);
} else {
m_advancedView->update(cluster);
}
m_tray->updateTrayActions(cluster);
m_tray->updateStatus(cluster);
}
void Operator::restoreWindow()
{
bool wasVisible = m_parent->isVisible();
m_parent->showNormal();
m_parent->activateWindow();
if (wasVisible) {
return;
}
if (m_commandRunner->isRunning())
return;
updateClusters();
}
void Operator::hideWindow()
{
m_parent->hide();
}
void Operator::commandOutput(QString text)
{
QStringList lines;
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
lines = text.split("\n", Qt::SkipEmptyParts);
#else
lines = text.split("\n", QString::SkipEmptyParts);
#endif
for (int i = 0; i < lines.size(); i++) {
QJsonDocument json = QJsonDocument::fromJson(lines[i].toUtf8());
QJsonObject object = json.object();
QString type = object["type"].toString();
if (type != "io.k8s.sigs.minikube.step") {
return;
}
QJsonObject data = object["data"].toObject();
QString stringStep = data["currentstep"].toString();
int currStep = stringStep.toInt();
QString totalString = data["totalsteps"].toString();
int totalSteps = totalString.toInt();
QString message = data["message"].toString();
m_progressWindow->setBarMaximum(totalSteps);
m_progressWindow->setBarValue(currStep);
m_progressWindow->setText(message);
}
}
void Operator::commandError(QStringList args, QString text)
{
#if __APPLE__
if (m_hyperKit->hyperkitPermissionFix(args, text)) {
return;
}
#endif
QStringList lines;
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
lines = text.split("\n", Qt::SkipEmptyParts);
#else
lines = text.split("\n", QString::SkipEmptyParts);
#endif
for (int i = 0; i < lines.size(); i++) {
QString line = lines.at(i);
QJsonParseError error;
QJsonDocument json = QJsonDocument::fromJson(line.toUtf8(), &error);
if (json.isNull() || !json.isObject()) {
continue;
}
QJsonObject par = json.object();
QJsonObject data = par["data"].toObject();
if (!data.contains("exitcode")) {
continue;
}
QString advice = data["advice"].toString();
QString message = data["message"].toString();
QString name = data["name"].toString();
QString url = data["url"].toString();
QString issues = data["issues"].toString();
m_errorMessage->error(name, advice, message, url, issues);
break;
}
}
void Operator::cancelCommand()
{
m_commandRunner->stopCommand();
}
QString Operator::selectedClusterName()
{
if (m_isBasicView) {
return "minikube";
}
return m_advancedView->selectedClusterName();
}
Cluster Operator::selectedCluster()
{
QString clusterName = selectedClusterName();
if (clusterName.isEmpty()) {
return Cluster();
}
ClusterList clusters = m_clusterList;
ClusterHash clusterHash;
for (int i = 0; i < clusters.size(); i++) {
Cluster cluster = clusters.at(i);
clusterHash[cluster.name()] = cluster;
}
return clusterHash[clusterName];
}
static QString minikubePath()
{
QString minikubePath = QStandardPaths::findExecutable("minikube");
if (!minikubePath.isEmpty()) {
return minikubePath;
}
QStringList path = { "/usr/local/bin" };
return QStandardPaths::findExecutable("minikube", path);
}
void Operator::sshConsole()
{
QString program = minikubePath();
2022-07-08 23:46:29 +00:00
QString commandArgs = QString("ssh -p %1").arg(selectedClusterName());
QString command = QString("%1 %2").arg(program, commandArgs);
#ifndef QT_NO_TERMWIDGET
QMainWindow *mainWindow = new QMainWindow();
int startnow = 0; // set shell program first
QTermWidget *console = new QTermWidget(startnow);
QFont font = QApplication::font();
font.setFamily("Monospace");
font.setPointSize(10);
console->setTerminalFont(font);
console->setColorScheme("Tango");
console->setShellProgram(program);
2022-07-08 23:46:29 +00:00
console->setArgs({ commandArgs });
console->startShellProgram();
QObject::connect(console, SIGNAL(finished()), mainWindow, SLOT(close()));
mainWindow->setWindowTitle(nameLabel->text());
mainWindow->resize(800, 400);
mainWindow->setCentralWidget(console);
mainWindow->show();
#elif __APPLE__
2022-07-08 23:46:29 +00:00
QStringList arguments = { "-e", "tell app \"Terminal\"",
"-e", "do script \"" + command + "\"",
"-e", "activate",
"-e", "end tell" };
2022-08-04 22:17:31 +00:00
m_commandRunner->executeCommand("/usr/bin/osascript", arguments);
#else
QString terminal = qEnvironmentVariable("TERMINAL");
if (terminal.isEmpty()) {
terminal = "x-terminal-emulator";
if (QStandardPaths::findExecutable(terminal).isEmpty()) {
terminal = "xterm";
}
}
2022-08-04 22:17:31 +00:00
m_commandRunner->executeCommand(QStandardPaths::findExecutable(terminal), { "-e", command });
2022-07-08 23:46:29 +00:00
#endif
}
void Operator::dockerEnv()
{
QString program = minikubePath();
QString commandArgs = QString("$(%1 -p %2 docker-env)").arg(program, selectedClusterName());
QString command = QString("eval %1").arg(commandArgs);
#ifndef QT_NO_TERMWIDGET
QMainWindow *mainWindow = new QMainWindow();
int startnow = 0; // set shell program first
QTermWidget *console = new QTermWidget(startnow);
QFont font = QApplication::font();
font.setFamily("Monospace");
font.setPointSize(10);
console->setTerminalFont(font);
console->setColorScheme("Tango");
console->setShellProgram("eval");
console->setArgs({ commandArgs });
console->startShellProgram();
QObject::connect(console, SIGNAL(finished()), mainWindow, SLOT(close()));
mainWindow->setWindowTitle(nameLabel->text());
mainWindow->resize(800, 400);
mainWindow->setCentralWidget(console);
mainWindow->show();
#elif __APPLE__
QStringList arguments = { "-e", "tell app \"Terminal\"",
"-e", "do script \"" + command + "\"",
"-e", "activate",
"-e", "end tell" };
2022-08-04 22:17:31 +00:00
m_commandRunner->executeCommand("/usr/bin/osascript", arguments);
2022-07-08 23:46:29 +00:00
#else
QString terminal = qEnvironmentVariable("TERMINAL");
if (terminal.isEmpty()) {
terminal = "x-terminal-emulator";
if (QStandardPaths::findExecutable(terminal).isEmpty()) {
terminal = "xterm";
}
}
2022-08-04 22:17:31 +00:00
m_commandRunner->executeCommand(QStandardPaths::findExecutable(terminal), { "-e", command });
#endif
}
void Operator::dashboardBrowser()
{
dashboardClose();
QString program = minikubePath();
QProcess *process = new QProcess(this);
QStringList arguments = { "dashboard", "-p", selectedClusterName() };
process->start(program, arguments);
dashboardProcess = process;
dashboardProcess->waitForStarted();
}
void Operator::dashboardClose()
{
if (dashboardProcess) {
dashboardProcess->terminate();
dashboardProcess->waitForFinished();
}
}