Docker: Make mounted volumes user-configurable

Still use the so-far hardcoded "/opt" and "/data" as default, i.e.
not the intended final setup which should at least pick up
the source and build dirs automatically.

Change-Id: If632f3f5a6e824a952938c97336df8ff58b39d67
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
hjk
2021-06-29 12:12:59 +02:00
parent 29704e60b0
commit 1afe21d41e
2 changed files with 32 additions and 13 deletions

View File

@@ -239,10 +239,6 @@ class DockerDevicePrivate : public QObject
public: public:
DockerDevicePrivate(DockerDevice *parent) : q(parent) DockerDevicePrivate(DockerDevice *parent) : q(parent)
{ {
// FIXME: Make mounts flexible
m_mounts.append("/opt");
m_mounts.append("/data");
connect(&m_mergedDirWatcher, &QFileSystemWatcher::fileChanged, this, [](const QString &path) { connect(&m_mergedDirWatcher, &QFileSystemWatcher::fileChanged, this, [](const QString &path) {
Q_UNUSED(path) Q_UNUSED(path)
LOG("Container watcher change, file: " << path); LOG("Container watcher change, file: " << path);
@@ -276,7 +272,6 @@ public:
QPointer<QtcProcess> m_shell; QPointer<QtcProcess> m_shell;
QString m_container; QString m_container;
QString m_mergedDir; QString m_mergedDir;
QStringList m_mounts;
QFileSystemWatcher m_mergedDirWatcher; QFileSystemWatcher m_mergedDirWatcher;
Environment m_cachedEnviroment; Environment m_cachedEnviroment;
@@ -293,12 +288,12 @@ public:
auto dockerDevice = device.dynamicCast<DockerDevice>(); auto dockerDevice = device.dynamicCast<DockerDevice>();
QTC_ASSERT(dockerDevice, return); QTC_ASSERT(dockerDevice, return);
m_idLabel = new QLabel(tr("Image Id:")); auto idLabel = new QLabel(tr("Image Id:"));
m_idLineEdit = new QLineEdit; m_idLineEdit = new QLineEdit;
m_idLineEdit->setText(dockerDevice->data().imageId); m_idLineEdit->setText(dockerDevice->data().imageId);
m_idLineEdit->setEnabled(false); m_idLineEdit->setEnabled(false);
m_repoLabel = new QLabel(tr("Repository:")); auto repoLabel = new QLabel(tr("Repository:"));
m_repoLineEdit = new QLineEdit; m_repoLineEdit = new QLineEdit;
m_repoLineEdit->setText(dockerDevice->data().repo); m_repoLineEdit->setText(dockerDevice->data().repo);
m_repoLineEdit->setEnabled(false); m_repoLineEdit->setEnabled(false);
@@ -309,6 +304,20 @@ public:
m_runAsOutsideUser->setChecked(dockerDevice->data().useLocalUidGid); m_runAsOutsideUser->setChecked(dockerDevice->data().useLocalUidGid);
m_runAsOutsideUser->setEnabled(HostOsInfo::isLinuxHost()); m_runAsOutsideUser->setEnabled(HostOsInfo::isLinuxHost());
connect(m_runAsOutsideUser, &QCheckBox::toggled, this, [this, dockerDevice](bool on) {
dockerDevice->data().useLocalUidGid = on;
});
m_pathsLineEdit = new QLineEdit;
m_pathsLineEdit->setText(dockerDevice->data().repo);
m_pathsLineEdit->setToolTip(tr("Paths in this semi-colon separated list will be "
"mapped one-to-one into the docker container."));
m_pathsLineEdit->setText(dockerDevice->data().mounts.join(';'));
connect(m_pathsLineEdit, &QLineEdit::textChanged, this, [this, dockerDevice](const QString &text) {
dockerDevice->data().mounts = text.split(';');
});
auto logView = new QTextBrowser; auto logView = new QTextBrowser;
auto autoDetectButton = new QPushButton(tr("Auto-detect Kit Items")); auto autoDetectButton = new QPushButton(tr("Auto-detect Kit Items"));
@@ -327,9 +336,10 @@ public:
using namespace Layouting; using namespace Layouting;
Form { Form {
m_idLabel, m_idLineEdit, Break(), idLabel, m_idLineEdit, Break(),
m_repoLabel, m_repoLineEdit, Break(), repoLabel, m_repoLineEdit, Break(),
m_runAsOutsideUser, Break(), m_runAsOutsideUser, Break(),
tr("Paths to mount:"), m_pathsLineEdit, Break(),
Column { Column {
Space(20), Space(20),
Row { autoDetectButton, undoAutoDetectButton, Stretch() }, Row { autoDetectButton, undoAutoDetectButton, Stretch() },
@@ -342,11 +352,10 @@ public:
void updateDeviceFromUi() final {} void updateDeviceFromUi() final {}
private: private:
QLabel *m_idLabel;
QLineEdit *m_idLineEdit; QLineEdit *m_idLineEdit;
QLabel *m_repoLabel;
QLineEdit *m_repoLineEdit; QLineEdit *m_repoLineEdit;
QCheckBox *m_runAsOutsideUser; QCheckBox *m_runAsOutsideUser;
QLineEdit *m_pathsLineEdit;
}; };
IDeviceWidget *DockerDevice::createWidget() IDeviceWidget *DockerDevice::createWidget()
@@ -410,6 +419,11 @@ const DockerDeviceData &DockerDevice::data() const
return d->m_data; return d->m_data;
} }
DockerDeviceData &DockerDevice::data()
{
return d->m_data;
}
void DockerDevicePrivate::undoAutoDetect(QTextBrowser *log) const void DockerDevicePrivate::undoAutoDetect(QTextBrowser *log) const
{ {
const QString id = q->id().toString(); const QString id = q->id().toString();
@@ -597,7 +611,7 @@ void DockerDevicePrivate::tryCreateLocalFileAccess()
dockerRun.addArgs({"-u", QString("%1:%2").arg(getuid()).arg(getgid())}); dockerRun.addArgs({"-u", QString("%1:%2").arg(getuid()).arg(getgid())});
#endif #endif
for (const QString &mount : qAsConst(m_mounts)) for (const QString &mount : qAsConst(m_data.mounts))
dockerRun.addArgs({"-v", mount + ':' + mount}); dockerRun.addArgs({"-v", mount + ':' + mount});
dockerRun.addArg(m_data.imageId); dockerRun.addArg(m_data.imageId);
@@ -661,7 +675,7 @@ FilePath DockerDevice::mapToLocalAccess(const FilePath &filePath) const
{ {
QTC_ASSERT(!d->m_mergedDir.isEmpty(), return {}); QTC_ASSERT(!d->m_mergedDir.isEmpty(), return {});
QString path = filePath.path(); QString path = filePath.path();
for (const QString &mount : qAsConst(d->m_mounts)) { for (const QString &mount : qAsConst(d->m_data.mounts)) {
if (path.startsWith(mount + '/')) if (path.startsWith(mount + '/'))
return FilePath::fromString(path); return FilePath::fromString(path);
} }
@@ -688,6 +702,7 @@ const char DockerDeviceDataRepoKey[] = "DockerDeviceDataRepo";
const char DockerDeviceDataTagKey[] = "DockerDeviceDataTag"; const char DockerDeviceDataTagKey[] = "DockerDeviceDataTag";
const char DockerDeviceDataSizeKey[] = "DockerDeviceDataSize"; const char DockerDeviceDataSizeKey[] = "DockerDeviceDataSize";
const char DockerDeviceUseOutsideUser[] = "DockerDeviceUseUidGid"; const char DockerDeviceUseOutsideUser[] = "DockerDeviceUseUidGid";
const char DockerDeviceMappedPaths[] = "DockerDeviceMappedPaths";
void DockerDevice::fromMap(const QVariantMap &map) void DockerDevice::fromMap(const QVariantMap &map)
{ {
@@ -698,6 +713,7 @@ void DockerDevice::fromMap(const QVariantMap &map)
d->m_data.size = map.value(DockerDeviceDataSizeKey).toString(); d->m_data.size = map.value(DockerDeviceDataSizeKey).toString();
d->m_data.useLocalUidGid = map.value(DockerDeviceUseOutsideUser, d->m_data.useLocalUidGid = map.value(DockerDeviceUseOutsideUser,
HostOsInfo::isLinuxHost()).toBool(); HostOsInfo::isLinuxHost()).toBool();
d->m_data.mounts = map.value(DockerDeviceMappedPaths).toStringList();
} }
QVariantMap DockerDevice::toMap() const QVariantMap DockerDevice::toMap() const
@@ -708,6 +724,7 @@ QVariantMap DockerDevice::toMap() const
map.insert(DockerDeviceDataTagKey, d->m_data.tag); map.insert(DockerDeviceDataTagKey, d->m_data.tag);
map.insert(DockerDeviceDataSizeKey, d->m_data.size); map.insert(DockerDeviceDataSizeKey, d->m_data.size);
map.insert(DockerDeviceUseOutsideUser, d->m_data.useLocalUidGid); map.insert(DockerDeviceUseOutsideUser, d->m_data.useLocalUidGid);
map.insert(DockerDeviceMappedPaths, d->m_data.mounts);
return map; return map;
} }

View File

@@ -44,6 +44,7 @@ public:
QString tag; QString tag;
QString size; QString size;
bool useLocalUidGid = true; bool useLocalUidGid = true;
QStringList mounts = {"/opt", "/data"};
}; };
class DockerDevice : public ProjectExplorer::IDevice class DockerDevice : public ProjectExplorer::IDevice
@@ -100,6 +101,7 @@ public:
Utils::Environment systemEnvironment() const override; Utils::Environment systemEnvironment() const override;
const DockerDeviceData &data() const; const DockerDeviceData &data() const;
DockerDeviceData &data();
void tryCreateLocalFileAccess() const; void tryCreateLocalFileAccess() const;
bool hasLocalFileAccess() const; bool hasLocalFileAccess() const;