mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 03:41:45 +00:00
Merge pull request #81910 from fabriziopandini/kubeadm-Json6902-Patches
kubeadm: add support for Json6902 Patches
This commit is contained in:
commit
b98f622852
@ -3,21 +3,25 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
|||||||
go_library(
|
go_library(
|
||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
srcs = [
|
srcs = [
|
||||||
|
"json6902.go",
|
||||||
"kustomize.go",
|
"kustomize.go",
|
||||||
"unstructured.go",
|
"strategicmerge.go",
|
||||||
],
|
],
|
||||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/util/kustomize",
|
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/util/kustomize",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
|
||||||
"//staging/src/k8s.io/cli-runtime/pkg/kustomize:go_default_library",
|
"//staging/src/k8s.io/cli-runtime/pkg/kustomize:go_default_library",
|
||||||
"//vendor/github.com/pkg/errors:go_default_library",
|
"//vendor/github.com/pkg/errors:go_default_library",
|
||||||
|
"//vendor/sigs.k8s.io/kustomize/pkg/constants:go_default_library",
|
||||||
"//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library",
|
"//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library",
|
||||||
"//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library",
|
"//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library",
|
||||||
"//vendor/sigs.k8s.io/kustomize/pkg/loader:go_default_library",
|
"//vendor/sigs.k8s.io/kustomize/pkg/loader:go_default_library",
|
||||||
|
"//vendor/sigs.k8s.io/kustomize/pkg/patch:go_default_library",
|
||||||
|
"//vendor/sigs.k8s.io/kustomize/pkg/types:go_default_library",
|
||||||
|
"//vendor/sigs.k8s.io/yaml:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -39,10 +43,11 @@ go_test(
|
|||||||
name = "go_default_test",
|
name = "go_default_test",
|
||||||
srcs = [
|
srcs = [
|
||||||
"kustomize_test.go",
|
"kustomize_test.go",
|
||||||
"unstructured_test.go",
|
"strategicmerge_test.go",
|
||||||
],
|
],
|
||||||
embed = [":go_default_library"],
|
embed = [":go_default_library"],
|
||||||
deps = [
|
deps = [
|
||||||
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||||
"//vendor/github.com/lithammer/dedent:go_default_library",
|
"//vendor/github.com/lithammer/dedent:go_default_library",
|
||||||
],
|
],
|
||||||
|
64
cmd/kubeadm/app/util/kustomize/json6902.go
Normal file
64
cmd/kubeadm/app/util/kustomize/json6902.go
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2019 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 kustomize contains helpers for working with embedded kustomize commands
|
||||||
|
package kustomize
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
|
"sigs.k8s.io/kustomize/pkg/ifc"
|
||||||
|
"sigs.k8s.io/kustomize/pkg/patch"
|
||||||
|
)
|
||||||
|
|
||||||
|
// json6902 represents a json6902 patch
|
||||||
|
type json6902 struct {
|
||||||
|
// Target refers to a Kubernetes object that the json patch will be applied to
|
||||||
|
*patch.Target
|
||||||
|
|
||||||
|
// Patch contain the json patch as a string
|
||||||
|
Patch string
|
||||||
|
}
|
||||||
|
|
||||||
|
// json6902Slice is a slice of json6902 patches.
|
||||||
|
type json6902Slice []*json6902
|
||||||
|
|
||||||
|
// newJSON6902FromFile returns a json6902 patch from a file
|
||||||
|
func newJSON6902FromFile(f patch.Json6902, ldr ifc.Loader, file string) (*json6902, error) {
|
||||||
|
patch, err := ldr.Load(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &json6902{
|
||||||
|
Target: f.Target,
|
||||||
|
Patch: string(patch),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// filterByResource returns all the json6902 patches in the json6902Slice corresponding to a given resource
|
||||||
|
func (s *json6902Slice) filterByResource(r *unstructured.Unstructured) json6902Slice {
|
||||||
|
var result json6902Slice
|
||||||
|
for _, p := range *s {
|
||||||
|
if p.Group == r.GroupVersionKind().Group &&
|
||||||
|
p.Version == r.GroupVersionKind().Version &&
|
||||||
|
p.Kind == r.GroupVersionKind().Kind &&
|
||||||
|
p.Namespace == r.GetNamespace() &&
|
||||||
|
p.Name == r.GetName() {
|
||||||
|
result = append(result, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
@ -25,15 +25,25 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
|
yamlutil "k8s.io/apimachinery/pkg/util/yaml"
|
||||||
"k8s.io/cli-runtime/pkg/kustomize"
|
"k8s.io/cli-runtime/pkg/kustomize"
|
||||||
|
"sigs.k8s.io/kustomize/pkg/constants"
|
||||||
"sigs.k8s.io/kustomize/pkg/fs"
|
"sigs.k8s.io/kustomize/pkg/fs"
|
||||||
|
"sigs.k8s.io/kustomize/pkg/ifc"
|
||||||
"sigs.k8s.io/kustomize/pkg/loader"
|
"sigs.k8s.io/kustomize/pkg/loader"
|
||||||
|
"sigs.k8s.io/kustomize/pkg/patch"
|
||||||
|
"sigs.k8s.io/kustomize/pkg/types"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Manager define a manager that allow access to kustomize capabilities
|
// Manager define a manager that allow access to kustomize capabilities
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
kustomizeDir string
|
kustomizeDir string
|
||||||
us UnstructuredSlice
|
kustomizationFile *types.Kustomization
|
||||||
|
strategicMergePatches strategicMergeSlice
|
||||||
|
json6902Patches json6902Slice
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -42,6 +52,8 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// GetManager return the KustomizeManager singleton instance
|
// GetManager return the KustomizeManager singleton instance
|
||||||
|
// NB. this is done at singleton instance level because kubeadm has a unique pool
|
||||||
|
// of patches that are applied to different content, at different time
|
||||||
func GetManager(kustomizeDir string) (*Manager, error) {
|
func GetManager(kustomizeDir string) (*Manager, error) {
|
||||||
lock.Lock()
|
lock.Lock()
|
||||||
defer lock.Unlock()
|
defer lock.Unlock()
|
||||||
@ -52,12 +64,31 @@ func GetManager(kustomizeDir string) (*Manager, error) {
|
|||||||
kustomizeDir: kustomizeDir,
|
kustomizeDir: kustomizeDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
// loads the UnstructuredSlice with all the patches into the Manager
|
// Create a loader that mimics the behavior of kubectl kustomize, including support for reading from
|
||||||
// NB. this is done at singleton instance level because kubeadm has a unique pool
|
// a local folder or git repository like git@github.com:someOrg/someRepo.git or https://github.com/someOrg/someRepo?ref=someHash
|
||||||
// of patches that are applied to different content, at different time
|
// in order to do so you must use ldr.Root() instead of km.kustomizeDir and ldr.Load instead of other ways to read files
|
||||||
if err := km.getUnstructuredSlice(); err != nil {
|
fSys := fs.MakeRealFS()
|
||||||
|
ldr, err := loader.NewLoader(km.kustomizeDir, fSys)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
defer ldr.Cleanup()
|
||||||
|
|
||||||
|
// read the Kustomization file and all the patches it is
|
||||||
|
// referencing (either stategicMerge or json6902 patches)
|
||||||
|
if err := km.loadFromKustomizationFile(ldr); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// if a Kustomization file was not found, kubeadm creates
|
||||||
|
// one using all the patches in the folder; however in this
|
||||||
|
// case only stategicMerge patches are supported
|
||||||
|
if km.kustomizationFile == nil {
|
||||||
|
km.kustomizationFile = &types.Kustomization{}
|
||||||
|
if err := km.loadFromFolder(ldr); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
instances[kustomizeDir] = km
|
instances[kustomizeDir] = km
|
||||||
}
|
}
|
||||||
@ -65,78 +96,103 @@ func GetManager(kustomizeDir string) (*Manager, error) {
|
|||||||
return instances[kustomizeDir], nil
|
return instances[kustomizeDir], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getUnstructuredSlice returns a UnstructuredSlice with all the patches.
|
// loadFromKustomizationFile reads a Kustomization file and all the patches it is
|
||||||
func (km *Manager) getUnstructuredSlice() error {
|
// referencing (either stategicMerge or json6902 patches)
|
||||||
// kubeadm does not require a kustomization.yaml file listing all the resources/patches, so it is necessary
|
func (km *Manager) loadFromKustomizationFile(ldr ifc.Loader) error {
|
||||||
// to rebuild the list of patches manually
|
// Kustomize support different KustomizationFileNames, so we try to read all
|
||||||
// TODO: make this git friendly - currently this works only for patches in local folders -
|
var content []byte
|
||||||
files, err := ioutil.ReadDir(km.kustomizeDir)
|
match := 0
|
||||||
|
for _, kf := range constants.KustomizationFileNames {
|
||||||
|
c, err := ldr.Load(kf)
|
||||||
|
if err == nil {
|
||||||
|
match++
|
||||||
|
content = c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no kustomization file is found return
|
||||||
|
if match == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// if more that one kustomization file is found, return error
|
||||||
|
if match > 1 {
|
||||||
|
return errors.Errorf("Found multiple kustomization files under: %s\n", ldr.Root())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode the kustomization file
|
||||||
|
decoder := yamlutil.NewYAMLOrJSONDecoder(bytes.NewReader(content), 1024)
|
||||||
|
var k = &types.Kustomization{}
|
||||||
|
if err := decoder.Decode(k); err != nil {
|
||||||
|
return errors.Wrap(err, "Error decoding kustomization file")
|
||||||
|
}
|
||||||
|
km.kustomizationFile = k
|
||||||
|
|
||||||
|
// gets all the strategic merge patches
|
||||||
|
for _, f := range km.kustomizationFile.PatchesStrategicMerge {
|
||||||
|
smp, err := newStrategicMergeSliceFromFile(ldr, string(f))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
km.strategicMergePatches = append(km.strategicMergePatches, smp...)
|
||||||
|
}
|
||||||
|
|
||||||
var paths = []string{}
|
// gets all the json6902 patches
|
||||||
for _, file := range files {
|
for _, f := range km.kustomizationFile.PatchesJson6902 {
|
||||||
if file.IsDir() {
|
jp, err := newJSON6902FromFile(f, ldr, f.Path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
km.json6902Patches = append(km.json6902Patches, jp)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadFromFolder returns all the stategicMerge patches in a folder
|
||||||
|
func (km *Manager) loadFromFolder(ldr ifc.Loader) error {
|
||||||
|
files, err := ioutil.ReadDir(ldr.Root())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, fileInfo := range files {
|
||||||
|
if fileInfo.IsDir() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
paths = append(paths, file.Name())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a loader that mimics the behavior of kubectl kustomize, including support for reading from
|
smp, err := newStrategicMergeSliceFromFile(ldr, fileInfo.Name())
|
||||||
// a local git repository like git@github.com:someOrg/someRepo.git or https://github.com/someOrg/someRepo?ref=someHash
|
|
||||||
fSys := fs.MakeRealFS()
|
|
||||||
ldr, err := loader.NewLoader(km.kustomizeDir, fSys)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer ldr.Cleanup()
|
km.strategicMergePatches = append(km.strategicMergePatches, smp...)
|
||||||
|
|
||||||
// read all the kustomizations and build the UnstructuredSlice
|
|
||||||
us, err := NewUnstructuredSliceFromFiles(ldr, paths)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
km.us = us
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kustomize apply a set of patches to a resource.
|
// Kustomize apply a set of patches to a resource.
|
||||||
// Portions of the kustomize logic in this function are taken from the kubernetes-sigs/kind project
|
// Portions of the kustomize logic in this function are taken from the kubernetes-sigs/kind project
|
||||||
func (km *Manager) Kustomize(res []byte) ([]byte, error) {
|
func (km *Manager) Kustomize(data []byte) ([]byte, error) {
|
||||||
// create a loader that mimics the behavior of kubectl kustomize
|
// parse the resource to kustomize
|
||||||
// and converts the resource into a UnstructuredSlice
|
decoder := yamlutil.NewYAMLOrJSONDecoder(bytes.NewReader(data), 1024)
|
||||||
// Nb. in kubeadm we are controlling resource generation, and so we
|
var resource *unstructured.Unstructured
|
||||||
// we are expecting 1 object into each resource, eg. the static pod.
|
if err := decoder.Decode(&resource); err != nil {
|
||||||
// Nevertheless, this code is ready for more than one object per resource
|
|
||||||
resList, err := NewUnstructuredSliceFromBytes(res)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a list of resource and corresponding patches
|
// get patches corresponding to this resource
|
||||||
var resources, patches UnstructuredSlice
|
strategicMerge := km.strategicMergePatches.filterByResource(resource)
|
||||||
for _, r := range resList {
|
json6902 := km.json6902Patches.filterByResource(resource)
|
||||||
resources = append(resources, r)
|
|
||||||
|
|
||||||
resourcePatches := km.us.FilterResource(r.GroupVersionKind(), r.GetNamespace(), r.GetName())
|
|
||||||
|
|
||||||
if len(resourcePatches) > 0 {
|
|
||||||
fmt.Printf("[kustomize] Applying %d patches to %s Resource=%s/%s\n", len(resourcePatches), r.GroupVersionKind(), r.GetNamespace(), r.GetName())
|
|
||||||
patches = append(patches, resourcePatches...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if there are no patches, for the target resources, exit
|
// if there are no patches, for the target resources, exit
|
||||||
if len(patches) == 0 {
|
if len(strategicMerge)+len(json6902) == 0 {
|
||||||
return res, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Printf("[kustomize] Applying %d patches to %s Resource=%s/%s\n", len(strategicMerge)+len(json6902), resource.GroupVersionKind(), resource.GetNamespace(), resource.GetName())
|
||||||
|
|
||||||
// create an in memory fs to use for the kustomization
|
// create an in memory fs to use for the kustomization
|
||||||
memFS := fs.MakeFakeFS()
|
memFS := fs.MakeFakeFS()
|
||||||
|
|
||||||
var kustomization bytes.Buffer
|
|
||||||
fakeDir := "/"
|
fakeDir := "/"
|
||||||
// for Windows we need this to be a drive because kustomize uses filepath.Abs()
|
// for Windows we need this to be a drive because kustomize uses filepath.Abs()
|
||||||
// which will add a drive letter if there is none. which drive letter is
|
// which will add a drive letter if there is none. which drive letter is
|
||||||
@ -145,33 +201,44 @@ func (km *Manager) Kustomize(res []byte) ([]byte, error) {
|
|||||||
fakeDir = `C:\`
|
fakeDir = `C:\`
|
||||||
}
|
}
|
||||||
|
|
||||||
// write resources and patches to the in memory fs, generate the kustomization.yaml
|
// writes the resource to a file in the temp file system
|
||||||
// that ties everything together
|
b, err := yaml.Marshal(resource)
|
||||||
kustomization.WriteString("resources:\n")
|
|
||||||
for i, r := range resources {
|
|
||||||
b, err := r.MarshalJSON()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
name := "resource.yaml"
|
||||||
name := fmt.Sprintf("resource-%d.json", i)
|
|
||||||
_ = memFS.WriteFile(filepath.Join(fakeDir, name), b)
|
_ = memFS.WriteFile(filepath.Join(fakeDir, name), b)
|
||||||
fmt.Fprintf(&kustomization, " - %s\n", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
kustomization.WriteString("patches:\n")
|
km.kustomizationFile.Resources = []string{name}
|
||||||
for i, p := range patches {
|
|
||||||
b, err := p.MarshalJSON()
|
// writes strategic merge patches to files in the temp file system
|
||||||
|
km.kustomizationFile.PatchesStrategicMerge = []patch.StrategicMerge{}
|
||||||
|
for i, p := range strategicMerge {
|
||||||
|
b, err := yaml.Marshal(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
name := fmt.Sprintf("patch-%d.yaml", i)
|
||||||
name := fmt.Sprintf("patch-%d.json", i)
|
|
||||||
_ = memFS.WriteFile(filepath.Join(fakeDir, name), b)
|
_ = memFS.WriteFile(filepath.Join(fakeDir, name), b)
|
||||||
fmt.Fprintf(&kustomization, " - %s\n", name)
|
|
||||||
|
km.kustomizationFile.PatchesStrategicMerge = append(km.kustomizationFile.PatchesStrategicMerge, patch.StrategicMerge(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
memFS.WriteFile(filepath.Join(fakeDir, "kustomization.yaml"), kustomization.Bytes())
|
// writes json6902 patches to files in the temp file system
|
||||||
|
km.kustomizationFile.PatchesJson6902 = []patch.Json6902{}
|
||||||
|
for i, p := range json6902 {
|
||||||
|
name := fmt.Sprintf("patchjson-%d.yaml", i)
|
||||||
|
_ = memFS.WriteFile(filepath.Join(fakeDir, name), []byte(p.Patch))
|
||||||
|
|
||||||
|
km.kustomizationFile.PatchesJson6902 = append(km.kustomizationFile.PatchesJson6902, patch.Json6902{Target: p.Target, Path: name})
|
||||||
|
}
|
||||||
|
|
||||||
|
// writes the kustomization file to the temp file system
|
||||||
|
kbytes, err := yaml.Marshal(km.kustomizationFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
memFS.WriteFile(filepath.Join(fakeDir, "kustomization.yaml"), kbytes)
|
||||||
|
|
||||||
// Finally customize the target resource
|
// Finally customize the target resource
|
||||||
var out bytes.Buffer
|
var out bytes.Buffer
|
||||||
|
@ -26,21 +26,14 @@ import (
|
|||||||
"github.com/lithammer/dedent"
|
"github.com/lithammer/dedent"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestKustomize(t *testing.T) {
|
func TestKustomizeWithoutKustomizationFile(t *testing.T) {
|
||||||
tmpdir, err := ioutil.TempDir("", "")
|
tmpdir, err := ioutil.TempDir("", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("Couldn't create tmpdir")
|
t.Fatal("Couldn't create tmpdir")
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(tmpdir)
|
defer os.RemoveAll(tmpdir)
|
||||||
|
|
||||||
resourceString := dedent.Dedent(`
|
strategicMergePatch1 := dedent.Dedent(`
|
||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
name: kube-apiserver
|
|
||||||
`)
|
|
||||||
|
|
||||||
patch1String := dedent.Dedent(`
|
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Pod
|
kind: Pod
|
||||||
metadata:
|
metadata:
|
||||||
@ -49,12 +42,12 @@ func TestKustomize(t *testing.T) {
|
|||||||
kustomize: patch for kube-apiserver
|
kustomize: patch for kube-apiserver
|
||||||
`)
|
`)
|
||||||
|
|
||||||
err = ioutil.WriteFile(filepath.Join(tmpdir, "patch-1.yaml"), []byte(patch1String), 0644)
|
err = ioutil.WriteFile(filepath.Join(tmpdir, "patch-1.yaml"), []byte(strategicMergePatch1), 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("WriteFile returned unexpected error: %v", err)
|
t.Fatalf("WriteFile returned unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
patch2String := dedent.Dedent(`
|
strategicMergePatch2 := dedent.Dedent(`
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Pod
|
kind: Pod
|
||||||
metadata:
|
metadata:
|
||||||
@ -63,26 +56,148 @@ func TestKustomize(t *testing.T) {
|
|||||||
kustomize: patch for kube-scheduler
|
kustomize: patch for kube-scheduler
|
||||||
`)
|
`)
|
||||||
|
|
||||||
err = ioutil.WriteFile(filepath.Join(tmpdir, "patch-2.yaml"), []byte(patch2String), 0644)
|
err = ioutil.WriteFile(filepath.Join(tmpdir, "patch-2.yaml"), []byte(strategicMergePatch2), 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("WriteFile returned unexpected error: %v", err)
|
t.Fatalf("WriteFile returned unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
km, err := GetManager(tmpdir)
|
km, err := GetManager(tmpdir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("GetManager returned unexpected error: %v", err)
|
t.Fatalf("GetManager returned unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
kustomized, err := km.Kustomize([]byte(resourceString))
|
resource := dedent.Dedent(`
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: kube-apiserver
|
||||||
|
`)
|
||||||
|
|
||||||
|
kustomized, err := km.Kustomize([]byte(resource))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Kustomize returned unexpected error: %v", err)
|
t.Fatalf("Kustomize returned unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !strings.Contains(string(kustomized), "kustomize: patch for kube-apiserver") {
|
if !strings.Contains(string(kustomized), "kustomize: patch for kube-apiserver") {
|
||||||
t.Error("Kustomize did not apply patches corresponding to the resource")
|
t.Error("Kustomize did not apply strategicMergePatch")
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.Contains(string(kustomized), "kustomize: patch for kube-scheduler") {
|
if strings.Contains(string(kustomized), "kustomize: patch for kube-scheduler") {
|
||||||
t.Error("Kustomize did apply patches not corresponding to the resource")
|
t.Error("Kustomize did apply patches not corresponding to the resource")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestKustomizeWithKustomizationFile(t *testing.T) {
|
||||||
|
tmpdir, err := ioutil.TempDir("", "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Couldn't create tmpdir")
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tmpdir)
|
||||||
|
|
||||||
|
kustomizationFile := dedent.Dedent(`
|
||||||
|
patchesJson6902:
|
||||||
|
- target:
|
||||||
|
version: v1
|
||||||
|
kind: Pod
|
||||||
|
name: kube-apiserver
|
||||||
|
path: patch-1.yaml
|
||||||
|
- target:
|
||||||
|
version: v1
|
||||||
|
kind: Pod
|
||||||
|
name: kube-scheduler
|
||||||
|
path: patch-2.yaml
|
||||||
|
patchesStrategicMerge:
|
||||||
|
- patch-3.yaml
|
||||||
|
- patch-4.yaml
|
||||||
|
`)
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filepath.Join(tmpdir, "kustomization.yaml"), []byte(kustomizationFile), 0644)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("WriteFile returned unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonPatch1 := dedent.Dedent(`
|
||||||
|
- op: add
|
||||||
|
path: "/metadata/labels"
|
||||||
|
value:
|
||||||
|
kustomize1: patch for kube-apiserver
|
||||||
|
`)
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filepath.Join(tmpdir, "patch-1.yaml"), []byte(jsonPatch1), 0644)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("WriteFile returned unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonPatch2 := dedent.Dedent(`
|
||||||
|
- op: add
|
||||||
|
path: "/metadata/labels"
|
||||||
|
value:
|
||||||
|
kustomize1: patch for kube-scheduler
|
||||||
|
`)
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filepath.Join(tmpdir, "patch-2.yaml"), []byte(jsonPatch2), 0644)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("WriteFile returned unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
strategicMergePatch1 := dedent.Dedent(`
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: kube-apiserver
|
||||||
|
annotations:
|
||||||
|
kustomize2: patch for kube-apiserver
|
||||||
|
`)
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filepath.Join(tmpdir, "patch-3.yaml"), []byte(strategicMergePatch1), 0644)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("WriteFile returned unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
strategicMergePatch2 := dedent.Dedent(`
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: kube-scheduler
|
||||||
|
annotations:
|
||||||
|
kustomize2: patch for kube-scheduler
|
||||||
|
`)
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filepath.Join(tmpdir, "patch-4.yaml"), []byte(strategicMergePatch2), 0644)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("WriteFile returned unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
km, err := GetManager(tmpdir)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("GetManager returned unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resource := dedent.Dedent(`
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: kube-apiserver
|
||||||
|
`)
|
||||||
|
|
||||||
|
kustomized, err := km.Kustomize([]byte(resource))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Kustomize returned unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(string(kustomized), "kustomize1: patch for kube-apiserver") {
|
||||||
|
t.Error("Kustomize did not apply json patches corresponding to the resource")
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(string(kustomized), "kustomize1: patch for kube-scheduler") {
|
||||||
|
t.Error("Kustomize did apply json patches not corresponding to the resource")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(string(kustomized), "kustomize2: patch for kube-apiserver") {
|
||||||
|
t.Error("Kustomize did not apply strategic merge patches corresponding to the resource")
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(string(kustomized), "kustomize2: patch for kube-scheduler") {
|
||||||
|
t.Error("Kustomize did apply strategic merge patches not corresponding to the resource")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -26,41 +26,33 @@ import (
|
|||||||
|
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
"k8s.io/apimachinery/pkg/util/yaml"
|
"k8s.io/apimachinery/pkg/util/yaml"
|
||||||
"sigs.k8s.io/kustomize/pkg/ifc"
|
"sigs.k8s.io/kustomize/pkg/ifc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UnstructuredSlice is a slice of Unstructured objects.
|
// strategicMergeSlice is a slice of strategic merge patches.
|
||||||
// Unstructured objects are used to represent both resources and patches of any group/version/kind.
|
// Unstructured objects are used to represent strategic merge patches of any group/version/kind.
|
||||||
type UnstructuredSlice []*unstructured.Unstructured
|
type strategicMergeSlice []*unstructured.Unstructured
|
||||||
|
|
||||||
// NewUnstructuredSliceFromFiles returns a ResMap given a resource path slice.
|
// newStrategicMergeSliceFromFile returns a slice of strategic merge patches from a file
|
||||||
// This func use a Loader to mimic the behavior of kubectl kustomize, and most specifically support for reading from
|
func newStrategicMergeSliceFromFile(loader ifc.Loader, path string) (strategicMergeSlice, error) {
|
||||||
// a local git repository like git@github.com:someOrg/someRepo.git or https://github.com/someOrg/someRepo?ref=someHash
|
|
||||||
func NewUnstructuredSliceFromFiles(loader ifc.Loader, paths []string) (UnstructuredSlice, error) {
|
|
||||||
var result UnstructuredSlice
|
|
||||||
for _, path := range paths {
|
|
||||||
content, err := loader.Load(path)
|
content, err := loader.Load(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "load from path %q failed", path)
|
return nil, errors.Wrapf(err, "load from path %q failed", path)
|
||||||
}
|
}
|
||||||
res, err := NewUnstructuredSliceFromBytes(content)
|
res, err := newStrategicMergeSliceFromBytes(content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "convert %q to Unstructured failed", path)
|
return nil, errors.Wrapf(err, "convert %q to Unstructured failed", path)
|
||||||
}
|
}
|
||||||
|
return res, nil
|
||||||
result = append(result, res...)
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUnstructuredSliceFromBytes returns a slice of Unstructured.
|
// newStrategicMergeSliceFromBytes returns a strategic merge patches contained in a []byte.
|
||||||
// This functions handles all the nuances of Kubernetes yaml (e.g. many yaml
|
// This functions handles all the nuances of Kubernetes yaml (e.g. many yaml
|
||||||
// documents in one file, List of objects)
|
// documents in one file, List of objects)
|
||||||
func NewUnstructuredSliceFromBytes(in []byte) (UnstructuredSlice, error) {
|
func newStrategicMergeSliceFromBytes(in []byte) (strategicMergeSlice, error) {
|
||||||
decoder := yaml.NewYAMLOrJSONDecoder(bytes.NewReader(in), 1024)
|
decoder := yaml.NewYAMLOrJSONDecoder(bytes.NewReader(in), 1024)
|
||||||
var result UnstructuredSlice
|
var result strategicMergeSlice
|
||||||
var err error
|
var err error
|
||||||
// Parse all the yaml documents in the file
|
// Parse all the yaml documents in the file
|
||||||
for err == nil || isEmptyYamlError(err) {
|
for err == nil || isEmptyYamlError(err) {
|
||||||
@ -88,13 +80,13 @@ func NewUnstructuredSliceFromBytes(in []byte) (UnstructuredSlice, error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the UnstructuredSlice for the item
|
// Get the stategicMergeSlice for the item
|
||||||
itemU, err := NewUnstructuredSliceFromBytes(itemJSON)
|
itemU, err := newStrategicMergeSliceFromBytes(itemJSON)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// append the UnstructuredSlice for the item to the UnstructuredSlice
|
// append the stategicMergeSlice for the item to the stategicMergeSlice
|
||||||
result = append(result, itemU...)
|
result = append(result, itemU...)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -105,7 +97,7 @@ func NewUnstructuredSliceFromBytes(in []byte) (UnstructuredSlice, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// append the object to the UnstructuredSlice
|
// append the object to the stategicMergeSlice
|
||||||
result = append(result, &u)
|
result = append(result, &u)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -115,14 +107,14 @@ func NewUnstructuredSliceFromBytes(in []byte) (UnstructuredSlice, error) {
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterResource returns all the Unstructured items in the UnstructuredSlice corresponding to a given resource
|
// filterByResource returns all the strategic merge patches in the strategicMergeSlice corresponding to a given resource
|
||||||
func (rs *UnstructuredSlice) FilterResource(gvk schema.GroupVersionKind, namespace, name string) UnstructuredSlice {
|
func (s *strategicMergeSlice) filterByResource(r *unstructured.Unstructured) strategicMergeSlice {
|
||||||
var result UnstructuredSlice
|
var result strategicMergeSlice
|
||||||
for _, r := range *rs {
|
for _, p := range *s {
|
||||||
if r.GroupVersionKind() == gvk &&
|
if p.GroupVersionKind() == r.GroupVersionKind() &&
|
||||||
r.GetNamespace() == namespace &&
|
p.GetNamespace() == r.GetNamespace() &&
|
||||||
r.GetName() == name {
|
p.GetName() == r.GetName() {
|
||||||
result = append(result, r)
|
result = append(result, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
@ -20,20 +20,21 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/lithammer/dedent"
|
"github.com/lithammer/dedent"
|
||||||
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewUnstructuredSliceFromBytes(t *testing.T) {
|
func TestNewStategicMergeSliceFromBytes(t *testing.T) {
|
||||||
var useCases = []struct {
|
var useCases = []struct {
|
||||||
name string
|
name string
|
||||||
in string
|
in string
|
||||||
expectedUnctructured int
|
expectedPatches int
|
||||||
expectedError bool
|
expectedError bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "empty",
|
name: "empty",
|
||||||
in: "",
|
in: "",
|
||||||
expectedUnctructured: 0,
|
expectedPatches: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "single patch",
|
name: "single patch",
|
||||||
@ -43,7 +44,7 @@ func TestNewUnstructuredSliceFromBytes(t *testing.T) {
|
|||||||
metadata:
|
metadata:
|
||||||
name: kube-apiserver
|
name: kube-apiserver
|
||||||
`),
|
`),
|
||||||
expectedUnctructured: 1,
|
expectedPatches: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "two patches as separated yaml documents",
|
name: "two patches as separated yaml documents",
|
||||||
@ -58,7 +59,7 @@ func TestNewUnstructuredSliceFromBytes(t *testing.T) {
|
|||||||
metadata:
|
metadata:
|
||||||
name: kube-apiserver
|
name: kube-apiserver
|
||||||
`),
|
`),
|
||||||
expectedUnctructured: 2,
|
expectedPatches: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "two patches as a k8s list",
|
name: "two patches as a k8s list",
|
||||||
@ -75,7 +76,7 @@ func TestNewUnstructuredSliceFromBytes(t *testing.T) {
|
|||||||
metadata:
|
metadata:
|
||||||
name: kube-apiserver
|
name: kube-apiserver
|
||||||
`),
|
`),
|
||||||
expectedUnctructured: 2,
|
expectedPatches: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "nested k8s lists",
|
name: "nested k8s lists",
|
||||||
@ -95,7 +96,7 @@ func TestNewUnstructuredSliceFromBytes(t *testing.T) {
|
|||||||
metadata:
|
metadata:
|
||||||
name: kube-apiserver
|
name: kube-apiserver
|
||||||
`),
|
`),
|
||||||
expectedUnctructured: 2,
|
expectedPatches: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "invalid yaml",
|
name: "invalid yaml",
|
||||||
@ -125,18 +126,18 @@ func TestNewUnstructuredSliceFromBytes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, rt := range useCases {
|
for _, rt := range useCases {
|
||||||
t.Run(rt.name, func(t *testing.T) {
|
t.Run(rt.name, func(t *testing.T) {
|
||||||
r, err := NewUnstructuredSliceFromBytes([]byte(rt.in))
|
r, err := newStrategicMergeSliceFromBytes([]byte(rt.in))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !rt.expectedError {
|
if !rt.expectedError {
|
||||||
t.Errorf("NewUnstructuredSliceFromBytes returned unexpected error: %v", err)
|
t.Errorf("newStrategicMergeSliceFromBytes returned unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err == nil && rt.expectedError {
|
if err == nil && rt.expectedError {
|
||||||
t.Error("NewUnstructuredSliceFromBytes does not returned expected error")
|
t.Error("newStrategicMergeSliceFromBytes does not returned expected error")
|
||||||
}
|
}
|
||||||
if len(r) != rt.expectedUnctructured {
|
if len(r) != rt.expectedPatches {
|
||||||
t.Errorf("Expected %d Unstructured items in the slice, actual %d", rt.expectedUnctructured, len(r))
|
t.Errorf("Expected %d strategic merge patches in the slice, actual %d", rt.expectedPatches, len(r))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -162,9 +163,9 @@ func TestFilterResource(t *testing.T) {
|
|||||||
name: kube-scheduler
|
name: kube-scheduler
|
||||||
namespace: kube-system
|
namespace: kube-system
|
||||||
`)
|
`)
|
||||||
u, err := NewUnstructuredSliceFromBytes([]byte(in))
|
u, err := newStrategicMergeSliceFromBytes([]byte(in))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("NewUnstructuredSliceFromBytes returned unexpected error: %v", err)
|
t.Fatalf("newStategicMergeSliceFromBytes returned unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var useCases = []struct {
|
var useCases = []struct {
|
||||||
@ -172,50 +173,55 @@ func TestFilterResource(t *testing.T) {
|
|||||||
rgvk schema.GroupVersionKind
|
rgvk schema.GroupVersionKind
|
||||||
rnamespace string
|
rnamespace string
|
||||||
rname string
|
rname string
|
||||||
expectedUnctructured int
|
expectedPatches int
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "match 1",
|
name: "match 1",
|
||||||
rgvk: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"},
|
rgvk: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"},
|
||||||
rnamespace: "kube-system",
|
rnamespace: "kube-system",
|
||||||
rname: "kube-apiserver",
|
rname: "kube-apiserver",
|
||||||
expectedUnctructured: 1,
|
expectedPatches: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "match 2",
|
name: "match 2",
|
||||||
rgvk: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"},
|
rgvk: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"},
|
||||||
rnamespace: "kube-system",
|
rnamespace: "kube-system",
|
||||||
rname: "kube-scheduler",
|
rname: "kube-scheduler",
|
||||||
expectedUnctructured: 2,
|
expectedPatches: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "match 0 (wrong gvk)",
|
name: "match 0 (wrong gvk)",
|
||||||
rgvk: schema.GroupVersionKind{Group: "something", Version: "v1", Kind: "Pod"},
|
rgvk: schema.GroupVersionKind{Group: "something", Version: "v1", Kind: "Pod"},
|
||||||
rnamespace: "kube-system",
|
rnamespace: "kube-system",
|
||||||
rname: "kube-scheduler",
|
rname: "kube-scheduler",
|
||||||
expectedUnctructured: 0,
|
expectedPatches: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "match 0 (wrong namespace)",
|
name: "match 0 (wrong namespace)",
|
||||||
rgvk: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"},
|
rgvk: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"},
|
||||||
rnamespace: "kube-something",
|
rnamespace: "kube-something",
|
||||||
rname: "kube-scheduler",
|
rname: "kube-scheduler",
|
||||||
expectedUnctructured: 0,
|
expectedPatches: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "match 0 (wrong namr)",
|
name: "match 0 (wrong namr)",
|
||||||
rgvk: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"},
|
rgvk: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"},
|
||||||
rnamespace: "kube-system",
|
rnamespace: "kube-system",
|
||||||
rname: "kube-something",
|
rname: "kube-something",
|
||||||
expectedUnctructured: 0,
|
expectedPatches: 0,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, rt := range useCases {
|
for _, rt := range useCases {
|
||||||
t.Run(rt.name, func(t *testing.T) {
|
t.Run(rt.name, func(t *testing.T) {
|
||||||
r := u.FilterResource(rt.rgvk, rt.rnamespace, rt.rname)
|
resource := &unstructured.Unstructured{}
|
||||||
|
resource.SetGroupVersionKind(rt.rgvk)
|
||||||
|
resource.SetNamespace(rt.rnamespace)
|
||||||
|
resource.SetName(rt.rname)
|
||||||
|
|
||||||
if len(r) != rt.expectedUnctructured {
|
r := u.filterByResource(resource)
|
||||||
t.Errorf("Expected %d Unstructured items in the slice, actual %d", rt.expectedUnctructured, len(r))
|
|
||||||
|
if len(r) != rt.expectedPatches {
|
||||||
|
t.Errorf("Expected %d strategic merge patches in the slice, actual %d", rt.expectedPatches, len(r))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user