cli: publish availability of wsl on tunnel tags (#186016)

I plan to use this in the explorer to add a 'connect to wsl' button on relevant tunnels
This commit is contained in:
Connor Peet
2023-06-23 12:12:18 -07:00
committed by GitHub
parent e64712a094
commit d0d97015b0
3 changed files with 98 additions and 16 deletions

View File

@@ -12,6 +12,7 @@ pub mod shutdown_signal;
pub mod singleton_client;
pub mod singleton_server;
mod wsl_detect;
mod challenge;
mod control_server;
mod nosleep;

View File

@@ -4,8 +4,7 @@
*--------------------------------------------------------------------------------------------*/
use crate::auth;
use crate::constants::{
CONTROL_PORT, IS_INTERACTIVE_CLI, PROTOCOL_VERSION_TAG, PROTOCOL_VERSION_TAG_PREFIX,
TUNNEL_SERVICE_USER_AGENT,
CONTROL_PORT, IS_INTERACTIVE_CLI, PROTOCOL_VERSION_TAG, TUNNEL_SERVICE_USER_AGENT,
};
use crate::state::{LauncherPaths, PersistedState};
use crate::util::errors::{
@@ -32,6 +31,8 @@ use tunnels::management::{
NO_REQUEST_OPTIONS,
};
use super::wsl_detect::is_wsl_installed;
#[derive(Clone, Serialize, Deserialize)]
pub struct PersistedTunnel {
pub name: String,
@@ -304,7 +305,7 @@ impl DevTunnels {
return Ok((full_tunnel, persisted));
}
full_tunnel.tags = vec![name.to_string(), VSCODE_CLI_TUNNEL_TAG.to_string()];
full_tunnel.tags = self.get_tags(&name);
let new_tunnel = spanf!(
self.log,
@@ -383,11 +384,9 @@ impl DevTunnels {
}
};
if !tunnel.tags.iter().any(|t| t == PROTOCOL_VERSION_TAG) {
tunnel = self
.update_protocol_version_tag(tunnel, &HOST_TUNNEL_REQUEST_OPTIONS)
.await?;
}
tunnel = self
.sync_tunnel_tags(&persisted.name, tunnel, &HOST_TUNNEL_REQUEST_OPTIONS)
.await?;
let locator = TunnelLocator::try_from(&tunnel).unwrap();
let host_token = get_host_token_from_tunnel(&tunnel);
@@ -504,23 +503,40 @@ impl DevTunnels {
}
}
/// Gets the expected tunnel tags
fn get_tags(&self, name: &str) -> Vec<String> {
let mut tags = vec![
name.to_string(),
PROTOCOL_VERSION_TAG.to_string(),
VSCODE_CLI_TUNNEL_TAG.to_string(),
];
if is_wsl_installed(&self.log) {
tags.push("_wsl".to_string())
}
tags
}
/// Ensures the tunnel contains a tag for the current PROTCOL_VERSION, and no
/// other version tags.
async fn update_protocol_version_tag(
async fn sync_tunnel_tags(
&self,
name: &str,
tunnel: Tunnel,
options: &TunnelRequestOptions,
) -> Result<Tunnel, AnyError> {
let new_tags = self.get_tags(name);
if vec_eq_unsorted(&tunnel.tags, &new_tags) {
return Ok(tunnel);
}
debug!(
self.log,
"Updating tunnel protocol version tag to {}", PROTOCOL_VERSION_TAG
"Updating tunnel tags {} -> {}",
tunnel.tags.join(", "),
new_tags.join(", ")
);
let mut new_tags: Vec<String> = tunnel
.tags
.into_iter()
.filter(|t| !t.starts_with(PROTOCOL_VERSION_TAG_PREFIX))
.collect();
new_tags.push(PROTOCOL_VERSION_TAG.to_string());
let tunnel_update = Tunnel {
tags: new_tags,
@@ -982,6 +998,20 @@ fn clean_hostname_for_tunnel(hostname: &str) -> String {
}
}
fn vec_eq_unsorted(a: &[String], b: &[String]) -> bool {
if a.len() != b.len() {
return false;
}
for item in a {
if !b.contains(item) {
return false;
}
}
true
}
#[cfg(test)]
mod test {
use super::*;

View File

@@ -0,0 +1,51 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
use crate::log;
#[cfg(not(windows))]
pub fn is_wsl_installed(_log: &log::Logger) -> bool {
false
}
#[cfg(windows)]
pub fn is_wsl_installed(log: &log::Logger) -> bool {
use std::{path::PathBuf, process::Command};
let system32 = {
let sys_root = match std::env::var("SystemRoot") {
Ok(s) => s,
Err(_) => return false,
};
let is_32_on_64 = std::env::var("PROCESSOR_ARCHITEW6432").is_ok();
let mut system32 = PathBuf::from(sys_root);
system32.push(if is_32_on_64 { "Sysnative" } else { "System32" });
system32
};
// Windows builds < 22000
let mut maybe_lxss = system32.join("lxss");
maybe_lxss.push("LxssManager.dll");
if maybe_lxss.exists() {
trace!(log, "wsl availability detected via lxss");
return true;
}
// Windows builds >= 22000
let maybe_wsl = system32.join("wsl.exe");
if maybe_wsl.exists() {
if let Ok(s) = Command::new(maybe_wsl).arg("--status").output() {
if s.status.success() {
trace!(log, "wsl availability detected via subprocess");
return true;
}
}
}
trace!(log, "wsl not detected");
false
}