Add cluster name filter for phase list cmd
This patch implements ability to filter phase by given cluster name. Change-Id: I4eb95f9f75c57eff4ae8eb41c608c6f6d7fa009c Signed-off-by: Ruslan Aliev <raliev@mirantis.com>
This commit is contained in:
parent
a527b7f1f5
commit
d1c7913ed3
@ -29,8 +29,8 @@ are executed in parallel.
|
||||
`
|
||||
)
|
||||
|
||||
// NewPlanCommand creates a command which prints available phases
|
||||
func NewPlanCommand(cfgFactory config.Factory) *cobra.Command {
|
||||
// NewListCommand creates a command which prints available phases
|
||||
func NewListCommand(cfgFactory config.Factory) *cobra.Command {
|
||||
p := &phase.ListCommand{Factory: cfgFactory}
|
||||
|
||||
planCmd := &cobra.Command{
|
||||
@ -42,5 +42,24 @@ func NewPlanCommand(cfgFactory config.Factory) *cobra.Command {
|
||||
return p.RunE()
|
||||
},
|
||||
}
|
||||
addListFlags(p, planCmd)
|
||||
return planCmd
|
||||
}
|
||||
|
||||
// addListFlags adds flags for phase list sub-command
|
||||
func addListFlags(options *phase.ListCommand, cmd *cobra.Command) {
|
||||
flags := cmd.Flags()
|
||||
|
||||
flags.StringVarP(
|
||||
&options.ClusterName,
|
||||
"cluster-name",
|
||||
"c",
|
||||
"",
|
||||
"filter documents by cluster name")
|
||||
|
||||
flags.StringVar(
|
||||
&options.PlanID.Name,
|
||||
"plan",
|
||||
"",
|
||||
"Plan name of a plan")
|
||||
}
|
@ -26,7 +26,7 @@ func TestNewPlanCommand(t *testing.T) {
|
||||
{
|
||||
Name: "phase-plan-cmd-with-help",
|
||||
CmdLine: "--help",
|
||||
Cmd: phase.NewPlanCommand(nil),
|
||||
Cmd: phase.NewListCommand(nil),
|
||||
},
|
||||
}
|
||||
for _, testcase := range tests {
|
@ -36,7 +36,7 @@ func NewPhaseCommand(cfgFactory config.Factory) *cobra.Command {
|
||||
}
|
||||
|
||||
phaseRootCmd.AddCommand(NewRenderCommand(cfgFactory))
|
||||
phaseRootCmd.AddCommand(NewPlanCommand(cfgFactory))
|
||||
phaseRootCmd.AddCommand(NewListCommand(cfgFactory))
|
||||
phaseRootCmd.AddCommand(NewRunCommand(cfgFactory))
|
||||
phaseRootCmd.AddCommand(NewTreeCommand(cfgFactory))
|
||||
|
||||
|
@ -6,4 +6,6 @@ Usage:
|
||||
list [flags]
|
||||
|
||||
Flags:
|
||||
-h, --help help for list
|
||||
-c, --cluster-name string filter documents by cluster name
|
||||
-h, --help help for list
|
||||
--plan string Plan name of a plan
|
||||
|
@ -16,7 +16,9 @@ airshipctl phase list [flags]
|
||||
### Options
|
||||
|
||||
```
|
||||
-h, --help help for list
|
||||
-c, --cluster-name string filter documents by cluster name
|
||||
-h, --help help for list
|
||||
--plan string Plan name of a plan
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
@ -76,8 +76,10 @@ func (c *RunCommand) RunE() error {
|
||||
|
||||
// ListCommand phase list command
|
||||
type ListCommand struct {
|
||||
Factory config.Factory
|
||||
Writer io.Writer
|
||||
Factory config.Factory
|
||||
Writer io.Writer
|
||||
ClusterName string
|
||||
PlanID ifc.ID
|
||||
}
|
||||
|
||||
// RunE runs a phase plan command
|
||||
@ -92,7 +94,8 @@ func (c *ListCommand) RunE() error {
|
||||
return err
|
||||
}
|
||||
|
||||
phases, err := helper.ListPhases()
|
||||
o := ifc.ListPhaseOptions{ClusterName: c.ClusterName, PlanID: c.PlanID}
|
||||
phases, err := helper.ListPhases(o)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
package phase
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"path/filepath"
|
||||
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@ -25,6 +26,7 @@ import (
|
||||
"opendev.org/airship/airshipctl/pkg/document"
|
||||
"opendev.org/airship/airshipctl/pkg/inventory"
|
||||
inventoryifc "opendev.org/airship/airshipctl/pkg/inventory/ifc"
|
||||
"opendev.org/airship/airshipctl/pkg/log"
|
||||
"opendev.org/airship/airshipctl/pkg/phase/ifc"
|
||||
"opendev.org/airship/airshipctl/pkg/util"
|
||||
)
|
||||
@ -124,7 +126,7 @@ func (helper *Helper) Plan(planID ifc.ID) (*v1alpha1.PhasePlan, error) {
|
||||
}
|
||||
|
||||
// ListPhases returns all phases associated with manifest
|
||||
func (helper *Helper) ListPhases() ([]*v1alpha1.Phase, error) {
|
||||
func (helper *Helper) ListPhases(o ifc.ListPhaseOptions) ([]*v1alpha1.Phase, error) {
|
||||
bundle, err := document.NewBundleByPath(helper.phaseBundleRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -136,12 +138,32 @@ func (helper *Helper) ListPhases() ([]*v1alpha1.Phase, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
docs, err := bundle.Select(selector)
|
||||
bundle, err = bundle.SelectBundle(selector)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
phases := []*v1alpha1.Phase{}
|
||||
if o.ClusterName != "" {
|
||||
if bundle, err = bundle.SelectByFieldValue("metadata.clusterName", func(v interface{}) bool {
|
||||
if field, ok := v.(string); ok {
|
||||
return field == o.ClusterName
|
||||
}
|
||||
return false
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var docs []document.Document
|
||||
if o.PlanID.Name != "" {
|
||||
if docs, err = helper.getDocsByPhasePlan(o.PlanID, bundle); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if docs, err = bundle.GetAllDocuments(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
phases := make([]*v1alpha1.Phase, 0)
|
||||
for _, doc := range docs {
|
||||
p := v1alpha1.DefaultPhase()
|
||||
if err = doc.ToAPIObject(p, v1alpha1.Scheme); err != nil {
|
||||
@ -152,6 +174,37 @@ func (helper *Helper) ListPhases() ([]*v1alpha1.Phase, error) {
|
||||
return phases, nil
|
||||
}
|
||||
|
||||
func (helper *Helper) getDocsByPhasePlan(planID ifc.ID, bundle document.Bundle) ([]document.Document, error) {
|
||||
docs := make([]document.Document, 0)
|
||||
plan, filterErr := helper.Plan(planID)
|
||||
if filterErr != nil {
|
||||
return nil, filterErr
|
||||
}
|
||||
for _, phaseStep := range plan.Phases {
|
||||
p := &v1alpha1.Phase{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: phaseStep.Name,
|
||||
},
|
||||
}
|
||||
selector, filterErr := document.NewSelector().ByObject(p, v1alpha1.Scheme)
|
||||
if filterErr != nil {
|
||||
return nil, filterErr
|
||||
}
|
||||
|
||||
doc, filterErr := bundle.SelectOne(selector)
|
||||
if filterErr != nil {
|
||||
if errors.As(filterErr, &document.ErrDocNotFound{}) {
|
||||
log.Debug(filterErr.Error())
|
||||
continue
|
||||
}
|
||||
return nil, filterErr
|
||||
}
|
||||
|
||||
docs = append(docs, doc)
|
||||
}
|
||||
return docs, nil
|
||||
}
|
||||
|
||||
// ListPlans returns all phases associated with manifest
|
||||
func (helper *Helper) ListPlans() ([]*v1alpha1.PhasePlan, error) {
|
||||
bundle, err := document.NewBundleByPath(helper.phaseBundleRoot)
|
||||
|
@ -186,6 +186,7 @@ func TestHelperListPhases(t *testing.T) {
|
||||
errContains string
|
||||
phaseLen int
|
||||
config func(t *testing.T) *config.Config
|
||||
options ifc.ListPhaseOptions
|
||||
}{
|
||||
{
|
||||
name: "Success phase list",
|
||||
@ -210,6 +211,25 @@ func TestHelperListPhases(t *testing.T) {
|
||||
},
|
||||
phaseLen: 0,
|
||||
},
|
||||
{
|
||||
name: "Success with cluster name and phase plan",
|
||||
config: func(t *testing.T) *config.Config {
|
||||
conf := testConfig(t)
|
||||
return conf
|
||||
},
|
||||
options: ifc.ListPhaseOptions{ClusterName: "some_cluster", PlanID: ifc.ID{Name: "phasePlan"}},
|
||||
phaseLen: 1,
|
||||
},
|
||||
{
|
||||
name: "Invalid phase plan name",
|
||||
config: func(t *testing.T) *config.Config {
|
||||
conf := testConfig(t)
|
||||
return conf
|
||||
},
|
||||
options: ifc.ListPhaseOptions{PlanID: ifc.ID{Name: "NonExistentPlan"}},
|
||||
phaseLen: 0,
|
||||
errContains: "found no documents",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
@ -219,7 +239,7 @@ func TestHelperListPhases(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, helper)
|
||||
|
||||
actualList, actualErr := helper.ListPhases()
|
||||
actualList, actualErr := helper.ListPhases(tt.options)
|
||||
if tt.errContains != "" {
|
||||
require.Error(t, actualErr)
|
||||
assert.Contains(t, actualErr.Error(), tt.errContains)
|
||||
|
@ -29,7 +29,7 @@ type Helper interface {
|
||||
WorkDir() (string, error)
|
||||
Phase(phaseID ID) (*v1alpha1.Phase, error)
|
||||
Plan(planID ID) (*v1alpha1.PhasePlan, error)
|
||||
ListPhases() ([]*v1alpha1.Phase, error)
|
||||
ListPhases(o ListPhaseOptions) ([]*v1alpha1.Phase, error)
|
||||
ListPlans() ([]*v1alpha1.PhasePlan, error)
|
||||
ClusterMapAPIobj() (*v1alpha1.ClusterMap, error)
|
||||
ClusterMap() (clustermap.ClusterMap, error)
|
||||
|
@ -43,6 +43,12 @@ type ID struct {
|
||||
Namespace string
|
||||
}
|
||||
|
||||
// ListPhaseOptions is used to filter phases
|
||||
type ListPhaseOptions struct {
|
||||
ClusterName string
|
||||
PlanID ID
|
||||
}
|
||||
|
||||
// Client is a phase client that can be used by command line or ui packages
|
||||
type Client interface {
|
||||
PhaseByID(ID) (Phase, error)
|
||||
|
@ -2,6 +2,7 @@ apiVersion: airshipit.org/v1alpha1
|
||||
kind: Phase
|
||||
metadata:
|
||||
name: some_phase
|
||||
clusterName: some_cluster
|
||||
config:
|
||||
executorRef:
|
||||
apiVersion: airshipit.org/v1alpha1
|
||||
|
Loading…
Reference in New Issue
Block a user