Skip to content

Commit

Permalink
Add tests for creating instances w/ different ssh configs
Browse files Browse the repository at this point in the history
  • Loading branch information
zephraph committed Jan 25, 2024
1 parent 64a2afd commit df90c2c
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 1 deletion.
184 changes: 184 additions & 0 deletions nexus/tests/integration_tests/instances.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@ use nexus_test_utils::resource_helpers::object_put;
use nexus_test_utils::resource_helpers::objects_list_page_authz;
use nexus_test_utils::resource_helpers::DiskTest;
use nexus_test_utils::start_sled_agent;
use nexus_types::external_api::params::SshKeyCreate;
use nexus_types::external_api::shared::IpKind;
use nexus_types::external_api::shared::IpRange;
use nexus_types::external_api::shared::Ipv4Range;
use nexus_types::external_api::shared::SiloIdentityMode;
use nexus_types::external_api::views::SshKey;
use nexus_types::external_api::{params, views};
use nexus_types::identity::Resource;
use omicron_common::api::external::ByteCount;
Expand Down Expand Up @@ -3282,6 +3284,188 @@ async fn test_instances_memory_greater_than_max_size(
assert!(error.message.contains("memory must be less than"));
}

#[nexus_test]
async fn test_instance_create_with_ssh_keys(
cptestctx: &ControlPlaneTestContext,
) {
let client = &cptestctx.external_client;
let instance_name = "ssh-keys";

cptestctx
.sled_agent
.sled_agent
.start_local_mock_propolis_server(&cptestctx.logctx.log)
.await
.unwrap();

// Test pre-reqs
DiskTest::new(&cptestctx).await;
create_project_and_pool(&client).await;

// Add some SSH keys
let key_configs = vec![
("key1", "an SSH public key", "ssh-test AAAAAAAA"),
("key2", "another SSH public key", "ssh-test BBBBBBBB"),
("key3", "yet another public key", "ssh-test CCCCCCCC"),
];
let mut user_keys: Vec<SshKey> = Vec::new();
for (name, description, public_key) in &key_configs {
let new_key: SshKey = NexusRequest::objects_post(
client,
"/v1/me/ssh-keys",
&SshKeyCreate {
identity: IdentityMetadataCreateParams {
name: name.parse().unwrap(),
description: description.to_string(),
},
public_key: public_key.to_string(),
},
)
.authn_as(AuthnMode::PrivilegedUser)
.execute()
.await
.expect("failed to make POST request")
.parsed_body()
.unwrap();
assert_eq!(new_key.identity.name.as_str(), *name);
assert_eq!(new_key.identity.description, *description);
assert_eq!(new_key.public_key, *public_key);
user_keys.push(new_key);
}

// Create an instance
let instance_params = params::InstanceCreate {
identity: IdentityMetadataCreateParams {
name: instance_name.parse().unwrap(),
description: String::from("probably serving data"),
},
ncpus: InstanceCpuCount::try_from(2).unwrap(),
memory: ByteCount::from_gibibytes_u32(4),
// By default should transfer all profile keys
ssh_keys: None,
start: false,
hostname: instance_name.to_string(),
user_data: vec![],
network_interfaces: params::InstanceNetworkInterfaceAttachment::Default,
external_ips: vec![],
disks: vec![],
};

let builder =
RequestBuilder::new(client, http::Method::POST, &get_instances_url())
.body(Some(&instance_params))
.expect_status(Some(http::StatusCode::CREATED));

let response = NexusRequest::new(builder)
.authn_as(AuthnMode::PrivilegedUser)
.execute()
.await
.expect("Expected instance creation!");

let instance = response.parsed_body::<Instance>().unwrap();

let keys = objects_list_page_authz::<SshKey>(
client,
format!("/v1/instances/{}/ssh-public-keys", instance.identity.id)
.as_str(),
)
.await
.items;

assert_eq!(keys[0], user_keys[0]);
assert_eq!(keys[1], user_keys[1]);
assert_eq!(keys[2], user_keys[2]);

// Test creating an instance with only allow listed keys

let instance_name = "ssh-keys-2";
// Create an instance
let instance_params = params::InstanceCreate {
identity: IdentityMetadataCreateParams {
name: instance_name.parse().unwrap(),
description: String::from("probably serving data"),
},
ncpus: InstanceCpuCount::try_from(2).unwrap(),
memory: ByteCount::from_gibibytes_u32(4),
// Should only transfer the first key
ssh_keys: Some(vec![user_keys[0].identity.name.clone().into()]),
start: false,
hostname: instance_name.to_string(),
user_data: vec![],
network_interfaces: params::InstanceNetworkInterfaceAttachment::Default,
external_ips: vec![],
disks: vec![],
};

let builder =
RequestBuilder::new(client, http::Method::POST, &get_instances_url())
.body(Some(&instance_params))
.expect_status(Some(http::StatusCode::CREATED));

let response = NexusRequest::new(builder)
.authn_as(AuthnMode::PrivilegedUser)
.execute()
.await
.expect("Expected instance creation!");

let instance = response.parsed_body::<Instance>().unwrap();

let keys = objects_list_page_authz::<SshKey>(
client,
format!("/v1/instances/{}/ssh-public-keys", instance.identity.id)
.as_str(),
)
.await
.items;

assert_eq!(keys.len(), 1);
assert_eq!(keys[0], user_keys[0]);

// Test creating an instance with no keys

let instance_name = "ssh-keys-3";
// Create an instance
let instance_params = params::InstanceCreate {
identity: IdentityMetadataCreateParams {
name: instance_name.parse().unwrap(),
description: String::from("probably serving data"),
},
ncpus: InstanceCpuCount::try_from(2).unwrap(),
memory: ByteCount::from_gibibytes_u32(4),
// Should transfer no keys
ssh_keys: Some(vec![]),
start: false,
hostname: instance_name.to_string(),
user_data: vec![],
network_interfaces: params::InstanceNetworkInterfaceAttachment::Default,
external_ips: vec![],
disks: vec![],
};

let builder =
RequestBuilder::new(client, http::Method::POST, &get_instances_url())
.body(Some(&instance_params))
.expect_status(Some(http::StatusCode::CREATED));

let response = NexusRequest::new(builder)
.authn_as(AuthnMode::PrivilegedUser)
.execute()
.await
.expect("Expected instance creation!");

let instance = response.parsed_body::<Instance>().unwrap();

let keys = objects_list_page_authz::<SshKey>(
client,
format!("/v1/instances/{}/ssh-public-keys", instance.identity.id)
.as_str(),
)
.await
.items;

assert_eq!(keys.len(), 0);
}

async fn expect_instance_start_fail_507(
client: &ClientTestContext,
instance_name: &str,
Expand Down
4 changes: 3 additions & 1 deletion nexus/types/src/external_api/views.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,9 @@ pub struct Role {
// SSH KEYS

/// View of an SSH Key
#[derive(ObjectIdentity, Clone, Debug, Deserialize, Serialize, JsonSchema)]
#[derive(
ObjectIdentity, Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq,
)]
pub struct SshKey {
#[serde(flatten)]
pub identity: IdentityMetadata,
Expand Down

0 comments on commit df90c2c

Please sign in to comment.