github.com/oam-dev/kubevela@v1.9.11/references/cli/top/model/application.go (about)

     1  /*
     2  Copyright 2022 The KubeVela Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package model
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  
    23  	workflowv1alpha1 "github.com/kubevela/workflow/api/v1alpha1"
    24  	"sigs.k8s.io/controller-runtime/pkg/client"
    25  
    26  	"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
    27  	"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
    28  	"github.com/oam-dev/kubevela/pkg/velaql/providers/query"
    29  	"github.com/oam-dev/kubevela/pkg/velaql/providers/query/types"
    30  	clicommon "github.com/oam-dev/kubevela/references/common"
    31  )
    32  
    33  // Application is the application resource object
    34  type Application struct {
    35  	name         string
    36  	namespace    string
    37  	phase        string
    38  	service      string
    39  	workflow     string
    40  	workflowMode string
    41  	createTime   string
    42  }
    43  
    44  // ApplicationList is application resource list
    45  type ApplicationList []Application
    46  
    47  // ToTableBody generate body of table in application view
    48  func (l ApplicationList) ToTableBody() [][]string {
    49  	data := make([][]string, len(l))
    50  	for index, app := range l {
    51  		data[index] = []string{app.name, app.namespace, app.phase, app.workflowMode, app.workflow, app.service, app.createTime}
    52  	}
    53  	return data
    54  }
    55  
    56  // ListApplications list all apps in all namespaces
    57  func ListApplications(ctx context.Context, c client.Client) (ApplicationList, error) {
    58  	apps := v1beta1.ApplicationList{}
    59  	namespace := ctx.Value(&CtxKeyNamespace).(string)
    60  
    61  	if err := c.List(ctx, &apps, client.InNamespace(namespace)); err != nil {
    62  		return ApplicationList{}, err
    63  	}
    64  	appList := make(ApplicationList, len(apps.Items))
    65  	for index, app := range apps.Items {
    66  		appList[index] = Application{name: app.Name, namespace: app.Namespace, phase: string(app.Status.Phase), createTime: app.CreationTimestamp.String()}
    67  		appList[index].service = serviceNum(app)
    68  		appList[index].workflow = workflowStepNum(app)
    69  		appList[index].workflowMode = workflowMode(app)
    70  	}
    71  	return appList, nil
    72  }
    73  
    74  // LoadApplication load the corresponding application according to name and namespace
    75  func LoadApplication(c client.Client, name, ns string) (*v1beta1.Application, error) {
    76  	app := new(v1beta1.Application)
    77  	err := c.Get(context.Background(), client.ObjectKey{
    78  		Name:      name,
    79  		Namespace: ns,
    80  	}, app)
    81  	if err != nil {
    82  		return nil, err
    83  	}
    84  	return app, nil
    85  }
    86  
    87  // ApplicationResourceTopology return the applied resource of the app in tree form
    88  func ApplicationResourceTopology(c client.Client, name, ns string) ([]*types.AppliedResource, error) {
    89  	opt := query.Option{
    90  		Name:       name,
    91  		Namespace:  ns,
    92  		WithStatus: true,
    93  		WithTree:   true,
    94  	}
    95  	collector := query.NewAppCollector(c, opt)
    96  	app := new(v1beta1.Application)
    97  	appKey := client.ObjectKey{Name: opt.Name, Namespace: opt.Namespace}
    98  	if err := c.Get(context.Background(), appKey, app); err != nil {
    99  		return nil, err
   100  	}
   101  	appResList, err := collector.ListApplicationResources(context.Background(), app)
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  	return appResList, nil
   106  }
   107  
   108  // applicationNum return the num of application
   109  func applicationNum(ctx context.Context, c client.Client) (int, error) {
   110  	apps := v1beta1.ApplicationList{}
   111  	if err := c.List(ctx, &apps); err != nil {
   112  		return 0, err
   113  	}
   114  	return len(apps.Items), nil
   115  }
   116  
   117  // runningApplicationNum return the num of running application
   118  func runningApplicationNum(ctx context.Context, c client.Client) (int, error) {
   119  	num := 0
   120  	apps := v1beta1.ApplicationList{}
   121  	if err := c.List(ctx, &apps); err != nil {
   122  		return num, err
   123  	}
   124  	for _, app := range apps.Items {
   125  		if app.Status.Phase == common.ApplicationRunning {
   126  			num++
   127  		}
   128  	}
   129  	return num, nil
   130  }
   131  
   132  func serviceNum(app v1beta1.Application) string {
   133  	total, healthy := len(app.Status.Services), 0
   134  	for _, service := range app.Status.Services {
   135  		if service.Healthy {
   136  			healthy++
   137  		}
   138  	}
   139  	return fmt.Sprintf("%d/%d", healthy, total)
   140  }
   141  
   142  func workflowMode(app v1beta1.Application) string {
   143  	if app.Status.Workflow == nil {
   144  		return Unknown
   145  	}
   146  	return app.Status.Workflow.Mode
   147  }
   148  
   149  func workflowStepNum(app v1beta1.Application) string {
   150  	if app.Status.Workflow == nil {
   151  		return clicommon.MetricsNA
   152  	}
   153  	total, succeed := len(app.Status.Workflow.Steps), 0
   154  	for _, step := range app.Status.Workflow.Steps {
   155  		if step.Phase == workflowv1alpha1.WorkflowStepPhaseSucceeded {
   156  			succeed++
   157  		}
   158  	}
   159  	return fmt.Sprintf("%d/%d", succeed, total)
   160  }