Merge "Add phase tree command in package module"
This commit is contained in:
commit
991fcdcd9e
@ -37,3 +37,6 @@ const (
|
|||||||
ClusterctlMetadataVersion = "v1alpha3"
|
ClusterctlMetadataVersion = "v1alpha3"
|
||||||
ClusterctlMetadataGroup = "clusterctl.cluster.x-k8s.io"
|
ClusterctlMetadataGroup = "clusterctl.cluster.x-k8s.io"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// KustomizationFile is used for kustomization file
|
||||||
|
const KustomizationFile = "kustomization.yaml"
|
||||||
|
4
pkg/document/testdata/no_plan_site/metadata.yaml
vendored
Normal file
4
pkg/document/testdata/no_plan_site/metadata.yaml
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
inventory:
|
||||||
|
path: "manifests/site/inventory"
|
||||||
|
phase:
|
||||||
|
path: "no_plan_site/phases"
|
0
pkg/document/testdata/no_plan_site/phases/kustomization.yaml
vendored
Normal file
0
pkg/document/testdata/no_plan_site/phases/kustomization.yaml
vendored
Normal file
10
pkg/document/testdata/workers-targetphase/hostgenerator/host-generation.yaml
vendored
Normal file
10
pkg/document/testdata/workers-targetphase/hostgenerator/host-generation.yaml
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# Site-level, phase-specific lists of hosts to generate
|
||||||
|
# This is used by the hostgenerator-m3 function to narrow down the site-level
|
||||||
|
# host-catalogue to just the hosts needed for a particular phase.
|
||||||
|
apiVersion: airshipit.org/v1alpha1
|
||||||
|
kind: VariableCatalogue
|
||||||
|
metadata:
|
||||||
|
name: host-generation-catalogue
|
||||||
|
hosts:
|
||||||
|
m3:
|
||||||
|
- node03
|
4
pkg/document/testdata/workers-targetphase/hostgenerator/kustomization.yaml
vendored
Normal file
4
pkg/document/testdata/workers-targetphase/hostgenerator/kustomization.yaml
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- host-generation.yaml
|
6
pkg/document/testdata/workers-targetphase/kustomization.yaml
vendored
Normal file
6
pkg/document/testdata/workers-targetphase/kustomization.yaml
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- nodes
|
||||||
|
generators:
|
||||||
|
- hostgenerator
|
5
pkg/document/testdata/workers-targetphase/nodes/kustomization.yaml
vendored
Normal file
5
pkg/document/testdata/workers-targetphase/nodes/kustomization.yaml
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
commonLabels:
|
||||||
|
airshipit.org/k8s-role: controlplane-host
|
186
pkg/document/tree.go
Normal file
186
pkg/document/tree.go
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
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
|
||||||
|
|
||||||
|
http://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 document
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
|
||||||
|
"opendev.org/airship/airshipctl/pkg/fs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// KustomNode is used to create name and data to display tree structure
|
||||||
|
type KustomNode struct {
|
||||||
|
Name string // name used for display purposes (cli)
|
||||||
|
Data string // this could be a Kustomization object, or a string containing a file path
|
||||||
|
Children []KustomNode
|
||||||
|
Writer io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildKustomTree creates a tree based on entrypoint
|
||||||
|
func BuildKustomTree(entrypoint string, writer io.Writer, manifestsDir string) (KustomNode, error) {
|
||||||
|
fs := fs.NewDocumentFs()
|
||||||
|
name, err := filepath.Rel(manifestsDir, entrypoint)
|
||||||
|
if err != nil {
|
||||||
|
name = entrypoint
|
||||||
|
}
|
||||||
|
root := KustomNode{
|
||||||
|
Name: name,
|
||||||
|
Data: entrypoint,
|
||||||
|
Children: []KustomNode{},
|
||||||
|
Writer: writer,
|
||||||
|
}
|
||||||
|
|
||||||
|
resMap, err := MakeResMap(fs, entrypoint)
|
||||||
|
if err != nil {
|
||||||
|
return KustomNode{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for sourceType, sources := range resMap {
|
||||||
|
n := KustomNode{
|
||||||
|
Name: sourceType,
|
||||||
|
Writer: writer,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range sources {
|
||||||
|
if !fs.IsDir(s) {
|
||||||
|
name, err := filepath.Rel(manifestsDir, s)
|
||||||
|
if err != nil {
|
||||||
|
name = s
|
||||||
|
}
|
||||||
|
n.Children = append(n.Children, KustomNode{
|
||||||
|
Name: name,
|
||||||
|
Data: s,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
s = filepath.Join(s, KustomizationFile)
|
||||||
|
child, err := BuildKustomTree(s, writer, "")
|
||||||
|
if err != nil {
|
||||||
|
return KustomNode{}, err
|
||||||
|
}
|
||||||
|
n.Children = append(n.Children, child)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
root.Children = append(root.Children, n)
|
||||||
|
}
|
||||||
|
return root, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//MakeResMap creates resmap based of kustomize types
|
||||||
|
func MakeResMap(fs fs.FileSystem, kfile string) (map[string][]string, error) {
|
||||||
|
if fs == nil {
|
||||||
|
return nil, fmt.Errorf("received nil filesystem")
|
||||||
|
}
|
||||||
|
bytes, err := fs.ReadFile(kfile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
k := types.Kustomization{}
|
||||||
|
err = k.Unmarshal(bytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
basedir := filepath.Dir(kfile)
|
||||||
|
var resMap = make(map[string][]string)
|
||||||
|
for _, p := range k.Resources {
|
||||||
|
path := filepath.Join(basedir, p)
|
||||||
|
resMap["Resources"] = append(resMap["Resources"], path)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range k.Crds {
|
||||||
|
path := filepath.Join(basedir, p)
|
||||||
|
resMap["Crds"] = append(resMap["Crds"], path)
|
||||||
|
}
|
||||||
|
|
||||||
|
buildConfigMapAndSecretGenerator(k, basedir, resMap)
|
||||||
|
|
||||||
|
for _, p := range k.Generators {
|
||||||
|
path := filepath.Join(basedir, p)
|
||||||
|
resMap["Generators"] = append(resMap["Generators"], path)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range k.Transformers {
|
||||||
|
path := filepath.Join(basedir, p)
|
||||||
|
resMap["Transformers"] = append(resMap["Transformers"], path)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resMap, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildConfigMapAndSecretGenerator(k types.Kustomization, basedir string, resMap map[string][]string) {
|
||||||
|
for _, p := range k.SecretGenerator {
|
||||||
|
for _, s := range p.FileSources {
|
||||||
|
path := filepath.Join(basedir, s)
|
||||||
|
resMap["SecretGenerator"] = append(resMap["SecretGenerator"], path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, p := range k.ConfigMapGenerator {
|
||||||
|
for _, s := range p.FileSources {
|
||||||
|
path := filepath.Join(basedir, s)
|
||||||
|
resMap["ConfigMapGenerator"] = append(resMap["ConfigMapGenerator"], path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrintTree prints tree view of phase
|
||||||
|
func (k KustomNode) PrintTree(prefix string) {
|
||||||
|
if prefix == "" {
|
||||||
|
basedir := filepath.Dir(k.Name)
|
||||||
|
dir := filepath.Base(basedir)
|
||||||
|
fmt.Fprintf(k.Writer, "%s [%s]\n", dir, basedir)
|
||||||
|
}
|
||||||
|
for i, child := range k.Children {
|
||||||
|
var subprefix string
|
||||||
|
knodes := GetKustomChildren(child)
|
||||||
|
if len(knodes) > 0 {
|
||||||
|
// we found a kustomize file, so print the subtree name first
|
||||||
|
if i == len(k.Children)-1 {
|
||||||
|
fmt.Fprintf(k.Writer, "%s└── %s\n", prefix, child.Name)
|
||||||
|
subprefix = " "
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(k.Writer, "%s├── %s\n", prefix, child.Name)
|
||||||
|
subprefix = "│ "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for j, c := range knodes {
|
||||||
|
bd := filepath.Dir(c.Name)
|
||||||
|
d := filepath.Base(bd)
|
||||||
|
name := fmt.Sprintf("%s [%s]", d, bd)
|
||||||
|
|
||||||
|
if j == len(knodes)-1 {
|
||||||
|
fmt.Printf("%s%s└── %s\n", prefix, subprefix, name)
|
||||||
|
c.PrintTree(fmt.Sprintf("%s%s ", prefix, subprefix))
|
||||||
|
} else {
|
||||||
|
fmt.Printf("%s%s├── %s\n", prefix, subprefix, name)
|
||||||
|
c.PrintTree(fmt.Sprintf("%s%s│ ", prefix, subprefix))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetKustomChildren returns children nodes of kustomnode
|
||||||
|
func GetKustomChildren(k KustomNode) []KustomNode {
|
||||||
|
nodes := []KustomNode{}
|
||||||
|
for _, c := range k.Children {
|
||||||
|
if len(c.Children) > 0 {
|
||||||
|
nodes = append(nodes, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nodes
|
||||||
|
}
|
297
pkg/document/tree_test.go
Normal file
297
pkg/document/tree_test.go
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
/*
|
||||||
|
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 document_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"bufio"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"opendev.org/airship/airshipctl/pkg/document"
|
||||||
|
"opendev.org/airship/airshipctl/pkg/fs"
|
||||||
|
)
|
||||||
|
|
||||||
|
func KustomNodeTestdata(writer io.Writer) document.KustomNode {
|
||||||
|
return document.KustomNode{
|
||||||
|
Name: "workers-targetphase/kustomization.yaml",
|
||||||
|
Data: "testdata/workers-targetphase/kustomization.yaml",
|
||||||
|
Children: []document.KustomNode{
|
||||||
|
{
|
||||||
|
Name: "Resources",
|
||||||
|
Data: "",
|
||||||
|
Children: []document.KustomNode{
|
||||||
|
{
|
||||||
|
Name: "workers-targetphase/nodes/kustomization.yaml",
|
||||||
|
Data: "testdata/workers-targetphase/nodes/kustomization.yaml",
|
||||||
|
Children: []document.KustomNode{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Writer: writer,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Generators",
|
||||||
|
Data: "",
|
||||||
|
Children: []document.KustomNode{
|
||||||
|
{
|
||||||
|
Name: "workers-targetphase/hostgenerator/kustomization.yaml",
|
||||||
|
Data: "testdata/workers-targetphase/hostgenerator/kustomization.yaml",
|
||||||
|
Children: []document.KustomNode{{
|
||||||
|
Name: "Resources",
|
||||||
|
Data: "",
|
||||||
|
Children: []document.KustomNode{{
|
||||||
|
Name: "workers-targetphase/hostgenerator/host-generation.yaml",
|
||||||
|
Data: "testdata/workers-targetphase/hostgenerator/host-generation.yaml",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Writer: writer,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Writer: writer,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Writer: writer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildKustomTree(t *testing.T) {
|
||||||
|
var b bytes.Buffer
|
||||||
|
w := bufio.NewWriter(&b)
|
||||||
|
type args struct {
|
||||||
|
entrypoint string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args func(t *testing.T) args
|
||||||
|
want1 document.KustomNode
|
||||||
|
errContains string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "success build tree",
|
||||||
|
args: func(t *testing.T) args {
|
||||||
|
return args{entrypoint: "testdata/workers-targetphase/kustomization.yaml"}
|
||||||
|
},
|
||||||
|
want1: KustomNodeTestdata(w),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "entrypoint doesn't exist",
|
||||||
|
args: func(t *testing.T) args {
|
||||||
|
return args{entrypoint: "tdata/kustomization.yaml"}
|
||||||
|
},
|
||||||
|
want1: KustomNodeTestdata(w),
|
||||||
|
errContains: "no such file or directory",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
tArgs := tt.args(t)
|
||||||
|
manifestsDir := "testdata"
|
||||||
|
got1, actualErr := document.BuildKustomTree(tArgs.entrypoint, w, manifestsDir)
|
||||||
|
if tt.errContains != "" {
|
||||||
|
require.Error(t, actualErr)
|
||||||
|
assert.Contains(t, actualErr.Error(), tt.errContains)
|
||||||
|
} else {
|
||||||
|
require.NoError(t, actualErr)
|
||||||
|
assert.Equal(t, got1.Name, tt.want1.Name)
|
||||||
|
assert.Equal(t, len(got1.Children), len(tt.want1.Children))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_makeResMap(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
kfile string
|
||||||
|
fs fs.FileSystem
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args func(t *testing.T) args
|
||||||
|
|
||||||
|
want1 map[string][]string
|
||||||
|
errContains string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
args: func(t *testing.T) args {
|
||||||
|
return args{kfile: "testdata/workers-targetphase/kustomization.yaml", fs: fs.NewDocumentFs()}
|
||||||
|
},
|
||||||
|
name: "success resmap",
|
||||||
|
want1: map[string][]string{
|
||||||
|
"Generators": {
|
||||||
|
"testdata/workers-targetphase/hostgenerator",
|
||||||
|
},
|
||||||
|
"Resources": {
|
||||||
|
"testdata/workers-targetphase/nodes",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
args: func(t *testing.T) args {
|
||||||
|
return args{kfile: "testdata/no_plan_site/phases/kustomization.yaml"}
|
||||||
|
},
|
||||||
|
name: "nil case",
|
||||||
|
want1: map[string][]string{},
|
||||||
|
errContains: "received nil filesystem",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
args: func(t *testing.T) args {
|
||||||
|
return args{kfile: "t/workers-targetphase/kustomization.yaml", fs: fs.NewDocumentFs()}
|
||||||
|
},
|
||||||
|
name: "fail resmap,entrypoint not found",
|
||||||
|
want1: map[string][]string{
|
||||||
|
"Resources": {
|
||||||
|
"testdata/workers-targetphase/nodes",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
errContains: "no such file or directory",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
tArgs := tt.args(t)
|
||||||
|
|
||||||
|
got1, actualErr := document.MakeResMap(tArgs.fs, tArgs.kfile)
|
||||||
|
if tt.errContains != "" {
|
||||||
|
require.Error(t, actualErr)
|
||||||
|
assert.Contains(t, actualErr.Error(), tt.errContains)
|
||||||
|
} else {
|
||||||
|
require.NoError(t, actualErr)
|
||||||
|
assert.Equal(t, got1, tt.want1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKustomNode_PrintTree(t *testing.T) {
|
||||||
|
var b bytes.Buffer
|
||||||
|
writer := bufio.NewWriter(&b)
|
||||||
|
type args struct {
|
||||||
|
prefix string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
init func(t *testing.T) document.KustomNode
|
||||||
|
want string
|
||||||
|
|
||||||
|
args func(t *testing.T) args
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "valid print tree",
|
||||||
|
args: func(t *testing.T) args {
|
||||||
|
return args{prefix: ""}
|
||||||
|
},
|
||||||
|
init: func(t *testing.T) document.KustomNode {
|
||||||
|
return KustomNodeTestdata(writer)
|
||||||
|
},
|
||||||
|
want: " └── hostgenerator [workers-targetphase/hostgenerator]\n",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
rescueStdout := os.Stdout
|
||||||
|
r, w, err := os.Pipe()
|
||||||
|
if err != nil {
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
os.Stdout = w
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
tArgs := tt.args(t)
|
||||||
|
|
||||||
|
receiver := tt.init(t)
|
||||||
|
receiver.PrintTree(tArgs.prefix)
|
||||||
|
w.Close()
|
||||||
|
out, err := ioutil.ReadAll(r)
|
||||||
|
if err != nil {
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
os.Stdout = rescueStdout
|
||||||
|
assert.Equal(t, string(out), tt.want)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_getKustomChildren(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
k document.KustomNode
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args func(t *testing.T) args
|
||||||
|
|
||||||
|
want1 []document.KustomNode
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "success getkustomchildren",
|
||||||
|
args: func(t *testing.T) args {
|
||||||
|
return args{k: document.KustomNode{
|
||||||
|
Name: "Generators",
|
||||||
|
Data: "",
|
||||||
|
Children: []document.KustomNode{
|
||||||
|
{
|
||||||
|
Name: "workers-targetphase/hostgenerator/kustomization.yaml",
|
||||||
|
Data: "testdata/workers-targetphase/hostgenerator/kustomization.yaml",
|
||||||
|
Children: []document.KustomNode{{
|
||||||
|
Name: "workers-targetphase/hostgenerator/host-generation.yaml",
|
||||||
|
Data: "testdata/workers-targetphase/hostgenerator/host-generation.yaml",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
want1: []document.KustomNode{
|
||||||
|
{
|
||||||
|
Name: "workers-targetphase/hostgenerator/kustomization.yaml",
|
||||||
|
Data: "testdata/workers-targetphase/hostgenerator/kustomization.yaml",
|
||||||
|
Children: []document.KustomNode{{
|
||||||
|
Name: "workers-targetphase/hostgenerator/host-generation.yaml",
|
||||||
|
Data: "testdata/workers-targetphase/hostgenerator/host-generation.yaml",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no children nodes",
|
||||||
|
args: func(t *testing.T) args {
|
||||||
|
return args{k: document.KustomNode{
|
||||||
|
Name: "Transformers",
|
||||||
|
Data: "",
|
||||||
|
}}
|
||||||
|
},
|
||||||
|
want1: []document.KustomNode{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
tArgs := tt.args(t)
|
||||||
|
|
||||||
|
got1 := document.GetKustomChildren(tArgs.k)
|
||||||
|
assert.Equal(t, got1, tt.want1)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -16,9 +16,13 @@ package phase
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"opendev.org/airship/airshipctl/pkg/config"
|
"opendev.org/airship/airshipctl/pkg/config"
|
||||||
|
"opendev.org/airship/airshipctl/pkg/document"
|
||||||
"opendev.org/airship/airshipctl/pkg/phase/ifc"
|
"opendev.org/airship/airshipctl/pkg/phase/ifc"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -84,3 +88,54 @@ func (c *PlanCommand) RunE() error {
|
|||||||
|
|
||||||
return PrintPlan(plan, c.Writer)
|
return PrintPlan(plan, c.Writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TreeCommand plan command
|
||||||
|
type TreeCommand struct {
|
||||||
|
Factory config.Factory
|
||||||
|
PhaseID ifc.ID
|
||||||
|
Writer io.Writer
|
||||||
|
Argument string
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunE runs the phase tree command
|
||||||
|
func (c *TreeCommand) RunE() error {
|
||||||
|
var entrypoint string
|
||||||
|
cfg, err := c.Factory()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
helper, err := NewHelper(cfg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client := NewClient(helper)
|
||||||
|
var manifestsDir string
|
||||||
|
// check if its a relative path
|
||||||
|
if _, err = os.Stat(c.Argument); err == nil {
|
||||||
|
// capture manifests directory from phase relative path
|
||||||
|
manifestsDir = strings.SplitAfter(c.Argument, "/manifests")[0]
|
||||||
|
entrypoint = filepath.Join(c.Argument, document.KustomizationFile)
|
||||||
|
} else {
|
||||||
|
c.PhaseID.Name = c.Argument
|
||||||
|
manifestsDir = filepath.Join(helper.TargetPath(), helper.PhaseRepoDir())
|
||||||
|
var phase ifc.Phase
|
||||||
|
phase, err = client.PhaseByID(c.PhaseID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var rootPath string
|
||||||
|
rootPath, err = phase.DocumentRoot()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
entrypoint = filepath.Join(rootPath, document.KustomizationFile)
|
||||||
|
}
|
||||||
|
t, err := document.BuildKustomTree(entrypoint, c.Writer, manifestsDir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
t.PrintTree("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -169,3 +169,70 @@ func TestPlanCommand(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTreeCommand(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
errContains string
|
||||||
|
factory config.Factory
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Error config factory",
|
||||||
|
factory: func() (*config.Config, error) {
|
||||||
|
return nil, fmt.Errorf(testFactoryErr)
|
||||||
|
},
|
||||||
|
errContains: testFactoryErr,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Error new helper",
|
||||||
|
factory: func() (*config.Config, error) {
|
||||||
|
return &config.Config{
|
||||||
|
CurrentContext: "does not exist",
|
||||||
|
Contexts: make(map[string]*config.Context),
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
|
errContains: testNewHelperErr,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Error phase by id",
|
||||||
|
factory: func() (*config.Config, error) {
|
||||||
|
conf := config.NewConfig()
|
||||||
|
conf.Manifests = map[string]*config.Manifest{
|
||||||
|
"manifest": {
|
||||||
|
MetadataPath: "broken_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
|
||||||
|
},
|
||||||
|
errContains: testNoBundlePath,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
tt := tt
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
command := phase.TreeCommand{
|
||||||
|
Factory: tt.factory,
|
||||||
|
}
|
||||||
|
err := command.RunE()
|
||||||
|
if tt.errContains != "" {
|
||||||
|
require.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), tt.errContains)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user