Skip to content

Commit e14bb15

Browse files
committed
Introducing ota cancel command
1 parent 4022ef6 commit e14bb15

File tree

5 files changed

+130
-2
lines changed

5 files changed

+130
-2
lines changed

cli/ota/cancel.go

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// This file is part of arduino-cloud-cli.
2+
//
3+
// Copyright (C) 2021 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This program is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU Affero General Public License as published
7+
// by the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU Affero General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU Affero General Public License
16+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
18+
package ota
19+
20+
import (
21+
"fmt"
22+
"os"
23+
24+
"github.com/arduino/arduino-cli/cli/errorcodes"
25+
"github.com/arduino/arduino-cli/cli/feedback"
26+
"github.com/arduino/arduino-cloud-cli/command/ota"
27+
"github.com/arduino/arduino-cloud-cli/config"
28+
"github.com/spf13/cobra"
29+
)
30+
31+
type cancelFlags struct {
32+
otaID string
33+
}
34+
35+
func initOtaCancelCommand() *cobra.Command {
36+
flags := &statusFlags{}
37+
uploadCommand := &cobra.Command{
38+
Use: "cancel",
39+
Short: "OTA cancel",
40+
Long: "Cancel OTA by OTA ID",
41+
Run: func(cmd *cobra.Command, args []string) {
42+
if err := runOtaCancelCommand(flags); err != nil {
43+
feedback.Errorf("Error during ota cancel: %v", err)
44+
os.Exit(errorcodes.ErrGeneric)
45+
}
46+
},
47+
}
48+
uploadCommand.Flags().StringVarP(&flags.otaID, "ota-id", "o", "", "OTA ID")
49+
50+
return uploadCommand
51+
}
52+
53+
func runOtaCancelCommand(flags *statusFlags) error {
54+
if flags.otaID == "" {
55+
return fmt.Errorf("required flag \"ota-id\" not set")
56+
}
57+
58+
cred, err := config.RetrieveCredentials()
59+
if err != nil {
60+
return fmt.Errorf("retrieving credentials: %w", err)
61+
}
62+
63+
return ota.PrintOtaStatus(flags.otaID, flags.otaIDs, flags.deviceId, cred, int(flags.limit), flags.sort)
64+
}

cli/ota/ota.go

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ func NewCommand() *cobra.Command {
3333
otaCommand.AddCommand(initOtaStatusCommand())
3434
otaCommand.AddCommand(initEncodeBinaryCommand())
3535
otaCommand.AddCommand(initDecodeHeaderCommand())
36+
otaCommand.AddCommand(initOtaCancelCommand())
3637

3738
return otaCommand
3839
}

cli/ota/status.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func initOtaStatusCommand() *cobra.Command {
4343
Short: "OTA status",
4444
Long: "Get OTA status by OTA or device ID",
4545
Run: func(cmd *cobra.Command, args []string) {
46-
if err := runOtaStatusCommand(flags); err != nil {
46+
if err := runOtaCancelCommand(flags); err != nil {
4747
feedback.Errorf("Error during ota get status: %v", err)
4848
os.Exit(errorcodes.ErrGeneric)
4949
}

command/ota/cancel.go

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package ota
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/arduino/arduino-cli/cli/feedback"
7+
"github.com/arduino/arduino-cloud-cli/config"
8+
otaapi "github.com/arduino/arduino-cloud-cli/internal/ota-api"
9+
)
10+
11+
func CancelOta(otaid string, cred *config.Credentials) error {
12+
13+
if feedback.GetFormat() == feedback.JSONMini {
14+
return fmt.Errorf("jsonmini format is not supported for this command")
15+
}
16+
17+
otapi := otaapi.NewClient(cred)
18+
19+
if otaid != "" {
20+
_, err := otapi.CancelOta(otaid)
21+
if err != nil {
22+
return err
23+
}
24+
}
25+
26+
return nil
27+
}

internal/ota-api/client.go

+37-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,11 @@ func NewClient(credentials *config.Credentials) *OtaApiClient {
5858
}
5959

6060
func (c *OtaApiClient) performGetRequest(endpoint, token string) (*http.Response, error) {
61-
req, err := http.NewRequest("GET", endpoint, nil)
61+
return c.performRequest(endpoint, "GET", token)
62+
}
63+
64+
func (c *OtaApiClient) performRequest(endpoint, method, token string) (*http.Response, error) {
65+
req, err := http.NewRequest(method, endpoint, nil)
6266
if err != nil {
6367
return nil, err
6468
}
@@ -205,3 +209,35 @@ func (c *OtaApiClient) GetOtaStatusByDeviceID(deviceID string, limit int, order
205209

206210
return nil, err
207211
}
212+
213+
func (c *OtaApiClient) CancelOta(otaid string) (bool, error) {
214+
215+
if otaid == "" {
216+
return false, fmt.Errorf("invalid ota-id: empty")
217+
}
218+
219+
userRequestToken, err := c.src.Token()
220+
if err != nil {
221+
if strings.Contains(err.Error(), "401") {
222+
return false, errors.New("wrong credentials")
223+
}
224+
return false, fmt.Errorf("cannot retrieve a valid token: %w", err)
225+
}
226+
227+
endpoint := c.host + "/ota/v1/ota/" + otaid + "/cancel"
228+
res, err := c.performRequest(endpoint, "PUT", userRequestToken.AccessToken)
229+
if err != nil {
230+
return false, err
231+
}
232+
defer res.Body.Close()
233+
234+
if res.StatusCode == 200 {
235+
return true, nil
236+
} else if res.StatusCode == 404 || res.StatusCode == 400 {
237+
return false, fmt.Errorf("ota-id %s not found", otaid)
238+
} else if res.StatusCode == 409 {
239+
return false, ErrAlreadyInProgress
240+
}
241+
242+
return false, err
243+
}

0 commit comments

Comments
 (0)