Implement render methods

Change-Id: I03b7aad33576eaa9ef7dfaabfb579ac90cc26a12
Signed-off-by: Ruslan Aliev <raliev@mirantis.com>
This commit is contained in:
Ruslan Aliev 2020-09-18 16:53:55 -05:00
parent 0bdbd690db
commit 0c736af2e8
33 changed files with 140 additions and 242 deletions

@ -18,7 +18,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"opendev.org/airship/airshipctl/pkg/config" "opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/phase/render" "opendev.org/airship/airshipctl/pkg/phase"
) )
const ( const (
@ -35,48 +35,48 @@ 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 {
renderSettings := &render.Settings{} filterOptions := &phase.FilterOptions{}
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 renderSettings.Render(cfgFactory, args[0], cmd.OutOrStdout()) return filterOptions.Render(cfgFactory, args[0], cmd.OutOrStdout())
}, },
} }
addRenderFlags(renderSettings, renderCmd) addRenderFlags(filterOptions, renderCmd)
return renderCmd return renderCmd
} }
// addRenderFlags adds flags for document render sub-command // addRenderFlags adds flags for document render sub-command
func addRenderFlags(settings *render.Settings, cmd *cobra.Command) { func addRenderFlags(filterOptions *phase.FilterOptions, cmd *cobra.Command) {
flags := cmd.Flags() flags := cmd.Flags()
flags.StringVarP( flags.StringVarP(
&settings.Label, &filterOptions.Label,
"label", "label",
"l", "l",
"", "",
"filter documents by Labels") "filter documents by Labels")
flags.StringVarP( flags.StringVarP(
&settings.Annotation, &filterOptions.Annotation,
"annotation", "annotation",
"a", "a",
"", "",
"filter documents by Annotations") "filter documents by Annotations")
flags.StringVarP( flags.StringVarP(
&settings.APIVersion, &filterOptions.APIVersion,
"apiversion", "apiversion",
"g", "g",
"", "",
"filter documents by API version") "filter documents by API version")
flags.StringVarP( flags.StringVarP(
&settings.Kind, &filterOptions.Kind,
"kind", "kind",
"k", "k",
"", "",

@ -17,44 +17,17 @@ package phase_test
import ( import (
"testing" "testing"
"github.com/stretchr/testify/require"
"opendev.org/airship/airshipctl/cmd/phase" "opendev.org/airship/airshipctl/cmd/phase"
"opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/testutil" "opendev.org/airship/airshipctl/testutil"
) )
func TestRender(t *testing.T) { func TestRender(t *testing.T) {
cfg, cleanupCfg := testutil.InitConfig(t)
defer cleanupCfg(t)
cfg.CurrentContext = "def_ephemeral"
cfg.Manifests["test"] = &config.Manifest{
TargetPath: "testdata",
PrimaryRepositoryName: "testRepo",
Repositories: map[string]*config.Repository{
"testRepo": {
URLString: "http://localhost",
},
},
}
ctx, err := cfg.GetContext("def_ephemeral")
require.NoError(t, err)
ctx.Manifest = "test"
settings := func() (*config.Config, error) {
return cfg, nil
}
tests := []*testutil.CmdTest{ tests := []*testutil.CmdTest{
{ {
Name: "render-with-help", Name: "render-with-help",
CmdLine: "-h", CmdLine: "-h",
Cmd: phase.NewRenderCommand(nil), Cmd: phase.NewRenderCommand(nil),
}, },
{
Name: "render-with-multiple-labels",
CmdLine: "initinfra -l app=helm,name=tiller",
Cmd: phase.NewRenderCommand(settings),
},
} }
for _, tt := range tests { for _, tt := range tests {
testutil.RunTest(t, tt) testutil.RunTest(t, tt)

@ -1,52 +0,0 @@
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
annotations:
airshipit.org/clustertype: ephemeral
creationTimestamp: null
labels:
app: helm
name: tiller
name: tiller-deploy
namespace: kube-system
spec:
replicas: 1
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: helm
name: tiller
spec:
automountServiceAccountToken: true
containers:
- env:
- name: TILLER_NAMESPACE
value: kube-system
- name: TILLER_HISTORY_MAX
value: "0"
image: gcr.io/kubernetes-helm/tiller:v2.12.3
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
path: /liveness
port: 44135
initialDelaySeconds: 1
timeoutSeconds: 1
name: tiller
ports:
- containerPort: 44134
name: tiller
- containerPort: 44135
name: http
readinessProbe:
httpGet:
path: /readiness
port: 44135
initialDelaySeconds: 1
timeoutSeconds: 1
resources: {}
status: {}
...

@ -1,2 +0,0 @@
resources:
- tiller.yaml

@ -1,74 +0,0 @@
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
annotations:
airshipit.org/clustertype: ephemeral
creationTimestamp: null
labels:
app: helm
name: tiller
name: tiller-deploy
namespace: kube-system
spec:
replicas: 1
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: helm
name: tiller
spec:
automountServiceAccountToken: true
containers:
- env:
- name: TILLER_NAMESPACE
value: kube-system
- name: TILLER_HISTORY_MAX
value: "0"
image: gcr.io/kubernetes-helm/tiller:v2.12.3
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
path: /liveness
port: 44135
initialDelaySeconds: 1
timeoutSeconds: 1
name: tiller
ports:
- containerPort: 44134
name: tiller
- containerPort: 44135
name: http
readinessProbe:
httpGet:
path: /readiness
port: 44135
initialDelaySeconds: 1
timeoutSeconds: 1
resources: {}
status: {}
---
apiVersion: v1
kind: Service
metadata:
annotations:
airshipit.org/clustertype: ephemeral
creationTimestamp: null
labels:
app: helm
name: tiller-deploy
namespace: kube-system
spec:
ports:
- name: tiller
port: 44134
targetPort: tiller
selector:
app: helm
name: tiller
type: ClusterIP
status:
loadBalancer: {}
...

1
go.sum

@ -1507,6 +1507,7 @@ k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C
k8s.io/kube-state-metrics v1.7.2/go.mod h1:U2Y6DRi07sS85rmVPmBFlmv+2peBcL8IWGjM+IjYA/E= k8s.io/kube-state-metrics v1.7.2/go.mod h1:U2Y6DRi07sS85rmVPmBFlmv+2peBcL8IWGjM+IjYA/E=
k8s.io/kubectl v0.0.0-20191219154910-1528d4eea6dd h1:nZX5+wEqTu/EBIYjrZlFOA63z4+Zcy96lDkCZPU9a9c= k8s.io/kubectl v0.0.0-20191219154910-1528d4eea6dd h1:nZX5+wEqTu/EBIYjrZlFOA63z4+Zcy96lDkCZPU9a9c=
k8s.io/kubectl v0.0.0-20191219154910-1528d4eea6dd/go.mod h1:9ehGcuUGjXVZh0qbYSB0vvofQw2JQe6c6cO0k4wu/Oo= k8s.io/kubectl v0.0.0-20191219154910-1528d4eea6dd/go.mod h1:9ehGcuUGjXVZh0qbYSB0vvofQw2JQe6c6cO0k4wu/Oo=
k8s.io/kubernetes v1.13.0 h1:qTfB+u5M92k2fCCCVP2iuhgwwSOv1EkAkvQY1tQODD8=
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/metrics v0.0.0-20191214191643-6b1944c9f765/go.mod h1:5V7rewilItwK0cz4nomU0b3XCcees2Ka5EBYWS1HBeM= k8s.io/metrics v0.0.0-20191214191643-6b1944c9f765/go.mod h1:5V7rewilItwK0cz4nomU0b3XCcees2Ka5EBYWS1HBeM=
k8s.io/utils v0.0.0-20190308190857-21c4ce38f2a7/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0= k8s.io/utils v0.0.0-20190308190857-21c4ce38f2a7/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0=

@ -144,8 +144,10 @@ func (c *Executor) Validate() error {
} }
// Render executor documents // Render executor documents
func (c *Executor) Render(_ io.Writer, _ ifc.RenderOptions) error { func (c *Executor) Render(w io.Writer, _ ifc.RenderOptions) error {
return errors.ErrNotImplemented{} // will be implemented later
_, err := w.Write([]byte{})
return err
} }
func handleError(ch chan<- events.Event, err error) { func handleError(ch chan<- events.Event, err error) {

@ -182,6 +182,8 @@ func (c *ClusterctlExecutor) Validate() error {
} }
// Render executor documents // Render executor documents
func (c *ClusterctlExecutor) Render(_ io.Writer, _ ifc.RenderOptions) error { func (c *ClusterctlExecutor) Render(w io.Writer, _ ifc.RenderOptions) error {
return errors.ErrNotImplemented{} // will be implemented later
_, err := w.Write([]byte{})
return err
} }

@ -218,7 +218,6 @@ func TestExecutorRender(t *testing.T) {
sampleCfgDoc := executorDoc(t, "init") sampleCfgDoc := executorDoc(t, "init")
bundle, err := document.NewBundleByPath("testdata/executor_init") bundle, err := document.NewBundleByPath("testdata/executor_init")
require.NoError(t, err) require.NoError(t, err)
expectedErr := airerrors.ErrNotImplemented{}
executor, err := cctlclient.NewExecutor( executor, err := cctlclient.NewExecutor(
ifc.ExecutorConfig{ ifc.ExecutorConfig{
@ -229,7 +228,7 @@ func TestExecutorRender(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
actualOut := &bytes.Buffer{} actualOut := &bytes.Buffer{}
actualErr := executor.Render(actualOut, ifc.RenderOptions{}) actualErr := executor.Render(actualOut, ifc.RenderOptions{})
assert.Equal(t, expectedErr, actualErr) assert.Equal(t, nil, actualErr)
} }
func makeDefaultHelper(t *testing.T) ifc.Helper { func makeDefaultHelper(t *testing.T) ifc.Helper {

@ -93,7 +93,7 @@ func (a *Applier) ApplyBundle(bundle document.Bundle, ao ApplyOptions) {
func (a *Applier) getInfos(bundleName string, bundle document.Bundle) ([]*resource.Info, error) { func (a *Applier) getInfos(bundleName string, bundle document.Bundle) ([]*resource.Info, error) {
if bundle == nil { if bundle == nil {
return nil, ErrApplyNilBundle{} return nil, ErrNilBundle{}
} }
selector := document. selector := document.
NewSelector(). NewSelector().

@ -94,7 +94,7 @@ func TestApplierRun(t *testing.T) {
}, },
{ {
name: "bundle failure", name: "bundle failure",
expectedString: "Cannot apply nil bundle", expectedString: "nil bundle provided",
expectErr: true, expectErr: true,
}, },
{ {

@ -28,10 +28,10 @@ func (e ErrApply) Error() string {
return fmt.Sprintf("Applying of resources to kubernetes cluster has failed, errors are:\n%v", e.errors) return fmt.Sprintf("Applying of resources to kubernetes cluster has failed, errors are:\n%v", e.errors)
} }
// ErrApplyNilBundle returned when nil bundle is passed to ApplyBundle function // ErrNilBundle returned when bundle is nil
type ErrApplyNilBundle struct { type ErrNilBundle struct {
} }
func (e ErrApplyNilBundle) Error() string { func (e ErrNilBundle) Error() string {
return "Cannot apply nil bundle" return "nil bundle provided"
} }

@ -82,6 +82,9 @@ func NewExecutor(opts ExecutorOptions) (*Executor, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if opts.ExecutorBundle == nil {
return nil, ErrNilBundle{}
}
return &Executor{ return &Executor{
Options: opts, Options: opts,
apiObject: apiObj, apiObject: apiObj,
@ -116,9 +119,6 @@ func (e *Executor) prepareApplier(ch chan events.Event) (*Applier, document.Bund
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
if e.Options.ExecutorBundle == nil {
return nil, nil, ErrApplyNilBundle{}
}
log.Debug("Filtering out documents that shouldn't be applied to kubernetes from document bundle") log.Debug("Filtering out documents that shouldn't be applied to kubernetes from document bundle")
bundle, err := e.Options.ExecutorBundle.SelectBundle(document.NewDeployToK8sSelector()) bundle, err := e.Options.ExecutorBundle.SelectBundle(document.NewDeployToK8sSelector())
if err != nil { if err != nil {
@ -139,6 +139,10 @@ func (e *Executor) Validate() error {
} }
// Render document set // Render document set
func (e *Executor) Render(w io.Writer, _ ifc.RenderOptions) error { func (e *Executor) Render(w io.Writer, o ifc.RenderOptions) error {
return e.Options.ExecutorBundle.Write(w) bundle, err := e.Options.ExecutorBundle.SelectBundle(o.FilterSelector)
if err != nil {
return err
}
return bundle.Write(w)
} }

@ -167,7 +167,7 @@ func TestExecutorRun(t *testing.T) {
{ {
name: "Nil bundle provided", name: "Nil bundle provided",
execDoc: toKubernetesApply(t, ValidExecutorDoc), execDoc: toKubernetesApply(t, ValidExecutorDoc),
containsErr: "Cannot apply nil bundle", containsErr: "nil bundle provided",
kubeconf: testKubeconfig(testValidKubeconfig), kubeconf: testKubeconfig(testValidKubeconfig),
helper: makeDefaultHelper(t), helper: makeDefaultHelper(t),
bundleFunc: func(t *testing.T) document.Bundle { bundleFunc: func(t *testing.T) document.Bundle {
@ -185,17 +185,22 @@ func TestExecutorRun(t *testing.T) {
ExecutorBundle: tt.bundleFunc(t), ExecutorBundle: tt.bundleFunc(t),
Kubeconfig: tt.kubeconf, Kubeconfig: tt.kubeconf,
}) })
require.NoError(t, err) if tt.name == "Nil bundle provided" {
require.NotNil(t, exec)
ch := make(chan events.Event)
go exec.Run(ch, ifc.RunOptions{})
processor := events.NewDefaultProcessor(utils.Streams())
err = processor.Process(ch)
if tt.containsErr != "" {
require.Error(t, err) require.Error(t, err)
assert.Contains(t, err.Error(), tt.containsErr) assert.Contains(t, err.Error(), tt.containsErr)
} else { } else {
assert.NoError(t, err) require.NoError(t, err)
require.NotNil(t, exec)
ch := make(chan events.Event)
go exec.Run(ch, ifc.RunOptions{})
processor := events.NewDefaultProcessor(utils.Streams())
err = processor.Process(ch)
if tt.containsErr != "" {
require.Error(t, err)
assert.Contains(t, err.Error(), tt.containsErr)
} else {
assert.NoError(t, err)
}
} }
}) })
} }

@ -15,6 +15,7 @@
package phase package phase
import ( import (
"io"
"path/filepath" "path/filepath"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
@ -131,6 +132,16 @@ func (p *phase) Validate() error {
return nil return nil
} }
// Render executor documents
func (p *phase) Render(w io.Writer, options ifc.RenderOptions) error {
executor, err := p.Executor()
if err != nil {
return err
}
return executor.Render(w, options)
}
// DocumentRoot root that holds all the documents associated with the phase // DocumentRoot root that holds all the documents associated with the phase
func (p *phase) DocumentRoot() string { func (p *phase) DocumentRoot() string {
if p.apiObj.Config.DocumentEntryPoint == "" { if p.apiObj.Config.DocumentEntryPoint == "" {

@ -177,11 +177,11 @@ var _ ifc.Executor = fakeExecutor{}
type fakeExecutor struct { type fakeExecutor struct {
} }
func (e fakeExecutor) Render(w io.Writer, ro ifc.RenderOptions) error { func (e fakeExecutor) Render(_ io.Writer, _ ifc.RenderOptions) error {
return nil return nil
} }
func (e fakeExecutor) Run(ch chan events.Event, ro ifc.RunOptions) { func (e fakeExecutor) Run(ch chan events.Event, _ ifc.RunOptions) {
defer close(ch) defer close(ch)
} }

@ -40,8 +40,10 @@ type RunOptions struct {
Timeout time.Duration Timeout time.Duration
} }
// RenderOptions is empty for now, but may hold things like format in future // RenderOptions holds options for render method
type RenderOptions struct{} type RenderOptions struct {
FilterSelector document.Selector
}
// WaitOptions holds only timeout now, but may be extended in the future // WaitOptions holds only timeout now, but may be extended in the future
type WaitOptions struct { type WaitOptions struct {

@ -15,18 +15,20 @@
package ifc package ifc
import ( import (
"io"
"opendev.org/airship/airshipctl/pkg/api/v1alpha1" "opendev.org/airship/airshipctl/pkg/api/v1alpha1"
"opendev.org/airship/airshipctl/pkg/cluster/clustermap" "opendev.org/airship/airshipctl/pkg/cluster/clustermap"
) )
// Phase provides a way to interact with a phase // Phase provides a way to interact with a phase
// TODO add render method
type Phase interface { type Phase interface {
Validate() error Validate() error
Run(RunOptions) error Run(RunOptions) error
DocumentRoot() string DocumentRoot() string
Details() (string, error) Details() (string, error)
Executor() (Executor, error) Executor() (Executor, error)
Render(io.Writer, RenderOptions) error
} }
// ID uniquely identifies the phase // ID uniquely identifies the phase

@ -12,7 +12,7 @@
limitations under the License. limitations under the License.
*/ */
package render package phase
import ( import (
"io" "io"
@ -20,26 +20,40 @@ import (
"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/phase/ifc"
) )
// FilterOptions holds filters for selector
type FilterOptions struct {
// Label filters documents by label string
Label string
// Annotation filters documents by annotation string
Annotation string
// APIVersion filters documents by API group and version
APIVersion string
// Kind filters documents by document kind
Kind string
}
// Render prints out filtered documents // Render prints out filtered documents
func (s *Settings) Render(cfgFactory config.Factory, phaseName string, out io.Writer) error { func (fo *FilterOptions) Render(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
} }
path, err := cfg.CurrentContextEntryPoint(phaseName) helper, err := NewHelper(cfg)
if err != nil { if err != nil {
return err return err
} }
docBundle, err := document.NewBundleByPath(path) client := NewClient(helper)
phase, err := client.PhaseByID(ifc.ID{Name: phaseName})
if err != nil { if err != nil {
return err return err
} }
groupVersion := strings.Split(s.APIVersion, "/") groupVersion := strings.Split(fo.APIVersion, "/")
group := "" group := ""
version := groupVersion[0] version := groupVersion[0]
if len(groupVersion) > 1 { if len(groupVersion) > 1 {
@ -47,11 +61,7 @@ func (s *Settings) Render(cfgFactory config.Factory, phaseName string, out io.Wr
version = strings.Join(groupVersion[1:], "/") version = strings.Join(groupVersion[1:], "/")
} }
sel := document.NewSelector().ByLabel(s.Label).ByAnnotation(s.Annotation).ByGvk(group, version, s.Kind) sel := document.NewSelector().ByLabel(fo.Label).ByAnnotation(fo.Annotation).ByGvk(group, version, fo.Kind)
filteredBundle, err := docBundle.SelectBundle(sel)
if err != nil {
return err
}
return filteredBundle.Write(out) return phase.Render(out, ifc.RenderOptions{FilterSelector: sel})
} }

@ -1,27 +0,0 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package render
// Settings for document rendering
type Settings struct {
// Label filters documents by label string
Label string
// Annotation filters documents by annotation string
Annotation string
// APIVersion filters documents by API group and version
APIVersion string
// Kind filters documents by document kind
Kind string
}

@ -12,7 +12,7 @@
limitations under the License. limitations under the License.
*/ */
package render_test package phase_test
import ( import (
"bytes" "bytes"
@ -25,7 +25,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"opendev.org/airship/airshipctl/pkg/config" "opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/phase/render" "opendev.org/airship/airshipctl/pkg/phase"
"opendev.org/airship/airshipctl/testutil" "opendev.org/airship/airshipctl/testutil"
) )
@ -34,22 +34,23 @@ func TestRender(t *testing.T) {
dummyManifest := rs.Manifests["dummy_manifest"] dummyManifest := rs.Manifests["dummy_manifest"]
dummyManifest.TargetPath = "testdata" dummyManifest.TargetPath = "testdata"
dummyManifest.SubPath = "" dummyManifest.SubPath = ""
dummyManifest.MetadataPath = "metadata.yaml"
fixturePath := "phase" fixturePath := "phase"
tests := []struct { tests := []struct {
name string name string
settings *render.Settings settings *phase.FilterOptions
expResFile string expResFile string
expErr error expErr error
}{ }{
{ {
name: "No Filters", name: "No Filters",
settings: &render.Settings{}, settings: &phase.FilterOptions{},
expResFile: "noFilter.yaml", expResFile: "noFilter.yaml",
expErr: nil, expErr: nil,
}, },
{ {
name: "All Filters", name: "All Filters",
settings: &render.Settings{ settings: &phase.FilterOptions{
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",
@ -60,7 +61,7 @@ func TestRender(t *testing.T) {
}, },
{ {
name: "Multiple Labels", name: "Multiple Labels",
settings: &render.Settings{ settings: &phase.FilterOptions{
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",
@ -68,7 +69,7 @@ func TestRender(t *testing.T) {
}, },
{ {
name: "Malformed Label", name: "Malformed Label",
settings: &render.Settings{ settings: &phase.FilterOptions{
Label: "app=(", Label: "app=(",
}, },
expResFile: "", expResFile: "",

2
pkg/phase/testdata/metadata.yaml vendored Executable file

@ -0,0 +1,2 @@
phase:
path: phases

11
pkg/phase/testdata/phases/cluster-map.yaml vendored Executable file

@ -0,0 +1,11 @@
---
apiVersion: airshipit.org/v1alpha1
kind: ClusterMap
metadata:
labels:
airshipit.org/deploy-k8s: "false"
name: main-map
map:
target-cluster:
parent: ephemeral-cluster
ephemeral-cluster: {}

12
pkg/phase/testdata/phases/executors.yaml vendored Executable file

@ -0,0 +1,12 @@
---
apiVersion: airshipit.org/v1alpha1
kind: KubernetesApply
metadata:
labels:
airshipit.org/deploy-k8s: "false"
name: kubernetes-apply
config:
waitOptions:
timeout: 2000
pruneOptions:
prune: false

@ -0,0 +1,4 @@
resources:
- phases.yaml
- executors.yaml
- cluster-map.yaml

12
pkg/phase/testdata/phases/phases.yaml vendored Executable file

@ -0,0 +1,12 @@
---
apiVersion: airshipit.org/v1alpha1
kind: Phase
metadata:
name: phase
clusterName: ephemeral-cluster
config:
executorRef:
apiVersion: airshipit.org/v1alpha1
kind: KubernetesApply
name: kubernetes-apply
documentEntryPoint: ephemeral/phase

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
set -e set -xe
# The root of the manifest structure to be validated. # The root of the manifest structure to be validated.
# This corresponds to the targetPath in an airshipctl config # This corresponds to the targetPath in an airshipctl config
@ -109,7 +109,7 @@ for cluster in ephemeral target; do
# removed since it was choking in certain cases and got to be more trouble than was worth. # removed since it was choking in certain cases and got to be more trouble than was worth.
# This should be removed once we have a phase map that is smarter. # This should be removed once we have a phase map that is smarter.
# In the meantime, as new phases are added, please add them here as well. # In the meantime, as new phases are added, please add them here as well.
phases="bootstrap initinfra controlplane baremetalhost workers workload tenant" phases="initinfra-ephemeral controlplane-ephemeral initinfra-target workers-target"
for phase in $phases; do for phase in $phases; do
# Guard against bootstrap or initinfra being missing, which could be the case for some configs # Guard against bootstrap or initinfra being missing, which could be the case for some configs