X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?p=src%2Fxds%2Fxds-cli.git;a=blobdiff_plain;f=cmd-sdks.go;h=00052156b498ac157aec5272a1bda2f2fcb1ed5d;hp=af6c417173f52cb9e5716ab5adcfb579bb8b38a2;hb=3b5e82b55433fd49cfe0cd0349756e0c2e9a9c12;hpb=75416fe01aa98b53c57315a050fc58f0879a238d diff --git a/cmd-sdks.go b/cmd-sdks.go index af6c417..0005215 100644 --- a/cmd-sdks.go +++ b/cmd-sdks.go @@ -1,10 +1,30 @@ +/* + * Copyright (C) 2017-2018 "IoT.bzh" + * Author Sebastien Douheret + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + package main import ( "fmt" - "strconv" + "os" + "regexp" + "sort" - "github.com/iotbzh/xds-agent/lib/xaapiv1" + "gerrit.automotivelinux.org/gerrit/src/xds/xds-agent.git/lib/xaapiv1" "github.com/urfave/cli" ) @@ -15,20 +35,15 @@ func initCmdSdks(cmdDef *[]cli.Command) { HideHelp: true, Usage: "SDKs commands group", Subcommands: []cli.Command{ - { - Name: "add", - Aliases: []string{"a"}, - Usage: "Add a new SDK", - Action: sdksAdd, - }, { Name: "get", Usage: "Get a property of a SDK", Action: sdksGet, Flags: []cli.Flag{ cli.StringFlag{ - Name: "id", - Usage: "sdk id", + Name: "id", + Usage: "sdk id", + EnvVar: "XDS_SDK_ID", }, }, }, @@ -38,6 +53,14 @@ func initCmdSdks(cmdDef *[]cli.Command) { Usage: "List installed SDKs", Action: sdksList, Flags: []cli.Flag{ + cli.BoolFlag{ + Name: "all, a", + Usage: "display all existing sdks (installed + downloadable)", + }, + cli.StringFlag{ + Name: "filter, f", + Usage: "regexp to filter output (filtering done only on ID, Name, Version and Arch fields) ", + }, cli.BoolFlag{ Name: "verbose, v", Usage: "display verbose output", @@ -45,14 +68,61 @@ func initCmdSdks(cmdDef *[]cli.Command) { }, }, { - Name: "remove", + Name: "install", + Aliases: []string{"i"}, + Usage: "Install a SDK", + Action: sdksInstall, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "id", + Usage: "sdk id to install", + EnvVar: "XDS_SDK_ID", + }, + cli.StringFlag{ + Name: "file, f", + Usage: "use this file to install SDK", + }, + cli.BoolFlag{ + Name: "debug", + Usage: "enable debug mode (useful to investigate install issue)", + }, + cli.BoolFlag{ + Name: "force", + Usage: "force SDK installation when already installed", + }, + cli.BoolFlag{ + Name: "short, s", + Usage: "short output, only print create sdk id (useful from scripting)", + }, + }, + }, + { + Name: "uninstall", Aliases: []string{"rm"}, - Usage: "Remove an existing SDK", - Action: sdksRemove, + Usage: "UnInstall an existing SDK", + Action: sdksUnInstall, Flags: []cli.Flag{ cli.StringFlag{ - Name: "id", - Usage: "sdk id", + Name: "id", + Usage: "sdk id to un-install", + EnvVar: "XDS_SDK_ID", + }, + cli.BoolFlag{ + Name: "force, f", + Usage: "remove confirmation prompt before removal", + }, + }, + }, + { + Name: "abort", + Aliases: []string{"a"}, + Usage: "Abort an install action", + Action: sdksAbort, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "id", + Usage: "sdk id to which abort action", + EnvVar: "XDS_SDK_ID", }, }, }, @@ -63,74 +133,243 @@ func initCmdSdks(cmdDef *[]cli.Command) { func sdksList(ctx *cli.Context) error { // Get SDKs list sdks := []xaapiv1.SDK{} - if err := sdksListGet(&sdks); err != nil { + if err := _sdksListGet(&sdks); err != nil { return cli.NewExitError(err.Error(), 1) } - _displaySdks(sdks, ctx.Bool("verbose")) + + _displaySdks(sdks, ctx.Bool("verbose"), ctx.Bool("all"), ctx.String("filter")) return nil } func sdksGet(ctx *cli.Context) error { - id := GetID(ctx) + id := GetID(ctx, "XDS_SDK_ID") if id == "" { return cli.NewExitError("id parameter or option must be set", 1) } sdks := xaapiv1.SDK{} - url := "servers/" + strconv.Itoa(XdsServerIndexGet()) + "/sdks/" + id + url := XdsServerComputeURL("/sdks/" + id) if err := HTTPCli.Get(url, &sdks); err != nil { return cli.NewExitError(err.Error(), 1) } - _displaySdks([]xaapiv1.SDK{sdks}, true) + + _displaySdks([]xaapiv1.SDK{sdks}, true, true, "") return nil } -func _displaySdks(sdks []xaapiv1.SDK, verbose bool) { +func _displaySdks(sdks []xaapiv1.SDK, verbose bool, all bool, filter string) { // Display result first := true writer := NewTableWriter() for _, s := range sdks { + if s.Status != xaapiv1.SdkStatusInstalled && + s.Status != xaapiv1.SdkStatusInstalling && + !all { + continue + } + if filter != "" { + re := regexp.MustCompile(filter) + if !(re.MatchString(s.ID) || re.MatchString(s.Name) || + re.MatchString(s.Profile) || re.MatchString(s.Arch) || + re.MatchString(s.Version)) { + continue + } + } + if verbose { if !first { fmt.Fprintln(writer) } fmt.Fprintln(writer, "ID\t"+s.ID) fmt.Fprintln(writer, "Name\t"+s.Name) + fmt.Fprintln(writer, "Description\t"+s.Description) fmt.Fprintln(writer, "Profile\t"+s.Profile) fmt.Fprintln(writer, "Arch\t"+s.Arch) fmt.Fprintln(writer, "Version\t"+s.Version) + fmt.Fprintln(writer, "Status\t"+s.Status) fmt.Fprintln(writer, "Path\t"+s.Path) + fmt.Fprintln(writer, "Url\t"+formatURL(s.URL)) + fmt.Fprintln(writer, "Image Url\t"+formatURL(s.ImageURL)) } else { if first { - fmt.Fprintf(writer, "List of installed SDKs: \n") - fmt.Fprintf(writer, " ID\tNAME\n") + if all { + fmt.Fprintf(writer, "List of available SDKs: \n") + } else { + fmt.Fprintf(writer, "List of installed SDKs: \n") + } + fmt.Fprintf(writer, "ID\t NAME\t STATUS\t VERSION\t ARCH\n") } - fmt.Fprintf(writer, " %s\t%s\n", s.ID, s.Name) + fmt.Fprintf(writer, "%s\t %s\t %s\t %s\t %s\n", s.ID[:8], s.Name, s.Status, s.Version, s.Arch) } first = false } writer.Flush() } -func sdksListGet(sdks *[]xaapiv1.SDK) error { - url := "servers/" + strconv.Itoa(XdsServerIndexGet()) + "/sdks" +// Sort SDKs by ID +type _SdkByID []xaapiv1.SDK + +func (s _SdkByID) Len() int { return len(s) } +func (s _SdkByID) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s _SdkByID) Less(i, j int) bool { return s[i].ID < s[j].ID } + +// _sdksListGet Get the list of existing sdks +func _sdksListGet(sdks *[]xaapiv1.SDK) error { + url := XdsServerComputeURL("/sdks") if err := HTTPCli.Get(url, &sdks); err != nil { return err } Log.Debugf("Result of %s: %v", url, sdks) + sort.Sort(_SdkByID(*sdks)) + return nil } -func sdksAdd(ctx *cli.Context) error { - return fmt.Errorf("not supported yet") +func sdksInstall(ctx *cli.Context) error { + id := GetID(ctx, "XDS_SDK_ID") + file := ctx.String("file") + force := ctx.Bool("force") + shortOut := ctx.Bool("short") + + if id == "" && file == "" { + return cli.NewExitError("id or file parameter or option must be set", 1) + } + + // Process Socket IO events + type exitResult struct { + error string + code int + } + exitChan := make(chan exitResult, 1) + + IOSkClient.On("disconnection", func(err error) { + Log.Debugf("WS disconnection event with err: %v\n", err) + errMsg := "" + if err != nil { + errMsg = err.Error() + } + exitChan <- exitResult{errMsg, 2} + }) + + IOSkClient.On(xaapiv1.EVTSDKManagement, func(ev xaapiv1.EventMsg) { + sdkEvt, _ := ev.DecodeSDKMgtMsg() + + if sdkEvt.Action != xaapiv1.SdkMgtActionInstall { + Log.Debugf("EVTSDKManagement (action %s) IGNORED", sdkEvt.Action) + return + } + + if !shortOut && len(sdkEvt.Stdout) > 0 { + os.Stdout.Write([]byte(sdkEvt.Stdout)) + } + if !shortOut && len(sdkEvt.Stderr) > 0 { + os.Stderr.Write([]byte(sdkEvt.Stderr)) + } + + if sdkEvt.Exited { + exitChan <- exitResult{sdkEvt.Error, sdkEvt.Code} + } + }) + + IOSkClient.On(xaapiv1.EVTSDKStateChange, func(ev xaapiv1.EventMsg) { + sdk, _ := ev.DecodeSDKEvent() + Log.Debugf("EVTSDKStateChange: %v", sdk) + }) + + evReg := xaapiv1.EventRegisterArgs{Name: xaapiv1.EVTAll} + if err := HTTPCli.Post("/events/register", &evReg, nil); err != nil { + return cli.NewExitError(err, 1) + } + + url := XdsServerComputeURL("/sdks") + sdks := xaapiv1.SDKInstallArgs{ + ID: id, + Filename: file, + Force: force, + } + + if ctx.Bool("debug") { + sdks.InstallArgs = []string{"--debug"} + } + + newSdk := xaapiv1.SDK{} + if err := HTTPCli.Post(url, &sdks, &newSdk); err != nil { + return cli.NewExitError(err, 1) + } + Log.Debugf("Result of %s: %v", url, newSdk) + if !shortOut { + fmt.Printf("Installation of '%s' SDK successfully started.\n", newSdk.Name) + } + + // TODO: trap CTRL+C and print question: "Installation of xxx is in progress, press 'a' to abort, 'b' to continue in background or 'c' to continue installation" + + // Wait exit + select { + case res := <-IOSkClient.ServerDiscoChan: + Log.Debugf("XDS Server disconnected %v", res) + return cli.NewExitError(res.error, res.code) + + case res := <-exitChan: + if res.code == 0 { + Log.Debugln("Exit successfully") + if shortOut { + fmt.Println(newSdk.ID) + } else { + fmt.Println("SDK ID " + newSdk.ID + " successfully installed.") + } + } + if res.error != "" { + Log.Debugln("Exit with ERROR: ", res.error) + } + return cli.NewExitError(res.error, res.code) + } } -func sdksRemove(ctx *cli.Context) error { - id := GetID(ctx) +func sdksUnInstall(ctx *cli.Context) error { + id := GetID(ctx, "XDS_SDK_ID") if id == "" { return cli.NewExitError("id parameter or option must be set", 1) } - return fmt.Errorf("not supported yet") + if !ctx.Bool("force") { + if !Confirm("Do you permanently remove SDK id '" + id + "' [yes/No] ? ") { + return nil + } + } + + delSdk := xaapiv1.SDK{} + url := XdsServerComputeURL("/sdks/" + id) + if err := HTTPCli.Delete(url, &delSdk); err != nil { + return cli.NewExitError(err, 1) + } + + Log.Debugf("Result of %s: %v", url, delSdk) + + fmt.Println("SDK ID " + delSdk.ID + " successfully deleted.") + return nil +} + +func sdksAbort(ctx *cli.Context) error { + id := GetID(ctx, "XDS_SDK_ID") + if id == "" { + return cli.NewExitError("id parameter or option must be set", 1) + } + + sdks := xaapiv1.SDKInstallArgs{ID: id} + newSdk := xaapiv1.SDK{} + url := XdsServerComputeURL("/sdks/abortinstall") + if err := HTTPCli.Post(url, &sdks, &newSdk); err != nil { + return cli.NewExitError(err, 1) + } + + Log.Debugf("Result of %s: %v", url, newSdk) + return nil +} + +func formatURL(u string) string { + if u == "" { + return "-" + } + return u }