Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 111 additions & 4 deletions smartcontract/cli/src/link/dzx_create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ use clap::Args;
use doublezero_program_common::validate_iface;
use doublezero_sdk::{
commands::{
contributor::get::GetContributorCommand, device::get::GetDeviceCommand,
link::create::CreateLinkCommand,
contributor::get::GetContributorCommand,
device::get::GetDeviceCommand,
link::{create::CreateLinkCommand, get::GetLinkCommand},
},
*,
};
Expand Down Expand Up @@ -109,6 +110,15 @@ impl CreateDZXLinkCliCommand {
));
}

if client
.get_link(GetLinkCommand {
pubkey_or_code: self.code.clone(),
})
.is_ok()
{
return Err(eyre!("Link with code '{}' already exists", self.code));
}

let (signature, pubkey) = client.create_link(CreateLinkCommand {
code: self.code.clone(),
contributor_pk,
Expand Down Expand Up @@ -142,10 +152,14 @@ mod tests {
requirements::{CHECK_BALANCE, CHECK_ID_JSON},
tests::utils::create_test_client,
};
use doublezero_program_common::types::NetworkV4;
use doublezero_sdk::{
commands::{device::get::GetDeviceCommand, link::create::CreateLinkCommand},
commands::{
device::get::GetDeviceCommand,
link::{create::CreateLinkCommand, get::GetLinkCommand},
},
get_device_pda, AccountType, CurrentInterfaceVersion, Device, DeviceStatus, DeviceType,
InterfaceStatus, LinkLinkType,
InterfaceStatus, Link, LinkLinkType, LinkStatus,
};
use doublezero_serviceability::state::device::{Interface, InterfaceType, LoopbackType};
use mockall::predicate;
Expand Down Expand Up @@ -228,6 +242,58 @@ mod tests {
max_users: 255,
users_count: 0,
};
let location3_pk = Pubkey::from_str_const("HQ2UUt18uJqKaQFJhgV9zaTdQxUZjNrsKFgoEDquCkcx");
let exchange3_pk = Pubkey::from_str_const("HQ2UUt18uJqKaQFJhgV9zaTdQxUZjNrsKFgoEDquCkce");
let device3_pk = Pubkey::from_str_const("HQ2UUt18uJqKaQFJhgV9zaTdQxUZjNrsKFgoEDquCkcf");
let device3 = Device {
account_type: AccountType::Device,
index: 1,
bump_seed: 255,
reference_count: 0,
code: "test".to_string(),
contributor_pk,
location_pk: location3_pk,
exchange_pk: exchange3_pk,
device_type: DeviceType::Switch,
public_ip: [10, 0, 0, 1].into(),
dz_prefixes: "10.1.0.0/16".parse().unwrap(),
metrics_publisher_pk: Pubkey::default(),
status: DeviceStatus::Activated,
owner: pda_pubkey,
mgmt_vrf: "default".to_string(),
interfaces: vec![Interface::V1(CurrentInterfaceVersion {
status: InterfaceStatus::Unlinked,
name: "Ethernet1/3".to_string(),
interface_type: InterfaceType::Physical,
loopback_type: LoopbackType::None,
vlan_id: 16,
ip_net: "10.2.0.3/24".parse().unwrap(),
node_segment_idx: 0,
user_tunnel_endpoint: true,
})],
max_users: 255,
users_count: 0,
};
let link = Link {
account_type: AccountType::Link,
owner: pda_pubkey,
index: 1,
bump_seed: 255,
side_a_pk: device1_pk,
side_z_pk: device2_pk,
link_type: LinkLinkType::WAN,
bandwidth: 1000000000,
mtu: 1500,
delay_ns: 10000000000,
jitter_ns: 5000000000,
tunnel_id: 500,
tunnel_net: NetworkV4::default(),
status: LinkStatus::Activated,
code: "test".to_string(),
contributor_pk,
side_a_iface_name: "Ethernet1/1".to_string(),
side_z_iface_name: "Ethernet1/2".to_string(),
};

client
.expect_check_requirements()
Expand All @@ -245,6 +311,19 @@ mod tests {
pubkey_or_code: device2_pk.to_string(),
}))
.returning(move |_| Ok((device2_pk, device2.clone())));
client
.expect_get_device()
.with(predicate::eq(GetDeviceCommand {
pubkey_or_code: device3_pk.to_string(),
}))
.returning(move |_| Ok((device3_pk, device3.clone())));
client
.expect_get_link()
.with(predicate::eq(GetLinkCommand {
pubkey_or_code: "test".to_string(),
}))
.times(1)
.returning(move |_| Err(eyre::eyre!("Link not found")));
client
.expect_create_link()
.with(predicate::eq(CreateLinkCommand {
Expand Down Expand Up @@ -283,5 +362,33 @@ mod tests {
assert_eq!(
output_str,"Signature: 3QnHBSdd4doEF6FgpLCejqEw42UQjfvNhQJwoYDSpoBszpCCqVft4cGoneDCnZ6Ez3ujzavzUu85u6F79WtLhcsv\n"
);

client
.expect_get_link()
.with(predicate::eq(GetLinkCommand {
pubkey_or_code: "test".to_string(),
}))
.returning(move |_| Ok((Pubkey::default(), link.clone())));

let mut output = Vec::new();
let res = CreateDZXLinkCliCommand {
code: "test".to_string(),
contributor: contributor_pk.to_string(),
side_a: device2_pk.to_string(),
side_z: device3_pk.to_string(),
bandwidth: 1000000000,
mtu: 1500,
delay_ms: 10000.0,
jitter_ms: 5000.0,
side_a_interface: "Ethernet1/2".to_string(),
wait: false,
}
.execute(&client, &mut output);
assert_eq!(
res.unwrap_err().to_string(),
"Link with code 'test' already exists"
);
let output_str = String::from_utf8(output).unwrap();
assert_eq!(output_str, "");
}
}
72 changes: 69 additions & 3 deletions smartcontract/cli/src/link/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ impl UpdateLinkCliCommand {
// Check requirements
client.check_requirements(CHECK_ID_JSON | CHECK_BALANCE)?;

let (pubkey, _) = client.get_link(GetLinkCommand {
let (pubkey, link) = client.get_link(GetLinkCommand {
pubkey_or_code: self.pubkey,
})?;

Expand Down Expand Up @@ -82,6 +82,18 @@ impl UpdateLinkCliCommand {
.transpose()
.map_err(|e| eyre!("Invalid status: {e}"))?;

if let Some(ref code) = self.code {
if link.code != *code
&& client
.get_link(GetLinkCommand {
pubkey_or_code: code.clone(),
})
.is_ok()
{
return Err(eyre!("Link with code '{}' already exists", &code,));
}
}

let signature = client.update_link(UpdateLinkCommand {
pubkey,
code: self.code.clone(),
Expand Down Expand Up @@ -139,6 +151,7 @@ mod tests {
code: "co01".to_string(),
};
let (pda_pubkey, _bump_seed) = get_link_pda(&client.get_program_id(), 1);
let (pda_pubkey2, _bump_seed) = get_link_pda(&client.get_program_id(), 2);
let signature = Signature::from([
120, 138, 162, 185, 59, 209, 241, 157, 71, 157, 74, 131, 4, 87, 54, 28, 38, 180, 222,
82, 64, 62, 61, 62, 22, 46, 17, 203, 187, 136, 62, 43, 11, 38, 235, 17, 239, 82, 240,
Expand All @@ -149,7 +162,7 @@ mod tests {
let device1_pk = Pubkey::from_str_const("HQ2UUt18uJqKaQFJhgV9zaTdQxUZjNrsKFgoEDquBkcb");
let device2_pk = Pubkey::from_str_const("HQ2UUt18uJqKaQFJhgV9zaTdQxUZjNrsKFgoEDquBkcf");

let tunnel = Link {
let link1 = Link {
account_type: AccountType::Link,
index: 1,
bump_seed: 255,
Expand All @@ -170,6 +183,27 @@ mod tests {
side_z_iface_name: "eth1".to_string(),
};

let link2 = Link {
account_type: AccountType::Link,
index: 1,
bump_seed: 255,
code: "test2".to_string(),
contributor_pk,
side_a_pk: device1_pk,
side_z_pk: device2_pk,
link_type: LinkLinkType::WAN,
bandwidth: 1000000000,
mtu: 1500,
delay_ns: 10000000000,
jitter_ns: 5000000000,
tunnel_id: 1,
tunnel_net: "10.0.0.1/16".parse().unwrap(),
status: LinkStatus::Activated,
owner: pda_pubkey,
side_a_iface_name: "eth2".to_string(),
side_z_iface_name: "eth3".to_string(),
};

client
.expect_get_contributor()
.with(predicate::eq(GetContributorCommand {
Expand All @@ -185,7 +219,19 @@ mod tests {
.with(predicate::eq(GetLinkCommand {
pubkey_or_code: pda_pubkey.to_string(),
}))
.returning(move |_| Ok((pda_pubkey, tunnel.clone())));
.returning(move |_| Ok((pda_pubkey, link1.clone())));
client
.expect_get_link()
.with(predicate::eq(GetLinkCommand {
pubkey_or_code: "new_code".to_string(),
}))
.returning(move |_| Err(eyre::eyre!("Link not found")));
client
.expect_get_link()
.with(predicate::eq(GetLinkCommand {
pubkey_or_code: "test2".to_string(),
}))
.returning(move |_| Ok((pda_pubkey2, link2.clone())));
client
.expect_update_link()
.with(predicate::eq(UpdateLinkCommand {
Expand Down Expand Up @@ -221,5 +267,25 @@ mod tests {
assert_eq!(
output_str,"Signature: 3QnHBSdd4doEF6FgpLCejqEw42UQjfvNhQJwoYDSpoBszpCCqVft4cGoneDCnZ6Ez3ujzavzUu85u6F79WtLhcsv\n"
);

// try to rename code to an existing one
let mut output = Vec::new();
let res = UpdateLinkCliCommand {
pubkey: pda_pubkey.to_string(),
code: Some("test2".to_string()),
contributor: Some(contributor_pk.to_string()),
tunnel_type: None,
bandwidth: Some(1000000000),
mtu: Some(1500),
delay_ms: Some(10.0),
jitter_ms: Some(5.0),
wait: false,
status: None,
}
.execute(&client, &mut output);
assert_eq!(
res.unwrap_err().to_string(),
"Link with code 'test2' already exists"
);
}
}
Loading
Loading