Allow to perform phase render using document entrypoint
In current setup, we rely on executor to perform render operation, however there are many usecases, when we want to have a simple `kustomize build` performed against document entrypoint in phase. Now this will be a default behaviour and if a user would like executor to perform rendering to actually understand what it's doing, he will be able to specify --executor boolean flag. Relates-To: #403 Change-Id: I181830f9814ff48a19ba0a1284e89900187bc7d8
This commit is contained in:
parent
f2e305a56d
commit
a6987107bd
@ -35,14 +35,14 @@ 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(cfgFactory config.Factory) *cobra.Command {
|
func NewRenderCommand(cfgFactory config.Factory) *cobra.Command {
|
||||||
filterOptions := &phase.FilterOptions{}
|
filterOptions := &phase.RenderCommand{}
|
||||||
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 {
|
||||||
return filterOptions.Render(cfgFactory, args[0], cmd.OutOrStdout())
|
return filterOptions.RunE(cfgFactory, args[0], cmd.OutOrStdout())
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ func NewRenderCommand(cfgFactory config.Factory) *cobra.Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// addRenderFlags adds flags for document render sub-command
|
// addRenderFlags adds flags for document render sub-command
|
||||||
func addRenderFlags(filterOptions *phase.FilterOptions, cmd *cobra.Command) {
|
func addRenderFlags(filterOptions *phase.RenderCommand, cmd *cobra.Command) {
|
||||||
flags := cmd.Flags()
|
flags := cmd.Flags()
|
||||||
|
|
||||||
flags.StringVarP(
|
flags.StringVarP(
|
||||||
@ -81,4 +81,12 @@ func addRenderFlags(filterOptions *phase.FilterOptions, cmd *cobra.Command) {
|
|||||||
"k",
|
"k",
|
||||||
"",
|
"",
|
||||||
"filter documents by Kinds")
|
"filter documents by Kinds")
|
||||||
|
flags.BoolVarP(
|
||||||
|
&filterOptions.Executor,
|
||||||
|
"executor",
|
||||||
|
"e",
|
||||||
|
false,
|
||||||
|
"if set to true rendering will be performed by executor "+
|
||||||
|
"otherwise phase entrypoint will be rendered by kustomize, if entrypoint is not specified "+
|
||||||
|
"error will be returned")
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ airshipctl phase render initinfra -l app=helm,service=tiller -k Deployment
|
|||||||
Flags:
|
Flags:
|
||||||
-a, --annotation string filter documents by Annotations
|
-a, --annotation string filter documents by Annotations
|
||||||
-g, --apiversion string filter documents by API version
|
-g, --apiversion string filter documents by API version
|
||||||
|
-e, --executor if set to true rendering will be performed by executor otherwise phase entrypoint will be rendered by kustomize, if entrypoint is not specified error will be returned
|
||||||
-h, --help help for render
|
-h, --help help for render
|
||||||
-k, --kind string filter documents by Kinds
|
-k, --kind string filter documents by Kinds
|
||||||
-l, --label string filter documents by Labels
|
-l, --label string filter documents by Labels
|
||||||
|
@ -29,6 +29,7 @@ airshipctl phase render initinfra -l app=helm,service=tiller -k Deployment
|
|||||||
```
|
```
|
||||||
-a, --annotation string filter documents by Annotations
|
-a, --annotation string filter documents by Annotations
|
||||||
-g, --apiversion string filter documents by API version
|
-g, --apiversion string filter documents by API version
|
||||||
|
-e, --executor if set to true rendering will be performed by executor otherwise phase entrypoint will be rendered by kustomize, if entrypoint is not specified error will be returned
|
||||||
-h, --help help for render
|
-h, --help help for render
|
||||||
-k, --kind string filter documents by Kinds
|
-k, --kind string filter documents by Kinds
|
||||||
-l, --label string filter documents by Labels
|
-l, --label string filter documents by Labels
|
||||||
|
@ -134,13 +134,30 @@ func (p *phase) Validate() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Render executor documents
|
// Render executor documents
|
||||||
func (p *phase) Render(w io.Writer, options ifc.RenderOptions) error {
|
func (p *phase) Render(w io.Writer, executorRender bool, options ifc.RenderOptions) error {
|
||||||
executor, err := p.Executor()
|
if executorRender {
|
||||||
|
executor, err := p.Executor()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return executor.Render(w, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
root, err := p.DocumentRoot()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return executor.Render(w, options)
|
bundle, err := document.NewBundleByPath(root)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
rendered, err := bundle.SelectBundle(options.FilterSelector)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return rendered.Write(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DocumentRoot root that holds all the documents associated with the phase
|
// DocumentRoot root that holds all the documents associated with the phase
|
||||||
|
@ -28,7 +28,7 @@ type Phase interface {
|
|||||||
DocumentRoot() (string, error)
|
DocumentRoot() (string, error)
|
||||||
Details() (string, error)
|
Details() (string, error)
|
||||||
Executor() (Executor, error)
|
Executor() (Executor, error)
|
||||||
Render(io.Writer, RenderOptions) error
|
Render(io.Writer, bool, RenderOptions) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// ID uniquely identifies the phase
|
// ID uniquely identifies the phase
|
||||||
|
@ -23,8 +23,8 @@ import (
|
|||||||
"opendev.org/airship/airshipctl/pkg/phase/ifc"
|
"opendev.org/airship/airshipctl/pkg/phase/ifc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FilterOptions holds filters for selector
|
// RenderCommand holds filters for selector
|
||||||
type FilterOptions struct {
|
type RenderCommand struct {
|
||||||
// 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
|
||||||
@ -33,10 +33,12 @@ type FilterOptions struct {
|
|||||||
APIVersion string
|
APIVersion string
|
||||||
// Kind filters documents by document kind
|
// Kind filters documents by document kind
|
||||||
Kind string
|
Kind string
|
||||||
|
// Executor identifies if executor should perform rendering
|
||||||
|
Executor bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render prints out filtered documents
|
// RunE prints out filtered documents
|
||||||
func (fo *FilterOptions) Render(cfgFactory config.Factory, phaseName string, out io.Writer) error {
|
func (fo *RenderCommand) RunE(cfgFactory config.Factory, phaseName string, out io.Writer) error {
|
||||||
cfg, err := cfgFactory()
|
cfg, err := cfgFactory()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -62,6 +64,5 @@ func (fo *FilterOptions) Render(cfgFactory config.Factory, phaseName string, out
|
|||||||
}
|
}
|
||||||
|
|
||||||
sel := document.NewSelector().ByLabel(fo.Label).ByAnnotation(fo.Annotation).ByGvk(group, version, fo.Kind)
|
sel := document.NewSelector().ByLabel(fo.Label).ByAnnotation(fo.Annotation).ByGvk(group, version, fo.Kind)
|
||||||
|
return phase.Render(out, fo.Executor, ifc.RenderOptions{FilterSelector: sel})
|
||||||
return phase.Render(out, ifc.RenderOptions{FilterSelector: sel})
|
|
||||||
}
|
}
|
||||||
|
@ -43,19 +43,19 @@ func TestRender(t *testing.T) {
|
|||||||
fixturePath := "phase"
|
fixturePath := "phase"
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
settings *phase.FilterOptions
|
settings *phase.RenderCommand
|
||||||
expResFile string
|
expResFile string
|
||||||
expErr error
|
expErr error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "No Filters",
|
name: "No Filters",
|
||||||
settings: &phase.FilterOptions{},
|
settings: &phase.RenderCommand{},
|
||||||
expResFile: "noFilter.yaml",
|
expResFile: "noFilter.yaml",
|
||||||
expErr: nil,
|
expErr: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "All Filters",
|
name: "All Filters",
|
||||||
settings: &phase.FilterOptions{
|
settings: &phase.RenderCommand{
|
||||||
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",
|
||||||
@ -66,7 +66,7 @@ func TestRender(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Multiple Labels",
|
name: "Multiple Labels",
|
||||||
settings: &phase.FilterOptions{
|
settings: &phase.RenderCommand{
|
||||||
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",
|
||||||
@ -74,12 +74,21 @@ func TestRender(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Malformed Label",
|
name: "Malformed Label",
|
||||||
settings: &phase.FilterOptions{
|
settings: &phase.RenderCommand{
|
||||||
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"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Malformed Label",
|
||||||
|
settings: &phase.RenderCommand{
|
||||||
|
Label: "app=(",
|
||||||
|
Executor: true,
|
||||||
|
},
|
||||||
|
expResFile: "",
|
||||||
|
expErr: fmt.Errorf("unable to parse requirement: found '(', expected: identifier"),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
@ -92,7 +101,7 @@ func TestRender(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
out := &bytes.Buffer{}
|
out := &bytes.Buffer{}
|
||||||
err = tt.settings.Render(func() (*config.Config, error) {
|
err = tt.settings.RunE(func() (*config.Config, error) {
|
||||||
return rs, nil
|
return rs, nil
|
||||||
}, fixturePath, out)
|
}, fixturePath, out)
|
||||||
assert.Equal(t, tt.expErr, err)
|
assert.Equal(t, tt.expErr, err)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user