Skip to content

Commit 7a63d5f

Browse files
dido18lucarin91
andauthored
fix(bricks): overwrite the brick variables of an app (#44)
--------- Co-authored-by: Luca Rinaldi <l.rinaldi@arduino.cc>
1 parent a6c084e commit 7a63d5f

File tree

6 files changed

+150
-10
lines changed

6 files changed

+150
-10
lines changed

internal/orchestrator/bricks/bricks.go

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -248,25 +248,24 @@ func (s *Service) BrickCreate(
248248
) error {
249249
brick, present := s.bricksIndex.FindBrickByID(req.ID)
250250
if !present {
251-
return fmt.Errorf("brick not found with id %s", req.ID)
251+
return fmt.Errorf("brick %q not found", req.ID)
252252
}
253253

254254
for name, reqValue := range req.Variables {
255255
value, exist := brick.GetVariable(name)
256256
if !exist {
257-
return errors.New("variable does not exist")
257+
return fmt.Errorf("variable %q does not exist on brick %q", name, brick.ID)
258258
}
259259
if value.DefaultValue == "" && reqValue == "" {
260-
return errors.New("variable default value cannot be empty")
260+
return fmt.Errorf("variable %q cannot be empty", name)
261261
}
262262
}
263263

264264
for _, brickVar := range brick.Variables {
265265
if brickVar.DefaultValue == "" {
266266
if _, exist := req.Variables[brickVar.Name]; !exist {
267-
return errors.New("variable does not exist")
267+
return fmt.Errorf("required variable %q is mandatory", brickVar.Name)
268268
}
269-
return errors.New("variable default value cannot be empty")
270269
}
271270
}
272271

@@ -289,25 +288,20 @@ func (s *Service) BrickCreate(
289288
if idx == -1 {
290289
return fmt.Errorf("model %s does not exsist", *req.Model)
291290
}
292-
293291
brickInstance.Model = models[idx].ID
294292
}
295293
brickInstance.Variables = req.Variables
296294

297295
if brickIndex == -1 {
298-
299296
appCurrent.Descriptor.Bricks = append(appCurrent.Descriptor.Bricks, brickInstance)
300-
301297
} else {
302298
appCurrent.Descriptor.Bricks[brickIndex] = brickInstance
303-
304299
}
305300

306301
err := appCurrent.Save()
307302
if err != nil {
308303
return fmt.Errorf("cannot save brick instance with id %s", req.ID)
309304
}
310-
311305
return nil
312306
}
313307

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// This file is part of arduino-app-cli.
2+
//
3+
// Copyright 2025 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This software is released under the GNU General Public License version 3,
6+
// which covers the main part of arduino-app-cli.
7+
// The terms of this license can be found at:
8+
// https://www.gnu.org/licenses/gpl-3.0.en.html
9+
//
10+
// You can be released from the requirements of the above licenses by purchasing
11+
// a commercial license. Buying such a license is mandatory if you want to
12+
// modify or otherwise use the software for commercial activities involving the
13+
// Arduino software without disclosing the source code of your own applications.
14+
// To purchase a commercial license, send an email to license@arduino.cc.
15+
16+
package bricks
17+
18+
import (
19+
"testing"
20+
21+
"github.com/arduino/go-paths-helper"
22+
"github.com/stretchr/testify/require"
23+
"go.bug.st/f"
24+
25+
"github.com/arduino/arduino-app-cli/internal/orchestrator/app"
26+
"github.com/arduino/arduino-app-cli/internal/orchestrator/bricksindex"
27+
)
28+
29+
func TestBrickCreate(t *testing.T) {
30+
bricksIndex, err := bricksindex.GenerateBricksIndexFromFile(paths.New("testdata"))
31+
require.Nil(t, err)
32+
brickService := NewService(nil, bricksIndex, nil)
33+
34+
t.Run("fails if brick id does not exist", func(t *testing.T) {
35+
err = brickService.BrickCreate(BrickCreateUpdateRequest{ID: "not-existing-id"}, f.Must(app.Load("testdata/dummy-app")))
36+
require.Error(t, err)
37+
require.Equal(t, "brick \"not-existing-id\" not found", err.Error())
38+
})
39+
40+
t.Run("fails if the requestes variable is not present in the brick definition", func(t *testing.T) {
41+
req := BrickCreateUpdateRequest{ID: "arduino:arduino_cloud", Variables: map[string]string{
42+
"NON_EXISTING_VARIABLE": "some-value",
43+
}}
44+
err = brickService.BrickCreate(req, f.Must(app.Load("testdata/dummy-app")))
45+
require.Error(t, err)
46+
require.Equal(t, "variable \"NON_EXISTING_VARIABLE\" does not exist on brick \"arduino:arduino_cloud\"", err.Error())
47+
})
48+
49+
t.Run("fails if a required variable is set empty", func(t *testing.T) {
50+
req := BrickCreateUpdateRequest{ID: "arduino:arduino_cloud", Variables: map[string]string{
51+
"ARDUINO_DEVICE_ID": "",
52+
"ARDUINO_SECRET": "a-secret-a",
53+
}}
54+
err = brickService.BrickCreate(req, f.Must(app.Load("testdata/dummy-app")))
55+
require.Error(t, err)
56+
require.Equal(t, "variable \"ARDUINO_DEVICE_ID\" cannot be empty", err.Error())
57+
})
58+
59+
t.Run("fails if a mandatory variable is not present in the request", func(t *testing.T) {
60+
req := BrickCreateUpdateRequest{ID: "arduino:arduino_cloud", Variables: map[string]string{
61+
"ARDUINO_SECRET": "a-secret-a",
62+
}}
63+
err = brickService.BrickCreate(req, f.Must(app.Load("testdata/dummy-app")))
64+
require.Error(t, err)
65+
require.Equal(t, "required variable \"ARDUINO_DEVICE_ID\" is mandatory", err.Error())
66+
})
67+
68+
t.Run("the brick is added if it does not exist in the app", func(t *testing.T) {
69+
tempDummyApp := paths.New("testdata/dummy-app.temp")
70+
err := tempDummyApp.RemoveAll()
71+
require.Nil(t, err)
72+
require.Nil(t, paths.New("testdata/dummy-app").CopyDirTo(tempDummyApp))
73+
74+
req := BrickCreateUpdateRequest{ID: "arduino:dbstorage_sqlstore"}
75+
err = brickService.BrickCreate(req, f.Must(app.Load(tempDummyApp.String())))
76+
require.Nil(t, err)
77+
after, err := app.Load(tempDummyApp.String())
78+
require.Nil(t, err)
79+
require.Len(t, after.Descriptor.Bricks, 2)
80+
require.Equal(t, "arduino:dbstorage_sqlstore", after.Descriptor.Bricks[1].ID)
81+
})
82+
t.Run("the variables of a brick are updated", func(t *testing.T) {
83+
tempDummyApp := paths.New("testdata/dummy-app.brick-override.temp")
84+
err := tempDummyApp.RemoveAll()
85+
require.Nil(t, err)
86+
err = paths.New("testdata/dummy-app").CopyDirTo(tempDummyApp)
87+
require.Nil(t, err)
88+
bricksIndex, err := bricksindex.GenerateBricksIndexFromFile(paths.New("testdata"))
89+
require.Nil(t, err)
90+
brickService := NewService(nil, bricksIndex, nil)
91+
92+
deviceID := "this-is-a-device-id"
93+
secret := "this-is-a-secret"
94+
req := BrickCreateUpdateRequest{
95+
ID: "arduino:arduino_cloud",
96+
Variables: map[string]string{
97+
"ARDUINO_DEVICE_ID": deviceID,
98+
"ARDUINO_SECRET": secret,
99+
},
100+
}
101+
102+
err = brickService.BrickCreate(req, f.Must(app.Load(tempDummyApp.String())))
103+
require.Nil(t, err)
104+
105+
after, err := app.Load(tempDummyApp.String())
106+
require.Nil(t, err)
107+
require.Len(t, after.Descriptor.Bricks, 1)
108+
require.Equal(t, "arduino:arduino_cloud", after.Descriptor.Bricks[0].ID)
109+
require.Equal(t, deviceID, after.Descriptor.Bricks[0].Variables["ARDUINO_DEVICE_ID"])
110+
require.Equal(t, secret, after.Descriptor.Bricks[0].Variables["ARDUINO_SECRET"])
111+
})
112+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.temp
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
bricks:
2+
- id: arduino:arduino_cloud
3+
name: Arduino Cloud
4+
description: Connects to Arduino Cloud
5+
require_container: false
6+
require_model: false
7+
require_devices: false
8+
mount_devices_into_container: false
9+
ports: []
10+
category: null
11+
variables:
12+
- name: ARDUINO_DEVICE_ID
13+
description: Arduino Cloud Device ID
14+
- name: ARDUINO_SECRET
15+
description: Arduino Cloud Secret
16+
- id: arduino:dbstorage_sqlstore
17+
name: Database - SQL
18+
description: Simplified database storage layer for Arduino sensor data using SQLite
19+
local database.
20+
require_container: false
21+
require_model: false
22+
require_devices: false
23+
mount_devices_into_container: false
24+
ports: []
25+
category: storage
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
name: Copy of Blinking LED from Arduino Cloud
2+
description: Control the LED from the Arduino IoT Cloud using RPC calls
3+
icon: ☁️
4+
ports: []
5+
bricks:
6+
- arduino:arduino_cloud:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
def main():
2+
pass

0 commit comments

Comments
 (0)