Skip to content

Commit fe5bdac

Browse files
committed
feat: assign-blueprint and provision lua-device with blueprint from path
1 parent 7fe0250 commit fe5bdac

28 files changed

Lines changed: 204 additions & 13 deletions

File tree

internal/app/enaptercli/cmd_blueprints_upload.go

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package enaptercli
33
import (
44
"bytes"
55
"context"
6+
"encoding/json"
67
"fmt"
78
"net/http"
89
"os"
@@ -41,25 +42,54 @@ func (c *cmdBlueprintsUpload) Flags() []cli.Flag {
4142
}
4243

4344
func (c *cmdBlueprintsUpload) upload(ctx context.Context) error {
44-
fi, err := os.Stat(c.blueprintPath)
45+
return uploadBlueprint(ctx, c.blueprintPath, c.doHTTPRequest)
46+
}
47+
48+
func uploadBlueprintAndReturnBlueprintID(ctx context.Context, blueprintPath string,
49+
doHTTPRequest func(context.Context, doHTTPRequestParams) error,
50+
) (string, error) {
51+
var blueprintID string
52+
err := uploadBlueprint(ctx, blueprintPath, func(ctx context.Context, reqParams doHTTPRequestParams) error {
53+
reqParams.RespProcessor = func(resp *http.Response) error {
54+
var respBlueprint struct {
55+
Blueprint struct {
56+
ID string `json:"id"`
57+
} `json:"blueprint"`
58+
}
59+
if err := json.NewDecoder(resp.Body).Decode(&respBlueprint); err != nil {
60+
return fmt.Errorf("decode blueprint response: %w", err)
61+
}
62+
blueprintID = respBlueprint.Blueprint.ID
63+
return nil
64+
}
65+
return doHTTPRequest(ctx, reqParams)
66+
})
67+
return blueprintID, err
68+
}
69+
70+
func uploadBlueprint(
71+
ctx context.Context, blueprintPath string,
72+
doHTTPRequest func(context.Context, doHTTPRequestParams) error,
73+
) error {
74+
fi, err := os.Stat(blueprintPath)
4575
if err != nil {
4676
return fmt.Errorf("check blueprint path: %w", err)
4777
}
4878

4979
var data []byte
5080
if fi.IsDir() {
51-
data, err = zipDir(c.blueprintPath)
81+
data, err = zipDir(blueprintPath)
5282
if err != nil {
5383
return fmt.Errorf("zip blueprint directory: %w", err)
5484
}
5585
} else {
56-
data, err = os.ReadFile(c.blueprintPath)
86+
data, err = os.ReadFile(blueprintPath)
5787
if err != nil {
5888
return fmt.Errorf("read blueprint zip file: %w", err)
5989
}
6090
}
6191

62-
return c.doHTTPRequest(ctx, doHTTPRequestParams{
92+
return doHTTPRequest(ctx, doHTTPRequestParams{
6393
Method: http.MethodPost,
6494
Path: "/blueprints/upload",
6595
Body: bytes.NewReader(data),

internal/app/enaptercli/cmd_device_assign_blueprint.go

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ import (
1212

1313
type cmdDevicesAssignBlueprint struct {
1414
cmdDevices
15-
deviceID string
16-
blueprintID string
15+
deviceID string
16+
blueprintID string
17+
blueprintPath string
1718
}
1819

1920
func buildCmdDevicesAssignBlueprint() *cli.Command {
@@ -43,12 +44,36 @@ func (c *cmdDevicesAssignBlueprint) Flags() []cli.Flag {
4344
Aliases: []string{"b"},
4445
Usage: "blueprint ID to assign",
4546
Destination: &c.blueprintID,
46-
Required: true,
47+
}, &cli.StringFlag{
48+
Name: "blueprint-path",
49+
Usage: "blueprint path (zip file or directory) to assign",
50+
Destination: &c.blueprintPath,
4751
})
4852
}
4953

54+
func (c *cmdDevicesAssignBlueprint) Before(cliCtx *cli.Context) error {
55+
if err := c.cmdDevices.Before(cliCtx); err != nil {
56+
return err
57+
}
58+
if c.blueprintID != "" && c.blueprintPath != "" {
59+
return fmt.Errorf("only one of --blueprint-id or --blueprint-path can be specified")
60+
}
61+
if c.blueprintID == "" && c.blueprintPath == "" {
62+
return fmt.Errorf("one of --blueprint-id or --blueprint-path must be specified")
63+
}
64+
return c.validateExpandFlag(cliCtx)
65+
}
66+
5067
func (c *cmdDevicesAssignBlueprint) do(ctx context.Context) error {
51-
body, err := json.Marshal(map[string]interface{}{
68+
if c.blueprintPath != "" {
69+
blueprintID, err := uploadBlueprintAndReturnBlueprintID(ctx, c.blueprintPath, c.cmdBase.doHTTPRequest)
70+
if err != nil {
71+
return fmt.Errorf("upload blueprint: %w", err)
72+
}
73+
c.blueprintID = blueprintID
74+
}
75+
76+
body, err := json.Marshal(map[string]any{
5277
"blueprint_id": c.blueprintID,
5378
})
5479
if err != nil {

internal/app/enaptercli/cmd_provisioning_lua_device.go

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ import (
1212

1313
type cmdProvisioningLua struct {
1414
cmdProvisioning
15-
deviceName string
16-
deviceSlug string
17-
runtimeID string
18-
blueprintID string
15+
deviceName string
16+
deviceSlug string
17+
runtimeID string
18+
blueprintID string
19+
blueprintPath string
1920
}
2021

2122
func buildCmdProvisioningLua() *cli.Command {
@@ -55,11 +56,35 @@ func (c *cmdProvisioningLua) Flags() []cli.Flag {
5556
Aliases: []string{"b"},
5657
Usage: "blueprint ID of a new Lua device",
5758
Destination: &c.blueprintID,
58-
Required: true,
59+
}, &cli.StringFlag{
60+
Name: "blueprint-path",
61+
Usage: "blueprint path (zip file or directory) to assign",
62+
Destination: &c.blueprintPath,
5963
})
6064
}
6165

66+
func (c *cmdProvisioningLua) Before(cliCtx *cli.Context) error {
67+
if err := c.cmdProvisioning.Before(cliCtx); err != nil {
68+
return err
69+
}
70+
if c.blueprintID != "" && c.blueprintPath != "" {
71+
return fmt.Errorf("only one of --blueprint-id or --blueprint-path can be specified")
72+
}
73+
if c.blueprintID == "" && c.blueprintPath == "" {
74+
return fmt.Errorf("one of --blueprint-id or --blueprint-path must be specified")
75+
}
76+
return nil
77+
}
78+
6279
func (c *cmdProvisioningLua) do(ctx context.Context) error {
80+
if c.blueprintPath != "" {
81+
blueprintID, err := uploadBlueprintAndReturnBlueprintID(ctx, c.blueprintPath, c.cmdBase.doHTTPRequest)
82+
if err != nil {
83+
return fmt.Errorf("upload blueprint: %w", err)
84+
}
85+
c.blueprintID = blueprintID
86+
}
87+
6388
body, err := json.Marshal(map[string]interface{}{
6489
"runtime_id": c.runtimeID,
6590
"name": c.deviceName,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
blueprint.zip
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
enapter.log("Hello from firmware.lua")
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
blueprint_spec: device/3.0
2+
display_name: Simple Lua
3+
4+
runtime:
5+
type: lua
6+
options:
7+
file: firmware.lua

internal/app/enaptercli/testdata/helps/enapter device assign-blueprint

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ OPTIONS:
88
--verbose log extra details about operation (default: false)
99
--device-id value, -d value device ID
1010
--blueprint-id value, -b value blueprint ID to assign
11+
--blueprint-path value blueprint path (zip file or directory) to assign
1112
--help, -h show help
1213

1314
ENVIRONMENT VARIABLES:

internal/app/enaptercli/testdata/helps/enapter provisioning lua-device

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ OPTIONS:
1010
--device-name value, -n value name of a new Lua device
1111
--device-slug value slug of a new Lua device
1212
--blueprint-id value, -b value blueprint ID of a new Lua device
13+
--blueprint-path value blueprint path (zip file or directory) to assign
1314
--help, -h show help
1415

1516
ENVIRONMENT VARIABLES:

internal/app/enaptercli/testdata/http_req_resp/device_assign_blueprint/cmd.tmpl renamed to internal/app/enaptercli/testdata/http_req_resp/device_assign_blueprint_by_id/cmd.tmpl

File renamed without changes.

internal/app/enaptercli/testdata/http_req_resp/device_assign_blueprint/out renamed to internal/app/enaptercli/testdata/http_req_resp/device_assign_blueprint_by_id/out

File renamed without changes.

0 commit comments

Comments
 (0)