Don't try to update devcontainers (#946)

This commit is contained in:
Roey Darwish Dror
2022-05-27 15:50:40 +03:00
committed by GitHub
parent 258515620f
commit abdd1db349

View File

@@ -1,104 +1,109 @@
use anyhow::Result; use anyhow::Result;
use crate::error::{self, TopgradeError}; use crate::error::{self, TopgradeError};
use crate::executor::CommandExt; use crate::executor::CommandExt;
use crate::terminal::print_separator; use crate::terminal::print_separator;
use crate::{execution_context::ExecutionContext, utils::require}; use crate::{execution_context::ExecutionContext, utils::require};
use log::{debug, error, warn}; use log::{debug, error, warn};
use std::path::Path; use std::path::Path;
use std::process::Command; use std::process::Command;
// A string found in the output of docker for containers that weren't found in // A string found in the output of docker for containers that weren't found in
// the docker registry. We use this to gracefully handle and skip containers // the docker registry. We use this to gracefully handle and skip containers
// that cannot be pulled, likely because they don't exist in the registry in // that cannot be pulled, likely because they don't exist in the registry in
// the first place. This happens e.g. when the user tags an image locally // the first place. This happens e.g. when the user tags an image locally
// themselves or when using docker-compose. // themselves or when using docker-compose.
const NONEXISTENT_REPO: &str = "repository does not exist"; const NONEXISTENT_REPO: &str = "repository does not exist";
/// Returns a Vector of all containers, with Strings in the format /// Returns a Vector of all containers, with Strings in the format
/// "REGISTRY/[PATH/]CONTAINER_NAME:TAG" /// "REGISTRY/[PATH/]CONTAINER_NAME:TAG"
fn list_containers(crt: &Path) -> Result<Vec<String>> { fn list_containers(crt: &Path) -> Result<Vec<String>> {
debug!( debug!(
"Querying '{} image ls --format \"{{{{.Repository}}}}:{{{{.Tag}}}}\"' for containers", "Querying '{} image ls --format \"{{{{.Repository}}}}:{{{{.Tag}}}}\"' for containers",
crt.display() crt.display()
); );
let output = Command::new(crt) let output = Command::new(crt)
.args(&["image", "ls", "--format", "{{.Repository}}:{{.Tag}}"]) .args(&["image", "ls", "--format", "{{.Repository}}:{{.Tag}}"])
.output()?; .output()?;
let output_str = String::from_utf8(output.stdout)?; let output_str = String::from_utf8(output.stdout)?;
let mut retval = vec![]; let mut retval = vec![];
for line in output_str.lines() { for line in output_str.lines() {
if line.starts_with("localhost") { if line.starts_with("localhost") {
// Don't know how to update self-built containers // Don't know how to update self-built containers
debug!("Skipping self-built container '{}'", line); debug!("Skipping self-built container '{}'", line);
continue; continue;
} }
if line.contains("<none>") { if line.contains("<none>") {
// Bogus/dangling container or intermediate layer // Bogus/dangling container or intermediate layer
debug!("Skipping bogus container '{}'", line); debug!("Skipping bogus container '{}'", line);
continue; continue;
} }
debug!("Using container '{}'", line); if line.starts_with("vsc-") {
retval.push(String::from(line)); debug!("Skipping visual studio code dev container '{}'", line);
} continue;
}
Ok(retval)
} debug!("Using container '{}'", line);
retval.push(String::from(line));
pub fn run_containers(ctx: &ExecutionContext) -> Result<()> { }
// Prefer podman, fall back to docker if not present
let crt = require("podman").or_else(|_| require("docker"))?; Ok(retval)
debug!("Using container runtime '{}'", crt.display()); }
print_separator("Containers"); pub fn run_containers(ctx: &ExecutionContext) -> Result<()> {
let mut success = true; // Prefer podman, fall back to docker if not present
let containers = list_containers(&crt)?; let crt = require("podman").or_else(|_| require("docker"))?;
debug!("Containers to inspect: {:?}", containers); debug!("Using container runtime '{}'", crt.display());
for container in containers.iter() { print_separator("Containers");
debug!("Pulling container '{}'", container); let mut success = true;
let args = vec!["pull", &container[..]]; let containers = list_containers(&crt)?;
let mut exec = ctx.run_type().execute(&crt); debug!("Containers to inspect: {:?}", containers);
if let Err(e) = exec.args(&args).check_run() { for container in containers.iter() {
error!("Pulling container '{}' failed: {}", container, e); debug!("Pulling container '{}'", container);
let args = vec!["pull", &container[..]];
// Find out if this is 'skippable' let mut exec = ctx.run_type().execute(&crt);
// This is necessary e.g. for docker, because unlike podman docker doesn't tell from
// which repository a container originates (such as `docker.io`). This has the if let Err(e) = exec.args(&args).check_run() {
// practical consequence that all containers, whether self-built, created by error!("Pulling container '{}' failed: {}", container, e);
// docker-compose or pulled from the docker hub, look exactly the same to us. We can
// only find out what went wrong by manually parsing the output of the command... // Find out if this is 'skippable'
if match exec.check_output() { // This is necessary e.g. for docker, because unlike podman docker doesn't tell from
Ok(s) => s.contains(NONEXISTENT_REPO), // which repository a container originates (such as `docker.io`). This has the
Err(e) => match e.downcast_ref::<TopgradeError>() { // practical consequence that all containers, whether self-built, created by
Some(TopgradeError::ProcessFailedWithOutput(_, stderr)) => stderr.contains(NONEXISTENT_REPO), // docker-compose or pulled from the docker hub, look exactly the same to us. We can
_ => false, // only find out what went wrong by manually parsing the output of the command...
}, if match exec.check_output() {
} { Ok(s) => s.contains(NONEXISTENT_REPO),
warn!("Skipping unknown container '{}'", container); Err(e) => match e.downcast_ref::<TopgradeError>() {
continue; Some(TopgradeError::ProcessFailedWithOutput(_, stderr)) => stderr.contains(NONEXISTENT_REPO),
} _ => false,
},
success = false; } {
} warn!("Skipping unknown container '{}'", container);
} continue;
}
if ctx.config().cleanup() {
// Remove dangling images success = false;
debug!("Removing dangling images"); }
if let Err(e) = ctx.run_type().execute(&crt).args(&["image", "prune", "-f"]).check_run() { }
error!("Removing dangling images failed: {}", e);
success = false; if ctx.config().cleanup() {
} // Remove dangling images
} debug!("Removing dangling images");
if let Err(e) = ctx.run_type().execute(&crt).args(&["image", "prune", "-f"]).check_run() {
if success { error!("Removing dangling images failed: {}", e);
Ok(()) success = false;
} else { }
Err(anyhow::anyhow!(error::StepFailed)) }
}
} if success {
Ok(())
} else {
Err(anyhow::anyhow!(error::StepFailed))
}
}