From 2713cd02962d2e4e6b7ce921fe905355d2b4ba10 Mon Sep 17 00:00:00 2001 From: Din Music Date: Fri, 20 Sep 2024 09:52:35 +0000 Subject: [PATCH] instance: Allow instance rename Signed-off-by: Din Music --- internal/instance/resource_instance.go | 39 +++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/internal/instance/resource_instance.go b/internal/instance/resource_instance.go index 45e230ac..25a51255 100644 --- a/internal/instance/resource_instance.go +++ b/internal/instance/resource_instance.go @@ -82,9 +82,6 @@ func (r InstanceResource) Schema(ctx context.Context, _ resource.SchemaRequest, Attributes: map[string]schema.Attribute{ "name": schema.StringAttribute{ Required: true, - PlanModifiers: []planmodifier.String{ - stringplanmodifier.RequiresReplace(), - }, }, "description": schema.StringAttribute{ @@ -789,13 +786,25 @@ func (r InstanceResource) Update(ctx context.Context, req resource.UpdateRequest return } - instanceName := plan.Name.ValueString() + instanceName := state.Name.ValueString() instanceState, _, err := server.GetInstanceState(instanceName) if err != nil { resp.Diagnostics.AddError(fmt.Sprintf("Failed to retrieve state of instance %q", instanceName), err.Error()) return } + // Handle instance rename if instance is already stopped. + newInstanceName := plan.Name.ValueString() + if instanceName != newInstanceName && isInstanceStopped(*instanceState) { + err := renameInstance(ctx, server, instanceName, newInstanceName) + if err != nil { + resp.Diagnostics.AddError(fmt.Sprintf("Failed to rename instance %q", instanceName), err.Error()) + return + } + + instanceName = newInstanceName + } + // Indicates if the instance has been just started. instanceStarted := false instanceRunning := isInstanceOperational(*instanceState) @@ -832,6 +841,17 @@ func (r InstanceResource) Update(ctx context.Context, req resource.UpdateRequest } } + // Handle instance rename. + if instanceName != newInstanceName { + err := renameInstance(ctx, server, instanceName, newInstanceName) + if err != nil { + resp.Diagnostics.AddError(fmt.Sprintf("Failed to rename instance %q", instanceName), err.Error()) + return + } + + instanceName = newInstanceName + } + // Get instance. instance, etag, err := server.GetInstance(instanceName) if err != nil { @@ -1307,6 +1327,17 @@ func stopInstance(ctx context.Context, server lxd.InstanceServer, instanceName s return true, nil } +// renameInstance renames an instance with the given old name to a new name. +// Instance has to be stopped beforehand, otherwise the operation will fail. +func renameInstance(ctx context.Context, server lxd.InstanceServer, oldName string, newName string) error { + op, err := server.RenameInstance(oldName, api.InstancePost{Name: newName}) + if err != nil { + return err + } + + return op.WaitContext(ctx) +} + // waitInstanceNetwork waits for an instance with the given name to receive // an IPv4 address on any interface (excluding loopback). This should be // called only if the instance is running.