Skip to content

Commit 89bb0b9

Browse files
committed
refactor: move ValidateBricks function to a new file and update references
1 parent d9992fe commit 89bb0b9

File tree

5 files changed

+65
-58
lines changed

5 files changed

+65
-58
lines changed

internal/orchestrator/app/parser.go

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ import (
2424
"github.com/arduino/go-paths-helper"
2525
"github.com/goccy/go-yaml"
2626
"github.com/goccy/go-yaml/ast"
27-
28-
"github.com/arduino/arduino-app-cli/internal/orchestrator/bricksindex"
2927
)
3028

3129
type Brick struct {
@@ -140,44 +138,6 @@ func (a *AppDescriptor) IsValid() error {
140138
return allErrors
141139
}
142140

143-
// ValidateBricks checks that all bricks referenced in the given AppDescriptor exist in the provided BricksIndex,
144-
// and that all required variables for each brick are present and valid. It collects and returns all validation
145-
// errors as a single joined error, allowing the caller to see all issues at once rather than stopping at the first error.
146-
// If the index is nil, validation is skipped and nil is returned.
147-
func (a *AppDescriptor) ValidateBricks(index *bricksindex.BricksIndex) error {
148-
if index == nil {
149-
return nil
150-
}
151-
152-
var allErrors error
153-
154-
for _, appBrick := range a.Bricks {
155-
indexBrick, found := index.FindBrickByID(appBrick.ID)
156-
if !found {
157-
allErrors = errors.Join(allErrors, fmt.Errorf("brick %q not found", appBrick.ID))
158-
continue // Skip further validation for this brick since it doesn't exist
159-
}
160-
161-
// Check that all app variables exist in brick definition
162-
for appBrickName := range appBrick.Variables {
163-
_, exist := indexBrick.GetVariable(appBrickName)
164-
if !exist {
165-
allErrors = errors.Join(allErrors, fmt.Errorf("variable %q does not exist on brick %q", appBrickName, indexBrick.ID))
166-
}
167-
}
168-
169-
// Check that all required brick variables are provided by app
170-
for _, indexBrickVariable := range indexBrick.Variables {
171-
if indexBrickVariable.IsRequired() {
172-
if _, exist := appBrick.Variables[indexBrickVariable.Name]; !exist {
173-
allErrors = errors.Join(allErrors, fmt.Errorf("variable %q is required by brick %q", indexBrickVariable.Name, indexBrick.ID))
174-
}
175-
}
176-
}
177-
}
178-
return allErrors
179-
}
180-
181141
func isSingleEmoji(s string) bool {
182142
emojis := 0
183143
for it := emoji.IterateChars(s); it.Next(); {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package app
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
7+
"github.com/arduino/arduino-app-cli/internal/orchestrator/bricksindex"
8+
)
9+
10+
// ValidateBricks checks that all bricks referenced in the given AppDescriptor exist in the provided BricksIndex,
11+
// It collects and returns all validatio errors as a single joined error, allowing the caller to see all issues at once rather than stopping at the first error.
12+
// If the index or the app is nil, validation is skipped and nil is returned.
13+
func ValidateBricks(a AppDescriptor, index *bricksindex.BricksIndex) error {
14+
if index == nil {
15+
return nil
16+
}
17+
18+
var allErrors error
19+
20+
for _, appBrick := range a.Bricks {
21+
indexBrick, found := index.FindBrickByID(appBrick.ID)
22+
if !found {
23+
allErrors = errors.Join(allErrors, fmt.Errorf("brick %q not found", appBrick.ID))
24+
continue // Skip further validation for this brick since it doesn't exist
25+
}
26+
27+
for appBrickName := range appBrick.Variables {
28+
_, exist := indexBrick.GetVariable(appBrickName)
29+
if !exist {
30+
allErrors = errors.Join(allErrors, fmt.Errorf("variable %q does not exist on brick %q", appBrickName, indexBrick.ID))
31+
}
32+
}
33+
34+
// Check that all required brick variables are provided by app
35+
for _, indexBrickVariable := range indexBrick.Variables {
36+
if indexBrickVariable.IsRequired() {
37+
if _, exist := appBrick.Variables[indexBrickVariable.Name]; !exist {
38+
allErrors = errors.Join(allErrors, fmt.Errorf("variable %q is required by brick %q", indexBrickVariable.Name, indexBrick.ID))
39+
}
40+
}
41+
}
42+
}
43+
return allErrors
44+
}

internal/orchestrator/app/validator_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func TestValidateAppDescriptorBricks(t *testing.T) {
7272
appDescriptor, err := ParseDescriptorFile(paths.New("testdata/validator/" + tc.filename))
7373
require.NoError(t, err)
7474

75-
err = appDescriptor.ValidateBricks(bricksIndex)
75+
err = ValidateBricks(appDescriptor, bricksIndex)
7676
if tc.expectedError == nil {
7777
assert.NoError(t, err, "Expected no validation errors")
7878
} else {
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
name: Copy of Blinking LED from Arduino Cloud
22
description: Control the LED from the Arduino IoT Cloud using RPC calls
3-
icon: ☁️
43
ports: []
54
bricks:
6-
- arduino:arduino_cloud:
5+
- arduino:arduino_cloud:
6+
variables:
7+
ARDUINO_SECRET: a-secret-a
8+
icon: ☁️

internal/orchestrator/orchestrator.go

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import (
4444
"github.com/arduino/arduino-app-cli/internal/helpers"
4545
"github.com/arduino/arduino-app-cli/internal/micro"
4646
"github.com/arduino/arduino-app-cli/internal/orchestrator/app"
47+
appspecification "github.com/arduino/arduino-app-cli/internal/orchestrator/app"
4748
appgenerator "github.com/arduino/arduino-app-cli/internal/orchestrator/app/generator"
4849
"github.com/arduino/arduino-app-cli/internal/orchestrator/bricksindex"
4950
"github.com/arduino/arduino-app-cli/internal/orchestrator/config"
@@ -114,15 +115,15 @@ func StartApp(
114115
provisioner *Provision,
115116
modelsIndex *modelsindex.ModelsIndex,
116117
bricksIndex *bricksindex.BricksIndex,
117-
app app.ArduinoApp,
118+
app appspecification.ArduinoApp,
118119
cfg config.Configuration,
119120
staticStore *store.StaticStore,
120121
) iter.Seq[StreamMessage] {
121122
return func(yield func(StreamMessage) bool) {
122123
ctx, cancel := context.WithCancel(ctx)
123124
defer cancel()
124125

125-
err := app.Descriptor.ValidateBricks(bricksIndex)
126+
err := appspecification.ValidateBricks(app.Descriptor, bricksIndex)
126127
if err != nil {
127128
yield(StreamMessage{error: err})
128129
return
@@ -255,7 +256,7 @@ func StartApp(
255256
// - model configuration variables (variables defined in the model configuration)
256257
// - brick instance variables (variables defined in the app.yaml for the brick instance)
257258
// In addition, it adds some useful environment variables like APP_HOME and HOST_IP.
258-
func getAppEnvironmentVariables(app app.ArduinoApp, brickIndex *bricksindex.BricksIndex, modelsIndex *modelsindex.ModelsIndex) helpers.EnvVars {
259+
func getAppEnvironmentVariables(app appspecification.ArduinoApp, brickIndex *bricksindex.BricksIndex, modelsIndex *modelsindex.ModelsIndex) helpers.EnvVars {
259260
envs := make(helpers.EnvVars)
260261

261262
for _, brick := range app.Descriptor.Bricks {
@@ -383,7 +384,7 @@ func getVideoDevices() map[int]string {
383384
return deviceMap
384385
}
385386

386-
func stopAppWithCmd(ctx context.Context, app app.ArduinoApp, cmd string) iter.Seq[StreamMessage] {
387+
func stopAppWithCmd(ctx context.Context, app appspecification.ArduinoApp, cmd string) iter.Seq[StreamMessage] {
387388
return func(yield func(StreamMessage) bool) {
388389
ctx, cancel := context.WithCancel(ctx)
389390
defer cancel()
@@ -431,11 +432,11 @@ func stopAppWithCmd(ctx context.Context, app app.ArduinoApp, cmd string) iter.Se
431432
}
432433
}
433434

434-
func StopApp(ctx context.Context, app app.ArduinoApp) iter.Seq[StreamMessage] {
435+
func StopApp(ctx context.Context, app appspecification.ArduinoApp) iter.Seq[StreamMessage] {
435436
return stopAppWithCmd(ctx, app, "stop")
436437
}
437438

438-
func StopAndDestroyApp(ctx context.Context, app app.ArduinoApp) iter.Seq[StreamMessage] {
439+
func StopAndDestroyApp(ctx context.Context, app appspecification.ArduinoApp) iter.Seq[StreamMessage] {
439440
return stopAppWithCmd(ctx, app, "down")
440441
}
441442

@@ -445,15 +446,15 @@ func RestartApp(
445446
provisioner *Provision,
446447
modelsIndex *modelsindex.ModelsIndex,
447448
bricksIndex *bricksindex.BricksIndex,
448-
appToStart app.ArduinoApp,
449+
appToStart appspecification.ArduinoApp,
449450
cfg config.Configuration,
450451
staticStore *store.StaticStore,
451452
) iter.Seq[StreamMessage] {
452453
return func(yield func(StreamMessage) bool) {
453454
ctx, cancel := context.WithCancel(ctx)
454455
defer cancel()
455456

456-
err := appToStart.Descriptor.ValidateBricks(bricksIndex)
457+
err := appspecification.ValidateBricks(appToStart.Descriptor, bricksIndex)
457458
if err != nil {
458459
yield(StreamMessage{error: err})
459460
return
@@ -677,7 +678,7 @@ type AppDetailedBrick struct {
677678
func AppDetails(
678679
ctx context.Context,
679680
docker command.Cli,
680-
userApp app.ArduinoApp,
681+
userApp appspecification.ArduinoApp,
681682
bricksIndex *bricksindex.BricksIndex,
682683
idProvider *app.IDProvider,
683684
cfg config.Configuration,
@@ -901,7 +902,7 @@ func CloneApp(
901902
return CloneAppResponse{ID: id}, nil
902903
}
903904

904-
func DeleteApp(ctx context.Context, app app.ArduinoApp) error {
905+
func DeleteApp(ctx context.Context, app appspecification.ArduinoApp) error {
905906
for msg := range StopApp(ctx, app) {
906907
if msg.error != nil {
907908
return fmt.Errorf("failed to stop app: %w", msg.error)
@@ -912,7 +913,7 @@ func DeleteApp(ctx context.Context, app app.ArduinoApp) error {
912913

913914
const defaultAppFileName = "default.app"
914915

915-
func SetDefaultApp(app *app.ArduinoApp, cfg config.Configuration) error {
916+
func SetDefaultApp(app *appspecification.ArduinoApp, cfg config.Configuration) error {
916917
defaultAppPath := cfg.DataDir().Join(defaultAppFileName)
917918

918919
// Remove the default app file if the app is nil.
@@ -927,7 +928,7 @@ func SetDefaultApp(app *app.ArduinoApp, cfg config.Configuration) error {
927928
return fatomic.WriteFile(defaultAppPath.String(), []byte(app.FullPath.String()), os.FileMode(0644))
928929
}
929930

930-
func GetDefaultApp(cfg config.Configuration) (*app.ArduinoApp, error) {
931+
func GetDefaultApp(cfg config.Configuration) (*appspecification.ArduinoApp, error) {
931932
defaultAppFilePath := cfg.DataDir().Join(defaultAppFileName)
932933
if !defaultAppFilePath.Exist() {
933934
return nil, nil
@@ -965,7 +966,7 @@ type AppEditRequest struct {
965966

966967
func EditApp(
967968
req AppEditRequest,
968-
editApp *app.ArduinoApp,
969+
editApp *appspecification.ArduinoApp,
969970
cfg config.Configuration,
970971
) (editErr error) {
971972
if req.Default != nil {
@@ -1005,7 +1006,7 @@ func EditApp(
10051006
return nil
10061007
}
10071008

1008-
func editAppDefaults(userApp *app.ArduinoApp, isDefault bool, cfg config.Configuration) error {
1009+
func editAppDefaults(userApp *appspecification.ArduinoApp, isDefault bool, cfg config.Configuration) error {
10091010
if isDefault {
10101011
if err := SetDefaultApp(userApp, cfg); err != nil {
10111012
return fmt.Errorf("failed to set default app: %w", err)
@@ -1134,7 +1135,7 @@ func addLedControl(volumes []volume) []volume {
11341135

11351136
func compileUploadSketch(
11361137
ctx context.Context,
1137-
arduinoApp *app.ArduinoApp,
1138+
arduinoApp *appspecification.ArduinoApp,
11381139
w io.Writer,
11391140
) error {
11401141
logrus.SetLevel(logrus.ErrorLevel) // Reduce the log level of arduino-cli

0 commit comments

Comments
 (0)