Skip to content

Commit

Permalink
feat(cdsctl): action usage command (#5025)
Browse files Browse the repository at this point in the history
  • Loading branch information
codebfu authored Mar 4, 2020
1 parent 9eb9721 commit 320bf76
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 43 deletions.
42 changes: 42 additions & 0 deletions cli/cdsctl/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io/ioutil"
"path"
"time"
"strings"

"github.com/spf13/cobra"

Expand All @@ -28,6 +29,7 @@ var actionBuiltinCmd = cli.Command{
func action() *cobra.Command {
return cli.NewCommand(actionCmd, nil, []*cobra.Command{
cli.NewListCommand(actionListCmd, actionListRun, nil),
cli.NewListCommand(actionUsageCmd, actionUsageRun, nil),
cli.NewGetCommand(actionShowCmd, actionShowRun, nil),
cli.NewCommand(actionDeleteCmd, actionDeleteRun, nil),
cli.NewCommand(actionDocCmd, actionDocRun, nil),
Expand Down Expand Up @@ -87,6 +89,46 @@ func actionListRun(v cli.Values) (cli.ListResult, error) {
return cli.AsListResult(ads), nil
}

var actionUsageCmd = cli.Command{
Name: "usage",
Short: "CDS action usage",
Args: []cli.Arg{
{Name: "action-path"},
},
}

func actionUsageRun(v cli.Values) (cli.ListResult, error) {
groupName, actionName, err := cli.ParsePath(v.GetString("action-path"))
if err != nil {
return nil, err
}

usages, err := client.ActionUsage(groupName, actionName)
if err != nil {
return nil, err
}

type ActionUsageDisplay struct {
Type string `cli:"Type"`
Path string `cli:"Path"`
}

au := []ActionUsageDisplay{}
for _, v := range usages.Pipelines {
au = append(au, ActionUsageDisplay{
Type: "pipeline",
Path: strings.Replace(fmt.Sprintf("%s - %s - %s", v.ProjectName, v.PipelineName, v.ActionName)," "," ",-1),
})
}
for _, v := range usages.Actions {
au = append(au, ActionUsageDisplay{
Type: "action",
Path: fmt.Sprintf("%s/%s", v.GroupName, v.ParentActionName),
})
}
return cli.AsListResult(au), nil
}

var actionShowCmd = cli.Command{
Name: "show",
Short: "Show a CDS action",
Expand Down
8 changes: 4 additions & 4 deletions engine/api/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -823,8 +823,8 @@ func (api *API) getActionBuiltinUsageHandler() service.Handler {
}
}

func getActionUsage(ctx context.Context, db gorp.SqlExecutor, store cache.Store, a *sdk.Action) (action.Usage, error) {
var usage action.Usage
func getActionUsage(ctx context.Context, db gorp.SqlExecutor, store cache.Store, a *sdk.Action) (sdk.ActionUsages, error) {
var usage sdk.ActionUsages
var err error
usage.Pipelines, err = action.GetPipelineUsages(db, group.SharedInfraGroup.ID, a.ID)
if err != nil {
Expand All @@ -848,7 +848,7 @@ func getActionUsage(ctx context.Context, db gorp.SqlExecutor, store cache.Store,
mProjectIDs[ps[i].ID] = struct{}{}
}

filteredPipelines := make([]action.UsagePipeline, 0, len(usage.Pipelines))
filteredPipelines := make([]sdk.UsagePipeline, 0, len(usage.Pipelines))
for i := range usage.Pipelines {
if _, ok := mProjectIDs[usage.Pipelines[i].ProjectID]; ok {
filteredPipelines = append(filteredPipelines, usage.Pipelines[i])
Expand All @@ -863,7 +863,7 @@ func getActionUsage(ctx context.Context, db gorp.SqlExecutor, store cache.Store,
mGroupIDs[groupIDs[i]] = struct{}{}
}

filteredActions := make([]action.UsageAction, 0, len(usage.Actions))
filteredActions := make([]sdk.UsageAction, 0, len(usage.Actions))
for i := range usage.Actions {
if _, ok := mGroupIDs[usage.Actions[i].GroupID]; ok {
filteredActions = append(filteredActions, usage.Actions[i])
Expand Down
45 changes: 6 additions & 39 deletions engine/api/action/usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,8 @@ import (
"github.com/ovh/cds/sdk"
)

// Usage for action.
type Usage struct {
Pipelines []UsagePipeline `json:"pipelines"`
Actions []UsageAction `json:"actions"`
}

// UsagePipeline represent a pipeline using an action.
type UsagePipeline struct {
ProjectID int64 `json:"project_id"`
ProjectKey string `json:"project_key"`
ProjectName string `json:"project_name"`
PipelineID int64 `json:"pipeline_id"`
PipelineName string `json:"pipeline_name"`
StageID int64 `json:"stage_id"`
StageName string `json:"stage_name"`
JobID int64 `json:"job_id"`
JobName string `json:"job_name"`
ActionID int64 `json:"action_id"`
ActionName string `json:"action_name"`
Warning bool `json:"warning"`
}

// GetPipelineUsages returns the list of pipelines using an action
func GetPipelineUsages(db gorp.SqlExecutor, sharedInfraGroupID, actionID int64) ([]UsagePipeline, error) {
func GetPipelineUsages(db gorp.SqlExecutor, sharedInfraGroupID, actionID int64) ([]sdk.UsagePipeline, error) {
rows, err := db.Query(`
SELECT DISTINCT
project.id, project.projectKey, project.name,
Expand All @@ -54,9 +32,9 @@ func GetPipelineUsages(db gorp.SqlExecutor, sharedInfraGroupID, actionID int64)
}
defer rows.Close()

us := []UsagePipeline{}
us := []sdk.UsagePipeline{}
for rows.Next() {
var u UsagePipeline
var u sdk.UsagePipeline
if err := rows.Scan(
&u.ProjectID, &u.ProjectKey, &u.ProjectName,
&u.PipelineID, &u.PipelineName,
Expand All @@ -73,19 +51,8 @@ func GetPipelineUsages(db gorp.SqlExecutor, sharedInfraGroupID, actionID int64)
return us, nil
}

// UsageAction represent a action using an action.
type UsageAction struct {
GroupID int64 `json:"group_id"`
GroupName string `json:"group_name"`
ParentActionID int64 `json:"parent_action_id"`
ParentActionName string `json:"parent_action_name"`
ActionID int64 `json:"action_id"`
ActionName string `json:"action_name"`
Warning bool `json:"warning"`
}

// GetActionUsages returns the list of actions using an action
func GetActionUsages(db gorp.SqlExecutor, sharedInfraGroupID, actionID int64) ([]UsageAction, error) {
func GetActionUsages(db gorp.SqlExecutor, sharedInfraGroupID, actionID int64) ([]sdk.UsageAction, error) {
rows, err := db.Query(`
SELECT DISTINCT
"group".id, "group".name,
Expand All @@ -104,9 +71,9 @@ func GetActionUsages(db gorp.SqlExecutor, sharedInfraGroupID, actionID int64) ([
}
defer rows.Close()

us := []UsageAction{}
us := []sdk.UsageAction{}
for rows.Next() {
var u UsageAction
var u sdk.UsageAction
if err := rows.Scan(
&u.GroupID, &u.GroupName,
&u.ParentActionID, &u.ParentActionName,
Expand Down
33 changes: 33 additions & 0 deletions sdk/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,39 @@ type Action struct {
Editable bool `json:"editable,omitempty" db:"-"`
}

// UsageAction represent a action using an action.
type UsageAction struct {
GroupID int64 `json:"group_id"`
GroupName string `json:"group_name"`
ParentActionID int64 `json:"parent_action_id"`
ParentActionName string `json:"parent_action_name"`
ActionID int64 `json:"action_id"`
ActionName string `json:"action_name"`
Warning bool `json:"warning"`
}

// ActionUsages for action.
type ActionUsages struct {
Pipelines []UsagePipeline `json:"pipelines"`
Actions []UsageAction `json:"actions"`
}

// UsagePipeline represent a pipeline using an action.
type UsagePipeline struct {
ProjectID int64 `json:"project_id"`
ProjectKey string `json:"project_key"`
ProjectName string `json:"project_name"`
PipelineID int64 `json:"pipeline_id"`
PipelineName string `json:"pipeline_name"`
StageID int64 `json:"stage_id"`
StageName string `json:"stage_name"`
JobID int64 `json:"job_id"`
JobName string `json:"job_name"`
ActionID int64 `json:"action_id"`
ActionName string `json:"action_name"`
Warning bool `json:"warning"`
}

// Value returns driver.Value from action.
func (a Action) Value() (driver.Value, error) {
j, err := json.Marshal(a)
Expand Down
11 changes: 11 additions & 0 deletions sdk/cdsclient/client_action.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ func (c *client) ActionGet(groupName, name string, mods ...RequestModifier) (*sd
return &a, nil
}

func (c *client) ActionUsage(groupName, name string, mods ...RequestModifier) (*sdk.ActionUsages, error) {
var a sdk.ActionUsages

path := fmt.Sprintf("/action/%s/%s/usage", groupName, name)
if _, err := c.GetJSON(context.Background(), path, &a, mods...); err != nil {
return nil, err
}

return &a, nil
}

func (c *client) ActionList() ([]sdk.Action, error) {
actions := []sdk.Action{}
if _, err := c.GetJSON(context.Background(), "/action", &actions); err != nil {
Expand Down
1 change: 1 addition & 0 deletions sdk/cdsclient/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ type DownloadClient interface {
type ActionClient interface {
ActionDelete(groupName, name string) error
ActionGet(groupName, name string, mods ...RequestModifier) (*sdk.Action, error)
ActionUsage(groupName, name string, mods ...RequestModifier) (*sdk.ActionUsages, error)
ActionList() ([]sdk.Action, error)
ActionImport(content io.Reader, format string) error
ActionExport(groupName, name string, format string) ([]byte, error)
Expand Down
40 changes: 40 additions & 0 deletions sdk/cdsclient/mock_cdsclient/interface_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 320bf76

Please sign in to comment.