/* * Copyright (C) 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 ( "encoding/json" "fmt" "io" "os" "sort" "strings" "time" "gerrit.automotivelinux.org/gerrit/src/xds/xds-agent.git/lib/xaapiv1" "github.com/creack/goselect" "github.com/golang/crypto/ssh/terminal" "github.com/urfave/cli" ) func initCmdTargets(cmdDef *[]cli.Command) { *cmdDef = append(*cmdDef, cli.Command{ Name: "targets", Aliases: []string{"tgt"}, HideHelp: true, Usage: "targets commands group", Subcommands: []cli.Command{ { Name: "add", Aliases: []string{"a"}, Usage: "Add a new target", Action: targetsAdd, Flags: []cli.Flag{ cli.StringFlag{ Name: "name, n", Usage: "target name (free form string)", }, cli.StringFlag{ Name: "ip", Usage: "IP address", }, cli.BoolFlag{ Name: "short, s", Usage: "short output, only print create target id (useful from scripting)", }, cli.StringFlag{ Name: "type, t", Usage: "target type (standard|std)", }, }, }, { Name: "get", Usage: "Get properties of a target", Action: targetsGet, Flags: []cli.Flag{ cli.StringFlag{ Name: "id", Usage: "target id", EnvVar: "XDS_TARGET_ID", }, }, }, { Name: "list", Aliases: []string{"ls"}, Usage: "List existing targets", Action: targetsList, Flags: []cli.Flag{ cli.BoolFlag{ Name: "verbose, v", Usage: "display verbose output", }, }, }, { Name: "remove", Aliases: []string{"rm"}, Usage: "Remove an existing target", Action: targetsRemove, Flags: []cli.Flag{ cli.StringFlag{ Name: "id", Usage: "target id", EnvVar: "XDS_TARGET_ID", }, cli.BoolFlag{ Name: "force, f", Usage: "remove confirmation prompt before removal", }, }, }, { Name: "terminal", Aliases: []string{"term"}, Usage: "Open a target terminal", Action: terminalOpen, Flags: []cli.Flag{ cli.StringFlag{ Name: "id", Usage: "target id", EnvVar: "XDS_TARGET_ID", }, cli.StringSliceFlag{ Name: "options, o", Usage: "passthrough options set to command line used to start terminal", }, cli.StringFlag{ Name: "termId, tid", Usage: "terminal id", EnvVar: "XDS_TERMINAL_ID", }, cli.StringFlag{ Name: "user, u", Usage: "user name used to connect terminal", EnvVar: "XDS_TERMINAL_USER", }, }, }, { Name: "terminal-remove", Aliases: []string{"term-rm"}, Usage: "Remove a target terminal", Action: terminalRemove, Flags: []cli.Flag{ cli.StringFlag{ Name: "id", Usage: "target id", EnvVar: "XDS_TARGET_ID", }, cli.StringFlag{ Name: "termId, tid", Usage: "terminal id", EnvVar: "XDS_TERMINAL_ID", }, }, }, }, }) } func targetsList(ctx *cli.Context) error { // Get targets list tgts := []xaapiv1.TargetConfig{} if err := TargetsListGet(&tgts); err != nil { return cli.NewExitError(err.Error(), 1) } _displayTargets(tgts, ctx.Bool("verbose")) return nil } func targetsGet(ctx *cli.Context) error { id := GetID(ctx) if id == "" { return cli.NewExitError("id parameter or option must be set", 1) } tgts := make([]xaapiv1.TargetConfig, 1) url := XdsServerComputeURL("/targets/" + id) if err := HTTPCli.Get(url, &tgts[0]); err != nil { return cli.NewExitError(err, 1) } _displayTargets(tgts, true) return nil } func _displayTargets(tgts []xaapiv1.TargetConfig, verbose bool) { // Display result first := true writer := NewTableWriter() for _, tgt := range tgts { if verbose { if !first { fmt.Fprintln(writer) } fmt.Fprintln(writer, "ID:\t", tgt.ID) fmt.Fprintln(writer, "Name:\t", tgt.Name) fmt.Fprintln(writer, "Type:\t", tgt.Type) fmt.Fprintln(writer, "IP:\t", tgt.IP) fmt.Fprintln(writer, "Status:\t", tgt.Status) if len(tgt.Terms) > 0 { tmNfo := "\t\n" for _, tt := range tgt.Terms { tmNfo += "\t ID:\t" + tt.ID + "\n" tmNfo += "\t Name:\t" + tt.Name + "\n" tmNfo += "\t Type:\t" + string(tt.Type) + "\n" tmNfo += "\t Status:\t" + tt.Status + "\n" tmNfo += "\t User:\t" + tt.User + "\n" tmNfo += "\t Options:\t" + strings.Join(tt.Options, " ") + "\n" tmNfo += fmt.Sprintf("\t Size:\t%v x %v\n", tt.Cols, tt.Rows) } fmt.Fprintln(writer, "Terminals:", tmNfo) } else { fmt.Fprintln(writer, "Terminals:\t None") } } else { if first { fmt.Fprintln(writer, "ID\t Name\t IP\t Terminals #") } fmt.Fprintln(writer, tgt.ID[0:8], "\t", tgt.Name, "\t", tgt.IP, "\t", len(tgt.Terms)) } first = false } writer.Flush() } func targetsAdd(ctx *cli.Context) error { // Decode target type var tType xaapiv1.TargetType switch strings.ToLower(ctx.String("type")) { case "standard", "std": tType = xaapiv1.TypeTgtStandard default: tType = xaapiv1.TypeTgtStandard } tgt := xaapiv1.TargetConfig{ Name: ctx.String("name"), Type: tType, IP: ctx.String("ip"), } Log.Infof("POST /target %v", tgt) newTgt := xaapiv1.TargetConfig{} err := HTTPCli.Post(XdsServerComputeURL("/targets"), tgt, &newTgt) if err != nil { return cli.NewExitError(err, 1) } if ctx.Bool("short") { fmt.Println(newTgt.ID) } else { fmt.Printf("New target '%s' (id %v) successfully created.\n", newTgt.Name, newTgt.ID) } return nil } func targetsRemove(ctx *cli.Context) error { var res xaapiv1.TargetConfig id := GetID(ctx) if id == "" { return cli.NewExitError("id parameter or option must be set", 1) } if !ctx.Bool("force") { if !Confirm("Do you permanently remove target id '" + id + "' [yes/No] ? ") { return nil } } if err :=