add tree builder
This commit is contained in:
parent
c7739649af
commit
d19bd04960
|
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
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 tree
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
manifest "k8s.io/kubectl/pkg/apis/manifest/v1alpha1"
|
||||
"k8s.io/kubectl/pkg/kinflate/adjustpath"
|
||||
cutil "k8s.io/kubectl/pkg/kinflate/configmapandsecret"
|
||||
"k8s.io/kubectl/pkg/kinflate/constants"
|
||||
"k8s.io/kubectl/pkg/kinflate/gvkn"
|
||||
"k8s.io/kubectl/pkg/kinflate/mergemap"
|
||||
kutil "k8s.io/kubectl/pkg/kinflate/util"
|
||||
)
|
||||
|
||||
// BuildManifestTree takes a path to a Kube-manifest.yaml or a dir that has a Kube-manifest.yaml.
|
||||
// It returns a tree of ManifestNode.
|
||||
func BuildManifestTree(path string) (*ManifestNode, error) {
|
||||
return manifestPathToManifestNode(path)
|
||||
}
|
||||
|
||||
func manifestPathToManifestNode(path string) (*ManifestNode, error) {
|
||||
path, err := validateManifestPath(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m, err := manifestPathToManifest(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return manifestToManifestNode(m)
|
||||
}
|
||||
|
||||
func manifestToManifestNode(m *manifest.Manifest) (*ManifestNode, error) {
|
||||
mnode := &ManifestNode{}
|
||||
var err error
|
||||
mnode.Data, err = manifestToManifestData(m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mnode.Children = []*ManifestNode{}
|
||||
for _, pkg := range m.Packages {
|
||||
child, err := manifestPathToManifestNode(pkg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mnode.Children = append(mnode.Children, child)
|
||||
}
|
||||
return mnode, nil
|
||||
}
|
||||
|
||||
// manifestPathToManifest loads a manifest file and parse it in to the Manifest object.
|
||||
func manifestPathToManifest(filename string) (*manifest.Manifest, error) {
|
||||
bytes, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var m manifest.Manifest
|
||||
// TODO: support json
|
||||
err = yaml.Unmarshal(bytes, &m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dir, _ := path.Split(filename)
|
||||
adjustpath.AdjustPathsForManifest(&m, []string{dir})
|
||||
return &m, err
|
||||
}
|
||||
|
||||
// validateManifestPath loads the manifest from the given path.
|
||||
// It returns ManifestData and an potential error.
|
||||
func validateManifestPath(mPath string) (string, error) {
|
||||
f, err := os.Stat(mPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if f.IsDir() {
|
||||
mPath = path.Join(mPath, constants.KubeManifestFileName)
|
||||
_, err = os.Stat(mPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
if !strings.HasSuffix(mPath, constants.KubeManifestFileName) {
|
||||
return "", fmt.Errorf("expecting file: %q, but got: %q", constants.KubeManifestFileName, mPath)
|
||||
}
|
||||
}
|
||||
return mPath, nil
|
||||
}
|
||||
|
||||
func manifestToManifestData(m *manifest.Manifest) (*ManifestData, error) {
|
||||
mdata := &ManifestData{}
|
||||
var err error
|
||||
mdata.Name = m.Name
|
||||
mdata.NamePrefix = NamePrefixType(m.NamePrefix)
|
||||
mdata.ObjectLabels = m.ObjectLabels
|
||||
mdata.ObjectAnnotations = m.ObjectAnnotations
|
||||
mdata.Resources, err = pathsToMap(m.Resources)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mdata.Patches, err = pathsToMap(m.Patches)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mdata.Configmaps, err = cutil.MakeMapOfConfigMap(m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mdata.Secrets, err = cutil.MakeMapOfGenericSecret(m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
TLSSecrets, err := cutil.MakeMapOfTLSSecret(m)
|
||||
err = mergemap.Merge(mdata.Secrets, TLSSecrets)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mdata, nil
|
||||
}
|
||||
|
||||
func pathsToMap(paths []string) (map[gvkn.GroupVersionKindName]*unstructured.Unstructured, error) {
|
||||
res := map[gvkn.GroupVersionKindName]*unstructured.Unstructured{}
|
||||
for _, path := range paths {
|
||||
err := pathToMap(path, res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func pathToMap(path string, into map[gvkn.GroupVersionKindName]*unstructured.Unstructured) error {
|
||||
_, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if into == nil {
|
||||
into = map[gvkn.GroupVersionKindName]*unstructured.Unstructured{}
|
||||
}
|
||||
|
||||
var e error
|
||||
filepath.Walk(path, func(filepath string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
e = err
|
||||
return err
|
||||
}
|
||||
// Skip all the dir
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
err = fileToMap(filepath, into)
|
||||
return nil
|
||||
})
|
||||
return e
|
||||
}
|
||||
|
||||
func fileToMap(filename string, into map[gvkn.GroupVersionKindName]*unstructured.Unstructured) error {
|
||||
f, err := os.Stat(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if f.IsDir() {
|
||||
return fmt.Errorf("%q is NOT expected to be an dir", filename)
|
||||
}
|
||||
content, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = kutil.Decode(content, into)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,394 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
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 tree
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
manifest "k8s.io/kubectl/pkg/apis/manifest/v1alpha1"
|
||||
"k8s.io/kubectl/pkg/kinflate/gvkn"
|
||||
"k8s.io/kubectl/pkg/kinflate/mergemap"
|
||||
)
|
||||
|
||||
func makeMapOfConfigMap() map[gvkn.GroupVersionKindName]*unstructured.Unstructured {
|
||||
return map[gvkn.GroupVersionKindName]*unstructured.Unstructured{
|
||||
{
|
||||
GVK: schema.GroupVersionKind{Version: "v1", Kind: "ConfigMap"},
|
||||
Name: "cm1",
|
||||
}: {
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "v1",
|
||||
"kind": "ConfigMap",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "cm1",
|
||||
},
|
||||
"data": map[string]interface{}{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func makeMapOfPod() map[gvkn.GroupVersionKindName]*unstructured.Unstructured {
|
||||
return makeMapOfPodWithImageName("nginx")
|
||||
}
|
||||
|
||||
func makeMapOfPodWithImageName(imageName string) map[gvkn.GroupVersionKindName]*unstructured.Unstructured {
|
||||
return map[gvkn.GroupVersionKindName]*unstructured.Unstructured{
|
||||
{
|
||||
GVK: schema.GroupVersionKind{Version: "v1", Kind: "Pod"},
|
||||
Name: "pod1",
|
||||
}: {
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "pod1",
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"containers": []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "nginx",
|
||||
"image": imageName,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func makeManifestData(name string) *ManifestData {
|
||||
return &ManifestData{
|
||||
Name: name,
|
||||
Resources: map[gvkn.GroupVersionKindName]*unstructured.Unstructured{},
|
||||
Patches: map[gvkn.GroupVersionKindName]*unstructured.Unstructured{},
|
||||
Configmaps: map[gvkn.GroupVersionKindName]*unstructured.Unstructured{},
|
||||
Secrets: map[gvkn.GroupVersionKindName]*unstructured.Unstructured{},
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateManifestPath(t *testing.T) {
|
||||
type testcase struct {
|
||||
filename string
|
||||
expectErr bool
|
||||
errorStr string
|
||||
}
|
||||
|
||||
testcases := []testcase{
|
||||
{
|
||||
filename: "testdata/valid/",
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
filename: "testdata/valid/Kube-manifest.yaml",
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
filename: "does-not-exist",
|
||||
expectErr: true,
|
||||
errorStr: "no such file or directory",
|
||||
},
|
||||
{
|
||||
filename: "testdata/invalid/",
|
||||
expectErr: true,
|
||||
errorStr: "no such file or directory",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
_, err := validateManifestPath(tc.filename)
|
||||
if err == nil {
|
||||
if tc.expectErr {
|
||||
t.Errorf("filename: %q, expect an error containing %q, but didn't get an error", tc.filename, tc.errorStr)
|
||||
}
|
||||
} else {
|
||||
if tc.expectErr {
|
||||
if !strings.Contains(err.Error(), tc.errorStr) {
|
||||
t.Errorf("filename: %q, expect an error containing %q, but got %v", tc.filename, tc.errorStr, err)
|
||||
}
|
||||
} else {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileToMap(t *testing.T) {
|
||||
type testcase struct {
|
||||
filename string
|
||||
expected map[gvkn.GroupVersionKindName]*unstructured.Unstructured
|
||||
expectErr bool
|
||||
errorStr string
|
||||
}
|
||||
|
||||
testcases := []testcase{
|
||||
{
|
||||
filename: "testdata/valid/cm/configmap.yaml",
|
||||
expected: map[gvkn.GroupVersionKindName]*unstructured.Unstructured{
|
||||
{
|
||||
GVK: schema.GroupVersionKind{Version: "v1", Kind: "ConfigMap"},
|
||||
Name: "cm1",
|
||||
}: {
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "v1",
|
||||
"kind": "ConfigMap",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "cm1",
|
||||
},
|
||||
"data": map[string]interface{}{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
filename: "testdata/valid/cm/",
|
||||
expectErr: true,
|
||||
errorStr: "NOT expected to be an dir",
|
||||
},
|
||||
{
|
||||
filename: "does-not-exist",
|
||||
expectErr: true,
|
||||
errorStr: "no such file or directory",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
actual := map[gvkn.GroupVersionKindName]*unstructured.Unstructured{}
|
||||
err := fileToMap(tc.filename, actual)
|
||||
if err == nil {
|
||||
if tc.expectErr {
|
||||
t.Errorf("filename: %q, expect an error containing %q, but didn't get an error", tc.filename, tc.errorStr)
|
||||
}
|
||||
if !reflect.DeepEqual(actual, tc.expected) {
|
||||
t.Errorf("filename: %q, expect %v, but got %v", tc.filename, tc.expected, actual)
|
||||
}
|
||||
} else {
|
||||
if tc.expectErr {
|
||||
if !strings.Contains(err.Error(), tc.errorStr) {
|
||||
t.Errorf("filename: %q, expect an error containing %q, but got %v", tc.filename, tc.errorStr, err)
|
||||
}
|
||||
} else {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPathToMap(t *testing.T) {
|
||||
type testcase struct {
|
||||
filename string
|
||||
expected map[gvkn.GroupVersionKindName]*unstructured.Unstructured
|
||||
expectErr bool
|
||||
errorStr string
|
||||
}
|
||||
|
||||
expectedMap := makeMapOfConfigMap()
|
||||
|
||||
testcases := []testcase{
|
||||
{
|
||||
filename: "testdata/valid/cm/configmap.yaml",
|
||||
expected: expectedMap,
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
filename: "testdata/valid/cm/",
|
||||
expected: expectedMap,
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
filename: "does-not-exist",
|
||||
expectErr: true,
|
||||
errorStr: "no such file or directory",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
actual := map[gvkn.GroupVersionKindName]*unstructured.Unstructured{}
|
||||
err := pathToMap(tc.filename, actual)
|
||||
if err == nil {
|
||||
if tc.expectErr {
|
||||
t.Errorf("filename: %q, expect an error containing %q, but didn't get an error", tc.filename, tc.errorStr)
|
||||
}
|
||||
if !reflect.DeepEqual(actual, tc.expected) {
|
||||
t.Errorf("filename: %q, expect %v, but got %v", tc.filename, tc.expected, actual)
|
||||
}
|
||||
} else {
|
||||
if tc.expectErr {
|
||||
if !strings.Contains(err.Error(), tc.errorStr) {
|
||||
t.Errorf("filename: %q, expect an error containing %q, but got %v", tc.filename, tc.errorStr, err)
|
||||
}
|
||||
} else {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPathsToMap(t *testing.T) {
|
||||
type testcase struct {
|
||||
filenames []string
|
||||
expected map[gvkn.GroupVersionKindName]*unstructured.Unstructured
|
||||
expectErr bool
|
||||
errorStr string
|
||||
}
|
||||
|
||||
mapOfConfigMap := makeMapOfConfigMap()
|
||||
mapOfPod := makeMapOfPod()
|
||||
err := mergemap.Merge(mapOfPod, mapOfConfigMap)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
mergedMap := mapOfPod
|
||||
|
||||
testcases := []testcase{
|
||||
{
|
||||
filenames: []string{"testdata/valid/cm/"},
|
||||
expected: mapOfConfigMap,
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
filenames: []string{"testdata/valid/pod.yaml"},
|
||||
expected: makeMapOfPod(),
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
filenames: []string{"testdata/valid/cm/", "testdata/valid/pod.yaml"},
|
||||
expected: mergedMap,
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
filenames: []string{"does-not-exist"},
|
||||
expectErr: true,
|
||||
errorStr: "no such file or directory",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
actual, err := pathsToMap(tc.filenames)
|
||||
if err == nil {
|
||||
if tc.expectErr {
|
||||
t.Errorf("filenames: %q, expect an error containing %q, but didn't get an error", tc.filenames, tc.errorStr)
|
||||
}
|
||||
if !reflect.DeepEqual(actual, tc.expected) {
|
||||
t.Errorf("filenames: %q, expect %v, but got %v", tc.filenames, tc.expected, actual)
|
||||
}
|
||||
} else {
|
||||
if tc.expectErr {
|
||||
if !strings.Contains(err.Error(), tc.errorStr) {
|
||||
t.Errorf("filenames: %q, expect an error containing %q, but got %v", tc.filenames, tc.errorStr, err)
|
||||
}
|
||||
} else {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestManifestToManifestData(t *testing.T) {
|
||||
mapOfConfigMap := makeMapOfConfigMap()
|
||||
mapOfPod := makeMapOfPod()
|
||||
err := mergemap.Merge(mapOfPod, mapOfConfigMap)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
mergedMap := mapOfPod
|
||||
|
||||
m := &manifest.Manifest{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-manifest",
|
||||
},
|
||||
NamePrefix: "someprefix-",
|
||||
ObjectLabels: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
ObjectAnnotations: map[string]string{
|
||||
"note": "This is an annotation.",
|
||||
},
|
||||
Resources: []string{
|
||||
"testdata/valid/cm/",
|
||||
"testdata/valid/pod.yaml",
|
||||
},
|
||||
Patches: []string{
|
||||
"testdata/valid/patch.yaml",
|
||||
},
|
||||
}
|
||||
|
||||
expectedMd := &ManifestData{
|
||||
Name: "test-manifest",
|
||||
NamePrefix: "someprefix-",
|
||||
ObjectLabels: map[string]string{"foo": "bar"},
|
||||
ObjectAnnotations: map[string]string{"note": "This is an annotation."},
|
||||
Resources: mergedMap,
|
||||
Patches: makeMapOfPodWithImageName("nginx:latest"),
|
||||
Configmaps: map[gvkn.GroupVersionKindName]*unstructured.Unstructured{},
|
||||
Secrets: map[gvkn.GroupVersionKindName]*unstructured.Unstructured{},
|
||||
}
|
||||
|
||||
actual, err := manifestToManifestData(m)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(actual, expectedMd) {
|
||||
t.Errorf("expect:\n%#v\nbut got:\n%#v", expectedMd, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestManifestPathToManifestNode(t *testing.T) {
|
||||
expected := &ManifestNode{
|
||||
Data: makeManifestData("grandparent"),
|
||||
Children: []*ManifestNode{
|
||||
{
|
||||
Data: makeManifestData("parent1"),
|
||||
Children: []*ManifestNode{
|
||||
{
|
||||
Data: makeManifestData("child1"),
|
||||
Children: []*ManifestNode{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Data: makeManifestData("parent2"),
|
||||
Children: []*ManifestNode{
|
||||
{
|
||||
Data: makeManifestData("child2"),
|
||||
Children: []*ManifestNode{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
actual, err := manifestPathToManifestNode("testdata/hierarchy")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Fatalf("expect:\n%#v\nbut got:\n%#v", expected, actual)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
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 tree
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/kubectl/pkg/kinflate/gvkn"
|
||||
)
|
||||
|
||||
type NamePrefixType string
|
||||
|
||||
type ObjectLabelsType map[string]string
|
||||
|
||||
type ObjectAnnotationsType map[string]string
|
||||
|
||||
type ResourcesType map[gvkn.GroupVersionKindName]*unstructured.Unstructured
|
||||
|
||||
type PatchesType map[gvkn.GroupVersionKindName]*unstructured.Unstructured
|
||||
|
||||
type ConfigmapsType map[gvkn.GroupVersionKindName]*unstructured.Unstructured
|
||||
|
||||
type SecretsType map[gvkn.GroupVersionKindName]*unstructured.Unstructured
|
||||
|
||||
// ManifestNode is the node for building the manifest tree.
|
||||
// Children points to the packages defined on this node's Manifest.
|
||||
type ManifestNode struct {
|
||||
Data *ManifestData
|
||||
Children []*ManifestNode
|
||||
}
|
||||
|
||||
// ManifestData contains all the objects loaded from the filesystem according to
|
||||
// the Manifest Object.
|
||||
type ManifestData struct {
|
||||
Name string
|
||||
NamePrefix NamePrefixType
|
||||
ObjectLabels ObjectLabelsType
|
||||
ObjectAnnotations ObjectAnnotationsType
|
||||
Resources ResourcesType
|
||||
Patches PatchesType
|
||||
Configmaps ConfigmapsType
|
||||
Secrets SecretsType
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
apiVersion: manifest.k8s.io/v1alpha1
|
||||
kind: Manifest
|
||||
metadata:
|
||||
name: grandparent
|
||||
packages:
|
||||
- parent1/
|
||||
- parent2/
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
apiVersion: manifest.k8s.io/v1alpha1
|
||||
kind: Manifest
|
||||
metadata:
|
||||
name: parent1
|
||||
packages:
|
||||
- child1/
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
apiVersion: manifest.k8s.io/v1alpha1
|
||||
kind: Manifest
|
||||
metadata:
|
||||
name: child1
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
apiVersion: manifest.k8s.io/v1alpha1
|
||||
kind: Manifest
|
||||
metadata:
|
||||
name: parent2
|
||||
packages:
|
||||
- child2/
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
apiVersion: manifest.k8s.io/v1alpha1
|
||||
kind: Manifest
|
||||
metadata:
|
||||
name: child2
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
apiVersion: manifest.k8s.io/v1alpha1
|
||||
kind: Manifest
|
||||
metadata:
|
||||
name: valid-app
|
||||
namePrefix: someprefix-
|
||||
objectLabels:
|
||||
foo: bar
|
||||
objectAnnotations:
|
||||
baseAnno: This is an annotation.
|
||||
resources:
|
||||
- deployment.yaml
|
||||
- cm/configmap.yaml
|
||||
patches:
|
||||
- patch.yaml
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
apiVersion: v1
|
||||
data:
|
||||
foo: bar
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm1
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: pod1
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:latest
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: pod1
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx
|
||||
Loading…
Reference in New Issue