Implement plan run command
Change-Id: Ie627ce670cd2b19d6999dc7c7a7a6dc12b25cace Closes: #395
This commit is contained in:
parent
4cba00d98c
commit
178b0eff3e
@ -18,7 +18,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"opendev.org/airship/airshipctl/pkg/config"
|
||||
"opendev.org/airship/airshipctl/pkg/errors"
|
||||
"opendev.org/airship/airshipctl/pkg/phase"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -29,14 +29,37 @@ Run life-cycle phase plan which was defined in document model.
|
||||
|
||||
// NewRunCommand creates a command which execute a particular phase plan
|
||||
func NewRunCommand(cfgFactory config.Factory) *cobra.Command {
|
||||
listCmd := &cobra.Command{
|
||||
r := &phase.PlanRunCommand{
|
||||
Factory: cfgFactory,
|
||||
Options: phase.PlanRunFlags{},
|
||||
}
|
||||
runCmd := &cobra.Command{
|
||||
Use: "run PLAN_NAME",
|
||||
Short: "Run plan",
|
||||
Long: runLong[1:],
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return errors.ErrNotImplemented{What: "airshipctl plan run"}
|
||||
r.Options.PlanID.Name = args[0]
|
||||
return r.RunE()
|
||||
},
|
||||
}
|
||||
return listCmd
|
||||
|
||||
flags := runCmd.Flags()
|
||||
flags.BoolVar(
|
||||
&r.Options.DryRun,
|
||||
"dry-run",
|
||||
false,
|
||||
"simulate phase execution")
|
||||
flags.DurationVar(
|
||||
&r.Options.Timeout,
|
||||
"wait-timeout",
|
||||
0,
|
||||
"wait timeout")
|
||||
flags.StringVar(
|
||||
&r.Options.Kubeconfig,
|
||||
"kubeconfig",
|
||||
"",
|
||||
"Path to kubeconfig associated with site being managed")
|
||||
|
||||
return runCmd
|
||||
}
|
||||
|
@ -4,4 +4,7 @@ Usage:
|
||||
run PLAN_NAME [flags]
|
||||
|
||||
Flags:
|
||||
-h, --help help for run
|
||||
--dry-run simulate phase execution
|
||||
-h, --help help for run
|
||||
--kubeconfig string Path to kubeconfig associated with site being managed
|
||||
--wait-timeout duration wait timeout
|
||||
|
@ -14,7 +14,10 @@ airshipctl plan run PLAN_NAME [flags]
|
||||
### Options
|
||||
|
||||
```
|
||||
-h, --help help for run
|
||||
--dry-run simulate phase execution
|
||||
-h, --help help for run
|
||||
--kubeconfig string Path to kubeconfig associated with site being managed
|
||||
--wait-timeout duration wait timeout
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
@ -788,15 +788,13 @@ apiVersion: airshipit.org/v1alpha1
|
||||
kind: PhasePlan
|
||||
metadata:
|
||||
name: phasePlan
|
||||
phaseGroups:
|
||||
- name: group1
|
||||
phases:
|
||||
- name: clusterctl-init-ephemeral
|
||||
- name: controlplane-ephemeral
|
||||
- name: initinfra-target
|
||||
- name: clusterctl-init-target
|
||||
- name: clusterctl-move
|
||||
- name: workers-target
|
||||
phases:
|
||||
- name: clusterctl-init-ephemeral
|
||||
- name: controlplane-ephemeral
|
||||
- name: initinfra-target
|
||||
- name: clusterctl-init-target
|
||||
- name: clusterctl-move
|
||||
- name: workers-target
|
||||
```
|
||||
|
||||
### Cluster Templates
|
||||
|
@ -3,15 +3,13 @@ kind: PhasePlan
|
||||
metadata:
|
||||
name: phasePlan
|
||||
description: "Default phase plan"
|
||||
phaseGroups:
|
||||
- name: group1
|
||||
phases:
|
||||
- name: initinfra-ephemeral
|
||||
- name: initinfra-networking-ephemeral
|
||||
- name: clusterctl-init-ephemeral
|
||||
- name: controlplane-ephemeral
|
||||
- name: initinfra-target
|
||||
- name: initinfra-networking-target
|
||||
- name: workers-target
|
||||
- name: workers-classification
|
||||
- name: workload-target
|
||||
phases:
|
||||
- name: initinfra-ephemeral
|
||||
- name: initinfra-networking-ephemeral
|
||||
- name: clusterctl-init-ephemeral
|
||||
- name: controlplane-ephemeral
|
||||
- name: initinfra-target
|
||||
- name: initinfra-networking-target
|
||||
- name: workers-target
|
||||
- name: workers-classification
|
||||
- name: workload-target
|
||||
|
@ -2,15 +2,13 @@ apiVersion: airshipit.org/v1alpha1
|
||||
kind: PhasePlan
|
||||
metadata:
|
||||
name: phasePlan
|
||||
phaseGroups:
|
||||
- name: group1
|
||||
phases:
|
||||
- name: clusterctl-init-ephemeral
|
||||
- name: controlplane-ephemeral
|
||||
- name: initinfra-target
|
||||
- name: clusterctl-init-target
|
||||
- name: clusterctl-move
|
||||
- name: workers-target
|
||||
phases:
|
||||
- name: clusterctl-init-ephemeral
|
||||
- name: controlplane-ephemeral
|
||||
- name: initinfra-target
|
||||
- name: clusterctl-init-target
|
||||
- name: clusterctl-move
|
||||
- name: workers-target
|
||||
---
|
||||
apiVersion: airshipit.org/v1alpha1
|
||||
kind: Clusterctl
|
||||
|
@ -2,11 +2,9 @@ apiVersion: airshipit.org/v1alpha1
|
||||
kind: PhasePlan
|
||||
metadata:
|
||||
name: phasePlan
|
||||
phaseGroups:
|
||||
- name: group1
|
||||
phases:
|
||||
- name: clusterctl-init-ephemeral
|
||||
- name: controlplane-ephemeral
|
||||
- name: clusterctl-init-target
|
||||
- name: clusterctl-move
|
||||
- name: workers-target
|
||||
phases:
|
||||
- name: clusterctl-init-ephemeral
|
||||
- name: controlplane-ephemeral
|
||||
- name: clusterctl-init-target
|
||||
- name: clusterctl-move
|
||||
- name: workers-target
|
||||
|
@ -2,12 +2,10 @@ apiVersion: airshipit.org/v1alpha1
|
||||
kind: PhasePlan
|
||||
metadata:
|
||||
name: phasePlan
|
||||
phaseGroups:
|
||||
- name: group1
|
||||
phases:
|
||||
- name: clusterctl-init-ephemeral
|
||||
- name: controlplane-ephemeral
|
||||
- name: initinfra-networking-target
|
||||
- name: clusterctl-init-target
|
||||
- name: clusterctl-move
|
||||
- name: workers-target
|
||||
phases:
|
||||
- name: clusterctl-init-ephemeral
|
||||
- name: controlplane-ephemeral
|
||||
- name: initinfra-networking-target
|
||||
- name: clusterctl-init-target
|
||||
- name: clusterctl-move
|
||||
- name: workers-target
|
||||
|
@ -2,12 +2,10 @@ apiVersion: airshipit.org/v1alpha1
|
||||
kind: PhasePlan
|
||||
metadata:
|
||||
name: phasePlan
|
||||
phaseGroups:
|
||||
- name: group1
|
||||
phases:
|
||||
- name: clusterctl-init-ephemeral
|
||||
- name: controlplane-ephemeral
|
||||
- name: initinfra-target
|
||||
- name: clusterctl-init-target
|
||||
- name: clusterctl-move
|
||||
- name: workers-target
|
||||
phases:
|
||||
- name: clusterctl-init-ephemeral
|
||||
- name: controlplane-ephemeral
|
||||
- name: initinfra-target
|
||||
- name: clusterctl-init-target
|
||||
- name: clusterctl-move
|
||||
- name: workers-target
|
||||
|
@ -24,18 +24,11 @@ import (
|
||||
type PhasePlan struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
PhaseGroups []PhaseGroup `json:"phaseGroups,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Phases []PhaseStep `json:"phases,omitempty"`
|
||||
}
|
||||
|
||||
// PhaseGroup represents set of phases (i.e. steps) executed sequentially.
|
||||
// Phase groups are executed simultaneously
|
||||
type PhaseGroup struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Phases []PhaseGroupStep `json:"phases,omitempty"`
|
||||
}
|
||||
|
||||
// PhaseGroupStep represents phase (or step) within phase group
|
||||
type PhaseGroupStep struct {
|
||||
// PhaseStep represents phase (or step) within a phase plan
|
||||
type PhaseStep struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
|
@ -506,52 +506,15 @@ func (in *PhaseConfig) DeepCopy() *PhaseConfig {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *PhaseGroup) DeepCopyInto(out *PhaseGroup) {
|
||||
*out = *in
|
||||
if in.Phases != nil {
|
||||
in, out := &in.Phases, &out.Phases
|
||||
*out = make([]PhaseGroupStep, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PhaseGroup.
|
||||
func (in *PhaseGroup) DeepCopy() *PhaseGroup {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(PhaseGroup)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *PhaseGroupStep) DeepCopyInto(out *PhaseGroupStep) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PhaseGroupStep.
|
||||
func (in *PhaseGroupStep) DeepCopy() *PhaseGroupStep {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(PhaseGroupStep)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *PhasePlan) DeepCopyInto(out *PhasePlan) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
if in.PhaseGroups != nil {
|
||||
in, out := &in.PhaseGroups, &out.PhaseGroups
|
||||
*out = make([]PhaseGroup, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
if in.Phases != nil {
|
||||
in, out := &in.Phases, &out.Phases
|
||||
*out = make([]PhaseStep, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
@ -573,6 +536,21 @@ func (in *PhasePlan) DeepCopyObject() runtime.Object {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *PhaseStep) DeepCopyInto(out *PhaseStep) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PhaseStep.
|
||||
func (in *PhaseStep) DeepCopy() *PhaseStep {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(PhaseStep)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Provider) DeepCopyInto(out *Provider) {
|
||||
*out = *in
|
||||
|
@ -177,6 +177,34 @@ func (p *phase) Details() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
var _ ifc.Plan = &plan{}
|
||||
|
||||
type plan struct {
|
||||
helper ifc.Helper
|
||||
apiObj *v1alpha1.PhasePlan
|
||||
phaseClient ifc.Client
|
||||
}
|
||||
|
||||
// Validate makes sure that phase plan is properly configured
|
||||
// TODO implement this
|
||||
func (p *plan) Validate() error { return nil }
|
||||
|
||||
// Run function excutes Run method for each phase
|
||||
func (p *plan) Run(ro ifc.RunOptions) error {
|
||||
for _, step := range p.apiObj.Phases {
|
||||
phaseRunner, err := p.phaseClient.PhaseByID(ifc.ID{Name: step.Name})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("executing phase: %s\n", step)
|
||||
if err = phaseRunner.Run(ro); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ ifc.Client = &client{}
|
||||
|
||||
type client struct {
|
||||
@ -245,6 +273,18 @@ func (c *client) PhaseByID(id ifc.ID) (ifc.Phase, error) {
|
||||
return phase, nil
|
||||
}
|
||||
|
||||
func (c *client) PlanByID(id ifc.ID) (ifc.Plan, error) {
|
||||
planObj, err := c.Plan(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &plan{
|
||||
apiObj: planObj,
|
||||
helper: c.Helper,
|
||||
phaseClient: c,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *client) PhaseByAPIObj(phaseObj *v1alpha1.Phase) (ifc.Phase, error) {
|
||||
phase := &phase{
|
||||
apiObj: phaseObj,
|
||||
|
@ -123,7 +123,7 @@ func TestPhaseRun(t *testing.T) {
|
||||
client := phase.NewClient(helper, phase.InjectRegistry(tt.registryFunc))
|
||||
require.NotNil(t, client)
|
||||
p, err := client.PhaseByID(tt.phaseID)
|
||||
require.NotNil(t, client)
|
||||
require.NoError(t, err)
|
||||
err = p.Run(ifc.RunOptions{DryRun: true})
|
||||
if tt.errContains != "" {
|
||||
require.Error(t, err)
|
||||
@ -223,7 +223,7 @@ func TestBundleFactoryExecutor(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, helper)
|
||||
|
||||
fakeRegistry := func() map[schema.GroupVersionKind]ifc.ExecutorFactory {
|
||||
fakeReg := func() map[schema.GroupVersionKind]ifc.ExecutorFactory {
|
||||
validBundleFactory := schema.GroupVersionKind{
|
||||
Group: "airshipit.org",
|
||||
Version: "v1alpha1",
|
||||
@ -245,7 +245,7 @@ func TestBundleFactoryExecutor(t *testing.T) {
|
||||
invalidBundleFactory: bundleCheckFunc,
|
||||
}
|
||||
}
|
||||
c := phase.NewClient(helper, phase.InjectRegistry(fakeRegistry))
|
||||
c := phase.NewClient(helper, phase.InjectRegistry(fakeReg))
|
||||
p, err := c.PhaseByID(ifc.ID{Name: "capi_init"})
|
||||
require.NoError(t, err)
|
||||
_, err = p.Executor()
|
||||
@ -257,6 +257,50 @@ func TestBundleFactoryExecutor(t *testing.T) {
|
||||
assert.Equal(t, phase.ErrDocumentEntrypointNotDefined{PhaseName: "no_entry_point"}, err)
|
||||
}
|
||||
|
||||
func TestPlanRun(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
errContains string
|
||||
planID ifc.ID
|
||||
configFunc func(t *testing.T) *config.Config
|
||||
registryFunc phase.ExecutorRegistry
|
||||
}{
|
||||
{
|
||||
name: "Success fake executor",
|
||||
configFunc: testConfig,
|
||||
planID: ifc.ID{Name: "init"},
|
||||
registryFunc: fakeRegistry,
|
||||
},
|
||||
{
|
||||
name: "Error executor doc doesn't exist",
|
||||
configFunc: testConfig,
|
||||
planID: ifc.ID{Name: "some_plan"},
|
||||
registryFunc: fakeRegistry,
|
||||
errContains: "found no documents",
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tt := tc
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
conf := tt.configFunc(t)
|
||||
helper, err := phase.NewHelper(conf)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, helper)
|
||||
client := phase.NewClient(helper, phase.InjectRegistry(tt.registryFunc))
|
||||
require.NotNil(t, client)
|
||||
p, err := client.PlanByID(tt.planID)
|
||||
require.NoError(t, err)
|
||||
err = p.Run(ifc.RunOptions{DryRun: true})
|
||||
if tt.errContains != "" {
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), tt.errContains)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func fakeExecFactory(config ifc.ExecutorConfig) (ifc.Executor, error) {
|
||||
return fakeExecutor{}, nil
|
||||
}
|
||||
|
@ -32,15 +32,20 @@ import (
|
||||
"opendev.org/airship/airshipctl/pkg/util"
|
||||
)
|
||||
|
||||
// RunFlags options for phase run command
|
||||
type RunFlags struct {
|
||||
// GenericRunFlags generic options for run command
|
||||
type GenericRunFlags struct {
|
||||
DryRun bool
|
||||
Timeout time.Duration
|
||||
PhaseID ifc.ID
|
||||
Kubeconfig string
|
||||
Progress bool
|
||||
}
|
||||
|
||||
// RunFlags options for phase run command
|
||||
type RunFlags struct {
|
||||
GenericRunFlags
|
||||
PhaseID ifc.ID
|
||||
}
|
||||
|
||||
// RunCommand phase run command
|
||||
type RunCommand struct {
|
||||
Options RunFlags
|
||||
@ -202,3 +207,37 @@ func (c *PlanListCommand) RunE() error {
|
||||
printer.PrintTable(rt, 0)
|
||||
return nil
|
||||
}
|
||||
|
||||
// PlanRunFlags options for phase run command
|
||||
type PlanRunFlags struct {
|
||||
GenericRunFlags
|
||||
PlanID ifc.ID
|
||||
}
|
||||
|
||||
// PlanRunCommand phase run command
|
||||
type PlanRunCommand struct {
|
||||
Options PlanRunFlags
|
||||
Factory config.Factory
|
||||
}
|
||||
|
||||
// RunE executes phase plan
|
||||
func (c *PlanRunCommand) RunE() error {
|
||||
cfg, err := c.Factory()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
helper, err := NewHelper(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
kubeconfigOption := InjectKubeconfigPath(c.Options.Kubeconfig)
|
||||
client := NewClient(helper, kubeconfigOption)
|
||||
|
||||
plan, err := client.PlanByID(c.Options.PlanID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return plan.Run(ifc.RunOptions{DryRun: c.Options.DryRun, Timeout: c.Options.Timeout, Progress: c.Options.Progress})
|
||||
}
|
||||
|
@ -293,3 +293,77 @@ func TestPlanListCommand(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlanRunCommand(t *testing.T) {
|
||||
testErr := fmt.Errorf(testFactoryErr)
|
||||
testCases := []struct {
|
||||
name string
|
||||
factory config.Factory
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
name: "Error config factory",
|
||||
factory: func() (*config.Config, error) {
|
||||
return nil, testErr
|
||||
},
|
||||
expectedErr: testFactoryErr,
|
||||
},
|
||||
{
|
||||
name: "Error new helper",
|
||||
factory: func() (*config.Config, error) {
|
||||
return &config.Config{
|
||||
CurrentContext: "does not exist",
|
||||
Contexts: make(map[string]*config.Context),
|
||||
}, nil
|
||||
},
|
||||
expectedErr: "Missing configuration: Context with name 'does not exist'",
|
||||
},
|
||||
{
|
||||
name: "Error phase by id",
|
||||
factory: func() (*config.Config, error) {
|
||||
conf := config.NewConfig()
|
||||
conf.Manifests = map[string]*config.Manifest{
|
||||
"manifest": {
|
||||
MetadataPath: "metadata.yaml",
|
||||
TargetPath: "testdata",
|
||||
PhaseRepositoryName: config.DefaultTestPhaseRepo,
|
||||
Repositories: map[string]*config.Repository{
|
||||
config.DefaultTestPhaseRepo: {
|
||||
URLString: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
conf.CurrentContext = "context"
|
||||
conf.Contexts = map[string]*config.Context{
|
||||
"context": {
|
||||
Manifest: "manifest",
|
||||
},
|
||||
}
|
||||
return conf, nil
|
||||
},
|
||||
expectedErr: `Error events received on channel, errors are:
|
||||
[document filtered by selector [Group="airshipit.org", Version="v1alpha1", Kind="KubeConfig"] found no documents]`,
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tt := tc
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cmd := phase.PlanRunCommand{
|
||||
Options: phase.PlanRunFlags{
|
||||
GenericRunFlags: phase.GenericRunFlags{
|
||||
DryRun: true,
|
||||
},
|
||||
},
|
||||
Factory: tt.factory,
|
||||
}
|
||||
err := cmd.RunE()
|
||||
if tt.expectedErr != "" {
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, tt.expectedErr, err.Error())
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -90,13 +90,18 @@ func (helper *Helper) Phase(phaseID ifc.ID) (*v1alpha1.Phase, error) {
|
||||
}
|
||||
|
||||
// Plan returns plan associated with a manifest
|
||||
func (helper *Helper) Plan() (*v1alpha1.PhasePlan, error) {
|
||||
func (helper *Helper) Plan(planID ifc.ID) (*v1alpha1.PhasePlan, error) {
|
||||
bundle, err := document.NewBundleByPath(helper.phaseBundleRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
plan := &v1alpha1.PhasePlan{}
|
||||
plan := &v1alpha1.PhasePlan{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: planID.Name,
|
||||
Namespace: planID.Namespace,
|
||||
},
|
||||
}
|
||||
selector, err := document.NewSelector().ByObject(plan, v1alpha1.Scheme)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -104,6 +104,7 @@ func TestHelperPhase(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHelperPlan(t *testing.T) {
|
||||
testPlanName := "phasePlan"
|
||||
testCases := []struct {
|
||||
name string
|
||||
errContains string
|
||||
@ -119,28 +120,23 @@ func TestHelperPlan(t *testing.T) {
|
||||
APIVersion: "airshipit.org/v1alpha1",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "phasePlan",
|
||||
Name: testPlanName,
|
||||
},
|
||||
PhaseGroups: []airshipv1.PhaseGroup{
|
||||
Phases: []airshipv1.PhaseStep{
|
||||
{
|
||||
Name: "group1",
|
||||
Phases: []airshipv1.PhaseGroupStep{
|
||||
{
|
||||
Name: "isogen",
|
||||
},
|
||||
{
|
||||
Name: "remotedirect",
|
||||
},
|
||||
{
|
||||
Name: "initinfra",
|
||||
},
|
||||
{
|
||||
Name: "some_phase",
|
||||
},
|
||||
{
|
||||
Name: "capi_init",
|
||||
},
|
||||
},
|
||||
Name: "isogen",
|
||||
},
|
||||
{
|
||||
Name: "remotedirect",
|
||||
},
|
||||
{
|
||||
Name: "initinfra",
|
||||
},
|
||||
{
|
||||
Name: "some_phase",
|
||||
},
|
||||
{
|
||||
Name: "capi_init",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -172,7 +168,7 @@ func TestHelperPlan(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, helper)
|
||||
|
||||
actualPlan, actualErr := helper.Plan()
|
||||
actualPlan, actualErr := helper.Plan(ifc.ID{Name: testPlanName})
|
||||
if tt.errContains != "" {
|
||||
require.Error(t, actualErr)
|
||||
assert.Contains(t, actualErr.Error(), tt.errContains)
|
||||
@ -244,7 +240,7 @@ func TestHelperListPlans(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "Success plan list",
|
||||
expectedLen: 1,
|
||||
expectedLen: 3,
|
||||
config: testConfig,
|
||||
},
|
||||
{
|
||||
|
@ -27,7 +27,7 @@ type Helper interface {
|
||||
DocEntryPointPrefix() string
|
||||
WorkDir() (string, error)
|
||||
Phase(phaseID ID) (*v1alpha1.Phase, error)
|
||||
Plan() (*v1alpha1.PhasePlan, error)
|
||||
Plan(planID ID) (*v1alpha1.PhasePlan, error)
|
||||
ListPhases() ([]*v1alpha1.Phase, error)
|
||||
ListPlans() ([]*v1alpha1.PhasePlan, error)
|
||||
ClusterMapAPIobj() (*v1alpha1.ClusterMap, error)
|
||||
|
@ -31,6 +31,12 @@ type Phase interface {
|
||||
Render(io.Writer, bool, RenderOptions) error
|
||||
}
|
||||
|
||||
// Plan provides a way to interact with phase plans
|
||||
type Plan interface {
|
||||
Validate() error
|
||||
Run(RunOptions) error
|
||||
}
|
||||
|
||||
// ID uniquely identifies the phase
|
||||
type ID struct {
|
||||
Name string
|
||||
@ -40,6 +46,7 @@ type ID struct {
|
||||
// Client is a phase client that can be used by command line or ui packages
|
||||
type Client interface {
|
||||
PhaseByID(ID) (Phase, error)
|
||||
PlanByID(ID) (Plan, error)
|
||||
PhaseByAPIObj(*v1alpha1.Phase) (Phase, error)
|
||||
ClusterMap() (clustermap.ClusterMap, error)
|
||||
}
|
||||
|
6
pkg/phase/testdata/phases/phaseplan.yaml
vendored
6
pkg/phase/testdata/phases/phaseplan.yaml
vendored
@ -3,7 +3,5 @@ kind: PhasePlan
|
||||
metadata:
|
||||
name: phasePlan
|
||||
description: "Default phase plan"
|
||||
phaseGroups:
|
||||
- name: group1
|
||||
phases:
|
||||
- name: phase
|
||||
phases:
|
||||
- name: phase
|
||||
|
@ -2,11 +2,23 @@ apiVersion: airshipit.org/v1alpha1
|
||||
kind: PhasePlan
|
||||
metadata:
|
||||
name: phasePlan
|
||||
phaseGroups:
|
||||
- name: group1
|
||||
phases:
|
||||
- name: isogen
|
||||
- name: remotedirect
|
||||
- name: initinfra
|
||||
- name: some_phase
|
||||
- name: capi_init
|
||||
phases:
|
||||
- name: isogen
|
||||
- name: remotedirect
|
||||
- name: initinfra
|
||||
- name: some_phase
|
||||
- name: capi_init
|
||||
---
|
||||
apiVersion: airshipit.org/v1alpha1
|
||||
kind: PhasePlan
|
||||
metadata:
|
||||
name: init
|
||||
phases:
|
||||
- name: capi_init
|
||||
---
|
||||
apiVersion: airshipit.org/v1alpha1
|
||||
kind: PhasePlan
|
||||
metadata:
|
||||
name: some_plan
|
||||
phases:
|
||||
- name: some_phase
|
||||
|
Loading…
Reference in New Issue
Block a user