mirror of https://github.com/kubevela/kubevela.git
Feat: Add command to list all workflows in vela-cli (#6326)
- fixes #6326 Signed-off-by: Muralicharan Gurumoorthy <muralicharan.gurumoorthy@gmail.com> Co-authored-by: Muralicharan Gurumoorthy <muralicharan.gurumoorthy@gmail.com>
This commit is contained in:
parent
26faaaf4f9
commit
a07acc02c9
|
|
@ -63,6 +63,8 @@ import (
|
|||
terraformapiv1 "github.com/oam-dev/terraform-controller/api/v1beta1"
|
||||
terraformapi "github.com/oam-dev/terraform-controller/api/v1beta2"
|
||||
|
||||
workflowv1alpha1 "github.com/kubevela/workflow/api/v1alpha1"
|
||||
|
||||
oamcore "github.com/oam-dev/kubevela/apis/core.oam.dev"
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
velacue "github.com/oam-dev/kubevela/pkg/cue"
|
||||
|
|
@ -93,6 +95,7 @@ func init() {
|
|||
_ = metricsV1beta1api.AddToScheme(Scheme)
|
||||
_ = kruisev1alpha1.AddToScheme(Scheme)
|
||||
_ = gatewayv1beta1.AddToScheme(Scheme)
|
||||
_ = workflowv1alpha1.AddToScheme(Scheme)
|
||||
// +kubebuilder:scaffold:scheme
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,12 +23,13 @@ import (
|
|||
"os"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/gosuri/uitable"
|
||||
workflowv1alpha1 "github.com/kubevela/workflow/api/v1alpha1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
pkgmulticluster "github.com/kubevela/pkg/multicluster"
|
||||
workflowv1alpha1 "github.com/kubevela/workflow/api/v1alpha1"
|
||||
wfTypes "github.com/kubevela/workflow/pkg/types"
|
||||
wfUtils "github.com/kubevela/workflow/pkg/utils"
|
||||
|
||||
|
|
@ -65,6 +66,7 @@ func NewWorkflowCommand(c common.Args, order string, ioStreams cmdutil.IOStreams
|
|||
NewWorkflowRollbackCommand(c, ioStreams, wargs),
|
||||
NewWorkflowLogsCommand(c, ioStreams, wargs),
|
||||
NewWorkflowDebugCommand(c, ioStreams, wargs),
|
||||
NewWorkflowListCommand(c, ioStreams, wargs),
|
||||
)
|
||||
return cmd
|
||||
}
|
||||
|
|
@ -246,6 +248,85 @@ func NewWorkflowDebugCommand(c common.Args, ioStream cmdutil.IOStreams, wargs *W
|
|||
return cmd
|
||||
}
|
||||
|
||||
// NewWorkflowListCommand create workflow list command
|
||||
func NewWorkflowListCommand(c common.Args, ioStream cmdutil.IOStreams, wargs *WorkflowArgs) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "List running workflows",
|
||||
Long: "List running workflows",
|
||||
Example: "vela workflow list",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
cli, err := c.GetClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
namespace, err := GetFlagNamespaceOrEnv(cmd, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if AllNamespace {
|
||||
namespace = ""
|
||||
}
|
||||
ctx := context.Background()
|
||||
return printWorkflowList(ctx, cli, namespace, ioStream)
|
||||
},
|
||||
}
|
||||
cmd.Flags().BoolVarP(&AllNamespace, "all-namespaces", "A", false, "If true, check the specified action in all namespaces.")
|
||||
addNamespaceAndEnvArg(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func printWorkflowList(ctx context.Context, c client.Reader, namespace string, ioStream cmdutil.IOStreams) error {
|
||||
table, err := buildWorkflowListTable(ctx, c, namespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ioStream.Info(table.String())
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildWorkflowListTable(ctx context.Context, c client.Reader, namespace string) (*uitable.Table, error) {
|
||||
table := newUITable()
|
||||
header := []interface{}{"NAME", "TYPE", "PHASE", "START-TIME", "END-TIME"}
|
||||
if AllNamespace {
|
||||
header = append([]interface{}{"NAMESPACE"}, header...)
|
||||
}
|
||||
table.AddRow(header...)
|
||||
applist := v1beta1.ApplicationList{}
|
||||
if err := c.List(ctx, &applist, client.InNamespace(namespace)); err != nil {
|
||||
return nil, errors.WithMessage(err, "unable to list application workflows")
|
||||
}
|
||||
|
||||
for _, a := range applist.Items {
|
||||
status := a.Status.Workflow
|
||||
if a.Status.Workflow != nil {
|
||||
if AllNamespace {
|
||||
table.AddRow(a.Namespace, a.Name, "Application", status.Phase, status.StartTime, status.EndTime)
|
||||
} else {
|
||||
table.AddRow(a.Name, "Application", status.Phase, status.StartTime, status.EndTime)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wrList := workflowv1alpha1.WorkflowRunList{}
|
||||
|
||||
if err := c.List(ctx, &wrList, client.InNamespace(namespace)); err != nil {
|
||||
return nil, errors.WithMessage(err, "unable to list workflowruns")
|
||||
}
|
||||
|
||||
for _, w := range wrList.Items {
|
||||
status := w.Status
|
||||
if status.Phase != "" {
|
||||
if AllNamespace {
|
||||
table.AddRow(w.Namespace, w.Name, "WorkflowRun", status.Phase, status.StartTime, status.EndTime)
|
||||
} else {
|
||||
table.AddRow(w.Name, "WorkflowRun", status.Phase, status.StartTime, status.EndTime)
|
||||
}
|
||||
}
|
||||
}
|
||||
return table, nil
|
||||
}
|
||||
|
||||
// WorkflowArgs is the args for workflow command
|
||||
type WorkflowArgs struct {
|
||||
Type string
|
||||
|
|
|
|||
|
|
@ -17,10 +17,13 @@ limitations under the License.
|
|||
package cli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
|
@ -818,3 +821,154 @@ func TestWorkflowRollback(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWorkflowList(t *testing.T) {
|
||||
c := initArgs()
|
||||
buf := new(bytes.Buffer)
|
||||
ioStream := cmdutil.IOStreams{In: os.Stdin, Out: buf, ErrOut: os.Stderr}
|
||||
ctx := context.TODO()
|
||||
testCases := map[string]struct {
|
||||
workflows []interface{}
|
||||
apps []*v1beta1.Application
|
||||
workflowRuns []*workflowv1alpha1.WorkflowRun
|
||||
expectedErr error
|
||||
namespace string
|
||||
expectAppListSize int
|
||||
}{
|
||||
"specified all namespaces flag": {
|
||||
workflows: []interface{}{
|
||||
&v1beta1.Application{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "app-workflow",
|
||||
Namespace: "some-ns",
|
||||
},
|
||||
Spec: workflowSpec,
|
||||
Status: common.AppStatus{
|
||||
LatestRevision: &common.Revision{
|
||||
Name: "revision-v1",
|
||||
},
|
||||
Workflow: &common.WorkflowStatus{
|
||||
Terminated: true,
|
||||
Phase: workflowv1alpha1.WorkflowStateInitializing,
|
||||
StartTime: metav1.NewTime(time.Now().Add(-10 * time.Minute)),
|
||||
EndTime: metav1.NewTime(time.Now()),
|
||||
},
|
||||
},
|
||||
},
|
||||
&workflowv1alpha1.WorkflowRun{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "workflow-run",
|
||||
Namespace: "some-ns",
|
||||
},
|
||||
Status: workflowv1alpha1.WorkflowRunStatus{
|
||||
Phase: workflowv1alpha1.WorkflowStateExecuting,
|
||||
StartTime: metav1.NewTime(time.Now().Add(-10 * time.Minute)),
|
||||
EndTime: metav1.NewTime(time.Now()),
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErr: nil,
|
||||
},
|
||||
"specified namespace flag": {
|
||||
workflows: []interface{}{
|
||||
&workflowv1alpha1.WorkflowRun{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "workflow-run-1",
|
||||
Namespace: "test",
|
||||
},
|
||||
Status: workflowv1alpha1.WorkflowRunStatus{
|
||||
Phase: workflowv1alpha1.WorkflowStateExecuting,
|
||||
StartTime: metav1.NewTime(time.Now().Add(-10 * time.Minute)),
|
||||
EndTime: metav1.NewTime(time.Now()),
|
||||
},
|
||||
},
|
||||
},
|
||||
namespace: "test",
|
||||
expectedErr: nil,
|
||||
},
|
||||
}
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
r := require.New(t)
|
||||
buf.Reset()
|
||||
cmd := NewWorkflowListCommand(c, ioStream, &WorkflowArgs{Args: c, Writer: ioStream.Out})
|
||||
initCommand(cmd)
|
||||
// clean up the arguments before start
|
||||
cmd.SetArgs([]string{})
|
||||
client, err := c.GetClient()
|
||||
r.NoError(err)
|
||||
if tc.workflows != nil && len(tc.workflows) > 0 {
|
||||
for _, w := range tc.workflows {
|
||||
if workflow, ok := w.(*workflowv1alpha1.WorkflowRun); ok {
|
||||
err := client.Create(ctx, workflow)
|
||||
r.NoError(err)
|
||||
} else if app, ok := w.(*v1beta1.Application); ok {
|
||||
err := client.Create(ctx, app)
|
||||
r.NoError(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
args := []string{}
|
||||
if tc.namespace == "" {
|
||||
args = append(args, "-A")
|
||||
} else {
|
||||
args = append(args, "-n", tc.namespace)
|
||||
}
|
||||
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
|
||||
lines := strings.Split(strings.TrimSpace(buf.String()), "\n")
|
||||
|
||||
headerFields := strings.Fields(lines[0])
|
||||
if tc.namespace == "" {
|
||||
r.Equal(headerFields[0], "NAMESPACE")
|
||||
|
||||
} else {
|
||||
r.Equal(headerFields[0], "NAME")
|
||||
}
|
||||
offset := 0
|
||||
for i, line := range lines[1:] {
|
||||
fields := strings.Fields(line)
|
||||
if workflow, ok := tc.workflows[i].(*workflowv1alpha1.WorkflowRun); ok {
|
||||
if tc.namespace == "" {
|
||||
r.Equal(fields[0], workflow.Namespace)
|
||||
offset = offset + 1
|
||||
} else if tc.namespace == workflow.Namespace {
|
||||
r.Equal(fields[0+offset], workflow.Name)
|
||||
r.Equal(fields[1+offset], "WorkflowRun")
|
||||
r.Equal(fields[2+offset], string(workflow.Status.Phase))
|
||||
r.Equal(fields[3+offset], workflow.Status.StartTime.Format("2006-01-02"))
|
||||
r.Equal(fields[4+offset], workflow.Status.StartTime.Format("15:04:05"))
|
||||
//skipping a few fields due to the format including timezone information
|
||||
r.Equal(fields[7+offset], workflow.Status.EndTime.Format("2006-01-02"))
|
||||
r.Equal(fields[8+offset], workflow.Status.EndTime.Format("15:04:05"))
|
||||
}
|
||||
} else if app, ok := tc.workflows[i].(*v1beta1.Application); ok {
|
||||
offset = 0
|
||||
if tc.namespace == "" {
|
||||
r.Equal(fields[0+offset], app.Namespace)
|
||||
offset = offset + 1
|
||||
} else if tc.namespace == app.Namespace {
|
||||
r.Equal(fields[0+offset], app.Name)
|
||||
r.Equal(fields[1+offset], "Application")
|
||||
r.Equal(fields[2+offset], string(app.Status.Workflow.Phase))
|
||||
r.Equal(fields[3+offset], app.Status.Workflow.StartTime.Format("2006-01-02"))
|
||||
r.Equal(fields[4+offset], app.Status.Workflow.StartTime.Format("15:04:05"))
|
||||
//skipping a few fields due to the format including timezone information
|
||||
r.Equal(fields[7+offset], app.Status.Workflow.EndTime.Format("2006-01-02"))
|
||||
r.Equal(fields[8+offset], app.Status.Workflow.EndTime.Format("15:04:05"))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if tc.expectedErr != nil {
|
||||
r.Equal(tc.expectedErr, err)
|
||||
return
|
||||
}
|
||||
r.NoError(err)
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue