forked from qt-creator/qt-creator
Docker: Add network option to settings
Change-Id: Idb18435aa668f9219ae0eb2db6bd55d040ba5243 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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};
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user