Skip to content

Conversation

@cgwalters
Copy link
Collaborator

This is more convenient from the CLI and in theory we can make it race-free.

Motivated by supporting tests.

@gemini-code-assist
Copy link

Summary of Changes

Hello @cgwalters, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the libvirt run command by providing a more robust and convenient way to generate unique virtual machine names. Users can now specify a name template containing {shortuuid}, which will be automatically replaced with a unique identifier, aiming to prevent naming collisions. Additionally, a new flag allows the generated VM name to be outputted to a file, streamlining its use in automated scripts and test environments. These changes are primarily driven by the need to improve the reliability and maintainability of integration tests.

Highlights

  • Unique VM Name Generation: Introduced support for generating unique VM names directly within the libvirt run command using a {shortuuid} pattern, which replaces manual timestamp-based naming.
  • Output Generated VM ID: Added a new --write-id-to option to the libvirt run command, allowing the generated VM domain name to be written to a specified file path. This is particularly useful for scripting and test automation.
  • Integration Test Updates: All relevant integration tests have been refactored to leverage the new unique naming feature and the --write-id-to option, improving test reliability and simplifying cleanup procedures.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a convenient way to generate unique VM names directly from the CLI using a {shortuuid} template, which is a nice improvement for scripting and testing. The implementation is generally solid and includes new unit tests. My review focuses on a few areas to improve robustness and maintainability:

  • Test Robustness: The integration tests currently panic on VM creation failure without cleaning up potentially created resources. I've suggested adding cleanup logic to these failure paths to prevent leaving orphaned VMs.
  • Performance: The current method for checking name uniqueness involves a linear scan, which could be slow with many domains. I've recommended using a HashSet for more efficient lookups.
  • Test Correctness: One of the new unit tests doesn't fully validate its intended behavior. I've suggested an improvement to make it more accurate.
  • Maintainability: I've also proposed a small refactoring in the name generation logic to improve its clarity.

Overall, these are great changes that improve the usability of the tool.

Comment on lines 45 to 49
if !vm1_output.success() {
cleanup_domain(&vm1_name);
cleanup_domain(&vm2_name);

panic!("Failed to create first VM: {}", vm1_output.stderr);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If run_bcvk fails, the test panics without attempting to clean up the VM resources. Since the VM name is written to vm1_id_path before the domain creation is attempted, you can read this file to get the name and attempt a cleanup. This will make the tests more robust and prevent leaving orphaned VMs on test runners.

Suggested change
if !vm1_output.success() {
cleanup_domain(&vm1_name);
cleanup_domain(&vm2_name);
panic!("Failed to create first VM: {}", vm1_output.stderr);
}
if !vm1_output.success() {
// Attempt cleanup before panicking
let _ = std::fs::read_to_string(vm1_id_path).map(|name| cleanup_domain(name.trim()));
panic!("Failed to create first VM: {}", vm1_output.stderr);
}

Comment on lines 211 to 217
if !output.success() {
cleanup_domain(&vm_name);

panic!("Failed to create VM: {}", output.stderr);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to the other test, if run_bcvk fails here, the test panics without cleaning up resources. It's good practice to attempt cleanup in failure paths to ensure a clean test environment and prevent resource leaks.

Suggested change
if !output.success() {
cleanup_domain(&vm_name);
panic!("Failed to create VM: {}", output.stderr);
}
if !output.success() {
// Attempt cleanup before panicking
let _ = std::fs::read_to_string(id_path).map(|name| cleanup_domain(name.trim()));
panic!("Failed to create VM: {}", output.stderr);
}

Comment on lines 225 to 229
if !create_output.success() {
cleanup_domain(&domain_name);

panic!("Failed to create domain with SSH: {}", create_output.stderr);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If run_bcvk fails, the test panics without attempting to clean up the VM resources. Since the VM name is written to id_path before the domain creation is attempted, you can read this file to get the name and attempt a cleanup. This will make the tests more robust and prevent leaving orphaned VMs on test runners.

Suggested change
if !create_output.success() {
cleanup_domain(&domain_name);
panic!("Failed to create domain with SSH: {}", create_output.stderr);
}
if !create_output.success() {
// Attempt cleanup before panicking
let _ = std::fs::read_to_string(id_path).map(|name| cleanup_domain(name.trim()));
panic!("Failed to create domain with SSH: {}", create_output.stderr);
}

Comment on lines 410 to 421
// Fallback: append a counter if somehow we failed to find unique name
let shortuuid = generate_shortuuid();
let base = template.replace("{shortuuid}", &shortuuid);
let mut counter = 1;
let mut candidate = base.clone();

while existing_domains.contains(&candidate) {
counter += 1;
candidate = format!("{}-{}", base, counter);
}

candidate

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The fallback logic for generating a unique name is a bit complex and has an unusual behavior of starting its counter suffix from -2 if the base name collides. This can be simplified for better readability and more predictable behavior.

    // Fallback: append a counter if somehow we failed to find unique name
    let shortuuid = generate_shortuuid();
    let base = template.replace("{shortuuid}", &shortuuid);
    if !existing_domains.contains(&base) {
        return base;
    }

    let mut counter = 1;
    loop {
        let candidate = format!("{}-{}", base, counter);
        if !existing_domains.contains(&candidate) {
            return candidate;
        }
        counter += 1;
    }

Comment on lines +625 to +629
let parts: Vec<&str> = name.split("-bar-").collect();
assert_eq!(parts.len(), 2);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The test comment states that it verifies that both {shortuuid} placeholders are replaced with the same value, but the assertion only checks that splitting the string results in two parts. The test should be strengthened to actually compare the generated UUID parts to ensure the implementation is correct.

        let parts: Vec<&str> = name.split("-bar-").collect();
        assert_eq!(parts.len(), 2);
        let uuid_part1 = parts[0].strip_prefix("foo-").expect("name should start with 'foo-'");
        let uuid_part2 = parts[1];
        assert_eq!(uuid_part1, uuid_part2, "Both {{shortuuid}} placeholders should be replaced by the same value");

This is more convenient from the CLI and in theory we can
make it race-free.

Motivated by supporting tests.

Signed-off-by: Colin Walters <walters@verbum.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant