v0.27.3
This commit is contained in:
1 parent
e84df445c6
commit
e87a382a7e
109 files changed
+1092
-2925
No files matched your search
@@ -0,0 +1,128 @@
|
||||
async fn create_virtual_environment(
|
||||
python: &Path,
|
||||
staging: &Path,
|
||||
system_pip: bool,
|
||||
shutdown: &tokio_util::sync::CancellationToken,
|
||||
) -> bool {
|
||||
let mut create = Command::new(python);
|
||||
create.arg("-m").arg("venv").arg(staging);
|
||||
if command_success(create, Duration::from_secs(180), shutdown).await {
|
||||
return true;
|
||||
}
|
||||
if !system_pip {
|
||||
return false;
|
||||
}
|
||||
let _ = tokio::fs::remove_dir_all(staging).await;
|
||||
// Fall back to an application-local virtualenv bootstrap.
|
||||
let bootstrap = staging.with_extension("virtualenv-bootstrap");
|
||||
let _ = tokio::fs::remove_dir_all(&bootstrap).await;
|
||||
let install_bootstrap = |break_system_packages: bool| {
|
||||
let mut install = Command::new(python);
|
||||
install.args([
|
||||
"-m",
|
||||
"pip",
|
||||
"install",
|
||||
"--disable-pip-version-check",
|
||||
"--no-input",
|
||||
"--no-cache-dir",
|
||||
"--retries",
|
||||
"3",
|
||||
"--timeout",
|
||||
"30",
|
||||
]);
|
||||
// Some distro pip builds enforce PEP 668 even for --target. Retrying with
|
||||
// --break-system-packages is safe here because the destination is the
|
||||
// private bootstrap directory; distribution site-packages are untouched.
|
||||
if break_system_packages {
|
||||
install.arg("--break-system-packages");
|
||||
}
|
||||
install.arg("--target").arg(&bootstrap).arg("virtualenv>=20,<21");
|
||||
install
|
||||
};
|
||||
let installed = command_success(
|
||||
install_bootstrap(false),
|
||||
Duration::from_secs(300),
|
||||
shutdown,
|
||||
)
|
||||
.await;
|
||||
if !installed {
|
||||
let _ = tokio::fs::remove_dir_all(&bootstrap).await;
|
||||
if !command_success(
|
||||
install_bootstrap(true),
|
||||
Duration::from_secs(300),
|
||||
shutdown,
|
||||
)
|
||||
.await
|
||||
{
|
||||
let _ = tokio::fs::remove_dir_all(&bootstrap).await;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
let mut create = Command::new(python);
|
||||
create
|
||||
.arg("-c")
|
||||
.arg("import runpy,sys; sys.path.insert(0,sys.argv[1]); sys.argv=['virtualenv',sys.argv[2]]; runpy.run_module('virtualenv',run_name='__main__')")
|
||||
.arg(&bootstrap)
|
||||
.arg(staging);
|
||||
let created = command_success(create, Duration::from_secs(180), shutdown).await;
|
||||
let _ = tokio::fs::remove_dir_all(&bootstrap).await;
|
||||
created
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
enum BuildFailure {
|
||||
CreateEnvironment,
|
||||
PreparePip,
|
||||
InstallPackages,
|
||||
Validate,
|
||||
}
|
||||
|
||||
async fn build_managed_environment(
|
||||
python: &Path,
|
||||
target: &Path,
|
||||
system_pip: bool,
|
||||
shutdown: &tokio_util::sync::CancellationToken,
|
||||
) -> Result<(), BuildFailure> {
|
||||
let legacy_stage = target.with_extension("installing");
|
||||
let _ = tokio::fs::remove_dir_all(&legacy_stage).await;
|
||||
let _ = tokio::fs::remove_dir_all(target).await;
|
||||
let _ = tokio::fs::remove_file(target).await;
|
||||
if !create_virtual_environment(python, target, system_pip, shutdown).await {
|
||||
let _ = tokio::fs::remove_dir_all(target).await;
|
||||
return Err(BuildFailure::CreateEnvironment);
|
||||
}
|
||||
let target_python = venv_python(target);
|
||||
let mut pip_check = Command::new(&target_python);
|
||||
pip_check.args(["-m", "pip", "--version"]);
|
||||
if !command_success(pip_check, Duration::from_secs(30), shutdown).await {
|
||||
let mut ensurepip = Command::new(&target_python);
|
||||
ensurepip.args(["-m", "ensurepip", "--upgrade"]);
|
||||
if !command_success(ensurepip, Duration::from_secs(120), shutdown).await {
|
||||
let _ = tokio::fs::remove_dir_all(target).await;
|
||||
return Err(BuildFailure::PreparePip);
|
||||
}
|
||||
}
|
||||
let mut pip = Command::new(&target_python);
|
||||
pip.args([
|
||||
"-m",
|
||||
"pip",
|
||||
"install",
|
||||
"--disable-pip-version-check",
|
||||
"--no-input",
|
||||
"--no-cache-dir",
|
||||
"--retries",
|
||||
"3",
|
||||
"--timeout",
|
||||
"30",
|
||||
]);
|
||||
pip.args(CERTBOT_PACKAGES.iter().copied());
|
||||
if !command_success(pip, Duration::from_secs(600), shutdown).await {
|
||||
let _ = tokio::fs::remove_dir_all(target).await;
|
||||
return Err(BuildFailure::InstallPackages);
|
||||
}
|
||||
if !managed_environment_valid(target, shutdown).await {
|
||||
let _ = tokio::fs::remove_dir_all(target).await;
|
||||
return Err(BuildFailure::Validate);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
+38
-115
@@ -60,7 +60,7 @@ impl Manager {
|
||||
struct RuntimeLaunch {
|
||||
python: PathBuf,
|
||||
prepend_path: Option<PathBuf>,
|
||||
managed_certbot_python: Option<PathBuf>,
|
||||
managed_certbot_executable: Option<PathBuf>,
|
||||
}
|
||||
|
||||
fn find_on_path(name: &str) -> Option<PathBuf> {
|
||||
@@ -107,6 +107,15 @@ fn venv_python(directory: &Path) -> PathBuf {
|
||||
venv_bin(directory).join("python")
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn venv_certbot(directory: &Path) -> PathBuf {
|
||||
venv_bin(directory).join("certbot.exe")
|
||||
}
|
||||
#[cfg(not(windows))]
|
||||
fn venv_certbot(directory: &Path) -> PathBuf {
|
||||
venv_bin(directory).join("certbot")
|
||||
}
|
||||
|
||||
async fn command_success(
|
||||
mut command: Command,
|
||||
timeout: Duration,
|
||||
@@ -145,9 +154,12 @@ async fn managed_environment_valid(
|
||||
if !command_success(imports, Duration::from_secs(20), shutdown).await {
|
||||
return false;
|
||||
}
|
||||
let certbot = venv_bin(directory).join("certbot");
|
||||
let mut version = Command::new(&python);
|
||||
version.arg("-I").arg(certbot).arg("--version");
|
||||
let certbot = venv_certbot(directory);
|
||||
if !certbot.is_file() {
|
||||
return false;
|
||||
}
|
||||
let mut version = Command::new(&certbot);
|
||||
version.arg("--version");
|
||||
command_success(version, Duration::from_secs(20), shutdown).await
|
||||
}
|
||||
|
||||
@@ -172,107 +184,7 @@ async fn system_has_pip(python: &Path, shutdown: &tokio_util::sync::Cancellation
|
||||
command_success(command, Duration::from_secs(20), shutdown).await
|
||||
}
|
||||
|
||||
async fn create_virtual_environment(
|
||||
python: &Path,
|
||||
staging: &Path,
|
||||
system_pip: bool,
|
||||
shutdown: &tokio_util::sync::CancellationToken,
|
||||
) -> bool {
|
||||
let mut create = Command::new(python);
|
||||
create.arg("-m").arg("venv").arg(staging);
|
||||
if command_success(create, Duration::from_secs(180), shutdown).await {
|
||||
return true;
|
||||
}
|
||||
if !system_pip {
|
||||
return false;
|
||||
}
|
||||
let _ = tokio::fs::remove_dir_all(staging).await;
|
||||
// Fall back to an application-local virtualenv bootstrap.
|
||||
let bootstrap = staging.with_extension("virtualenv-bootstrap");
|
||||
let _ = tokio::fs::remove_dir_all(&bootstrap).await;
|
||||
let mut install = Command::new(python);
|
||||
install.args([
|
||||
"-m",
|
||||
"pip",
|
||||
"install",
|
||||
"--disable-pip-version-check",
|
||||
"--no-input",
|
||||
"--no-cache-dir",
|
||||
"--retries",
|
||||
"3",
|
||||
"--timeout",
|
||||
"30",
|
||||
"--target",
|
||||
]);
|
||||
install.arg(&bootstrap).arg("virtualenv>=20,<21");
|
||||
if !command_success(install, Duration::from_secs(300), shutdown).await {
|
||||
let _ = tokio::fs::remove_dir_all(&bootstrap).await;
|
||||
return false;
|
||||
}
|
||||
let mut create = Command::new(python);
|
||||
create
|
||||
.arg("-c")
|
||||
.arg("import runpy,sys; sys.path.insert(0,sys.argv[1]); sys.argv=['virtualenv',sys.argv[2]]; runpy.run_module('virtualenv',run_name='__main__')")
|
||||
.arg(&bootstrap)
|
||||
.arg(staging);
|
||||
let created = command_success(create, Duration::from_secs(180), shutdown).await;
|
||||
let _ = tokio::fs::remove_dir_all(&bootstrap).await;
|
||||
created
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
enum BuildFailure {
|
||||
Bootstrap,
|
||||
Install,
|
||||
}
|
||||
|
||||
async fn build_managed_environment(
|
||||
python: &Path,
|
||||
target: &Path,
|
||||
system_pip: bool,
|
||||
shutdown: &tokio_util::sync::CancellationToken,
|
||||
) -> Result<(), BuildFailure> {
|
||||
let legacy_stage = target.with_extension("installing");
|
||||
let _ = tokio::fs::remove_dir_all(&legacy_stage).await;
|
||||
let _ = tokio::fs::remove_dir_all(target).await;
|
||||
let _ = tokio::fs::remove_file(target).await;
|
||||
if !create_virtual_environment(python, target, system_pip, shutdown).await {
|
||||
let _ = tokio::fs::remove_dir_all(target).await;
|
||||
return Err(BuildFailure::Bootstrap);
|
||||
}
|
||||
let target_python = venv_python(target);
|
||||
let mut pip_check = Command::new(&target_python);
|
||||
pip_check.args(["-m", "pip", "--version"]);
|
||||
if !command_success(pip_check, Duration::from_secs(30), shutdown).await {
|
||||
let mut ensurepip = Command::new(&target_python);
|
||||
ensurepip.args(["-m", "ensurepip", "--upgrade"]);
|
||||
if !command_success(ensurepip, Duration::from_secs(120), shutdown).await {
|
||||
let _ = tokio::fs::remove_dir_all(target).await;
|
||||
return Err(BuildFailure::Bootstrap);
|
||||
}
|
||||
}
|
||||
let mut pip = Command::new(&target_python);
|
||||
pip.args([
|
||||
"-m",
|
||||
"pip",
|
||||
"install",
|
||||
"--disable-pip-version-check",
|
||||
"--no-input",
|
||||
"--no-cache-dir",
|
||||
"--retries",
|
||||
"3",
|
||||
"--timeout",
|
||||
"30",
|
||||
]);
|
||||
pip.args(CERTBOT_PACKAGES.iter().copied());
|
||||
if !command_success(pip, Duration::from_secs(600), shutdown).await
|
||||
|| !managed_environment_valid(target, shutdown).await
|
||||
{
|
||||
let _ = tokio::fs::remove_dir_all(target).await;
|
||||
return Err(BuildFailure::Install);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
include!("runtime_bootstrap.rs");
|
||||
|
||||
async fn ensure_runtime(state: &App) -> Result<RuntimeLaunch, String> {
|
||||
let _permit = state
|
||||
@@ -309,7 +221,7 @@ async fn ensure_runtime(state: &App) -> Result<RuntimeLaunch, String> {
|
||||
return Ok(RuntimeLaunch {
|
||||
python: venv_python(&managed),
|
||||
prepend_path: Some(venv_bin(&managed)),
|
||||
managed_certbot_python: Some(venv_python(&managed)),
|
||||
managed_certbot_executable: Some(venv_certbot(&managed)),
|
||||
});
|
||||
}
|
||||
let distro_certbot = find_on_path("certbot");
|
||||
@@ -357,7 +269,7 @@ async fn ensure_runtime(state: &App) -> Result<RuntimeLaunch, String> {
|
||||
return Ok(RuntimeLaunch {
|
||||
python: venv_python(&managed),
|
||||
prepend_path: Some(venv_bin(&managed)),
|
||||
managed_certbot_python: Some(venv_python(&managed)),
|
||||
managed_certbot_executable: Some(venv_certbot(&managed)),
|
||||
});
|
||||
}
|
||||
if distro_certbot_available {
|
||||
@@ -374,13 +286,23 @@ async fn ensure_runtime(state: &App) -> Result<RuntimeLaunch, String> {
|
||||
return Ok(RuntimeLaunch {
|
||||
python,
|
||||
prepend_path: None,
|
||||
managed_certbot_python: None,
|
||||
managed_certbot_executable: None,
|
||||
});
|
||||
}
|
||||
let message = if build == Err(BuildFailure::Bootstrap) && !system_pip {
|
||||
"acme.runtime_pip_missing"
|
||||
} else {
|
||||
"acme.runtime_setup_failed"
|
||||
tracing::warn!(
|
||||
python = %python.display(),
|
||||
managed = %managed.display(),
|
||||
system_pip,
|
||||
failure = ?build,
|
||||
"managed ACME runtime setup failed; no system Certbot fallback available"
|
||||
);
|
||||
let message = match build {
|
||||
Err(BuildFailure::CreateEnvironment) if !system_pip => "acme.runtime_pip_missing",
|
||||
Err(BuildFailure::CreateEnvironment) => "acme.runtime_venv_failed",
|
||||
Err(BuildFailure::PreparePip) => "acme.runtime_venv_pip_failed",
|
||||
Err(BuildFailure::InstallPackages) => "acme.runtime_certbot_install_failed",
|
||||
Err(BuildFailure::Validate) => "acme.runtime_certbot_validation_failed",
|
||||
Ok(()) => "acme.runtime_setup_failed",
|
||||
};
|
||||
state.acme.set_runtime(RuntimeStatus {
|
||||
status: "unavailable",
|
||||
@@ -428,19 +350,20 @@ async fn worker(state: &App, directory: PathBuf, raw: Zeroizing<String>) -> Resu
|
||||
command
|
||||
.arg("-I")
|
||||
.arg("-c")
|
||||
.arg(include_str!("../../scripts/acme_provider.py"))
|
||||
.arg(include_str!("../../scripts/runtime/acme_provider.py"))
|
||||
.arg("--cert-dir")
|
||||
.arg(&directory)
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::null())
|
||||
.kill_on_drop(true);
|
||||
command.env_remove("RUSTPROXY_CERTBOT_EXECUTABLE");
|
||||
command.env_remove("RUSTPROXY_CERTBOT_PYTHON");
|
||||
if let Some(prepend) = launch.prepend_path.as_deref() {
|
||||
command.env("PATH", merged_path(prepend)?);
|
||||
}
|
||||
if let Some(python) = launch.managed_certbot_python.as_deref() {
|
||||
command.env("RUSTPROXY_CERTBOT_PYTHON", python);
|
||||
if let Some(certbot) = launch.managed_certbot_executable.as_deref() {
|
||||
command.env("RUSTPROXY_CERTBOT_EXECUTABLE", certbot);
|
||||
}
|
||||
#[cfg(unix)]
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user