Skip to content

Commit

Permalink
RSDK-5608 - CLI commands for managing cloud builds (viamrobotics#3298)
Browse files Browse the repository at this point in the history
Co-authored-by: Abe Winter <abe-winter@users.noreply.github.com>
  • Loading branch information
zaporter-work and abe-winter authored Dec 8, 2023
1 parent a292ab3 commit 5c1ac8c
Show file tree
Hide file tree
Showing 12 changed files with 428 additions and 28 deletions.
69 changes: 67 additions & 2 deletions cli/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ const (
moduleFlagPlatform = "platform"
moduleFlagForce = "force"

moduleBuildFlagPath = "module"
moduleBuildFlagCount = "count"
moduleBuildFlagVersion = "version"
moduleBuildFlagBuildID = "id"
moduleBuildFlagPlatform = "platform"
moduleBuildFlagWait = "wait"

dataFlagDestination = "destination"
dataFlagDataType = "data-type"
dataFlagOrgIDs = "org-ids"
Expand Down Expand Up @@ -1084,8 +1091,8 @@ Uses the "build" section of your meta.json.
Example:
"build": {
"setup": "setup.sh", // optional - command to install your build dependencies
"build": "make module.tar.gz", // command that will build your module
"path" : "module.tar.gz", // optional - path to your built module
"build": "make module.tar.gz", // command that will build your module
"path" : "module.tar.gz", // optional - path to your built module
// (passed to the 'viam module upload' command)
"arch" : ["linux/amd64", "linux/arm64"] // architectures to build for
}`,
Expand All @@ -1103,6 +1110,64 @@ Example:
},
Action: ModuleBuildLocalAction,
},
{
Name: "start",
Description: "start a remote build",
Flags: []cli.Flag{
&cli.StringFlag{
Name: moduleBuildFlagPath,
Usage: "path to meta.json",
Value: "./meta.json",
TakesFile: true,
},
&cli.StringFlag{
Name: moduleBuildFlagVersion,
Usage: "version of the module to upload (semver2.0) ex: \"0.1.0\"",
Required: true,
},
},
Action: ModuleBuildStartAction,
},
{
Name: "list",
Usage: "check on the status of your cloud builds",
Flags: []cli.Flag{
&cli.StringFlag{
Name: moduleFlagPath,
Usage: "path to meta.json",
Value: "./meta.json",
TakesFile: true,
},
&cli.IntFlag{
Name: moduleBuildFlagCount,
Usage: "number of builds to list",
Aliases: []string{"c"},
DefaultText: "all",
},
&cli.StringFlag{
Name: moduleBuildFlagBuildID,
Usage: "restrict output to just return builds that match this id",
},
},
Action: ModuleBuildListAction,
},
{
Name: "logs",
Usage: "get the logs from one of your cloud builds",
Flags: []cli.Flag{
&cli.StringFlag{
Name: moduleBuildFlagBuildID,
Usage: "build that you want to get the logs for",
Required: true,
},
&cli.StringFlag{
Name: moduleBuildFlagPlatform,
Usage: "build platform to get the logs for. Ex: linux/arm64",
Required: true,
},
},
Action: ModuleBuildLogsAction,
},
},
},
},
Expand Down
2 changes: 2 additions & 0 deletions cli/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/golang-jwt/jwt/v4"
"github.com/pkg/errors"
"github.com/urfave/cli/v2"
buildpb "go.viam.com/api/app/build/v1"
datapb "go.viam.com/api/app/data/v1"
datasetpb "go.viam.com/api/app/dataset/v1"
mltrainingpb "go.viam.com/api/app/mltraining/v1"
Expand Down Expand Up @@ -501,6 +502,7 @@ func (c *viamClient) ensureLoggedIn() error {
c.packageClient = packagepb.NewPackageServiceClient(conn)
c.datasetClient = datasetpb.NewDatasetServiceClient(conn)
c.mlTrainingClient = mltrainingpb.NewMLTrainingServiceClient(conn)
c.buildClient = buildpb.NewBuildServiceClient(conn)

return nil
}
Expand Down
20 changes: 10 additions & 10 deletions cli/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
)

func TestLoginAction(t *testing.T) {
cCtx, ac, out, errOut := setup(nil, nil, nil, "token")
cCtx, ac, out, errOut := setup(nil, nil, nil, nil, "token")

test.That(t, ac.loginAction(cCtx), test.ShouldBeNil)
test.That(t, len(errOut.messages), test.ShouldEqual, 0)
Expand All @@ -26,7 +26,7 @@ func TestLoginAction(t *testing.T) {
}

func TestAPIKeyAuth(t *testing.T) {
_, ac, _, errOut := setup(nil, nil, nil, "apiKey")
_, ac, _, errOut := setup(nil, nil, nil, nil, "apiKey")
test.That(t, len(errOut.messages), test.ShouldEqual, 0)
APIKey, isAPIKey := ac.conf.Auth.(*apiKey)
test.That(t, isAPIKey, test.ShouldBeTrue)
Expand All @@ -36,7 +36,7 @@ func TestAPIKeyAuth(t *testing.T) {

func TestPrintAccessTokenAction(t *testing.T) {
// AppServiceClient needed for any Action that calls ensureLoggedIn.
cCtx, ac, out, errOut := setup(&inject.AppServiceClient{}, nil, nil, "token")
cCtx, ac, out, errOut := setup(&inject.AppServiceClient{}, nil, nil, nil, "token")

test.That(t, ac.printAccessTokenAction(cCtx), test.ShouldBeNil)
test.That(t, len(errOut.messages), test.ShouldEqual, 0)
Expand All @@ -53,7 +53,7 @@ func TestAPIKeyCreateAction(t *testing.T) {
asc := &inject.AppServiceClient{
CreateKeyFunc: createKeyFunc,
}
cCtx, ac, out, errOut := setup(asc, nil, nil, "token")
cCtx, ac, out, errOut := setup(asc, nil, nil, nil, "token")

test.That(t, ac.organizationsAPIKeyCreateAction(cCtx), test.ShouldBeNil)
test.That(t, len(errOut.messages), test.ShouldEqual, 0)
Expand All @@ -80,7 +80,7 @@ func TestRobotAPIKeyCreateAction(t *testing.T) {
flags[apiKeyCreateFlagOrgID] = fakeOrgID
flags[apiKeyFlagRobotID] = fakeRobotID
flags[apiKeyCreateFlagName] = "my-name"
cCtx, ac, out, errOut := setup(asc, nil, &flags, "token")
cCtx, ac, out, errOut := setup(asc, nil, nil, &flags, "token")

test.That(t, ac.robotAPIKeyCreateAction(cCtx), test.ShouldBeNil)
test.That(t, len(errOut.messages), test.ShouldEqual, 0)
Expand Down Expand Up @@ -135,7 +135,7 @@ func TestRobotAPIKeyCreateAction(t *testing.T) {
flags[apiKeyFlagRobotID] = fakeRobotID
flags[apiKeyCreateFlagOrgID] = ""
flags[apiKeyCreateFlagName] = "test-me"
cCtx, ac, out, _ = setup(asc, nil, &flags, "token")
cCtx, ac, out, _ = setup(asc, nil, nil, &flags, "token")
err = ac.robotAPIKeyCreateAction(cCtx)
test.That(t, err, test.ShouldNotBeNil)

Expand All @@ -162,7 +162,7 @@ func TestLocationAPIKeyCreateAction(t *testing.T) {
flags[apiKeyCreateFlagOrgID] = ""
flags[apiKeyCreateFlagName] = "" // testing no locationID

cCtx, ac, out, errOut := setup(asc, nil, &flags, "token")
cCtx, ac, out, errOut := setup(asc, nil, nil, &flags, "token")
err := ac.locationAPIKeyCreateAction(cCtx)
test.That(t, err, test.ShouldNotBeNil)
test.That(t, len(errOut.messages), test.ShouldEqual, 0)
Expand Down Expand Up @@ -203,7 +203,7 @@ func TestLocationAPIKeyCreateAction(t *testing.T) {
flags[apiKeyCreateFlagOrgID] = ""
flags[apiKeyCreateFlagName] = "test-name"

cCtx, ac, _, _ = setup(asc, nil, &flags, "token")
cCtx, ac, _, _ = setup(asc, nil, nil, &flags, "token")

err = ac.locationAPIKeyCreateAction(cCtx)
test.That(t, err, test.ShouldNotBeNil)
Expand All @@ -212,7 +212,7 @@ func TestLocationAPIKeyCreateAction(t *testing.T) {
}

func TestLogoutAction(t *testing.T) {
cCtx, ac, out, errOut := setup(nil, nil, nil, "token")
cCtx, ac, out, errOut := setup(nil, nil, nil, nil, "token")

test.That(t, ac.logoutAction(cCtx), test.ShouldBeNil)
test.That(t, len(errOut.messages), test.ShouldEqual, 0)
Expand All @@ -222,7 +222,7 @@ func TestLogoutAction(t *testing.T) {
}

func TestWhoAmIAction(t *testing.T) {
cCtx, ac, out, errOut := setup(nil, nil, nil, "token")
cCtx, ac, out, errOut := setup(nil, nil, nil, nil, "token")

test.That(t, ac.whoAmIAction(cCtx), test.ShouldBeNil)
test.That(t, len(errOut.messages), test.ShouldEqual, 0)
Expand Down
4 changes: 2 additions & 2 deletions cli/boards_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
)

func TestAppendAuthHeadersTokenAuth(t *testing.T) {
cCtx, ac, _, _ := setup(&inject.AppServiceClient{}, nil, nil, "token")
cCtx, ac, _, _ := setup(&inject.AppServiceClient{}, nil, nil, nil, "token")

testReq, err := http.NewRequestWithContext(cCtx.Context, http.MethodGet, "/test", nil)
test.That(t, err, test.ShouldBeNil)
Expand All @@ -21,7 +21,7 @@ func TestAppendAuthHeadersTokenAuth(t *testing.T) {
}

func TestAppendAuthHeadersAPIKeyAuth(t *testing.T) {
cCtx, ac, _, _ := setup(&inject.AppServiceClient{}, nil, nil, "apiKey")
cCtx, ac, _, _ := setup(&inject.AppServiceClient{}, nil, nil, nil, "apiKey")

testReq, err := http.NewRequestWithContext(cCtx.Context, http.MethodGet, "/test", nil)
test.That(t, err, test.ShouldBeNil)
Expand Down
2 changes: 2 additions & 0 deletions cli/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/pkg/errors"
"github.com/urfave/cli/v2"
"go.uber.org/zap"
buildpb "go.viam.com/api/app/build/v1"
datapb "go.viam.com/api/app/data/v1"
datasetpb "go.viam.com/api/app/dataset/v1"
mltrainingpb "go.viam.com/api/app/mltraining/v1"
Expand Down Expand Up @@ -48,6 +49,7 @@ type viamClient struct {
packageClient packagepb.PackageServiceClient
datasetClient datasetpb.DatasetServiceClient
mlTrainingClient mltrainingpb.MLTrainingServiceClient
buildClient buildpb.BuildServiceClient
baseURL *url.URL
rpcOpts []rpc.DialOption
authFlow *authFlow
Expand Down
22 changes: 14 additions & 8 deletions cli/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"time"

"github.com/urfave/cli/v2"
buildpb "go.viam.com/api/app/build/v1"
datapb "go.viam.com/api/app/data/v1"
apppb "go.viam.com/api/app/v1"
"go.viam.com/test"
Expand Down Expand Up @@ -39,8 +40,12 @@ func (tw *testWriter) Write(b []byte) (int, error) {
// setup creates a new cli.Context and viamClient with fake auth and the passed
// in AppServiceClient and DataServiceClient. It also returns testWriters that capture Stdout and
// Stdin.
func setup(asc apppb.AppServiceClient, dataClient datapb.DataServiceClient,
defaultFlags *map[string]string, authMethod string,
func setup(
asc apppb.AppServiceClient,
dataClient datapb.DataServiceClient,
buildClient buildpb.BuildServiceClient,
defaultFlags *map[string]string,
authMethod string,
) (*cli.Context, *viamClient, *testWriter, *testWriter) {
out := &testWriter{}
errOut := &testWriter{}
Expand Down Expand Up @@ -76,10 +81,11 @@ func setup(asc apppb.AppServiceClient, dataClient datapb.DataServiceClient,
}
}
ac := &viamClient{
client: asc,
conf: conf,
c: cCtx,
dataClient: dataClient,
client: asc,
conf: conf,
c: cCtx,
dataClient: dataClient,
buildClient: buildClient,
}
return cCtx, ac, out, errOut
}
Expand All @@ -94,7 +100,7 @@ func TestListOrganizationsAction(t *testing.T) {
asc := &inject.AppServiceClient{
ListOrganizationsFunc: listOrganizationsFunc,
}
cCtx, ac, out, errOut := setup(asc, nil, nil, "token")
cCtx, ac, out, errOut := setup(asc, nil, nil, nil, "token")

test.That(t, ac.listOrganizationsAction(cCtx), test.ShouldBeNil)
test.That(t, len(errOut.messages), test.ShouldEqual, 0)
Expand Down Expand Up @@ -129,7 +135,7 @@ func TestTabularDataByFilterAction(t *testing.T) {
TabularDataByFilterFunc: tabularDataByFilterFunc,
}

cCtx, ac, out, errOut := setup(&inject.AppServiceClient{}, dsc, nil, "token")
cCtx, ac, out, errOut := setup(&inject.AppServiceClient{}, dsc, nil, nil, "token")

test.That(t, ac.dataExportAction(cCtx), test.ShouldBeNil)
test.That(t, len(errOut.messages), test.ShouldEqual, 0)
Expand Down
Loading

0 comments on commit 5c1ac8c

Please sign in to comment.