コード例 #1
0
ファイル: auth.go プロジェクト: pauloalem/tsuru-client
func (c *teamList) Run(context *cmd.Context, client *cmd.Client) error {
	url, err := cmd.GetURL("/teams")
	if err != nil {
		return err
	}
	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return err
	}
	resp, err := client.Do(request)
	if err != nil {
		return err
	}
	if resp.StatusCode == http.StatusOK {
		defer resp.Body.Close()
		b, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return err
		}
		var teams []teamItem
		err = json.Unmarshal(b, &teams)
		if err != nil {
			return err
		}
		table := cmd.NewTable()
		table.Headers = cmd.Row{"Team", "Permissions"}
		table.LineSeparator = true
		for _, team := range teams {
			table.AddRow(cmd.Row{team.Name, strings.Join(team.Permissions, "\n")})
		}
		fmt.Fprint(context.Stdout, table.String())
	}
	return nil
}
コード例 #2
0
ファイル: services.go プロジェクト: dcarley/tsuru-client
func (c serviceInfo) BuildPlansTable(serviceName string, ctx *cmd.Context, client *cmd.Client) error {
	ctx.Stdout.Write([]byte("\nPlans\n"))
	url, err := cmd.GetURL(fmt.Sprintf("/services/%s/plans", serviceName))
	if err != nil {
		return err
	}
	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return err
	}
	resp, err := client.Do(request)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	result, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	var plans []map[string]string
	err = json.Unmarshal(result, &plans)
	if err != nil {
		return err
	}
	if len(plans) > 0 {
		table := cmd.NewTable()
		for _, plan := range plans {
			data := []string{plan["Name"], plan["Description"]}
			table.AddRow(cmd.Row(data))
		}
		table.Headers = cmd.Row([]string{"Name", "Description"})
		ctx.Stdout.Write(table.Bytes())
	}
	return nil
}
コード例 #3
0
ファイル: apps.go プロジェクト: tomzhang/golang-devops-stuff
func (a *app) String() string {
	format := `Application: {{.Name}}
Repository: {{.Repository}}
Platform: {{.Platform}}
Teams: {{.GetTeams}}
Address: {{.Addr}}
Owner: {{.Owner}}
Team owner: {{.TeamOwner}}
Deploys: {{.Deploys}}
`
	tmpl := template.Must(template.New("app").Parse(format))
	units := cmd.NewTable()
	units.Headers = cmd.Row([]string{"Unit", "State"})
	for _, unit := range a.Units {
		if unit.Name != "" {
			units.AddRow(cmd.Row([]string{unit.Name, unit.Status}))
		}
	}
	var buf bytes.Buffer
	tmpl.Execute(&buf, a)
	var suffix string
	if units.Rows() > 0 {
		suffix = fmt.Sprintf("Units:\n%s", units)
	}
	return buf.String() + suffix
}
コード例 #4
0
ファイル: auth.go プロジェクト: pauloalem/tsuru-client
func (c *listUsers) Run(ctx *cmd.Context, client *cmd.Client) error {
	if c.userEmail != "" && c.role != "" {
		return errors.New("You cannot set more than one flag. Enter <tsuru user-list --help> for more information.")
	}
	url := fmt.Sprintf("/users?userEmail=%s&role=%s", c.userEmail, c.role)
	url, err := cmd.GetURL(url)
	if err != nil {
		return err
	}
	request, _ := http.NewRequest("GET", url, nil)
	resp, err := client.Do(request)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	var users []cmd.APIUser
	err = json.NewDecoder(resp.Body).Decode(&users)
	if err != nil {
		return err
	}
	table := cmd.NewTable()
	table.Headers = cmd.Row([]string{"User", "Roles"})
	for _, u := range users {
		table.AddRow(cmd.Row([]string{
			u.Email,
			strings.Join(u.RoleInstances(), "\n"),
		}))
	}
	table.LineSeparator = true
	table.Sort()
	ctx.Stdout.Write(table.Bytes())
	return nil
}
コード例 #5
0
ファイル: cmd.go プロジェクト: tsuru/tsuru
func (c *NodeContainerInfo) Run(context *cmd.Context, client *cmd.Client) error {
	u, err := cmd.GetURL("/docker/nodecontainers/" + context.Args[0])
	if err != nil {
		return err
	}
	request, err := http.NewRequest("GET", u, nil)
	if err != nil {
		return err
	}
	rsp, err := client.Do(request)
	if err != nil {
		return err
	}
	var poolConfigs map[string]NodeContainerConfig
	err = json.NewDecoder(rsp.Body).Decode(&poolConfigs)
	if err != nil {
		return err
	}
	tbl := cmd.NewTable()
	tbl.LineSeparator = true
	tbl.Headers = cmd.Row{"Pool", "Config"}
	for poolName, config := range poolConfigs {
		data, err := json.MarshalIndent(config, "", "  ")
		if err != nil {
			return err
		}
		if poolName == "" {
			poolName = emptyPoolLabel
		}
		tbl.AddRow(cmd.Row{poolName, string(data)})
	}
	tbl.Sort()
	fmt.Fprint(context.Stdout, tbl.String())
	return nil
}
コード例 #6
0
ファイル: apps.go プロジェクト: dcarley/tsuru-client
func (c *appList) Show(result []byte, context *cmd.Context) error {
	var apps []app
	err := json.Unmarshal(result, &apps)
	if err != nil {
		return err
	}
	table := cmd.NewTable()
	table.Headers = cmd.Row([]string{"Application", "Units State Summary", "Address"})
	for _, app := range apps {
		var available int
		var total int
		for _, unit := range app.Units {
			if unit.Name != "" {
				total++
				if unit.Available() {
					available++
				}
			}
		}
		summary := fmt.Sprintf("%d of %d units in-service", available, total)
		addrs := strings.Replace(app.Addr(), ", ", "\n", -1)
		table.AddRow(cmd.Row([]string{app.Name, summary, addrs}))
	}
	table.LineSeparator = true
	table.Sort()
	context.Stdout.Write(table.Bytes())
	return nil
}
コード例 #7
0
ファイル: iaas.go プロジェクト: combor/tsuru-admin
func (c *machineList) Run(context *cmd.Context, client *cmd.Client) error {
	url, err := cmd.GetURL("/iaas/machines")
	if err != nil {
		return err
	}
	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return err
	}
	response, err := client.Do(request)
	if err != nil {
		return err
	}
	var machines []iaas.Machine
	err = json.NewDecoder(response.Body).Decode(&machines)
	if err != nil {
		return err
	}
	table := cmd.NewTable()
	table.Headers = cmd.Row([]string{"Id", "IaaS", "Address", "Creation Params"})
	table.LineSeparator = true
	for _, machine := range machines {
		var params []string
		for k, v := range machine.CreationParams {
			params = append(params, fmt.Sprintf("%s=%s", k, v))
		}
		sort.Strings(params)
		table.AddRow(cmd.Row([]string{machine.Id, machine.Iaas, machine.Address, strings.Join(params, "\n")}))
	}
	table.Sort()
	context.Stdout.Write(table.Bytes())
	return nil
}
コード例 #8
0
ファイル: auth.go プロジェクト: combor/tsuru-admin
func (c *listUsers) Run(ctx *cmd.Context, client *cmd.Client) error {
	url, err := cmd.GetURL("/users")
	if err != nil {
		return err
	}
	request, _ := http.NewRequest("GET", url, nil)
	resp, err := client.Do(request)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	var users []user
	err = json.NewDecoder(resp.Body).Decode(&users)
	if err != nil {
		return err
	}
	table := cmd.NewTable()
	table.Headers = cmd.Row([]string{"User", "Teams"})
	for _, u := range users {
		table.AddRow(cmd.Row([]string{u.Email, strings.Join(u.Teams, ", ")}))
	}
	table.LineSeparator = true
	table.Sort()
	ctx.Stdout.Write(table.Bytes())
	return nil
}
コード例 #9
0
ファイル: iaas.go プロジェクト: combor/tsuru-admin
func (c *templateList) Run(context *cmd.Context, client *cmd.Client) error {
	url, err := cmd.GetURL("/iaas/templates")
	if err != nil {
		return err
	}
	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return err
	}
	response, err := client.Do(request)
	if err != nil {
		return err
	}
	var templates []iaas.Template
	err = json.NewDecoder(response.Body).Decode(&templates)
	if err != nil {
		return err
	}
	table := cmd.NewTable()
	table.Headers = cmd.Row([]string{"Name", "IaaS", "Params"})
	table.LineSeparator = true
	for _, template := range templates {
		var params []string
		for _, data := range template.Data {
			params = append(params, fmt.Sprintf("%s=%s", data.Name, data.Value))
		}
		sort.Strings(params)
		table.AddRow(cmd.Row([]string{template.Name, template.IaaSName, strings.Join(params, "\n")}))
	}
	table.Sort()
	context.Stdout.Write(table.Bytes())
	return nil
}
コード例 #10
0
ファイル: plan.go プロジェクト: combor/tsuru-admin
func (c *planRoutersList) Run(context *cmd.Context, client *cmd.Client) error {
	url, err := cmd.GetURL("/plans/routers")
	if err != nil {
		return err
	}
	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return err
	}
	response, err := client.Do(request)
	if err != nil {
		return err
	}
	var routers []router.PlanRouter
	err = json.NewDecoder(response.Body).Decode(&routers)
	if err != nil {
		return err
	}
	table := cmd.NewTable()
	table.Headers = cmd.Row([]string{"Name", "Type"})
	table.LineSeparator = true
	for _, router := range routers {
		table.AddRow(cmd.Row([]string{router.Name, router.Type}))
	}
	context.Stdout.Write(table.Bytes())
	return nil
}
コード例 #11
0
ファイル: permission.go プロジェクト: pauloalem/tsuru-client
func (c *roleList) Run(context *cmd.Context, client *cmd.Client) error {
	addr, err := cmd.GetURL("/roles")
	if err != nil {
		return err
	}
	request, err := http.NewRequest("GET", addr, nil)
	if err != nil {
		return err
	}
	response, err := client.Do(request)
	if err != nil {
		return err
	}
	result, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return err
	}
	var roles []permission.Role
	err = json.Unmarshal(result, &roles)
	if err != nil {
		return err
	}
	table := cmd.NewTable()
	table.Headers = cmd.Row{"Role", "Context", "Permissions"}
	table.LineSeparator = true
	for _, r := range roles {
		table.AddRow(cmd.Row{r.Name, string(r.ContextType), strings.Join(r.SchemeNames, "\n")})
	}
	fmt.Fprint(context.Stdout, table.String())
	return nil
}
コード例 #12
0
ファイル: permission.go プロジェクト: pauloalem/tsuru-client
func (c *roleInfo) Run(context *cmd.Context, client *cmd.Client) error {
	roleName := context.Args[0]
	addr, err := cmd.GetURL(fmt.Sprintf("/roles/%s", roleName))
	if err != nil {
		return err
	}
	request, err := http.NewRequest("GET", addr, nil)
	if err != nil {
		return err
	}
	resp, err := client.Do(request)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	result, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	var perm permission.Role
	err = json.Unmarshal(result, &perm)
	if err != nil {
		return err
	}
	tbl := cmd.NewTable()
	tbl.LineSeparator = true
	tbl.Headers = cmd.Row{"Name", "Permissions"}
	tbl.AddRow(cmd.Row{perm.Name, strings.Join(perm.SchemeNames, "\n")})
	fmt.Fprintf(context.Stdout, tbl.String())
	return nil
}
コード例 #13
0
ファイル: services.go プロジェクト: pauloalem/tsuru-client
func (c serviceInfo) BuildInstancesTable(serviceName string, ctx *cmd.Context, client *cmd.Client) error {
	url, err := cmd.GetURL("/services/" + serviceName)
	if err != nil {
		return err
	}
	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return err
	}
	resp, err := client.Do(request)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	result, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	var instances []ServiceInstanceModel
	err = json.Unmarshal(result, &instances)
	if err != nil {
		return err
	}
	ctx.Stdout.Write([]byte(fmt.Sprintf("Info for \"%s\"\n\n", serviceName)))
	if len(instances) > 0 {
		ctx.Stdout.Write([]byte("Instances\n"))
		table := cmd.NewTable()
		extraHeaders := c.ExtraHeaders(instances)
		hasPlan := false
		var data []string
		var headers []string
		for _, instance := range instances {
			if instance.PlanName != "" {
				hasPlan = true
			}
		}
		for _, instance := range instances {
			apps := strings.Join(instance.Apps, ", ")
			if hasPlan {
				data = []string{instance.Name, instance.PlanName, apps}
			} else {
				data = []string{instance.Name, apps}
			}
			for _, h := range extraHeaders {
				data = append(data, instance.Info[h])
			}
			table.AddRow(cmd.Row(data))
		}
		if hasPlan {
			headers = []string{"Instances", "Plan", "Apps"}
		} else {
			headers = []string{"Instances", "Apps"}
		}
		headers = append(headers, extraHeaders...)
		table.Headers = cmd.Row(headers)
		ctx.Stdout.Write(table.Bytes())
	}
	return nil
}
コード例 #14
0
ファイル: permission.go プロジェクト: pauloalem/tsuru-client
func renderList(w io.Writer, permissions []*permissionData) {
	t := cmd.NewTable()
	t.Headers = cmd.Row{"Name", "Contexts"}
	for _, perm := range permissions {
		t.AddRow(cmd.Row{perm.Name, strings.Join(perm.Contexts, ", ")})
	}
	fmt.Fprint(w, t.String())
}
コード例 #15
0
ファイル: migrate.go プロジェクト: tsuru/tsuru
func (*migrationListCmd) Run(context *cmd.Context, client *cmd.Client) error {
	migrations, err := migration.List()
	if err != nil {
		return err
	}
	tbl := cmd.NewTable()
	tbl.Headers = cmd.Row{"Name", "Mandatory?", "Executed?"}
	for _, m := range migrations {
		tbl.AddRow(cmd.Row{m.Name, strconv.FormatBool(!m.Optional), strconv.FormatBool(m.Ran)})
	}
	fmt.Fprint(context.Stdout, tbl.String())
	return nil
}
コード例 #16
0
ファイル: cmd.go プロジェクト: tsuru/tsuru
func (c *NodeContainerList) Run(context *cmd.Context, client *cmd.Client) error {
	u, err := cmd.GetURL("/docker/nodecontainers")
	if err != nil {
		return err
	}
	request, err := http.NewRequest("GET", u, nil)
	if err != nil {
		return err
	}
	rsp, err := client.Do(request)
	if err != nil {
		return err
	}
	var all []NodeContainerConfigGroup
	err = json.NewDecoder(rsp.Body).Decode(&all)
	if err != nil {
		return err
	}
	if c.namesOnly {
		for _, entry := range all {
			fmt.Fprintln(context.Stdout, entry.Name)
		}
		return nil
	}
	tbl := cmd.NewTable()
	tbl.LineSeparator = true
	tbl.Headers = cmd.Row{"Name", "Pool Configs", "Image"}
	for _, entry := range all {
		var pools []string
		for poolName := range entry.ConfigPools {
			if poolName == "" {
				poolName = emptyPoolLabel
			}
			pools = append(pools, poolName)
		}
		sort.Strings(pools)
		var images []string
		for _, p := range pools {
			if p == emptyPoolLabel {
				p = ""
			}
			poolEntry := entry.ConfigPools[p]
			images = append(images, poolEntry.Image())
		}
		tbl.AddRow(cmd.Row{entry.Name, strings.Join(pools, "\n"), strings.Join(images, "\n")})
	}
	tbl.Sort()
	fmt.Fprint(context.Stdout, tbl.String())
	return nil
}
コード例 #17
0
ファイル: permission.go プロジェクト: pauloalem/tsuru-client
func (c *roleDefaultList) Run(context *cmd.Context, client *cmd.Client) error {
	addr, err := cmd.GetURL("/role/default")
	if err != nil {
		return err
	}
	request, err := http.NewRequest("GET", addr, nil)
	if err != nil {
		return err
	}
	response, err := client.Do(request)
	if err != nil {
		return err
	}
	defer response.Body.Close()
	result, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return err
	}
	var roles []permission.Role
	err = json.Unmarshal(result, &roles)
	if err != nil {
		return err
	}
	rolesByEvent := map[string][]permission.Role{}
	for _, r := range roles {
		for _, evt := range r.Events {
			rolesByEvent[evt] = append(rolesByEvent[evt], r)
		}
	}
	tbl := cmd.NewTable()
	tbl.LineSeparator = true
	tbl.Headers = cmd.Row{"Event", "Description", "Roles"}
	for _, event := range permission.RoleEventMap {
		roles := rolesByEvent[event.String()]
		roleNames := make([]string, len(roles))
		for i := range roles {
			roleNames[i] = roles[i].Name
		}
		tbl.AddRow(cmd.Row{event.String(), event.Description, strings.Join(roleNames, "\n")})
	}
	tbl.Sort()
	fmt.Fprint(context.Stdout, tbl.String())
	return nil
}
コード例 #18
0
ファイル: plan.go プロジェクト: wpjunior/tsuru-client
func renderPlans(plans []tsuruapp.Plan, isBytes bool) string {
	table := cmd.NewTable()
	table.Headers = []string{"Name", "Memory", "Swap", "Cpu Share", "Router", "Default"}
	for _, p := range plans {
		var memory, swap string
		if isBytes {
			memory = fmt.Sprintf("%d", p.Memory)
			swap = fmt.Sprintf("%d", p.Swap)
		} else {
			memory = fmt.Sprintf("%d MB", p.Memory/1024/1024)
			swap = fmt.Sprintf("%d MB", p.Swap/1024/1024)
		}
		table.AddRow([]string{
			p.Name, memory, swap,
			strconv.Itoa(p.CpuShare),
			p.Router,
			strconv.FormatBool(p.Default),
		})
	}
	return table.String()
}
コード例 #19
0
ファイル: apps.go プロジェクト: rochacon/tsuru
func (a *app) String() string {
	format := `Application: %s
Repository: %s
Platform: %s
Teams: %s
Address: %s
Owner: %s
Deploys: %d
`
	teams := strings.Join(a.Teams, ", ")
	units := cmd.NewTable()
	units.Headers = cmd.Row([]string{"Unit", "State"})
	for _, unit := range a.Units {
		if unit.Name != "" {
			units.AddRow(cmd.Row([]string{unit.Name, unit.State}))
		}
	}
	args := []interface{}{a.Name, a.Repository, a.Platform, teams, a.Addr(), a.Owner, a.Deploys}
	if units.Rows() > 0 {
		format += "Units:\n%s"
		args = append(args, units)
	}
	return fmt.Sprintf(format, args...)
}
コード例 #20
0
ファイル: apps.go プロジェクト: dcarley/tsuru-client
func (a *app) String() string {
	format := `Application: {{.Name}}
Repository: {{.Repository}}
Platform: {{.Platform}}
Teams: {{.GetTeams}}
Address: {{.Addr}}
Owner: {{.Owner}}
Team owner: {{.TeamOwner}}
Deploys: {{.Deploys}}
Pool: {{.Pool}}{{if .Lock.Locked}}
{{.Lock.String}}{{end}}
`
	var buf bytes.Buffer
	tmpl := template.Must(template.New("app").Parse(format))
	unitsByProcess := map[string][]unit{}
	for _, u := range a.Units {
		units := unitsByProcess[u.ProcessName]
		unitsByProcess[u.ProcessName] = append(units, u)
	}
	processes := make([]string, 0, len(unitsByProcess))
	for process := range unitsByProcess {
		processes = append(processes, process)
	}
	sort.Strings(processes)
	titles := []string{"Unit", "State"}
	contMap := map[string]container{}
	if len(a.containers) > 0 {
		for _, cont := range a.containers {
			id := cont.ID
			if len(cont.ID) > 10 {
				id = id[:10]
			}
			contMap[id] = cont
		}
		titles = append(titles, []string{"Host", "Port", "IP"}...)
	}
	for _, process := range processes {
		units := unitsByProcess[process]
		unitsTable := cmd.NewTable()
		unitsTable.Headers = cmd.Row(titles)
		for _, unit := range units {
			if unit.Name == "" {
				continue
			}
			id := unit.Name
			if len(unit.Name) > 10 {
				id = id[:10]
			}
			row := []string{id, unit.Status}
			cont, ok := contMap[id]
			if ok {
				row = append(row, []string{cont.HostAddr, cont.HostPort, cont.IP}...)
			}
			unitsTable.AddRow(cmd.Row(row))
		}
		if unitsTable.Rows() > 0 {
			if len(a.containers) > 0 {
				unitsTable.SortByColumn(2)
			}
			buf.WriteString("\n")
			processStr := ""
			if process != "" {
				processStr = fmt.Sprintf(" [%s]", process)
			}
			buf.WriteString(fmt.Sprintf("Units%s: %d\n", processStr, unitsTable.Rows()))
			buf.WriteString(unitsTable.String())
		}
	}
	servicesTable := cmd.NewTable()
	servicesTable.Headers = []string{"Service", "Instance"}
	for _, service := range a.services {
		if len(service.Instances) == 0 {
			continue
		}
		servicesTable.AddRow([]string{service.Service, strings.Join(service.Instances, ", ")})
	}
	if servicesTable.Rows() > 0 {
		buf.WriteString("\n")
		buf.WriteString(fmt.Sprintf("Service instances: %d\n", servicesTable.Rows()))
		buf.WriteString(servicesTable.String())
	}
	if a.Plan.Name != "" {
		buf.WriteString("\n")
		buf.WriteString("App Plan:\n")
		buf.WriteString(renderPlans([]tsuruapp.Plan{a.Plan}, true))
	}
	var tplBuffer bytes.Buffer
	tmpl.Execute(&tplBuffer, a)
	return tplBuffer.String() + buf.String()
}
コード例 #21
0
ファイル: deploy.go プロジェクト: wpjunior/tsuru-client
func (c *appDeployList) Run(context *cmd.Context, client *cmd.Client) error {
	appName, err := c.Guess()
	if err != nil {
		return err
	}
	url, err := cmd.GetURL(fmt.Sprintf("/deploys?app=%s&limit=10", appName))
	if err != nil {
		return err
	}
	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return err
	}
	response, err := client.Do(request)
	if err != nil {
		return err
	}
	if response.StatusCode == http.StatusNoContent {
		fmt.Fprintf(context.Stdout, "App %s has no deploy.\n", appName)
		return nil
	}
	defer response.Body.Close()
	result, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return err
	}
	var deploys []tsuruapp.DeployData
	err = json.Unmarshal(result, &deploys)
	if err != nil {
		return err
	}
	sort.Sort(sort.Reverse(deployList(deploys)))
	table := cmd.NewTable()
	table.Headers = cmd.Row([]string{"Image (Rollback)", "Origin", "User", "Date (Duration)", "Error"})
	for _, deploy := range deploys {
		timestamp := deploy.Timestamp.Local().Format(time.Stamp)
		seconds := deploy.Duration / time.Second
		minutes := seconds / 60
		seconds = seconds % 60
		if deploy.Origin == "git" {
			if len(deploy.Commit) > 7 {
				deploy.Commit = deploy.Commit[:7]
			}
			deploy.Origin = fmt.Sprintf("git (%s)", deploy.Commit)
		}
		timestamp = fmt.Sprintf("%s (%02d:%02d)", timestamp, minutes, seconds)
		if deploy.CanRollback {
			deploy.Image += " (*)"
		}
		rowData := []string{deploy.Image, deploy.Origin, deploy.User, timestamp, deploy.Error}
		if deploy.Error != "" {
			for i, el := range rowData {
				if el != "" {
					rowData[i] = cmd.Colorfy(el, "red", "", "")
				}
			}
		}
		table.LineSeparator = true
		table.AddRow(cmd.Row(rowData))
	}
	context.Stdout.Write(table.Bytes())
	return nil
}