aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/docker
diff options
context:
space:
mode:
authorMarcus Tillmanns <[email protected]>2023-09-15 14:17:11 +0200
committerMarcus Tillmanns <[email protected]>2023-09-20 08:02:04 +0000
commit189cf8054f4a75637bab70afc90be7fe65b410ed (patch)
tree1fc1532229621d64a22b847f827ef94659902905 /src/plugins/docker
parent881c48fbe78ce6cfd10fd359df29c752add521a7 (diff)
Docker: Add network option to settings
Diffstat (limited to 'src/plugins/docker')
-rw-r--r--src/plugins/docker/dockerapi.cpp72
-rw-r--r--src/plugins/docker/dockerapi.h16
-rw-r--r--src/plugins/docker/dockerdevice.cpp56
-rw-r--r--src/plugins/docker/dockerdevice.h1
-rw-r--r--src/plugins/docker/dockerdevicewidget.cpp1
5 files changed, 136 insertions, 10 deletions
diff --git a/src/plugins/docker/dockerapi.cpp b/src/plugins/docker/dockerapi.cpp
index fe89d590591..900e5bb18b2 100644
--- a/src/plugins/docker/dockerapi.cpp
+++ b/src/plugins/docker/dockerapi.cpp
@@ -105,4 +105,76 @@ FilePath DockerApi::dockerClient()
return settings().dockerBinaryPath();
}
+QFuture<Utils::expected_str<QList<Network>>> DockerApi::networks()
+{
+ return Utils::asyncRun([this]() -> Utils::expected_str<QList<Network>> {
+ QList<Network> result;
+
+ Process process;
+ FilePath dockerExe = dockerClient();
+ if (dockerExe.isEmpty() || !dockerExe.isExecutableFile())
+ return make_unexpected(Tr::tr("Docker executable not found"));
+
+ process.setCommand(
+ CommandLine(dockerExe, QStringList{"network", "ls", "--format", "{{json .}}"}));
+ process.runBlocking();
+
+ if (process.result() != ProcessResult::FinishedWithSuccess) {
+ return make_unexpected(
+ Tr::tr("Failed to retrieve docker networks. Exit code: %1. Error: %2")
+ .arg(process.exitCode())
+ .arg(process.allOutput()));
+ }
+
+ for (const auto &line : process.readAllStandardOutput().split('\n')) {
+ if (line.isEmpty())
+ continue;
+
+ QJsonParseError error;
+ QJsonDocument doc = QJsonDocument::fromJson(line.toUtf8(), &error);
+
+ if (error.error != QJsonParseError::NoError) {
+ qCWarning(dockerApiLog)
+ << "Failed to parse docker network info:" << error.errorString();
+ continue;
+ }
+
+ Network network;
+ network.id = doc["ID"].toString();
+ network.name = doc["Name"].toString();
+ network.driver = doc["Driver"].toString();
+ network.scope = doc["Scope"].toString();
+ network.internal = doc["Internal"].toString() == "true";
+ network.ipv6 = doc["IPv6"].toString() == "true";
+ network.createdAt = QDateTime::fromString(doc["CreatedAt"].toString(), Qt::ISODate);
+ network.labels = doc["Labels"].toString();
+
+ result.append(network);
+ }
+
+ return result;
+ });
+}
+
+QString Network::toString() const
+{
+ return QString(R"(ID: "%1"
+Name: "%2"
+Driver: "%3"
+Scope: "%4"
+Internal: "%5"
+IPv6: "%6"
+CreatedAt: "%7"
+Labels: "%8"
+ )")
+ .arg(id)
+ .arg(name)
+ .arg(driver)
+ .arg(scope)
+ .arg(internal)
+ .arg(ipv6)
+ .arg(createdAt.toString(Qt::ISODate))
+ .arg(labels);
+}
+
} // Docker::Internal
diff --git a/src/plugins/docker/dockerapi.h b/src/plugins/docker/dockerapi.h
index 4866e84c66a..3e697654a3a 100644
--- a/src/plugins/docker/dockerapi.h
+++ b/src/plugins/docker/dockerapi.h
@@ -5,6 +5,7 @@
#include "dockersettings.h"
+#include <utils/expected.h>
#include <utils/filepath.h>
#include <utils/guard.h>
@@ -15,6 +16,20 @@
namespace Docker::Internal {
+struct Network
+{
+ QString id;
+ QString name;
+ QString driver;
+ QString scope;
+ bool internal;
+ bool ipv6;
+ QDateTime createdAt;
+ QString labels;
+
+ QString toString() const;
+};
+
class DockerApi : public QObject
{
Q_OBJECT
@@ -27,6 +42,7 @@ public:
bool canConnect();
void checkCanConnect(bool async = true);
static void recheckDockerDaemon();
+ QFuture<Utils::expected_str<QList<Network>>> networks();
signals:
void dockerDaemonAvailableChanged();
diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp
index ef90a78b582..e2646dcaf30 100644
--- a/src/plugins/docker/dockerdevice.cpp
+++ b/src/plugins/docker/dockerdevice.cpp
@@ -69,6 +69,7 @@
#include <QPushButton>
#include <QRandomGenerator>
#include <QRegularExpression>
+#include <QStandardItem>
#include <QTextBrowser>
#include <QThread>
#include <QToolButton>
@@ -109,8 +110,8 @@ public:
private:
void setupShellProcess(Process *shellProcess) final
{
- shellProcess->setCommand({settings().dockerBinaryPath(),
- {"container", "start", "-i", "-a", m_containerId}});
+ shellProcess->setCommand(
+ {settings().dockerBinaryPath(), {"container", "start", "-i", "-a", m_containerId}});
}
CommandLine createFallbackCommand(const CommandLine &cmdLine)
@@ -132,8 +133,7 @@ public:
: m_dev(dev)
{}
- RunResult runInShell(const CommandLine &cmdLine,
- const QByteArray &stdInData) const override;
+ RunResult runInShell(const CommandLine &cmdLine, const QByteArray &stdInData) const override;
QString mapToDevicePath(const QString &hostPath) const override;
DockerDevicePrivate *m_dev = nullptr;
@@ -191,6 +191,40 @@ DockerDeviceSettings::DockerDeviceSettings()
clangdExecutable.setLabelText(Tr::tr("Clangd Executable:"));
clangdExecutable.setAllowPathFromDevice(true);
+ network.setSettingsKey("Network");
+ network.setLabelText(Tr::tr("Network:"));
+ network.setDefaultValue("bridge");
+ network.setFillCallback([this](const StringSelectionAspect::ResultCallback &cb) {
+ auto future = DockerApi::instance()->networks();
+
+ auto watcher = new QFutureWatcher<expected_str<QList<Network>>>(this);
+ watcher->setFuture(future);
+ QObject::connect(watcher,
+ &QFutureWatcher<expected_str<QList<Network>>>::finished,
+ this,
+ [watcher, cb]() {
+ expected_str<QList<Network>> result = watcher->result();
+ if (result) {
+ auto items = Utils::transform(*result, [](const Network &network) {
+ QStandardItem *item = new QStandardItem(network.name);
+ item->setData(network.name);
+ item->setToolTip(network.toString());
+ return item;
+ });
+ cb(items);
+ } else {
+ QStandardItem *errorItem = new QStandardItem(Tr::tr("Error!"));
+ errorItem->setToolTip(result.error());
+ cb({errorItem});
+ }
+ });
+ });
+
+ connect(DockerApi::instance(),
+ &DockerApi::dockerDaemonAvailableChanged,
+ &network,
+ &StringSelectionAspect::refill);
+
clangdExecutable.setValidationFunction(
[](const QString &newValue) -> FancyLineEdit::AsyncValidationFuture {
return Utils::asyncRun([newValue]() -> expected_str<QString> {
@@ -757,9 +791,7 @@ expected_str<QString> DockerDevicePrivate::createContainer()
"-e",
QString("DISPLAY=%1").arg(display),
"-e",
- "XAUTHORITY=/.Xauthority",
- "--net",
- "host"}};
+ "XAUTHORITY=/.Xauthority"}};
#ifdef Q_OS_UNIX
// no getuid() and getgid() on Windows.
@@ -767,6 +799,11 @@ expected_str<QString> DockerDevicePrivate::createContainer()
dockerCreate.addArgs({"-u", QString("%1:%2").arg(getuid()).arg(getgid())});
#endif
+ if (!deviceSettings->network().isEmpty()) {
+ dockerCreate.addArg("--network");
+ dockerCreate.addArg(deviceSettings->network());
+ }
+
dockerCreate.addArgs(createMountArgs());
if (!deviceSettings->keepEntryPoint())
@@ -1206,9 +1243,8 @@ bool DockerDevicePrivate::addTemporaryMount(const FilePath &path, const FilePath
if (alreadyAdded)
return false;
- const bool alreadyManuallyAdded = anyOf(deviceSettings->mounts(), [path](const FilePath &mount) {
- return mount == path;
- });
+ const bool alreadyManuallyAdded = anyOf(deviceSettings->mounts(),
+ [path](const FilePath &mount) { return mount == path; });
if (alreadyManuallyAdded)
return false;
diff --git a/src/plugins/docker/dockerdevice.h b/src/plugins/docker/dockerdevice.h
index c38a7746dbd..51fc05be28a 100644
--- a/src/plugins/docker/dockerdevice.h
+++ b/src/plugins/docker/dockerdevice.h
@@ -32,6 +32,7 @@ public:
Utils::BoolAspect keepEntryPoint{this};
Utils::BoolAspect enableLldbFlags{this};
Utils::FilePathAspect clangdExecutable{this};
+ Utils::StringSelectionAspect network{this};
Utils::TextDisplay containerStatus{this};
};
diff --git a/src/plugins/docker/dockerdevicewidget.cpp b/src/plugins/docker/dockerdevicewidget.cpp
index 018cabb07f6..eb910b41956 100644
--- a/src/plugins/docker/dockerdevicewidget.cpp
+++ b/src/plugins/docker/dockerdevicewidget.cpp
@@ -167,6 +167,7 @@ DockerDeviceWidget::DockerDeviceWidget(const IDevice::Ptr &device)
deviceSettings->keepEntryPoint, br,
deviceSettings->enableLldbFlags, br,
deviceSettings->clangdExecutable, br,
+ deviceSettings->network, br,
Column {
pathListLabel,
deviceSettings->mounts,