Skip to content
Open
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
84 changes: 84 additions & 0 deletions pkg/cmd/rename.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package cmd

import (
"context"
"fmt"
"net/http"
"net/url"

"github.com/dedalus-labs/dedalus-cli/internal/apiquery"
"github.com/dedalus-labs/dedalus-go"
"github.com/dedalus-labs/dedalus-go/option"
"github.com/urfave/cli/v3"
)

type renameMachineResponse struct {
MachineID string `json:"machine_id"`
Name string `json:"name"`
}

func init() {
Command.Commands = append(Command.Commands, &cli.Command{
Name: "rename",
Usage: "Rename a machine",
UsageText: "dedalus rename <current> <new-name>",
Category: "MACHINE",
Suggest: true,
Action: handleRename,
HideHelpCommand: true,
})
}

func handleRename(ctx context.Context, cmd *cli.Command) error {
args := cmd.Args().Slice()
if len(args) != 2 {
return fmt.Errorf("expected a current machine ID or name and a new name; usage: dedalus rename <current> <new-name>")
}
current, newName := args[0], args[1]

options, err := flagOptions(
cmd,
apiquery.NestedQueryFormatBrackets,
apiquery.ArrayQueryFormatRepeat,
ApplicationJSON,
false,
)
if err != nil {
return err
}

client := dedalus.NewClient(getDefaultRequestOptions(cmd)...)
result, err := renameMachine(ctx, &client, current, newName, options...)
if err != nil {
return err
}
acceptedName := result.Name
if acceptedName == "" {
acceptedName = newName
}

fmt.Printf("Successfully renamed %s to %s\nmachine-id: %s\n", current, acceptedName, result.MachineID)
return nil
}

func renameMachine(
ctx context.Context,
client *dedalus.Client,
current string,
newName string,
options ...option.RequestOption,
) (*renameMachineResponse, error) {
var result renameMachineResponse
err := client.Execute(
ctx,
http.MethodPatch,
fmt.Sprintf("v1/machines/%s", url.PathEscape(current)),
map[string]string{"name": newName},
&result,
options...,
)
if err != nil {
return nil, err
}
return &result, nil
}
55 changes: 55 additions & 0 deletions pkg/cmd/rename_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package cmd

import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"

"github.com/dedalus-labs/dedalus-go"
"github.com/dedalus-labs/dedalus-go/option"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestRenameMachine(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
assert.Equal(t, http.MethodPatch, request.Method)
assert.Equal(t, "/v1/machines/hotel-california", request.URL.Path)

var body map[string]string
require.NoError(t, json.NewDecoder(request.Body).Decode(&body))
assert.Equal(t, map[string]string{"name": "breakfast"}, body)

response.Header().Set("Content-Type", "application/json")
_, _ = response.Write([]byte(`{"machine_id":"dm-0198abc123","name":"breakfast"}`))
}))
defer server.Close()

client := dedalus.NewClient(option.WithBaseURL(server.URL))
result, err := renameMachine(context.Background(), &client, "hotel-california", "breakfast")

require.NoError(t, err)
assert.Equal(t, "dm-0198abc123", result.MachineID)
assert.Equal(t, "breakfast", result.Name)
}

func TestRenameMachineSurfacesServerMessage(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(response http.ResponseWriter, _ *http.Request) {
response.Header().Set("Content-Type", "application/json")
response.WriteHeader(http.StatusUnprocessableEntity)
_ = json.NewEncoder(response).Encode(map[string]string{
"error_code": "MACHINE_NAME_INVALID",
"message": `invalid name "My Box": names are lowercase with no spaces`,
})
}))
defer server.Close()

client := dedalus.NewClient(option.WithBaseURL(server.URL))
_, err := renameMachine(context.Background(), &client, "dm-0198abc123", "My Box")

require.Error(t, err)
assert.Contains(t, err.Error(), "MACHINE_NAME_INVALID")
assert.Contains(t, err.Error(), "names are lowercase with no spaces")
}