Skip to content

Commit 4fa1080

Browse files
committed
Refactoring 'board' commands
1 parent acf791e commit 4fa1080

File tree

7 files changed

+104
-57
lines changed

7 files changed

+104
-57
lines changed

commands/board/attach.go

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,25 +30,23 @@ import (
3030
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
3131
discovery "github.com/arduino/board-discovery"
3232
"github.com/arduino/go-paths-helper"
33-
"google.golang.org/grpc/codes"
34-
"google.golang.org/grpc/status"
3533
)
3634

3735
var tr = i18n.Tr
3836

3937
// Attach FIXMEDOC
40-
func Attach(ctx context.Context, req *rpc.BoardAttachRequest, taskCB commands.TaskProgressCB) (*rpc.BoardAttachResponse, *status.Status) {
38+
func Attach(ctx context.Context, req *rpc.BoardAttachRequest, taskCB commands.TaskProgressCB) (*rpc.BoardAttachResponse, error) {
4139
pm := commands.GetPackageManager(req.GetInstance().GetId())
4240
if pm == nil {
43-
return nil, status.New(codes.InvalidArgument, tr("Invalid instance"))
41+
return nil, &commands.InvalidInstanceError{}
4442
}
4543
var sketchPath *paths.Path
4644
if req.GetSketchPath() != "" {
4745
sketchPath = paths.New(req.GetSketchPath())
4846
}
4947
sk, err := sketch.New(sketchPath)
5048
if err != nil {
51-
return nil, status.Newf(codes.FailedPrecondition, tr("Error opening sketch: %s"), err)
49+
return nil, &commands.SketchNotFoundError{Cause: err}
5250
}
5351

5452
boardURI := req.GetBoardUri()
@@ -64,7 +62,7 @@ func Attach(ctx context.Context, req *rpc.BoardAttachRequest, taskCB commands.Ta
6462
} else {
6563
deviceURI, err := url.Parse(boardURI)
6664
if err != nil {
67-
return nil, status.Newf(codes.InvalidArgument, tr("Invalid Device URL format: %s"), err)
65+
return nil, &commands.InvalidArgumentError{Message: tr("Invalid Device URL format"), Cause: err}
6866
}
6967

7068
var findBoardFunc func(*packagemanager.PackageManager, *discovery.Monitor, *url.URL) *cores.Board
@@ -74,7 +72,7 @@ func Attach(ctx context.Context, req *rpc.BoardAttachRequest, taskCB commands.Ta
7472
case "http", "https", "tcp", "udp":
7573
findBoardFunc = findNetworkConnectedBoard
7674
default:
77-
return nil, status.New(codes.InvalidArgument, tr("Invalid device port type provided"))
75+
return nil, &commands.InvalidArgumentError{Message: tr("Invalid device port type provided")}
7876
}
7977

8078
duration, err := time.ParseDuration(req.GetSearchTimeout())
@@ -90,7 +88,7 @@ func Attach(ctx context.Context, req *rpc.BoardAttachRequest, taskCB commands.Ta
9088
// TODO: Handle the case when no board is found.
9189
board := findBoardFunc(pm, monitor, deviceURI)
9290
if board == nil {
93-
return nil, status.Newf(codes.NotFound, tr("No supported board found at %s"), deviceURI.String())
91+
return nil, &commands.InvalidArgumentError{Message: tr("No supported board found at %s", deviceURI)}
9492
}
9593
taskCB(&rpc.TaskProgress{Name: fmt.Sprintf(tr("Board found: %s"), board.Name())})
9694

@@ -105,7 +103,7 @@ func Attach(ctx context.Context, req *rpc.BoardAttachRequest, taskCB commands.Ta
105103

106104
err = sk.ExportMetadata()
107105
if err != nil {
108-
return nil, status.Newf(codes.PermissionDenied, tr("Cannot export sketch metadata: %s"), err)
106+
return nil, &commands.PermissionDeniedError{Message: tr("Cannot export sketch metadata"), Cause: err}
109107
}
110108
taskCB(&rpc.TaskProgress{Name: fmt.Sprintf(tr("Selected fqbn: %s"), sk.Metadata.CPU.Fqbn), Completed: true})
111109
return &rpc.BoardAttachResponse{}, nil

commands/board/details.go

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,27 +21,24 @@ import (
2121
"github.com/arduino/arduino-cli/arduino/cores"
2222
"github.com/arduino/arduino-cli/commands"
2323
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
24-
"google.golang.org/grpc/codes"
25-
"google.golang.org/grpc/status"
2624
)
2725

2826
// Details returns all details for a board including tools and HW identifiers.
2927
// This command basically gather al the information and translates it into the required grpc struct properties
30-
func Details(ctx context.Context, req *rpc.BoardDetailsRequest) (*rpc.BoardDetailsResponse, *status.Status) {
28+
func Details(ctx context.Context, req *rpc.BoardDetailsRequest) (*rpc.BoardDetailsResponse, error) {
3129
pm := commands.GetPackageManager(req.GetInstance().GetId())
3230
if pm == nil {
33-
return nil, status.New(codes.InvalidArgument, tr("Invalid instance"))
31+
return nil, &commands.InvalidInstanceError{}
3432
}
3533

3634
fqbn, err := cores.ParseFQBN(req.GetFqbn())
3735
if err != nil {
38-
return nil, status.Newf(codes.InvalidArgument, tr("Error parsing fqbn: %s"), err)
36+
return nil, &commands.InvalidFQBNError{Cause: err}
3937
}
4038

4139
boardPackage, boardPlatform, board, boardProperties, boardRefPlatform, err := pm.ResolveFQBN(fqbn)
42-
4340
if err != nil {
44-
return nil, status.Newf(codes.FailedPrecondition, tr("Error loading board data: %s"), err)
41+
return nil, &commands.UnknownFQBNError{Cause: err}
4542
}
4643

4744
details := &rpc.BoardDetailsResponse{}

commands/board/list.go

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ import (
3333
"github.com/pkg/errors"
3434
"github.com/segmentio/stats/v4"
3535
"github.com/sirupsen/logrus"
36-
"google.golang.org/grpc/codes"
37-
"google.golang.org/grpc/status"
3836
)
3937

4038
var (
@@ -139,7 +137,7 @@ func identify(pm *packagemanager.PackageManager, port *discovery.Port) ([]*rpc.B
139137
logrus.Debug("Board not recognized")
140138
} else if err != nil {
141139
// this is bad, bail out
142-
return nil, errors.Wrap(err, tr("error getting board info from Arduino Cloud"))
140+
return nil, &commands.UnavailableError{Message: tr("Error getting board info from Arduino Cloud")}
143141
}
144142

145143
// add a DetectedPort entry in any case: the `Boards` field will
@@ -170,7 +168,7 @@ func identify(pm *packagemanager.PackageManager, port *discovery.Port) ([]*rpc.B
170168
}
171169

172170
// List FIXMEDOC
173-
func List(req *rpc.BoardListRequest) (r []*rpc.DetectedPort, e *status.Status) {
171+
func List(req *rpc.BoardListRequest) (r []*rpc.DetectedPort, e error) {
174172
tags := map[string]string{}
175173
// Use defer func() to evaluate tags map when function returns
176174
// and set success flag inspecting the error named return parameter
@@ -184,15 +182,15 @@ func List(req *rpc.BoardListRequest) (r []*rpc.DetectedPort, e *status.Status) {
184182

185183
pm := commands.GetPackageManager(req.GetInstance().Id)
186184
if pm == nil {
187-
return nil, status.New(codes.InvalidArgument, tr("Invalid instance"))
185+
return nil, &commands.InvalidInstanceError{}
188186
}
189187

190188
dm := pm.DiscoveryManager()
191189
if errs := dm.RunAll(); len(errs) > 0 {
192-
return nil, status.New(codes.FailedPrecondition, tr("Error getting port list: %v", errs))
190+
return nil, &commands.UnavailableError{Message: tr("Error starting board discoveries"), Cause: errs[0]}
193191
}
194192
if errs := dm.StartAll(); len(errs) > 0 {
195-
return nil, status.New(codes.FailedPrecondition, tr("Error getting port list: %v", errs))
193+
return nil, &commands.UnavailableError{Message: tr("Error starting board discoveries"), Cause: errs[0]}
196194
}
197195
defer func() {
198196
if errs := dm.StopAll(); len(errs) > 0 {
@@ -204,12 +202,12 @@ func List(req *rpc.BoardListRequest) (r []*rpc.DetectedPort, e *status.Status) {
204202
retVal := []*rpc.DetectedPort{}
205203
ports, errs := pm.DiscoveryManager().List()
206204
if len(errs) > 0 {
207-
return nil, status.New(codes.FailedPrecondition, tr("Error getting port list: %v", errs))
205+
return nil, &commands.UnavailableError{Message: tr("Error getting board list"), Cause: errs[0]}
208206
}
209207
for _, port := range ports {
210208
boards, err := identify(pm, port)
211209
if err != nil {
212-
return nil, status.New(codes.Internal, err.Error())
210+
return nil, err
213211
}
214212

215213
// boards slice can be empty at this point if neither the cores nor the
@@ -226,14 +224,14 @@ func List(req *rpc.BoardListRequest) (r []*rpc.DetectedPort, e *status.Status) {
226224

227225
// Watch returns a channel that receives boards connection and disconnection events.
228226
// The discovery process can be interrupted by sending a message to the interrupt channel.
229-
func Watch(instanceID int32, interrupt <-chan bool) (<-chan *rpc.BoardListWatchResponse, *status.Status) {
227+
func Watch(instanceID int32, interrupt <-chan bool) (<-chan *rpc.BoardListWatchResponse, error) {
230228
pm := commands.GetPackageManager(instanceID)
231229
dm := pm.DiscoveryManager()
232230

233231
runErrs := dm.RunAll()
234232
if len(runErrs) == len(dm.IDs()) {
235233
// All discoveries failed to run, we can't do anything
236-
return nil, status.New(codes.FailedPrecondition, fmt.Sprintf("%v", runErrs))
234+
return nil, &commands.UnavailableError{Message: tr("Error starting board discoveries"), Cause: runErrs[0]}
237235
}
238236

239237
eventsChan, errs := dm.StartSyncAll()

commands/board/listall.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,13 @@ import (
2222
"github.com/arduino/arduino-cli/arduino/utils"
2323
"github.com/arduino/arduino-cli/commands"
2424
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
25-
"google.golang.org/grpc/codes"
26-
"google.golang.org/grpc/status"
2725
)
2826

2927
// ListAll FIXMEDOC
30-
func ListAll(ctx context.Context, req *rpc.BoardListAllRequest) (*rpc.BoardListAllResponse, *status.Status) {
28+
func ListAll(ctx context.Context, req *rpc.BoardListAllRequest) (*rpc.BoardListAllResponse, error) {
3129
pm := commands.GetPackageManager(req.GetInstance().GetId())
3230
if pm == nil {
33-
return nil, status.New(codes.InvalidArgument, tr("Invalid instance"))
31+
return nil, &commands.InvalidInstanceError{}
3432
}
3533

3634
searchArgs := strings.Join(req.GetSearchArgs(), " ")

commands/board/search.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,16 @@ import (
2323
"github.com/arduino/arduino-cli/arduino/utils"
2424
"github.com/arduino/arduino-cli/commands"
2525
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
26-
"google.golang.org/grpc/codes"
27-
"google.golang.org/grpc/status"
2826
)
2927

3028
// Search returns all boards that match the search arg.
3129
// Boards are searched in all platforms, including those in the index that are not yet
3230
// installed. Note that platforms that are not installed don't include boards' FQBNs.
3331
// If no search argument is used all boards are returned.
34-
func Search(ctx context.Context, req *rpc.BoardSearchRequest) (*rpc.BoardSearchResponse, *status.Status) {
32+
func Search(ctx context.Context, req *rpc.BoardSearchRequest) (*rpc.BoardSearchResponse, error) {
3533
pm := commands.GetPackageManager(req.GetInstance().GetId())
3634
if pm == nil {
37-
return nil, status.New(codes.InvalidArgument, tr("Invalid instance"))
35+
return nil, &commands.InvalidInstanceError{}
3836
}
3937

4038
res := &rpc.BoardSearchResponse{Boards: []*rpc.BoardListItem{}}

commands/daemon/daemon.go

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -51,20 +51,15 @@ func convertErrorToRPCStatus(err error) error {
5151
// BoardDetails FIXMEDOC
5252
func (s *ArduinoCoreServerImpl) BoardDetails(ctx context.Context, req *rpc.BoardDetailsRequest) (*rpc.BoardDetailsResponse, error) {
5353
resp, err := board.Details(ctx, req)
54-
if err != nil {
55-
return nil, err.Err()
56-
}
57-
58-
return resp, err.Err()
54+
return resp, convertErrorToRPCStatus(err)
5955
}
6056

6157
// BoardList FIXMEDOC
6258
func (s *ArduinoCoreServerImpl) BoardList(ctx context.Context, req *rpc.BoardListRequest) (*rpc.BoardListResponse, error) {
6359
ports, err := board.List(req)
6460
if err != nil {
65-
return nil, err.Err()
61+
return nil, convertErrorToRPCStatus(err)
6662
}
67-
6863
return &rpc.BoardListResponse{
6964
Ports: ports,
7065
}, nil
@@ -73,21 +68,13 @@ func (s *ArduinoCoreServerImpl) BoardList(ctx context.Context, req *rpc.BoardLis
7368
// BoardListAll FIXMEDOC
7469
func (s *ArduinoCoreServerImpl) BoardListAll(ctx context.Context, req *rpc.BoardListAllRequest) (*rpc.BoardListAllResponse, error) {
7570
resp, err := board.ListAll(ctx, req)
76-
if err != nil {
77-
return nil, err.Err()
78-
}
79-
80-
return resp, nil
71+
return resp, convertErrorToRPCStatus(err)
8172
}
8273

8374
// BoardSearch exposes to the gRPC interface the board search command
8475
func (s *ArduinoCoreServerImpl) BoardSearch(ctx context.Context, req *rpc.BoardSearchRequest) (*rpc.BoardSearchResponse, error) {
8576
resp, err := board.Search(ctx, req)
86-
if err != nil {
87-
return nil, err.Err()
88-
}
89-
90-
return resp, nil
77+
return resp, convertErrorToRPCStatus(err)
9178
}
9279

9380
// BoardListWatch FIXMEDOC
@@ -134,9 +121,9 @@ func (s *ArduinoCoreServerImpl) BoardListWatch(stream rpc.ArduinoCoreService_Boa
134121
}
135122
}()
136123

137-
eventsChan, stat := board.Watch(msg.Instance.Id, interrupt)
138-
if stat != nil {
139-
return stat.Err()
124+
eventsChan, err := board.Watch(msg.Instance.Id, interrupt)
125+
if err != nil {
126+
return convertErrorToRPCStatus(err)
140127
}
141128

142129
for event := range eventsChan {
@@ -151,12 +138,11 @@ func (s *ArduinoCoreServerImpl) BoardListWatch(stream rpc.ArduinoCoreService_Boa
151138

152139
// BoardAttach FIXMEDOC
153140
func (s *ArduinoCoreServerImpl) BoardAttach(req *rpc.BoardAttachRequest, stream rpc.ArduinoCoreService_BoardAttachServer) error {
154-
155141
resp, err := board.Attach(stream.Context(), req,
156142
func(p *rpc.TaskProgress) { stream.Send(&rpc.BoardAttachResponse{TaskProgress: p}) },
157143
)
158144
if err != nil {
159-
return err.Err()
145+
return convertErrorToRPCStatus(err)
160146
}
161147
return stream.Send(resp)
162148
}

commands/errors.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,75 @@ func (e *FailedUploadError) Unwrap() error {
205205
func (e *FailedUploadError) ToRPCStatus() *status.Status {
206206
return status.New(codes.Internal, e.Error())
207207
}
208+
209+
// InvalidArgumentError is returned when an invalid argument is passed to the command
210+
type InvalidArgumentError struct {
211+
Message string
212+
Cause error
213+
}
214+
215+
func (e *InvalidArgumentError) Error() string {
216+
return composeErrorMsg(e.Message, e.Cause)
217+
}
218+
219+
func (e *InvalidArgumentError) Unwrap() error {
220+
return e.Cause
221+
}
222+
223+
func (e *InvalidArgumentError) ToRPCStatus() *status.Status {
224+
return status.New(codes.InvalidArgument, e.Error())
225+
}
226+
227+
// NotFoundError is returned when a resource is not found
228+
type NotFoundError struct {
229+
Message string
230+
Cause error
231+
}
232+
233+
func (e *NotFoundError) Error() string {
234+
return composeErrorMsg(e.Message, e.Cause)
235+
}
236+
237+
func (e *NotFoundError) Unwrap() error {
238+
return e.Cause
239+
}
240+
241+
func (e *NotFoundError) ToRPCStatus() *status.Status {
242+
return status.New(codes.NotFound, e.Error())
243+
}
244+
245+
// PermissionDeniedError is returned when a resource cannot be accessed or modified
246+
type PermissionDeniedError struct {
247+
Message string
248+
Cause error
249+
}
250+
251+
func (e *PermissionDeniedError) Error() string {
252+
return composeErrorMsg(e.Message, e.Cause)
253+
}
254+
255+
func (e *PermissionDeniedError) Unwrap() error {
256+
return e.Cause
257+
}
258+
259+
func (e *PermissionDeniedError) ToRPCStatus() *status.Status {
260+
return status.New(codes.PermissionDenied, e.Error())
261+
}
262+
263+
// UnavailableError is returned when a resource is temporarily not available
264+
type UnavailableError struct {
265+
Message string
266+
Cause error
267+
}
268+
269+
func (e *UnavailableError) Error() string {
270+
return composeErrorMsg(e.Message, e.Cause)
271+
}
272+
273+
func (e *UnavailableError) Unwrap() error {
274+
return e.Cause
275+
}
276+
277+
func (e *UnavailableError) ToRPCStatus() *status.Status {
278+
return status.New(codes.Unavailable, e.Error())
279+
}

0 commit comments

Comments
 (0)