diff options
author | Marcus Tillmanns <[email protected]> | 2023-03-21 09:43:10 +0100 |
---|---|---|
committer | Marcus Tillmanns <[email protected]> | 2023-03-21 14:09:33 +0000 |
commit | 97c1bb53a501316505aec76e6e7b7222debaf60c (patch) | |
tree | 7ee988b7e8bed563f24934058299f91d737e90c9 | |
parent | 65814b124c2dcbd59f9bbd91a9c04c355ae37d4d (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]>
-rw-r--r-- | src/plugins/docker/dockerdevice.cpp | 64 | ||||
-rw-r--r-- | src/plugins/docker/dockerdevice.h | 2 |
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; |