Refactor phase* commands

All the phase commands was refactored for usage with new config
factory. Config object now is being initialized in pkg module on demand,
which provides more flexibility and cleaner code.

Change-Id: I742c39788098c3185ce89936ea81cd461bf97af3
Signed-off-by: Ruslan Aliev <raliev@mirantis.com>
Relates-To: #327
This commit is contained in:
Ruslan Aliev 2020-08-29 17:14:46 -05:00
parent 63b3501a53
commit 88ec55d34b
20 changed files with 116 additions and 128 deletions

View File

@ -21,7 +21,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"opendev.org/airship/airshipctl/pkg/environment" "opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/phase/apply" "opendev.org/airship/airshipctl/pkg/phase/apply"
) )
@ -36,10 +36,8 @@ airshipctl phase apply initinfra
) )
// NewApplyCommand creates a command to apply phase to k8s cluster. // NewApplyCommand creates a command to apply phase to k8s cluster.
func NewApplyCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { func NewApplyCommand(cfgFactory config.Factory) *cobra.Command {
i := &apply.Options{ i := &apply.Options{}
RootSettings: rootSettings,
}
applyCmd := &cobra.Command{ applyCmd := &cobra.Command{
Use: "apply PHASE_NAME", Use: "apply PHASE_NAME",
Short: "Apply phase to a cluster", Short: "Apply phase to a cluster",
@ -48,8 +46,12 @@ func NewApplyCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Comman
Example: applyExample, Example: applyExample,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
i.PhaseName = args[0] i.PhaseName = args[0]
i.Initialize() cfg, err := cfgFactory()
return i.Run() if err != nil {
return err
}
i.Initialize(cfg.KubeConfigPath())
return i.Run(cfg)
}, },
} }
addApplyFlags(i, applyCmd) addApplyFlags(i, applyCmd)

View File

@ -18,22 +18,15 @@ import (
"testing" "testing"
"opendev.org/airship/airshipctl/cmd/phase" "opendev.org/airship/airshipctl/cmd/phase"
"opendev.org/airship/airshipctl/pkg/environment"
"opendev.org/airship/airshipctl/testutil" "opendev.org/airship/airshipctl/testutil"
) )
func TestNewApplyCommand(t *testing.T) { func TestNewApplyCommand(t *testing.T) {
fakeRootSettings := &environment.AirshipCTLSettings{
AirshipConfigPath: "../../testdata/k8s/config.yaml",
KubeConfigPath: "../../testdata/k8s/kubeconfig.yaml",
}
fakeRootSettings.InitConfig()
tests := []*testutil.CmdTest{ tests := []*testutil.CmdTest{
{ {
Name: "phase-apply-cmd-with-help", Name: "phase-apply-cmd-with-help",
CmdLine: "--help", CmdLine: "--help",
Cmd: phase.NewApplyCommand(fakeRootSettings), Cmd: phase.NewApplyCommand(nil),
}, },
} }
for _, testcase := range tests { for _, testcase := range tests {

View File

@ -17,6 +17,7 @@ package phase
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/environment" "opendev.org/airship/airshipctl/pkg/environment"
) )
@ -33,19 +34,14 @@ func NewPhaseCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Comman
Use: "phase", Use: "phase",
Short: "Manage phases", Short: "Manage phases",
Long: clusterLong[1:], Long: clusterLong[1:],
PersistentPreRun: func(cmd *cobra.Command, args []string) {
if parentPreRun := cmd.Root().PersistentPreRun; parentPreRun != nil {
parentPreRun(cmd.Root(), args)
}
// Load or Initialize airship Config
rootSettings.InitConfig()
},
} }
phaseRootCmd.AddCommand(NewApplyCommand(rootSettings)) cfgFactory := config.CreateFactory(&rootSettings.AirshipConfigPath, &rootSettings.KubeConfigPath)
phaseRootCmd.AddCommand(NewRenderCommand(rootSettings))
phaseRootCmd.AddCommand(NewPlanCommand(rootSettings)) phaseRootCmd.AddCommand(NewApplyCommand(cfgFactory))
phaseRootCmd.AddCommand(NewRunCommand(rootSettings)) phaseRootCmd.AddCommand(NewRenderCommand(cfgFactory))
phaseRootCmd.AddCommand(NewPlanCommand(cfgFactory))
phaseRootCmd.AddCommand(NewRunCommand(cfgFactory))
return phaseRootCmd return phaseRootCmd
} }

View File

@ -19,7 +19,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"opendev.org/airship/airshipctl/pkg/environment" "opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/phase" "opendev.org/airship/airshipctl/pkg/phase"
"opendev.org/airship/airshipctl/pkg/util" "opendev.org/airship/airshipctl/pkg/util"
) )
@ -33,14 +33,17 @@ are executed in parallel.
) )
// NewPlanCommand creates a command which prints available phases // NewPlanCommand creates a command which prints available phases
func NewPlanCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { func NewPlanCommand(cfgFactory config.Factory) *cobra.Command {
p := &phase.Cmd{AirshipCTLSettings: rootSettings}
planCmd := &cobra.Command{ planCmd := &cobra.Command{
Use: "plan", Use: "plan",
Short: "List phases", Short: "List phases",
Long: cmdLong[1:], Long: cmdLong[1:],
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
cfg, err := cfgFactory()
if err != nil {
return err
}
p := &phase.Cmd{Config: cfg}
phases, err := p.Plan() phases, err := p.Plan()
if err != nil { if err != nil {
return err return err

View File

@ -17,7 +17,7 @@ package phase
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"opendev.org/airship/airshipctl/pkg/environment" "opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/phase/render" "opendev.org/airship/airshipctl/pkg/phase/render"
) )
@ -34,19 +34,15 @@ airshipctl phase render initinfra -l app=helm,service=tiller -k Deployment
) )
// NewRenderCommand create a new command for document rendering // NewRenderCommand create a new command for document rendering
func NewRenderCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { func NewRenderCommand(cfgFactory config.Factory) *cobra.Command {
renderSettings := &render.Settings{AirshipCTLSettings: rootSettings} renderSettings := &render.Settings{}
renderCmd := &cobra.Command{ renderCmd := &cobra.Command{
Use: "render PHASE_NAME", Use: "render PHASE_NAME",
Short: "Render phase documents from model", Short: "Render phase documents from model",
Example: renderExample, Example: renderExample,
Args: cobra.ExactArgs(1), Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
path, err := renderSettings.Config.CurrentContextEntryPoint(args[0]) return renderSettings.Render(cfgFactory, args[0], cmd.OutOrStdout())
if err != nil {
return err
}
return renderSettings.Render(path, cmd.OutOrStdout())
}, },
} }

View File

@ -21,7 +21,6 @@ import (
"opendev.org/airship/airshipctl/cmd/phase" "opendev.org/airship/airshipctl/cmd/phase"
"opendev.org/airship/airshipctl/pkg/config" "opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/environment"
"opendev.org/airship/airshipctl/testutil" "opendev.org/airship/airshipctl/testutil"
) )
@ -41,7 +40,9 @@ func TestRender(t *testing.T) {
ctx, err := cfg.GetContext("def_ephemeral") ctx, err := cfg.GetContext("def_ephemeral")
require.NoError(t, err) require.NoError(t, err)
ctx.Manifest = "test" ctx.Manifest = "test"
settings := &environment.AirshipCTLSettings{Config: cfg} settings := func() (*config.Config, error) {
return cfg, nil
}
tests := []*testutil.CmdTest{ tests := []*testutil.CmdTest{
{ {

View File

@ -17,7 +17,7 @@ package phase
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"opendev.org/airship/airshipctl/pkg/environment" "opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/events" "opendev.org/airship/airshipctl/pkg/events"
"opendev.org/airship/airshipctl/pkg/k8s/utils" "opendev.org/airship/airshipctl/pkg/k8s/utils"
"opendev.org/airship/airshipctl/pkg/phase" "opendev.org/airship/airshipctl/pkg/phase"
@ -36,10 +36,9 @@ airshipctl phase run ephemeral-control-plane
) )
// NewRunCommand creates a command to run specific phase // NewRunCommand creates a command to run specific phase
func NewRunCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { func NewRunCommand(cfgFactory config.Factory) *cobra.Command {
p := &phase.Cmd{ p := &phase.Cmd{
AirshipCTLSettings: rootSettings, Processor: events.NewDefaultProcessor(utils.Streams()),
Processor: events.NewDefaultProcessor(utils.Streams()),
} }
runCmd := &cobra.Command{ runCmd := &cobra.Command{
@ -49,6 +48,11 @@ func NewRunCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command
Args: cobra.ExactArgs(1), Args: cobra.ExactArgs(1),
Example: runExample, Example: runExample,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
cfg, err := cfgFactory()
if err != nil {
return err
}
p.Config = cfg
return p.Exec(args[0]) return p.Exec(args[0])
}, },
} }

View File

@ -59,7 +59,7 @@ func NewExecutor(cfg ifc.ExecutorConfig) (ifc.Executor, error) {
if err := cfg.ExecutorDocument.ToAPIObject(options, airshipv1.Scheme); err != nil { if err := cfg.ExecutorDocument.ToAPIObject(options, airshipv1.Scheme); err != nil {
return nil, err return nil, err
} }
tgtPath, err := cfg.AirshipSettings.Config.CurrentContextTargetPath() tgtPath, err := cfg.AirshipConfig.CurrentContextTargetPath()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -73,7 +73,7 @@ func NewExecutor(cfg ifc.ExecutorConfig) (ifc.Executor, error) {
bundle: cfg.ExecutorBundle, bundle: cfg.ExecutorBundle,
options: options, options: options,
kubecfg: cfg.KubeConfig, kubecfg: cfg.KubeConfig,
dumpRoot: filepath.Dir(cfg.AirshipSettings.AirshipConfigPath), dumpRoot: filepath.Dir(cfg.AirshipConfig.LoadedConfigPath()),
}, nil }, nil
} }

View File

@ -28,7 +28,6 @@ import (
cctlclient "opendev.org/airship/airshipctl/pkg/clusterctl/client" cctlclient "opendev.org/airship/airshipctl/pkg/clusterctl/client"
"opendev.org/airship/airshipctl/pkg/config" "opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/document" "opendev.org/airship/airshipctl/pkg/document"
"opendev.org/airship/airshipctl/pkg/environment"
airerrors "opendev.org/airship/airshipctl/pkg/errors" airerrors "opendev.org/airship/airshipctl/pkg/errors"
"opendev.org/airship/airshipctl/pkg/events" "opendev.org/airship/airshipctl/pkg/events"
"opendev.org/airship/airshipctl/pkg/k8s/kubeconfig" "opendev.org/airship/airshipctl/pkg/k8s/kubeconfig"
@ -77,7 +76,7 @@ func TestNewExecutor(t *testing.T) {
testCases := []struct { testCases := []struct {
name string name string
settings *environment.AirshipCTLSettings settings *config.Config
expectedErr error expectedErr error
}{ }{
{ {
@ -86,9 +85,9 @@ func TestNewExecutor(t *testing.T) {
}, },
{ {
name: "New Clusterctl Executor", name: "New Clusterctl Executor",
settings: func() *environment.AirshipCTLSettings { settings: func() *config.Config {
s := sampleSettings() s := sampleSettings()
s.Config.CurrentContext = "non-existent-ctx" s.CurrentContext = "non-existent-ctx"
return s return s
}(), }(),
expectedErr: config.ErrMissingConfig{What: "Context with name 'non-existent-ctx'"}, expectedErr: config.ErrMissingConfig{What: "Context with name 'non-existent-ctx'"},
@ -100,7 +99,7 @@ func TestNewExecutor(t *testing.T) {
_, actualErr := cctlclient.NewExecutor(ifc.ExecutorConfig{ _, actualErr := cctlclient.NewExecutor(ifc.ExecutorConfig{
ExecutorDocument: sampleCfgDoc, ExecutorDocument: sampleCfgDoc,
ExecutorBundle: bundle, ExecutorBundle: bundle,
AirshipSettings: tt.settings, AirshipConfig: tt.settings,
}) })
assert.Equal(t, tt.expectedErr, actualErr) assert.Equal(t, tt.expectedErr, actualErr)
}) })
@ -186,7 +185,7 @@ func TestExecutorRun(t *testing.T) {
ifc.ExecutorConfig{ ifc.ExecutorConfig{
ExecutorDocument: tt.cfgDoc, ExecutorDocument: tt.cfgDoc,
ExecutorBundle: bundle, ExecutorBundle: bundle,
AirshipSettings: sampleSettings(), AirshipConfig: sampleSettings(),
KubeConfig: kubeCfg, KubeConfig: kubeCfg,
}) })
require.NoError(t, err) require.NoError(t, err)
@ -209,7 +208,7 @@ func TestExecutorValidate(t *testing.T) {
ifc.ExecutorConfig{ ifc.ExecutorConfig{
ExecutorDocument: sampleCfgDoc, ExecutorDocument: sampleCfgDoc,
ExecutorBundle: bundle, ExecutorBundle: bundle,
AirshipSettings: sampleSettings(), AirshipConfig: sampleSettings(),
}) })
require.NoError(t, err) require.NoError(t, err)
expectedErr := airerrors.ErrNotImplemented{} expectedErr := airerrors.ErrNotImplemented{}
@ -226,7 +225,7 @@ func TestExecutorRender(t *testing.T) {
ifc.ExecutorConfig{ ifc.ExecutorConfig{
ExecutorDocument: sampleCfgDoc, ExecutorDocument: sampleCfgDoc,
ExecutorBundle: bundle, ExecutorBundle: bundle,
AirshipSettings: sampleSettings(), AirshipConfig: sampleSettings(),
}) })
require.NoError(t, err) require.NoError(t, err)
actualOut := &bytes.Buffer{} actualOut := &bytes.Buffer{}
@ -234,10 +233,11 @@ func TestExecutorRender(t *testing.T) {
assert.Equal(t, expectedErr, actualErr) assert.Equal(t, expectedErr, actualErr)
} }
func sampleSettings() *environment.AirshipCTLSettings { func sampleSettings() *config.Config {
cfg := config.NewConfig() cfg := config.NewConfig()
cfg.Manifests[config.AirshipDefaultManifest].TargetPath = "./testdata" cfg.Manifests[config.AirshipDefaultManifest].TargetPath = "./testdata"
return &environment.AirshipCTLSettings{Config: cfg, AirshipConfigPath: "."} cfg.SetLoadedConfigPath(".")
return cfg
} }
func executorDoc(t *testing.T, action string) document.Document { func executorDoc(t *testing.T, action string) document.Document {

View File

@ -59,7 +59,7 @@ func RegisterExecutor(registry map[schema.GroupVersionKind]ifc.ExecutorFactory)
func registerExecutor(cfg ifc.ExecutorConfig) (ifc.Executor, error) { func registerExecutor(cfg ifc.ExecutorConfig) (ifc.Executor, error) {
return NewExecutor(ExecutorOptions{ return NewExecutor(ExecutorOptions{
BundleName: cfg.PhaseName, BundleName: cfg.PhaseName,
AirshipConfig: cfg.AirshipSettings.Config, AirshipConfig: cfg.AirshipConfig,
ExecutorBundle: cfg.ExecutorBundle, ExecutorBundle: cfg.ExecutorBundle,
ExecutorDocument: cfg.ExecutorDocument, ExecutorDocument: cfg.ExecutorDocument,
Kubeconfig: cfg.KubeConfig, Kubeconfig: cfg.KubeConfig,

View File

@ -20,8 +20,8 @@ import (
"sigs.k8s.io/cli-utils/pkg/common" "sigs.k8s.io/cli-utils/pkg/common"
"opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/document" "opendev.org/airship/airshipctl/pkg/document"
"opendev.org/airship/airshipctl/pkg/environment"
"opendev.org/airship/airshipctl/pkg/events" "opendev.org/airship/airshipctl/pkg/events"
"opendev.org/airship/airshipctl/pkg/k8s/applier" "opendev.org/airship/airshipctl/pkg/k8s/applier"
"opendev.org/airship/airshipctl/pkg/k8s/utils" "opendev.org/airship/airshipctl/pkg/k8s/utils"
@ -35,15 +35,14 @@ type Options struct {
PhaseName string PhaseName string
WaitTimeout time.Duration WaitTimeout time.Duration
RootSettings *environment.AirshipCTLSettings
Applier *applier.Applier Applier *applier.Applier
Processor events.EventProcessor Processor events.EventProcessor
EventChannel chan events.Event EventChannel chan events.Event
} }
// Initialize Options with required field, such as Applier // Initialize Options with required field, such as Applier
func (o *Options) Initialize() { func (o *Options) Initialize(kubeConfigPath string) {
f := utils.FactoryFromKubeConfigPath(o.RootSettings.KubeConfigPath) f := utils.FactoryFromKubeConfigPath(kubeConfigPath)
streams := utils.Streams() streams := utils.Streams()
o.EventChannel = make(chan events.Event) o.EventChannel = make(chan events.Event)
o.Applier = applier.NewApplier(o.EventChannel, f, streams) o.Applier = applier.NewApplier(o.EventChannel, f, streams)
@ -51,7 +50,7 @@ func (o *Options) Initialize() {
} }
// Run apply subcommand logic // Run apply subcommand logic
func (o *Options) Run() error { func (o *Options) Run(cfg *config.Config) error {
ao := applier.ApplyOptions{ ao := applier.ApplyOptions{
DryRunStrategy: common.DryRunNone, DryRunStrategy: common.DryRunNone,
Prune: o.Prune, Prune: o.Prune,
@ -61,21 +60,16 @@ func (o *Options) Run() error {
ao.DryRunStrategy = common.DryRunClient ao.DryRunStrategy = common.DryRunClient
} }
globalConf := o.RootSettings.Config clusterName, err := cfg.CurrentContextClusterName()
if err := globalConf.EnsureComplete(); err != nil {
return err
}
clusterName, err := globalConf.CurrentContextClusterName()
if err != nil { if err != nil {
return err return err
} }
clusterType, err := globalConf.CurrentContextClusterType() clusterType, err := cfg.CurrentContextClusterType()
if err != nil { if err != nil {
return err return err
} }
ao.BundleName = fmt.Sprintf("%s-%s-%s", clusterName, clusterType, o.PhaseName) ao.BundleName = fmt.Sprintf("%s-%s-%s", clusterName, clusterType, o.PhaseName)
kustomizePath, err := globalConf.CurrentContextEntryPoint(o.PhaseName) kustomizePath, err := cfg.CurrentContextEntryPoint(o.PhaseName)
if err != nil { if err != nil {
return err return err
} }

View File

@ -70,11 +70,6 @@ func TestDeploy(t *testing.T) {
expectedErrorString: "", expectedErrorString: "",
events: k8sutils.SuccessEvents(), events: k8sutils.SuccessEvents(),
}, },
{
name: "missing clusters",
expectedErrorString: "At least one cluster needs to be defined",
clusterPurposes: map[string]*config.ClusterPurpose{},
},
{ {
name: "missing phase", name: "missing phase",
expectedErrorString: "Phase document 'missingPhase' was not found", expectedErrorString: "Phase document 'missingPhase' was not found",
@ -86,12 +81,9 @@ func TestDeploy(t *testing.T) {
tt := tt tt := tt
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
rs := makeNewFakeRootSettings(t, kubeconfigPath, airshipConfigFile) rs := makeNewFakeRootSettings(t, kubeconfigPath, airshipConfigFile)
ao := &apply.Options{ ao := &apply.Options{PhaseName: "initinfra", DryRun: true}
RootSettings: rs, ao.Initialize(rs.KubeConfigPath())
}
ao.Initialize()
ao.PhaseName = "initinfra"
ao.DryRun = true
if tt.events != nil { if tt.events != nil {
ch := make(chan events.Event) ch := make(chan events.Event)
cliApplier := applier.NewFakeApplier( cliApplier := applier.NewFakeApplier(
@ -105,12 +97,12 @@ func TestDeploy(t *testing.T) {
ao.EventChannel = ch ao.EventChannel = ch
} }
if tt.clusterPurposes != nil { if tt.clusterPurposes != nil {
ao.RootSettings.Config.Clusters = tt.clusterPurposes rs.Clusters = tt.clusterPurposes
} }
if tt.phaseName != "" { if tt.phaseName != "" {
ao.PhaseName = tt.phaseName ao.PhaseName = tt.phaseName
} }
actualErr := ao.Run() actualErr := ao.Run(rs)
if tt.expectedErrorString != "" { if tt.expectedErrorString != "" {
require.Error(t, actualErr) require.Error(t, actualErr)
assert.Contains(t, actualErr.Error(), tt.expectedErrorString) assert.Contains(t, actualErr.Error(), tt.expectedErrorString)
@ -122,7 +114,7 @@ func TestDeploy(t *testing.T) {
} }
// makeNewFakeRootSettings takes kubeconfig path and directory path to fixture dir as argument. // makeNewFakeRootSettings takes kubeconfig path and directory path to fixture dir as argument.
func makeNewFakeRootSettings(t *testing.T, kp string, dir string) *environment.AirshipCTLSettings { func makeNewFakeRootSettings(t *testing.T, kp string, dir string) *config.Config {
t.Helper() t.Helper()
akp, err := filepath.Abs(kp) akp, err := filepath.Abs(kp)
require.NoError(t, err) require.NoError(t, err)
@ -136,5 +128,7 @@ func makeNewFakeRootSettings(t *testing.T, kp string, dir string) *environment.A
} }
settings.InitConfig() settings.InitConfig()
return settings settings.Config.SetKubeConfigPath(kp)
settings.Config.SetLoadedConfigPath(dir)
return settings.Config
} }

View File

@ -19,8 +19,8 @@ import (
"time" "time"
"opendev.org/airship/airshipctl/pkg/api/v1alpha1" "opendev.org/airship/airshipctl/pkg/api/v1alpha1"
"opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/document" "opendev.org/airship/airshipctl/pkg/document"
"opendev.org/airship/airshipctl/pkg/environment"
"opendev.org/airship/airshipctl/pkg/events" "opendev.org/airship/airshipctl/pkg/events"
"opendev.org/airship/airshipctl/pkg/k8s/kubeconfig" "opendev.org/airship/airshipctl/pkg/k8s/kubeconfig"
) )
@ -59,6 +59,6 @@ type ExecutorConfig struct {
ClusterMap *v1alpha1.ClusterMap ClusterMap *v1alpha1.ClusterMap
ExecutorDocument document.Document ExecutorDocument document.Document
ExecutorBundle document.Bundle ExecutorBundle document.Bundle
AirshipSettings *environment.AirshipCTLSettings AirshipConfig *config.Config
KubeConfig kubeconfig.Interface KubeConfig kubeconfig.Interface
} }

View File

@ -22,8 +22,8 @@ import (
airshipv1 "opendev.org/airship/airshipctl/pkg/api/v1alpha1" airshipv1 "opendev.org/airship/airshipctl/pkg/api/v1alpha1"
clusterctl "opendev.org/airship/airshipctl/pkg/clusterctl/client" clusterctl "opendev.org/airship/airshipctl/pkg/clusterctl/client"
"opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/document" "opendev.org/airship/airshipctl/pkg/document"
"opendev.org/airship/airshipctl/pkg/environment"
"opendev.org/airship/airshipctl/pkg/events" "opendev.org/airship/airshipctl/pkg/events"
"opendev.org/airship/airshipctl/pkg/k8s/applier" "opendev.org/airship/airshipctl/pkg/k8s/applier"
"opendev.org/airship/airshipctl/pkg/k8s/kubeconfig" "opendev.org/airship/airshipctl/pkg/k8s/kubeconfig"
@ -55,11 +55,11 @@ type Cmd struct {
Registry ExecutorRegistry Registry ExecutorRegistry
// Will be used to get processor based on executor action // Will be used to get processor based on executor action
Processor events.EventProcessor Processor events.EventProcessor
*environment.AirshipCTLSettings *config.Config
} }
func (p *Cmd) getBundle() (document.Bundle, error) { func (p *Cmd) getBundle() (document.Bundle, error) {
tp, err := p.AirshipCTLSettings.Config.CurrentContextTargetPath() tp, err := p.CurrentContextTargetPath()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -190,7 +190,7 @@ func (p *Cmd) GetExecutor(phase *airshipv1.Phase) (ifc.Executor, error) {
ExecutorBundle: executorDocBundle, ExecutorBundle: executorDocBundle,
PhaseName: phase.Name, PhaseName: phase.Name,
ExecutorDocument: executorDoc, ExecutorDocument: executorDoc,
AirshipSettings: p.AirshipCTLSettings, AirshipConfig: p.Config,
KubeConfig: kubeConfig, KubeConfig: kubeConfig,
ClusterName: phase.ClusterName, ClusterName: phase.ClusterName,
ClusterMap: cMap, ClusterMap: cMap,

View File

@ -39,15 +39,15 @@ import (
func TestPhasePlan(t *testing.T) { func TestPhasePlan(t *testing.T) {
testCases := []struct { testCases := []struct {
name string name string
settings func() *environment.AirshipCTLSettings settings func() *config.Config
expectedPlan map[string][]string expectedPlan map[string][]string
expectedErr error expectedErr error
}{ }{
{ {
name: "No context", name: "No context",
settings: func() *environment.AirshipCTLSettings { settings: func() *config.Config {
s := makeDefaultSettings() s := makeDefaultSettings()
s.Config.CurrentContext = "badCtx" s.CurrentContext = "badCtx"
return s return s
}, },
expectedErr: config.ErrMissingConfig{What: "Context with name 'badCtx'"}, expectedErr: config.ErrMissingConfig{What: "Context with name 'badCtx'"},
@ -67,9 +67,9 @@ func TestPhasePlan(t *testing.T) {
}, },
{ {
name: "No Phase Plan", name: "No Phase Plan",
settings: func() *environment.AirshipCTLSettings { settings: func() *config.Config {
s := makeDefaultSettings() s := makeDefaultSettings()
m, err := s.Config.CurrentContextManifest() m, err := s.CurrentContextManifest()
require.NoError(t, err) require.NoError(t, err)
m.SubPath = "no_plan_site" m.SubPath = "no_plan_site"
m.MetadataPath = "no_plan_site/metadata.yaml" m.MetadataPath = "no_plan_site/metadata.yaml"
@ -92,7 +92,7 @@ func TestPhasePlan(t *testing.T) {
for _, test := range testCases { for _, test := range testCases {
tt := test tt := test
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
cmd := phase.Cmd{AirshipCTLSettings: tt.settings()} cmd := phase.Cmd{Config: tt.settings()}
actualPlan, actualErr := cmd.Plan() actualPlan, actualErr := cmd.Plan()
assert.Equal(t, tt.expectedErr, actualErr) assert.Equal(t, tt.expectedErr, actualErr)
assert.Equal(t, tt.expectedPlan, actualPlan) assert.Equal(t, tt.expectedPlan, actualPlan)
@ -103,16 +103,16 @@ func TestPhasePlan(t *testing.T) {
func TestGetPhase(t *testing.T) { func TestGetPhase(t *testing.T) {
testCases := []struct { testCases := []struct {
name string name string
settings func() *environment.AirshipCTLSettings settings func() *config.Config
phaseName string phaseName string
expectedPhase *airshipv1.Phase expectedPhase *airshipv1.Phase
expectedErr error expectedErr error
}{ }{
{ {
name: "No context", name: "No context",
settings: func() *environment.AirshipCTLSettings { settings: func() *config.Config {
s := makeDefaultSettings() s := makeDefaultSettings()
s.Config.CurrentContext = "badCtx" s.CurrentContext = "badCtx"
return s return s
}, },
expectedErr: config.ErrMissingConfig{What: "Context with name 'badCtx'"}, expectedErr: config.ErrMissingConfig{What: "Context with name 'badCtx'"},
@ -161,7 +161,7 @@ func TestGetPhase(t *testing.T) {
for _, test := range testCases { for _, test := range testCases {
tt := test tt := test
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
cmd := phase.Cmd{AirshipCTLSettings: tt.settings()} cmd := phase.Cmd{Config: tt.settings()}
actualPhase, actualErr := cmd.GetPhase(tt.phaseName) actualPhase, actualErr := cmd.GetPhase(tt.phaseName)
assert.Equal(t, tt.expectedErr, actualErr) assert.Equal(t, tt.expectedErr, actualErr)
assert.Equal(t, tt.expectedPhase, actualPhase) assert.Equal(t, tt.expectedPhase, actualPhase)
@ -172,16 +172,16 @@ func TestGetPhase(t *testing.T) {
func TestGetExecutor(t *testing.T) { func TestGetExecutor(t *testing.T) {
testCases := []struct { testCases := []struct {
name string name string
settings func() *environment.AirshipCTLSettings settings func() *config.Config
phase *airshipv1.Phase phase *airshipv1.Phase
expectedExc ifc.Executor expectedExc ifc.Executor
expectedErr error expectedErr error
}{ }{
{ {
name: "No context", name: "No context",
settings: func() *environment.AirshipCTLSettings { settings: func() *config.Config {
s := makeDefaultSettings() s := makeDefaultSettings()
s.Config.CurrentContext = "badCtx" s.CurrentContext = "badCtx"
return s return s
}, },
expectedErr: config.ErrMissingConfig{What: "Context with name 'badCtx'"}, expectedErr: config.ErrMissingConfig{What: "Context with name 'badCtx'"},
@ -250,7 +250,7 @@ func TestGetExecutor(t *testing.T) {
for _, test := range testCases { for _, test := range testCases {
tt := test tt := test
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
cmd := phase.Cmd{AirshipCTLSettings: tt.settings()} cmd := phase.Cmd{Config: tt.settings()}
actualExc, actualErr := cmd.GetExecutor(tt.phase) actualExc, actualErr := cmd.GetExecutor(tt.phase)
assert.Equal(t, tt.expectedErr, actualErr) assert.Equal(t, tt.expectedErr, actualErr)
assertEqualExecutor(t, tt.expectedExc, actualExc) assertEqualExecutor(t, tt.expectedExc, actualExc)
@ -268,11 +268,11 @@ func assertEqualExecutor(t *testing.T, expected, actual ifc.Executor) {
assert.IsType(t, expected, actual) assert.IsType(t, expected, actual)
} }
func makeDefaultSettings() *environment.AirshipCTLSettings { func makeDefaultSettings() *config.Config {
testSettings := &environment.AirshipCTLSettings{ testSettings := &environment.AirshipCTLSettings{
AirshipConfigPath: "testdata/airshipconfig.yaml", AirshipConfigPath: "testdata/airshipconfig.yaml",
KubeConfigPath: "testdata/kubeconfig.yaml", KubeConfigPath: "testdata/kubeconfig.yaml",
} }
testSettings.InitConfig() testSettings.InitConfig()
return testSettings return testSettings.Config
} }

View File

@ -18,14 +18,22 @@ import (
"io" "io"
"strings" "strings"
"opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/document" "opendev.org/airship/airshipctl/pkg/document"
) )
// Render prints out filtered documents // Render prints out filtered documents
func (s *Settings) Render(path string, out io.Writer) error { func (s *Settings) Render(cfgFactory config.Factory, phaseName string, out io.Writer) error {
if err := s.Config.EnsureComplete(); err != nil { cfg, err := cfgFactory()
if err != nil {
return err return err
} }
path, err := cfg.CurrentContextEntryPoint(phaseName)
if err != nil {
return err
}
docBundle, err := document.NewBundleByPath(path) docBundle, err := document.NewBundleByPath(path)
if err != nil { if err != nil {
return err return err

View File

@ -24,14 +24,17 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"opendev.org/airship/airshipctl/pkg/environment" "opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/phase/render" "opendev.org/airship/airshipctl/pkg/phase/render"
"opendev.org/airship/airshipctl/testutil" "opendev.org/airship/airshipctl/testutil"
) )
func TestRender(t *testing.T) { func TestRender(t *testing.T) {
rs := &environment.AirshipCTLSettings{Config: testutil.DummyConfig()} rs := testutil.DummyConfig()
fixturePath := "testdata/phase" dummyManifest := rs.Manifests["dummy_manifest"]
dummyManifest.TargetPath = "testdata"
dummyManifest.SubPath = ""
fixturePath := "phase"
tests := []struct { tests := []struct {
name string name string
settings *render.Settings settings *render.Settings
@ -40,18 +43,17 @@ func TestRender(t *testing.T) {
}{ }{
{ {
name: "No Filters", name: "No Filters",
settings: &render.Settings{AirshipCTLSettings: rs}, settings: &render.Settings{},
expResFile: "noFilter.yaml", expResFile: "noFilter.yaml",
expErr: nil, expErr: nil,
}, },
{ {
name: "All Filters", name: "All Filters",
settings: &render.Settings{ settings: &render.Settings{
AirshipCTLSettings: rs, Label: "airshipit.org/deploy-k8s=false",
Label: "airshipit.org/deploy-k8s=false", Annotation: "airshipit.org/clustertype=ephemeral",
Annotation: "airshipit.org/clustertype=ephemeral", APIVersion: "metal3.io/v1alpha1",
APIVersion: "metal3.io/v1alpha1", Kind: "BareMetalHost",
Kind: "BareMetalHost",
}, },
expResFile: "allFilters.yaml", expResFile: "allFilters.yaml",
expErr: nil, expErr: nil,
@ -59,8 +61,7 @@ func TestRender(t *testing.T) {
{ {
name: "Multiple Labels", name: "Multiple Labels",
settings: &render.Settings{ settings: &render.Settings{
AirshipCTLSettings: rs, Label: "airshipit.org/deploy-k8s=false, airshipit.org/ephemeral-node=true",
Label: "airshipit.org/deploy-k8s=false, airshipit.org/ephemeral-node=true",
}, },
expResFile: "multiLabels.yaml", expResFile: "multiLabels.yaml",
expErr: nil, expErr: nil,
@ -68,8 +69,7 @@ func TestRender(t *testing.T) {
{ {
name: "Malformed Label", name: "Malformed Label",
settings: &render.Settings{ settings: &render.Settings{
AirshipCTLSettings: rs, Label: "app=(",
Label: "app=(",
}, },
expResFile: "", expResFile: "",
expErr: fmt.Errorf("unable to parse requirement: found '(', expected: identifier"), expErr: fmt.Errorf("unable to parse requirement: found '(', expected: identifier"),
@ -86,7 +86,9 @@ func TestRender(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
} }
out := &bytes.Buffer{} out := &bytes.Buffer{}
err = tt.settings.Render(fixturePath, out) err = tt.settings.Render(func() (*config.Config, error) {
return rs, nil
}, fixturePath, out)
assert.Equal(t, tt.expErr, err) assert.Equal(t, tt.expErr, err)
assert.Equal(t, expectedOut, out.Bytes()) assert.Equal(t, expectedOut, out.Bytes())
}) })

View File

@ -14,13 +14,8 @@
package render package render
import (
"opendev.org/airship/airshipctl/pkg/environment"
)
// Settings for document rendering // Settings for document rendering
type Settings struct { type Settings struct {
*environment.AirshipCTLSettings
// Label filters documents by label string // Label filters documents by label string
Label string Label string
// Annotation filters documents by annotation string // Annotation filters documents by annotation string