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
|
// NewListCommand creates a command which prints available phases
|
||||||
func NewPlanCommand(cfgFactory config.Factory) *cobra.Command {
|
func NewListCommand(cfgFactory config.Factory) *cobra.Command {
|
||||||
p := &phase.ListCommand{Factory: cfgFactory}
|
p := &phase.ListCommand{Factory: cfgFactory}
|
||||||
|
|
||||||
planCmd := &cobra.Command{
|
planCmd := &cobra.Command{
|
||||||
|
@ -42,5 +42,24 @@ func NewPlanCommand(cfgFactory config.Factory) *cobra.Command {
|
||||||
return p.RunE()
|
return p.RunE()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
addListFlags(p, planCmd)
|
||||||
return 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",
|
Name: "phase-plan-cmd-with-help",
|
||||||
CmdLine: "--help",
|
CmdLine: "--help",
|
||||||
Cmd: phase.NewPlanCommand(nil),
|
Cmd: phase.NewListCommand(nil),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, testcase := range tests {
|
for _, testcase := range tests {
|
|
@ -36,7 +36,7 @@ func NewPhaseCommand(cfgFactory config.Factory) *cobra.Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
phaseRootCmd.AddCommand(NewRenderCommand(cfgFactory))
|
phaseRootCmd.AddCommand(NewRenderCommand(cfgFactory))
|
||||||
phaseRootCmd.AddCommand(NewPlanCommand(cfgFactory))
|
phaseRootCmd.AddCommand(NewListCommand(cfgFactory))
|
||||||
phaseRootCmd.AddCommand(NewRunCommand(cfgFactory))
|
phaseRootCmd.AddCommand(NewRunCommand(cfgFactory))
|
||||||
phaseRootCmd.AddCommand(NewTreeCommand(cfgFactory))
|
phaseRootCmd.AddCommand(NewTreeCommand(cfgFactory))
|
||||||
|
|
||||||
|
|
|
@ -6,4 +6,6 @@ Usage:
|
||||||
list [flags]
|
list [flags]
|
||||||
|
|
||||||
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
|
### 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
|
### Options inherited from parent commands
|
||||||
|
|
|
@ -76,8 +76,10 @@ func (c *RunCommand) RunE() error {
|
||||||
|
|
||||||
// ListCommand phase list command
|
// ListCommand phase list command
|
||||||
type ListCommand struct {
|
type ListCommand struct {
|
||||||
Factory config.Factory
|
Factory config.Factory
|
||||||
Writer io.Writer
|
Writer io.Writer
|
||||||
|
ClusterName string
|
||||||
|
PlanID ifc.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunE runs a phase plan command
|
// RunE runs a phase plan command
|
||||||
|
@ -92,7 +94,8 @@ func (c *ListCommand) RunE() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
phases, err := helper.ListPhases()
|
o := ifc.ListPhaseOptions{ClusterName: c.ClusterName, PlanID: c.PlanID}
|
||||||
|
phases, err := helper.ListPhases(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
package phase
|
package phase
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
@ -25,6 +26,7 @@ import (
|
||||||
"opendev.org/airship/airshipctl/pkg/document"
|
"opendev.org/airship/airshipctl/pkg/document"
|
||||||
"opendev.org/airship/airshipctl/pkg/inventory"
|
"opendev.org/airship/airshipctl/pkg/inventory"
|
||||||
inventoryifc "opendev.org/airship/airshipctl/pkg/inventory/ifc"
|
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/phase/ifc"
|
||||||
"opendev.org/airship/airshipctl/pkg/util"
|
"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
|
// 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)
|
bundle, err := document.NewBundleByPath(helper.phaseBundleRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -136,12 +138,32 @@ func (helper *Helper) ListPhases() ([]*v1alpha1.Phase, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
docs, err := bundle.Select(selector)
|
bundle, err = bundle.SelectBundle(selector)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
for _, doc := range docs {
|
||||||
p := v1alpha1.DefaultPhase()
|
p := v1alpha1.DefaultPhase()
|
||||||
if err = doc.ToAPIObject(p, v1alpha1.Scheme); err != nil {
|
if err = doc.ToAPIObject(p, v1alpha1.Scheme); err != nil {
|
||||||
|
@ -152,6 +174,37 @@ func (helper *Helper) ListPhases() ([]*v1alpha1.Phase, error) {
|
||||||
return phases, nil
|
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
|
// ListPlans returns all phases associated with manifest
|
||||||
func (helper *Helper) ListPlans() ([]*v1alpha1.PhasePlan, error) {
|
func (helper *Helper) ListPlans() ([]*v1alpha1.PhasePlan, error) {
|
||||||
bundle, err := document.NewBundleByPath(helper.phaseBundleRoot)
|
bundle, err := document.NewBundleByPath(helper.phaseBundleRoot)
|
||||||
|
|
|
@ -186,6 +186,7 @@ func TestHelperListPhases(t *testing.T) {
|
||||||
errContains string
|
errContains string
|
||||||
phaseLen int
|
phaseLen int
|
||||||
config func(t *testing.T) *config.Config
|
config func(t *testing.T) *config.Config
|
||||||
|
options ifc.ListPhaseOptions
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Success phase list",
|
name: "Success phase list",
|
||||||
|
@ -210,6 +211,25 @@ func TestHelperListPhases(t *testing.T) {
|
||||||
},
|
},
|
||||||
phaseLen: 0,
|
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 {
|
for _, test := range testCases {
|
||||||
|
@ -219,7 +239,7 @@ func TestHelperListPhases(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, helper)
|
require.NotNil(t, helper)
|
||||||
|
|
||||||
actualList, actualErr := helper.ListPhases()
|
actualList, actualErr := helper.ListPhases(tt.options)
|
||||||
if tt.errContains != "" {
|
if tt.errContains != "" {
|
||||||
require.Error(t, actualErr)
|
require.Error(t, actualErr)
|
||||||
assert.Contains(t, actualErr.Error(), tt.errContains)
|
assert.Contains(t, actualErr.Error(), tt.errContains)
|
||||||
|
|
|
@ -29,7 +29,7 @@ type Helper interface {
|
||||||
WorkDir() (string, error)
|
WorkDir() (string, error)
|
||||||
Phase(phaseID ID) (*v1alpha1.Phase, error)
|
Phase(phaseID ID) (*v1alpha1.Phase, error)
|
||||||
Plan(planID ID) (*v1alpha1.PhasePlan, error)
|
Plan(planID ID) (*v1alpha1.PhasePlan, error)
|
||||||
ListPhases() ([]*v1alpha1.Phase, error)
|
ListPhases(o ListPhaseOptions) ([]*v1alpha1.Phase, error)
|
||||||
ListPlans() ([]*v1alpha1.PhasePlan, error)
|
ListPlans() ([]*v1alpha1.PhasePlan, error)
|
||||||
ClusterMapAPIobj() (*v1alpha1.ClusterMap, error)
|
ClusterMapAPIobj() (*v1alpha1.ClusterMap, error)
|
||||||
ClusterMap() (clustermap.ClusterMap, error)
|
ClusterMap() (clustermap.ClusterMap, error)
|
||||||
|
|
|
@ -43,6 +43,12 @@ type ID struct {
|
||||||
Namespace string
|
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
|
// Client is a phase client that can be used by command line or ui packages
|
||||||
type Client interface {
|
type Client interface {
|
||||||
PhaseByID(ID) (Phase, error)
|
PhaseByID(ID) (Phase, error)
|
||||||
|
|
|
@ -2,6 +2,7 @@ apiVersion: airshipit.org/v1alpha1
|
||||||
kind: Phase
|
kind: Phase
|
||||||
metadata:
|
metadata:
|
||||||
name: some_phase
|
name: some_phase
|
||||||
|
clusterName: some_cluster
|
||||||
config:
|
config:
|
||||||
executorRef:
|
executorRef:
|
||||||
apiVersion: airshipit.org/v1alpha1
|
apiVersion: airshipit.org/v1alpha1
|
||||||
|
|
Loading…
Reference in New Issue