From 14953d6c9e7db300618efa67f5c175243cd8846d Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Mon, 11 Mar 2024 13:17:38 +1100 Subject: [PATCH 1/2] WIP Dobby: method to transfer image to @regions I'm not sure what should be handled by what. I can totally see an argument for Dobby having a method 'transfer_image_to_region()', note singular and have the InABox reactor handle transferring to multiple regions. I can also see how ignoring those 422 errors is a bit weird to have by default, might be worth having the method accept an argument on whether to ignore specific errors or to just 'die "..." unless $res->is_success' --- lib/Dobby/Client.pm | 54 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/lib/Dobby/Client.pm b/lib/Dobby/Client.pm index 4998e7f9..50fc7c13 100644 --- a/lib/Dobby/Client.pm +++ b/lib/Dobby/Client.pm @@ -142,6 +142,60 @@ async sub delete_url ($self, $path) { return; } +async sub transfer_image_to_regions ($self, $image, $regions) { + + my $image_id = $image->{id}; + + for my $region ($regions->@*) { + next if grep { $_ eq $region } $image->{regions}->@*; + + my $res = await $self->http->do_request( + method => 'POST', + uri => $self->api_base . "/images/$image_id/actions", + headers => { + 'Authorization' => "Bearer " . $self->bearer_token, + }, + + content_type => 'application/json', + content => encode_json({ + type => 'transfer', + region => $region, + }), + ); + + next if $res->is_success; + + # # # notes + # # # if an image has already been transferred we get a 422 code and this reply + # # # { + # # # "id": "unprocessable_entity", + # # # "message": "This image has already been transferred to this region." + # # # } + # # # If an image transfer is in progress we get a 422 and this reply + # # # { + # # # "id": "unprocessable_entity", + # # # "message": "The image is already being transferred to that region." + # # # } + # # # We shouldn't encounter the former (well small race between the last time we checked and the upcoming post) because we check in the for loop + # # # But we will definitely encounter cases where someone might try to spin up a box after the transfer has been requested but it isn't there yet + # # # we need to handle that case, ideally we should just handle both + + # Handle errors we expect + # 1. We've already requested the transfer and it is still in progress + # 2. We've raced and the transfer has completed since we got $image + if (! $res->is_success && $res->code == 422) { + my $json = $res->decoded_content(charset => undef); + my $data = decode_json($json); + # transfer already in progress + next if $data->{message} eq "The image is already being transferred to that region."; + # race! + next if $data->{message} eq "This image has already been transferred to this region."; + } + + die "error replication image $image_id to $region: " . $res->as_string; + } +} + async sub create_droplet ($self, $arg) { state @required_keys = qw( name region size tags image ssh_keys ); From 8495249d3b350caac2d5e754354ae8ece385956f Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Mon, 11 Mar 2024 13:18:17 +1100 Subject: [PATCH 2/2] WIP InABox: replicate fminabox to all configured regions If on box create we detect that the image isn't available in all our regions, request they be replicated there --- lib/Synergy/Reactor/InABox.pm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Synergy/Reactor/InABox.pm b/lib/Synergy/Reactor/InABox.pm index 9526378d..83e48992 100644 --- a/lib/Synergy/Reactor/InABox.pm +++ b/lib/Synergy/Reactor/InABox.pm @@ -260,6 +260,8 @@ async sub handle_create ($self, $event, $switches) { join ', ', grep { $snapshot_regions{$_} } $self->box_datacentres->@*; + await $self->dobby->transfer_image_to_regions($snapshot, $self->box_datacentres); + if ($compatible_regions) { return await $event->reply( "I'm unable to create snapshot in region '$region'. Available compatible regions are $compatible_regions."