Reduce the number of unnecessary document.NewBundleByPath() calls

Since document.NewBundleByPath() is pretty resource and time
consuming call (because it invokes kustomize under the hood),
we should avoid unnecessary calls of this function. There are
lots of the same constructor calls of new bundle from phase
bundle root path, mostly in helper, which slows airshipctl
and makes no sense. This patch fixes this problem by storing
phase root bundle variable in helper, which creates only once
during airshipctl execution.

Change-Id: I6b59d440f7ab7a68dc613091dafcc9e82df10eb7
Signed-off-by: Ruslan Aliev <raliev@mirantis.com>
Closes: #488
This commit is contained in:
Ruslan Aliev 2021-03-15 03:25:41 -05:00
parent 3749a8fe50
commit e9041a2a22
27 changed files with 250 additions and 95 deletions

View File

@ -78,22 +78,17 @@ func (cmd *GetKubeconfigCommand) RunE(cfgFactory config.Factory, writer io.Write
return err
}
wd, err := helper.WorkDir()
if err != nil {
return err
}
client, err := client.NewClient(helper.TargetPath(), log.DebugEnabled(), airshipv1.DefaultClusterctl())
if err != nil {
return err
}
kubeconf := kubeconfig.NewBuilder().
WithBundle(helper.PhaseBundleRoot()).
WithBundle(helper.PhaseConfigBundle()).
WithClusterctClient(client).
WithClusterMap(cMap).
WithClusterName(cmd.ClusterName).
WithTempRoot(wd).
WithTempRoot(helper.WorkDir()).
Build()
return kubeconf.Write(writer)

0
pkg/container/testdata/kustomization.yaml vendored Executable file
View File

View File

@ -23,6 +23,7 @@ import (
"opendev.org/airship/airshipctl/pkg/api/v1alpha1"
"opendev.org/airship/airshipctl/pkg/cluster/clustermap"
"opendev.org/airship/airshipctl/pkg/clusterctl/client"
"opendev.org/airship/airshipctl/pkg/document"
"opendev.org/airship/airshipctl/pkg/fs"
"opendev.org/airship/airshipctl/pkg/log"
)
@ -40,19 +41,19 @@ func NewBuilder() *Builder {
// Builder is an object that allows to build a kubeconfig based on various provided sources
// such as path to kubeconfig, path to bundle that should contain kubeconfig and parent cluster
type Builder struct {
bundlePath string
clusterName string
root string
bundle document.Bundle
clusterMap clustermap.ClusterMap
clusterctlClient client.Interface
fs fs.FileSystem
siteKubeconf *api.Config
}
// WithBundle allows to set path to bundle that should contain kubeconfig api object
func (b *Builder) WithBundle(bundlePath string) *Builder {
b.bundlePath = bundlePath
// WithBundle allows to set document.Bundle object that should contain kubeconfig api object
func (b *Builder) WithBundle(bundle document.Bundle) *Builder {
b.bundle = bundle
return b
}
@ -181,7 +182,7 @@ func (b *Builder) trySource(clusterID, dstContext string, source v1alpha1.Kubeco
getter = FromFile(source.FileSystem.Path, b.fs)
sourceContext = source.FileSystem.Context
case v1alpha1.KubeconfigSourceTypeBundle:
getter = FromBundle(b.bundlePath)
getter = FromBundle(b.bundle)
sourceContext = source.Bundle.Context
case v1alpha1.KubeconfigSourceTypeClusterAPI:
getter = b.fromClusterAPI(clusterID, source.ClusterAPI)

View File

@ -27,6 +27,7 @@ import (
"opendev.org/airship/airshipctl/pkg/api/v1alpha1"
"opendev.org/airship/airshipctl/pkg/cluster/clustermap"
"opendev.org/airship/airshipctl/pkg/clusterctl/client"
"opendev.org/airship/airshipctl/pkg/document"
"opendev.org/airship/airshipctl/pkg/fs"
"opendev.org/airship/airshipctl/pkg/k8s/kubeconfig"
"opendev.org/airship/airshipctl/testutil/clusterctl"
@ -85,8 +86,9 @@ func TestBuilderClusterctl(t *testing.T) {
parentUser := "parent_admin"
parentParentUser := "parent_parent_admin"
childUser := "child_user"
testBundlePath := "testdata"
kubeconfigPath := filepath.Join(testBundlePath, "kubeconfig-12341234")
testBundle, err := document.NewBundleByPath("testdata")
require.NoError(t, err)
kubeconfigPath := filepath.Join("testdata", "kubeconfig-12341234")
tests := []struct {
name string
@ -259,7 +261,7 @@ func TestBuilderClusterctl(t *testing.T) {
kube := kubeconfig.NewBuilder().
WithClusterMap(tt.clusterMap).
WithClusterName(tt.requestedClusterName).
WithBundle(testBundlePath).
WithBundle(testBundle).
WithTempRoot(tt.tempRoot).
WithClusterctClient(tt.clusterctlClient).
WithFilesytem(tt.fs).

View File

@ -122,20 +122,15 @@ func FromFile(path string, fSys fs.FileSystem) KubeSourceFunc {
}
// FromBundle returns KubeSource type, uses path to document bundle to find kubeconfig
func FromBundle(root string) KubeSourceFunc {
func FromBundle(bundle document.Bundle) KubeSourceFunc {
return func() ([]byte, error) {
docBundle, err := document.NewBundleByPath(root)
if err != nil {
return nil, err
}
config := &v1alpha1.KubeConfig{}
selector, err := document.NewSelector().ByObject(config, v1alpha1.Scheme)
if err != nil {
return nil, err
}
doc, err := docBundle.SelectOne(selector)
doc, err := bundle.SelectOne(selector)
if err != nil {
return nil, err
}

View File

@ -29,6 +29,7 @@ import (
"opendev.org/airship/airshipctl/pkg/api/v1alpha1"
"opendev.org/airship/airshipctl/pkg/clusterctl/client"
"opendev.org/airship/airshipctl/pkg/document"
"opendev.org/airship/airshipctl/pkg/fs"
"opendev.org/airship/airshipctl/pkg/k8s/kubeconfig"
testfs "opendev.org/airship/airshipctl/testutil/fs"
@ -184,14 +185,14 @@ func TestFromBundle(t *testing.T) {
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
kubeconf, err := kubeconfig.FromBundle(tt.rootPath)()
bundle, err := document.NewBundleByPath(tt.rootPath)
if tt.shouldFail {
require.Error(t, err)
assert.Nil(t, kubeconf)
} else {
return
}
kubeconf, err := kubeconfig.FromBundle(bundle)()
require.NoError(t, err)
assert.Contains(t, string(kubeconf), tt.expectedContains)
}
})
}
}

View File

@ -87,11 +87,6 @@ func (p *phase) Executor() (ifc.Executor, error) {
return nil, err
}
wd, err := p.helper.WorkDir()
if err != nil {
return nil, err
}
cctlClient, err := cctlclient.NewClient(
p.helper.PhaseBundleRoot(),
log.DebugEnabled(),
@ -101,9 +96,9 @@ func (p *phase) Executor() (ifc.Executor, error) {
}
kubeconf := kubeconfig.NewBuilder().
WithBundle(p.helper.PhaseBundleRoot()).
WithBundle(p.helper.PhaseConfigBundle()).
WithClusterMap(cMap).
WithTempRoot(wd).
WithTempRoot(p.helper.WorkDir()).
WithClusterctClient(cctlClient).
Build()

View File

@ -179,18 +179,14 @@ func (c *ContainerExecutor) Render(_ io.Writer, _ ifc.RenderOptions) error {
func (c *ContainerExecutor) setConfig() error {
if c.Container.ConfigRef != nil {
log.Printf("Config reference is specified, looking for the object in config ref: '%v'", c.Container.ConfigRef)
log.Printf("using bundle root %s", c.Helper.PhaseBundleRoot())
bundle, err := document.NewBundleByPath(c.Helper.PhaseBundleRoot())
if err != nil {
return err
}
log.Debugf("Config reference is specified, looking for the object in config ref: '%v'", c.Container.ConfigRef)
log.Debugf("using bundle root %s", c.Helper.PhaseBundleRoot())
gvk := c.Container.ConfigRef.GroupVersionKind()
selector := document.NewSelector().
ByName(c.Container.ConfigRef.Name).
ByNamespace(c.Container.ConfigRef.Namespace).
ByGvk(gvk.Group, gvk.Version, gvk.Kind)
doc, err := bundle.SelectOne(selector)
doc, err := c.Helper.PhaseConfigBundle().SelectOne(selector)
if err != nil {
return err
}

View File

@ -38,17 +38,16 @@ type Helper struct {
targetPath string
phaseRepoDir string
phaseEntryPointBasePath string
workDir string
inventory inventoryifc.Inventory
metadata *config.Metadata
config *config.Config
phaseConfigBundle document.Bundle
}
// NewHelper constructs metadata interface based on config
func NewHelper(cfg *config.Config) (ifc.Helper, error) {
helper := &Helper{
config: cfg,
}
helper := &Helper{}
var err error
helper.targetPath, err = cfg.CurrentContextTargetPath()
@ -63,20 +62,23 @@ func NewHelper(cfg *config.Config) (ifc.Helper, error) {
if err != nil {
return nil, err
}
helper.workDir, err = cfg.WorkDir()
if err != nil {
return nil, err
}
helper.phaseBundleRoot = filepath.Join(helper.targetPath, helper.phaseRepoDir, helper.metadata.PhaseMeta.Path)
helper.inventoryRoot = filepath.Join(helper.targetPath, helper.phaseRepoDir, helper.metadata.Inventory.Path)
helper.phaseEntryPointBasePath = filepath.Join(helper.targetPath, helper.phaseRepoDir,
helper.metadata.PhaseMeta.DocEntryPointPrefix)
helper.inventory = inventory.NewInventory(func() (*config.Config, error) { return cfg, nil })
if helper.phaseConfigBundle, err = document.NewBundleByPath(helper.phaseBundleRoot); err != nil {
return nil, err
}
return helper, nil
}
// Phase returns a phase APIObject based on phase selector
func (helper *Helper) Phase(phaseID ifc.ID) (*v1alpha1.Phase, error) {
bundle, err := document.NewBundleByPath(helper.phaseBundleRoot)
if err != nil {
return nil, err
}
phase := &v1alpha1.Phase{
ObjectMeta: v1.ObjectMeta{
Name: phaseID.Name,
@ -87,7 +89,7 @@ func (helper *Helper) Phase(phaseID ifc.ID) (*v1alpha1.Phase, error) {
if err != nil {
return nil, err
}
doc, err := bundle.SelectOne(selector)
doc, err := helper.phaseConfigBundle.SelectOne(selector)
if err != nil {
return nil, err
}
@ -101,11 +103,6 @@ func (helper *Helper) Phase(phaseID ifc.ID) (*v1alpha1.Phase, error) {
// Plan returns plan associated with a manifest
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{
ObjectMeta: v1.ObjectMeta{
Name: planID.Name,
@ -117,7 +114,7 @@ func (helper *Helper) Plan(planID ifc.ID) (*v1alpha1.PhasePlan, error) {
return nil, err
}
doc, err := bundle.SelectOne(selector)
doc, err := helper.phaseConfigBundle.SelectOne(selector)
if err != nil {
return nil, err
}
@ -130,18 +127,13 @@ func (helper *Helper) Plan(planID ifc.ID) (*v1alpha1.PhasePlan, error) {
// ListPhases returns all phases associated with manifest
func (helper *Helper) ListPhases(o ifc.ListPhaseOptions) ([]*v1alpha1.Phase, error) {
bundle, err := document.NewBundleByPath(helper.phaseBundleRoot)
if err != nil {
return nil, err
}
phase := &v1alpha1.Phase{}
selector, err := document.NewSelector().ByObject(phase, v1alpha1.Scheme)
if err != nil {
return nil, err
}
bundle, err = bundle.SelectBundle(selector)
bundle, err := helper.phaseConfigBundle.SelectBundle(selector)
if err != nil {
return nil, err
}
@ -210,18 +202,13 @@ func (helper *Helper) getDocsByPhasePlan(planID ifc.ID, bundle document.Bundle)
// ListPlans returns all phases associated with manifest
func (helper *Helper) ListPlans() ([]*v1alpha1.PhasePlan, error) {
bundle, err := document.NewBundleByPath(helper.phaseBundleRoot)
if err != nil {
return nil, err
}
plan := &v1alpha1.PhasePlan{}
selector, err := document.NewSelector().ByObject(plan, v1alpha1.Scheme)
if err != nil {
return nil, err
}
docs, err := bundle.Select(selector)
docs, err := helper.phaseConfigBundle.Select(selector)
if err != nil {
return nil, err
}
@ -239,18 +226,13 @@ func (helper *Helper) ListPlans() ([]*v1alpha1.PhasePlan, error) {
// ClusterMapAPIobj associated with the the manifest
func (helper *Helper) ClusterMapAPIobj() (*v1alpha1.ClusterMap, error) {
bundle, err := document.NewBundleByPath(helper.phaseBundleRoot)
if err != nil {
return nil, err
}
cMap := v1alpha1.DefaultClusterMap()
selector, err := document.NewSelector().ByObject(cMap, v1alpha1.Scheme)
if err != nil {
return nil, err
}
doc, err := bundle.SelectOne(selector)
doc, err := helper.phaseConfigBundle.SelectOne(selector)
if err != nil {
return nil, err
}
@ -272,10 +254,6 @@ func (helper *Helper) ClusterMap() (clustermap.ClusterMap, error) {
// ExecutorDoc returns executor document associated with phase
func (helper *Helper) ExecutorDoc(phaseID ifc.ID) (document.Document, error) {
bundle, err := document.NewBundleByPath(helper.phaseBundleRoot)
if err != nil {
return nil, err
}
phaseObj, err := helper.Phase(phaseID)
if err != nil {
return nil, err
@ -293,7 +271,7 @@ func (helper *Helper) ExecutorDoc(phaseID ifc.ID) (document.Document, error) {
ByGvk(refGVK.Group, refGVK.Version, refGVK.Kind).
ByName(phaseConfig.ExecutorRef.Name).
ByNamespace(phaseConfig.ExecutorRef.Namespace)
return bundle.SelectOne(selector)
return helper.phaseConfigBundle.SelectOne(selector)
}
// TargetPath returns manifest root
@ -324,12 +302,17 @@ func (helper *Helper) PhaseEntryPointBasePath() string {
return helper.phaseEntryPointBasePath
}
// WorkDir return working directory for aisrhipctl, creates it, if doesn't exist
func (helper *Helper) WorkDir() (string, error) {
return helper.config.WorkDir()
// WorkDir return working directory for airshipctl
func (helper *Helper) WorkDir() string {
return helper.workDir
}
// Inventory return inventory interface
func (helper *Helper) Inventory() (inventoryifc.Inventory, error) {
return helper.inventory, nil
}
// PhaseConfigBundle returns bundle based on phaseBundleRoot
func (helper *Helper) PhaseConfigBundle() document.Bundle {
return helper.phaseConfigBundle
}

View File

@ -41,6 +41,7 @@ func TestHelperPhase(t *testing.T) {
testCases := []struct {
name string
errContains string
helperErr bool
phaseID ifc.ID
config func(t *testing.T) *config.Config
@ -82,6 +83,7 @@ func TestHelperPhase(t *testing.T) {
return conf
},
errContains: "no such file or directory",
helperErr: true,
},
}
@ -89,9 +91,11 @@ func TestHelperPhase(t *testing.T) {
tt := test
t.Run(tt.name, func(t *testing.T) {
helper, err := phase.NewHelper(tt.config(t))
require.NoError(t, err)
if tt.helperErr {
require.Error(t, err)
return
}
require.NotNil(t, helper)
actualPhase, actualErr := helper.Phase(tt.phaseID)
if tt.errContains != "" {
require.Error(t, actualErr)
@ -111,6 +115,7 @@ func TestHelperPlan(t *testing.T) {
errContains string
expectedPlan *v1alpha1.PhasePlan
config func(t *testing.T) *config.Config
bundleErr bool
}{
{
name: "Valid Phase Plan",
@ -156,6 +161,7 @@ func TestHelperPlan(t *testing.T) {
return conf
},
errContains: "no such file or directory",
bundleErr: true,
},
}
@ -163,6 +169,10 @@ func TestHelperPlan(t *testing.T) {
tt := test
t.Run(tt.name, func(t *testing.T) {
helper, err := phase.NewHelper(tt.config(t))
if tt.bundleErr {
require.Error(t, err)
return
}
require.NoError(t, err)
require.NotNil(t, helper)
@ -185,6 +195,7 @@ func TestHelperListPhases(t *testing.T) {
phaseLen int
config func(t *testing.T) *config.Config
options ifc.ListPhaseOptions
bundleErr bool
}{
{
name: "Success phase list",
@ -199,6 +210,7 @@ func TestHelperListPhases(t *testing.T) {
return conf
},
errContains: "no such file or directory",
bundleErr: true,
},
{
name: "Success 0 phases",
@ -234,6 +246,10 @@ func TestHelperListPhases(t *testing.T) {
tt := test
t.Run(tt.name, func(t *testing.T) {
helper, err := phase.NewHelper(tt.config(t))
if tt.bundleErr {
require.Error(t, err)
return
}
require.NoError(t, err)
require.NotNil(t, helper)
@ -253,6 +269,7 @@ func TestHelperListPlans(t *testing.T) {
testCases := []struct {
name string
errContains string
bundleErr bool
expectedLen int
config func(t *testing.T) *config.Config
}{
@ -269,6 +286,7 @@ func TestHelperListPlans(t *testing.T) {
return conf
},
errContains: "no such file or directory",
bundleErr: true,
},
{
name: "Success 0 plans",
@ -285,6 +303,10 @@ func TestHelperListPlans(t *testing.T) {
tt := test
t.Run(tt.name, func(t *testing.T) {
helper, err := phase.NewHelper(tt.config(t))
if tt.bundleErr {
require.Error(t, err)
return
}
require.NoError(t, err)
require.NotNil(t, helper)
@ -304,6 +326,7 @@ func TestHelperClusterMapAPI(t *testing.T) {
testCases := []struct {
name string
errContains string
helperErr bool
expectedCMap *v1alpha1.ClusterMap
config func(t *testing.T) *config.Config
}{
@ -345,6 +368,7 @@ func TestHelperClusterMapAPI(t *testing.T) {
return conf
},
errContains: "no such file or directory",
helperErr: true,
},
{
name: "Error no cluster map",
@ -361,6 +385,10 @@ func TestHelperClusterMapAPI(t *testing.T) {
tt := test
t.Run(tt.name, func(t *testing.T) {
helper, err := phase.NewHelper(tt.config(t))
if tt.helperErr {
require.Error(t, err)
return
}
require.NoError(t, err)
require.NotNil(t, helper)
@ -421,6 +449,7 @@ func TestHelperExecutorDoc(t *testing.T) {
name string
errContains string
expectedExecutor string
helperErr bool
phaseID ifc.ID
config func(t *testing.T) *config.Config
@ -445,6 +474,7 @@ func TestHelperExecutorDoc(t *testing.T) {
return conf
},
errContains: "no such file or directory",
helperErr: true,
},
{
name: "Error get phase without executor",
@ -460,6 +490,10 @@ func TestHelperExecutorDoc(t *testing.T) {
tt := test
t.Run(tt.name, func(t *testing.T) {
helper, err := phase.NewHelper(tt.config(t))
if tt.helperErr {
require.Error(t, err)
return
}
require.NoError(t, err)
actualDoc, actualErr := helper.ExecutorDoc(tt.phaseID)
@ -533,8 +567,7 @@ func TestHelperWorkdir(t *testing.T) {
helper, err := phase.NewHelper(testConfig(t))
require.NoError(t, err)
require.NotNil(t, helper)
workDir, err := helper.WorkDir()
assert.NoError(t, err)
workDir := helper.WorkDir()
assert.Greater(t, len(workDir), 0)
}

View File

@ -26,7 +26,7 @@ type Helper interface {
TargetPath() string
PhaseRepoDir() string
DocEntryPointPrefix() string
WorkDir() (string, error)
WorkDir() string
Phase(phaseID ID) (*v1alpha1.Phase, error)
Plan(planID ID) (*v1alpha1.PhasePlan, error)
ListPhases(o ListPhaseOptions) ([]*v1alpha1.Phase, error)
@ -37,4 +37,5 @@ type Helper interface {
PhaseBundleRoot() string
Inventory() (ifc.Inventory, error)
PhaseEntryPointBasePath() string
PhaseConfigBundle() document.Bundle
}

View File

@ -104,12 +104,7 @@ func (fo *RenderCommand) RunE(cfgFactory config.Factory, out io.Writer) error {
}
func renderConfigBundle(out io.Writer, h ifc.Helper, sel document.Selector) error {
bundle, err := document.NewBundleByPath(h.PhaseBundleRoot())
if err != nil {
return err
}
bundle, err = bundle.SelectBundle(sel)
bundle, err := h.PhaseConfigBundle().SelectBundle(sel)
if err != nil {
return err
}

View File

@ -0,0 +1,4 @@
inventory:
path: "manifests/site/inventory"
phase:
path: "valid_site/phases"

View File

@ -0,0 +1,10 @@
apiVersion: airshipit.org/v1alpha1
kind: Phase
metadata:
name: capi_init
config:
executorRef:
apiVersion: airshipit.org/v1alpha1
kind: Clusterctl
name: clusterctl-v1
documentEntryPoint: valid_site/phases

View File

@ -0,0 +1,12 @@
apiVersion: airshipit.org/v1alpha1
kind: ClusterMap
metadata:
name: clusterctl-v1
map:
target:
parent: ephemeral
kubeconfigSources:
- type: bundle
ephemeral:
kubeconfigSources:
- type: bundle

View File

@ -0,0 +1,12 @@
apiVersion: airshipit.org/v1alpha1
kind: Clusterctl
metadata:
name: clusterctl-v1
action: init
init-options:
core-provider: "cluster-api:v0.3.3"
providers:
- name: "cluster-api"
type: "CoreProvider"
versions:
v0.3.3: manifests/function/capi/v0.3.3

View File

@ -0,0 +1,10 @@
apiVersion: airshipit.org/v1alpha1
kind: Phase
metadata:
name: kube_apply
config:
executorRef:
apiVersion: airshipit.org/v1alpha1
kind: KubernetesApply
name: kubernetes-apply
documentEntryPoint: valid_site/phases

View File

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

View File

@ -0,0 +1,11 @@
resources:
- phaseplan.yaml
- some_phase.yaml
- some_exc.yaml
- capi_init.yaml
- clusterctl.yaml
- kubernetes_apply.yaml
- cluster_map.yaml
- phase_no_docentrypoint.yaml
- no_executor_phase.yaml
- kubeapply_phase.yaml

View File

@ -0,0 +1,7 @@
apiVersion: airshipit.org/v1alpha1
kind: Phase
metadata:
name: no_executor_phase
config:
documentEntryPoint: valid_site/phases

View File

@ -0,0 +1,9 @@
apiVersion: airshipit.org/v1alpha1
kind: Phase
metadata:
name: no_entry_point
config:
executorRef:
apiVersion: airshipit.org/v1alpha1
kind: SomeExecutor
name: executor-name

View File

@ -0,0 +1,37 @@
apiVersion: airshipit.org/v1alpha1
kind: PhasePlan
metadata:
name: phasePlan
phases:
- 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
---
apiVersion: airshipit.org/v1alpha1
kind: PhasePlan
metadata:
name: plan_invalid_phase
phases:
- name: no_entry_point
---
apiVersion: airshipit.org/v1alpha1
kind: PhasePlan
metadata:
name: phase_not_exist
phases:
- name: non_existent_name

View File

@ -0,0 +1,13 @@
apiVersion: airshipit.org/v1alpha1
kind: SomeExecutor
metadata:
labels:
airshipit.org/deploy-k8s: "false"
name: executor-name
init-options:
core-provider: "cluster-api:v0.3.3"
providers:
- name: "cluster-api"
type: "CoreProvider"
versions:
v0.3.3: manifests/function/capi/v0.3.3

View File

@ -0,0 +1,10 @@
apiVersion: airshipit.org/v1alpha1
kind: Phase
metadata:
name: some_phase
clusterName: some_cluster
config:
executorRef:
apiVersion: airshipit.org/v1alpha1
kind: Does not exist
name: executor-name

View File

@ -0,0 +1,3 @@
phase:
path: "valid_site_with_doc_prefix/phases"
docEntryPointPrefix: "valid_site_with_doc_prefix/phases"

View File

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

View File

@ -0,0 +1,6 @@
apiVersion: airshipit.org/v1alpha1
kind: Phase
metadata:
name: sample
config:
documentEntryPoint: entrypoint