Skip to content

Commit bafd442

Browse files
authored
cli: improve code tunnel with existing tunnels (microsoft#188091)
- Apply the name/tunnel-name from the CLI to automatically (do a normal tag sync). Previously the CLI could host tunnels that were unusable unless the consumer did the tag setup, which they should not. - Allow "tunnel ID" to be specified in the new `<id>.<cluster>` format that devtunnels has adopted.
1 parent 1bd2fc7 commit bafd442

File tree

3 files changed

+59
-20
lines changed

3 files changed

+59
-20
lines changed

cli/src/commands/args.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,7 @@ pub enum OutputFormat {
548548
#[derive(Args, Clone, Debug, Default)]
549549
pub struct ExistingTunnelArgs {
550550
/// Name you'd like to assign preexisting tunnel to use to connect the tunnel
551+
/// Old option, new code sohuld just use `--name`.
551552
#[clap(long, hide = true)]
552553
pub tunnel_name: Option<String>,
553554

cli/src/commands/tunnels.rs

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,20 +59,31 @@ impl From<AuthProvider> for crate::auth::AuthProvider {
5959
}
6060
}
6161

62-
impl From<ExistingTunnelArgs> for Option<dev_tunnels::ExistingTunnel> {
63-
fn from(d: ExistingTunnelArgs) -> Option<dev_tunnels::ExistingTunnel> {
64-
if let (Some(tunnel_id), Some(tunnel_name), Some(cluster), Some(host_token)) =
65-
(d.tunnel_id, d.tunnel_name, d.cluster, d.host_token)
66-
{
62+
fn fulfill_existing_tunnel_args(
63+
d: ExistingTunnelArgs,
64+
name_arg: &Option<String>,
65+
) -> Option<dev_tunnels::ExistingTunnel> {
66+
let tunnel_name = d.tunnel_name.or_else(|| name_arg.clone());
67+
68+
match (d.tunnel_id, d.cluster, d.host_token) {
69+
(Some(tunnel_id), None, Some(host_token)) => {
70+
let i = tunnel_id.find('.')?;
6771
Some(dev_tunnels::ExistingTunnel {
68-
tunnel_id,
72+
tunnel_id: tunnel_id[..i].to_string(),
73+
cluster: tunnel_id[i + 1..].to_string(),
6974
tunnel_name,
7075
host_token,
71-
cluster,
7276
})
73-
} else {
74-
None
7577
}
78+
79+
(Some(tunnel_id), Some(cluster), Some(host_token)) => Some(dev_tunnels::ExistingTunnel {
80+
tunnel_id,
81+
tunnel_name,
82+
host_token,
83+
cluster,
84+
}),
85+
86+
_ => None,
7687
}
7788
}
7889

@@ -412,8 +423,10 @@ async fn serve_with_csa(
412423
let auth = Auth::new(&paths, log.clone());
413424
let mut dt = dev_tunnels::DevTunnels::new(&log, auth, &paths);
414425
loop {
415-
let tunnel = if let Some(d) = gateway_args.tunnel.clone().into() {
416-
dt.start_existing_tunnel(d).await
426+
let tunnel = if let Some(t) =
427+
fulfill_existing_tunnel_args(gateway_args.tunnel.clone(), &gateway_args.name)
428+
{
429+
dt.start_existing_tunnel(t).await
417430
} else {
418431
dt.start_new_launcher_tunnel(gateway_args.name.as_deref(), gateway_args.random_name)
419432
.await

cli/src/tunnels/dev_tunnels.rs

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ lazy_static! {
229229
#[derive(Clone, Debug)]
230230
pub struct ExistingTunnel {
231231
/// Name you'd like to assign preexisting tunnel to use to connect to the VS Code Server
232-
pub tunnel_name: String,
232+
pub tunnel_name: Option<String>,
233233

234234
/// Token to authenticate and use preexisting tunnel
235235
pub host_token: String,
@@ -393,7 +393,12 @@ impl DevTunnels {
393393
};
394394

395395
tunnel = self
396-
.sync_tunnel_tags(&persisted.name, tunnel, &HOST_TUNNEL_REQUEST_OPTIONS)
396+
.sync_tunnel_tags(
397+
&self.client,
398+
&persisted.name,
399+
tunnel,
400+
&HOST_TUNNEL_REQUEST_OPTIONS,
401+
)
397402
.await?;
398403

399404
let locator = TunnelLocator::try_from(&tunnel).unwrap();
@@ -532,6 +537,7 @@ impl DevTunnels {
532537
/// other version tags.
533538
async fn sync_tunnel_tags(
534539
&self,
540+
client: &TunnelManagementClient,
535541
name: &str,
536542
tunnel: Tunnel,
537543
options: &TunnelRequestOptions,
@@ -558,7 +564,7 @@ impl DevTunnels {
558564
let result = spanf!(
559565
self.log,
560566
self.log.span("dev-tunnel.protocol-tag-update"),
561-
self.client.update_tunnel(&tunnel_update, options)
567+
client.update_tunnel(&tunnel_update, options)
562568
);
563569

564570
result.map_err(|e| wrap(e, "tunnel tag update failed").into())
@@ -639,6 +645,12 @@ impl DevTunnels {
639645
Ok(())
640646
}
641647

648+
fn get_placeholder_name() -> String {
649+
let mut n = clean_hostname_for_tunnel(&gethostname::gethostname().to_string_lossy());
650+
n.make_ascii_lowercase();
651+
n
652+
}
653+
642654
async fn get_name_for_tunnel(
643655
&mut self,
644656
preferred_name: Option<&str>,
@@ -670,10 +682,7 @@ impl DevTunnels {
670682
use_random_name = true;
671683
}
672684

673-
let mut placeholder_name =
674-
clean_hostname_for_tunnel(&gethostname::gethostname().to_string_lossy());
675-
placeholder_name.make_ascii_lowercase();
676-
685+
let mut placeholder_name = Self::get_placeholder_name();
677686
if !is_name_free(&placeholder_name) {
678687
for i in 2.. {
679688
let fixed_name = format!("{}{}", placeholder_name, i);
@@ -715,7 +724,10 @@ impl DevTunnels {
715724
tunnel: ExistingTunnel,
716725
) -> Result<ActiveTunnel, AnyError> {
717726
let tunnel_details = PersistedTunnel {
718-
name: tunnel.tunnel_name,
727+
name: match tunnel.tunnel_name {
728+
Some(n) => n,
729+
None => Self::get_placeholder_name(),
730+
},
719731
id: tunnel.tunnel_id,
720732
cluster: tunnel.cluster,
721733
};
@@ -725,10 +737,23 @@ impl DevTunnels {
725737
tunnel.host_token.clone(),
726738
));
727739

740+
let client = mgmt.into();
741+
self.sync_tunnel_tags(
742+
&client,
743+
&tunnel_details.name,
744+
Tunnel {
745+
cluster_id: Some(tunnel_details.cluster.clone()),
746+
tunnel_id: Some(tunnel_details.id.clone()),
747+
..Default::default()
748+
},
749+
&HOST_TUNNEL_REQUEST_OPTIONS,
750+
)
751+
.await?;
752+
728753
self.start_tunnel(
729754
tunnel_details.locator(),
730755
&tunnel_details,
731-
mgmt.into(),
756+
client,
732757
StaticAccessTokenProvider::new(tunnel.host_token),
733758
)
734759
.await

0 commit comments

Comments
 (0)