Skip to content
Merged
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
6 changes: 5 additions & 1 deletion foxglove/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,11 @@ type CreateDeviceResponse struct {
ProjectID string `json:"projectId"`
}

type EditDeviceRequest struct {
type EditDeviceRequestQuery struct {
ProjectID string `form:"projectId,omitempty"`
}

type EditDeviceRequestBody struct {
Name string `json:"name"`
Properties map[string]interface{} `json:"properties,omitempty"`
}
Expand Down
22 changes: 17 additions & 5 deletions foxglove/api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,15 +216,23 @@ func (c *FoxgloveClient) post(

func (c *FoxgloveClient) patch(
endpoint string,
reqQuery any,
reqBody any,
target any,
) error {
buf := bytes.Buffer{}
err := json.NewEncoder(&buf).Encode(reqBody)
queryBuf := bytes.Buffer{}
encoder := form.NewEncoder(&queryBuf)
encoder.DelimitWith('/') // required to support dotted fields in query strings
err := encoder.Encode(reqQuery)
if err != nil {
return fmt.Errorf("failed to encode request: %w", err)
}
bodyBuf := bytes.Buffer{}
err = json.NewEncoder(&bodyBuf).Encode(reqBody)
if err != nil {
return fmt.Errorf("failed to encode request: %w", err)
}
req, err := http.NewRequest(http.MethodPatch, c.baseurl+endpoint, &buf)
req, err := http.NewRequest(http.MethodPatch, c.baseurl+endpoint+"?"+queryBuf.String(), &bodyBuf)
if err != nil {
return fmt.Errorf("failed to create request: %w", err)
}
Expand Down Expand Up @@ -284,12 +292,16 @@ func (c *FoxgloveClient) CreateDevice(req CreateDeviceRequest) (resp CreateDevic
return resp, err
}

func (c *FoxgloveClient) EditDevice(nameOrId string, req CreateDeviceRequest) (resp EditDeviceResponse, err error) {
func (c *FoxgloveClient) EditDevice(
nameOrId string,
reqQuery EditDeviceRequestQuery,
reqBody EditDeviceRequestBody,
) (resp EditDeviceResponse, err error) {
path, err := url.JoinPath("/v1/devices", nameOrId)
if err != nil {
return EditDeviceResponse{}, err
}
err = c.patch(path, req, &resp)
err = c.patch(path, reqQuery, reqBody, &resp)
return resp, err
}

Expand Down
5 changes: 3 additions & 2 deletions foxglove/api/mock_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ func (s *MockFoxgloveServer) createDevice(w http.ResponseWriter, r *http.Request
// Send response, but don't actually edit
func (s *MockFoxgloveServer) editDevice(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]
req := EditDeviceRequest{}
projectId := r.URL.Query().Get("projectId")
req := EditDeviceRequestBody{}
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
Expand All @@ -186,7 +187,7 @@ func (s *MockFoxgloveServer) editDevice(w http.ResponseWriter, r *http.Request)

found := false
for _, dev := range s.registeredDevices {
if dev.ID == id {
if dev.ID == id && dev.ProjectID == projectId {
found = true
}
}
Expand Down
25 changes: 16 additions & 9 deletions foxglove/cmd/devices.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@ func newAddDeviceCommand(params *baseParams) *cobra.Command {

func newEditDeviceCommand(params *baseParams) *cobra.Command {
var name string
var projectID string
var propertyPairs []string
addDeviceCmd := &cobra.Command{
editDeviceCmd := &cobra.Command{
Use: "edit",
Short: "Edit a device",
Args: cobra.ExactArgs(1),
Expand Down Expand Up @@ -119,18 +120,24 @@ func newEditDeviceCommand(params *baseParams) *cobra.Command {
reqBody.Properties = properties
}

resp, err := client.EditDevice(nameOrId, api.CreateDeviceRequest{
Name: name,
Properties: properties,
})
resp, err := client.EditDevice(
nameOrId,
api.EditDeviceRequestQuery{
ProjectID: projectID,
},
api.EditDeviceRequestBody{
Name: name,
Properties: properties,
})
if err != nil {
dief("Failed to edit device: %s", err)
}
fmt.Fprintf(os.Stderr, "Device updated: %s\n", resp.Name)
},
}
addDeviceCmd.InheritedFlags()
addDeviceCmd.PersistentFlags().StringVarP(&name, "name", "", "", "New name for the device")
addDeviceCmd.PersistentFlags().StringArrayVarP(&propertyPairs, "property", "p", []string{}, "Custom property colon-separated key value pair. Multiple may be specified.")
return addDeviceCmd
editDeviceCmd.InheritedFlags()
editDeviceCmd.PersistentFlags().StringVarP(&name, "name", "", "", "New name for the device")
editDeviceCmd.PersistentFlags().StringVarP(&projectID, "project-id", "", viper.GetString("default_project_id"), "Project ID")
editDeviceCmd.PersistentFlags().StringArrayVarP(&propertyPairs, "property", "p", []string{}, "Custom property colon-separated key value pair. Multiple may be specified.")
return editDeviceCmd
}
15 changes: 10 additions & 5 deletions foxglove/cmd/devices_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,17 @@ func TestEditDeviceCommand(t *testing.T) {
sv, err := api.NewMockServer(ctx)
assert.Nil(t, err)

t.Run("creates a device", func(t *testing.T) {
t.Run("edits a device", func(t *testing.T) {
client := api.NewMockAuthedClient(t, sv.BaseURL())
dev, err := client.EditDevice("test-device", api.CreateDeviceRequest{
Name: "new-name",
Properties: map[string]interface{}{"key": "val"},
})
dev, err := client.EditDevice(
"test-device",
api.EditDeviceRequestQuery{
ProjectID: "prj_1234abcd",
},
api.EditDeviceRequestBody{
Name: "new-name",
Properties: map[string]interface{}{"key": "val"},
})
assert.Nil(t, err)

assert.Equal(t, dev.Name, "new-name")
Expand Down
Loading