aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarcus Tillmanns <[email protected]>2023-03-21 09:43:10 +0100
committerMarcus Tillmanns <[email protected]>2023-03-21 14:09:33 +0000
commit97c1bb53a501316505aec76e6e7b7222debaf60c (patch)
tree7ee988b7e8bed563f24934058299f91d737e90c9 /src
parent65814b124c2dcbd59f9bbd91a9c04c355ae37d4d (diff)
Docker: Check Image available
Docker will try to download images from the registry if an image is not available locally. This takes a while, even if the image is not available remotely. To circumvent the hangs resulting from this we first check if the image is available locally and if it is not we do not try to start it. Fixes: QTCREATORBUG-28880 Change-Id: I6b9de8601b87e3050ae9ac5f1bbe3fa9701d4cc1 Reviewed-by: David Schulz <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/docker/dockerdevice.cpp64
-rw-r--r--src/plugins/docker/dockerdevice.h2
2 files changed, 47 insertions, 19 deletions
diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp
index 020aeec31f4..7bac522c5ba 100644
--- a/src/plugins/docker/dockerdevice.cpp
+++ b/src/plugins/docker/dockerdevice.cpp
@@ -143,7 +143,7 @@ public:
RunResult runInShell(const CommandLine &cmd, const QByteArray &stdInData = {});
- void updateContainerAccess();
+ bool updateContainerAccess();
void changeMounts(QStringList newMounts);
bool ensureReachable(const FilePath &other);
void shutdown();
@@ -171,7 +171,7 @@ public:
Tasks validateMounts() const;
bool createContainer();
- void startContainer();
+ bool startContainer();
void stopCurrentContainer();
void fetchSystemEnviroment();
@@ -186,6 +186,8 @@ public:
QStringList createMountArgs() const;
+ bool isImageAvailable() const;
+
DockerDevice *const q;
DockerDeviceData m_data;
DockerSettings *m_settings;
@@ -392,7 +394,9 @@ DockerDevice::DockerDevice(DockerSettings *settings, const DockerDeviceData &dat
setOpenTerminal([this, settings](const Environment &env, const FilePath &workingDir) {
Q_UNUSED(env); // TODO: That's the runnable's environment in general. Use it via -e below.
- updateContainerAccess();
+ if (!updateContainerAccess())
+ return;
+
if (d->containerId().isEmpty()) {
MessageManager::writeDisrupting(Tr::tr("Error starting remote shell. No container."));
return;
@@ -446,9 +450,9 @@ void DockerDevice::setData(const DockerDeviceData &data)
d->setData(data);
}
-void DockerDevice::updateContainerAccess() const
+bool DockerDevice::updateContainerAccess() const
{
- d->updateContainerAccess();
+ return d->updateContainerAccess();
}
CommandLine DockerDevicePrivate::withDockerExecCmd(const CommandLine &cmd,
@@ -461,7 +465,8 @@ CommandLine DockerDevicePrivate::withDockerExecCmd(const CommandLine &cmd,
if (!m_settings)
return {};
- updateContainerAccess();
+ if (!updateContainerAccess())
+ return {};
CommandLine dockerCmd{m_settings->dockerBinaryPath.filePath(), {"exec"}};
@@ -614,11 +619,30 @@ QStringList DockerDevicePrivate::createMountArgs() const
return cmds;
}
+bool DockerDevicePrivate::isImageAvailable() const
+{
+ QtcProcess proc;
+ proc.setCommand(
+ {m_settings->dockerBinaryPath.filePath(),
+ {"image", "list", m_data.repoAndTag(), "--format", "{{.Repository}}:{{.Tag}}"}});
+ proc.runBlocking();
+ if (proc.result() != ProcessResult::FinishedWithSuccess)
+ return false;
+
+ if (proc.stdOut().trimmed() == m_data.repoAndTag())
+ return true;
+
+ return false;
+}
+
bool DockerDevicePrivate::createContainer()
{
if (!m_settings)
return false;
+ if (!isImageAvailable())
+ return false;
+
const QString display = HostOsInfo::isLinuxHost() ? QString(":0")
: QString("host.docker.internal:0");
CommandLine dockerCreate{m_settings->dockerBinaryPath.filePath(),
@@ -671,10 +695,10 @@ bool DockerDevicePrivate::createContainer()
return true;
}
-void DockerDevicePrivate::startContainer()
+bool DockerDevicePrivate::startContainer()
{
if (!createContainer())
- return;
+ return false;
m_shell = std::make_unique<ContainerShell>(m_settings, m_container, q->rootPath());
@@ -693,23 +717,25 @@ void DockerDevicePrivate::startContainer()
"or restart Qt Creator."));
});
- if (!m_shell->start()) {
- qCWarning(dockerDeviceLog) << "Container shell failed to start";
- }
+ if (m_shell->start())
+ return true;
+
+ qCWarning(dockerDeviceLog) << "Container shell failed to start";
+ return false;
}
-void DockerDevicePrivate::updateContainerAccess()
+bool DockerDevicePrivate::updateContainerAccess()
{
if (m_isShutdown)
- return;
+ return false;
if (DockerApi::isDockerDaemonAvailable(false).value_or(false) == false)
- return;
+ return false;
if (m_shell)
- return;
+ return true;
- startContainer();
+ return startContainer();
}
void DockerDevice::setMounts(const QStringList &mounts) const
@@ -881,7 +907,8 @@ void DockerDevice::aboutToBeRemoved() const
void DockerDevicePrivate::fetchSystemEnviroment()
{
- updateContainerAccess();
+ if (!updateContainerAccess())
+ return;
if (m_shell && m_shell->state() == DeviceShell::State::Succeeded) {
const RunResult result = runInShell({"env", {}});
@@ -905,7 +932,8 @@ void DockerDevicePrivate::fetchSystemEnviroment()
RunResult DockerDevicePrivate::runInShell(const CommandLine &cmd, const QByteArray &stdInData)
{
- updateContainerAccess();
+ if (!updateContainerAccess())
+ return {};
QTC_ASSERT(m_shell, return {});
return m_shell->runInShell(cmd, stdInData);
}
diff --git a/src/plugins/docker/dockerdevice.h b/src/plugins/docker/dockerdevice.h
index 38e9956a230..affe4cf2714 100644
--- a/src/plugins/docker/dockerdevice.h
+++ b/src/plugins/docker/dockerdevice.h
@@ -95,7 +95,7 @@ public:
void setData(const DockerDeviceData &data);
- void updateContainerAccess() const;
+ bool updateContainerAccess() const;
void setMounts(const QStringList &mounts) const;
bool prepareForBuild(const ProjectExplorer::Target *target) override;