mirror of https://github.com/fluxcd/cli-utils.git
Handle the --namespace flag
This commit is contained in:
parent
5a58b89413
commit
e43565ef80
|
|
@ -117,10 +117,21 @@ func (r *ApplyRunner) RunE(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch the namespace from the configloader. The source of this
|
||||||
|
// either the namespace flag or the context. If the namespace is provided
|
||||||
|
// with the flag, enforceNamespace will be true. In this case, it is
|
||||||
|
// an error if any of the resources in the package has a different
|
||||||
|
// namespace set.
|
||||||
|
namespace, enforceNamespace, err := r.provider.Factory().ToRawKubeConfigLoader().Namespace()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
var reader manifestreader.ManifestReader
|
var reader manifestreader.ManifestReader
|
||||||
readerOptions := manifestreader.ReaderOptions{
|
readerOptions := manifestreader.ReaderOptions{
|
||||||
Factory: r.provider.Factory(),
|
Factory: r.provider.Factory(),
|
||||||
Namespace: metav1.NamespaceDefault,
|
Namespace: namespace,
|
||||||
|
EnforceNamespace: enforceNamespace,
|
||||||
}
|
}
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
reader = &manifestreader.StreamManifestReader{
|
reader = &manifestreader.StreamManifestReader{
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,15 @@ package initcmd
|
||||||
import (
|
import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
|
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||||
"k8s.io/kubectl/pkg/util/i18n"
|
"k8s.io/kubectl/pkg/util/i18n"
|
||||||
"sigs.k8s.io/cli-utils/pkg/config"
|
"sigs.k8s.io/cli-utils/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewCmdInit creates the `init` command, which generates the
|
// NewCmdInit creates the `init` command, which generates the
|
||||||
// inventory object template ConfigMap for a package.
|
// inventory object template ConfigMap for a package.
|
||||||
func NewCmdInit(ioStreams genericclioptions.IOStreams) *cobra.Command {
|
func NewCmdInit(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
|
||||||
io := config.NewInitOptions(ioStreams)
|
io := config.NewInitOptions(f, ioStreams)
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "init DIRECTORY",
|
Use: "init DIRECTORY",
|
||||||
DisableFlagsInUseLine: true,
|
DisableFlagsInUseLine: true,
|
||||||
|
|
@ -27,6 +28,5 @@ func NewCmdInit(ioStreams genericclioptions.IOStreams) *cobra.Command {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cmd.Flags().StringVarP(&io.InventoryID, "inventory-id", "i", "", "Identifier for group of applied resources. Must be composed of valid label characters.")
|
cmd.Flags().StringVarP(&io.InventoryID, "inventory-id", "i", "", "Identifier for group of applied resources. Must be composed of valid label characters.")
|
||||||
cmd.Flags().StringVarP(&io.Namespace, "inventory-namespace", "", "", "namespace for the resources to be initialized")
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
names := []string{"init", "apply", "preview", "diff", "destroy", "status"}
|
names := []string{"init", "apply", "preview", "diff", "destroy", "status"}
|
||||||
initCmd := initcmd.NewCmdInit(ioStreams)
|
initCmd := initcmd.NewCmdInit(f, ioStreams)
|
||||||
updateHelp(names, initCmd)
|
updateHelp(names, initCmd)
|
||||||
applyCmd := apply.ApplyCommand(f, ioStreams)
|
applyCmd := apply.ApplyCommand(f, ioStreams)
|
||||||
updateHelp(names, applyCmd)
|
updateHelp(names, applyCmd)
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||||
"k8s.io/kubectl/pkg/util/i18n"
|
"k8s.io/kubectl/pkg/util/i18n"
|
||||||
|
|
@ -117,10 +116,21 @@ func (r *PreviewRunner) RunE(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch the namespace from the configloader. The source of this
|
||||||
|
// either the namespace flag or the context. If the namespace is provided
|
||||||
|
// with the flag, enforceNamespace will be true. In this case, it is
|
||||||
|
// an error if any of the resources in the package has a different
|
||||||
|
// namespace set.
|
||||||
|
namespace, enforceNamespace, err := r.provider.Factory().ToRawKubeConfigLoader().Namespace()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
var reader manifestreader.ManifestReader
|
var reader manifestreader.ManifestReader
|
||||||
readerOptions := manifestreader.ReaderOptions{
|
readerOptions := manifestreader.ReaderOptions{
|
||||||
Factory: r.provider.Factory(),
|
Factory: r.provider.Factory(),
|
||||||
Namespace: metav1.NamespaceDefault,
|
Namespace: namespace,
|
||||||
|
EnforceNamespace: enforceNamespace,
|
||||||
}
|
}
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
reader = &manifestreader.StreamManifestReader{
|
reader = &manifestreader.StreamManifestReader{
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-errors/errors"
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
|
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||||
"sigs.k8s.io/cli-utils/pkg/common"
|
"sigs.k8s.io/cli-utils/pkg/common"
|
||||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
)
|
)
|
||||||
|
|
@ -62,6 +61,8 @@ metadata:
|
||||||
// InitOptions contains the fields necessary to generate a
|
// InitOptions contains the fields necessary to generate a
|
||||||
// inventory object template ConfigMap.
|
// inventory object template ConfigMap.
|
||||||
type InitOptions struct {
|
type InitOptions struct {
|
||||||
|
factory cmdutil.Factory
|
||||||
|
|
||||||
ioStreams genericclioptions.IOStreams
|
ioStreams genericclioptions.IOStreams
|
||||||
// Package directory argument; must be valid directory.
|
// Package directory argument; must be valid directory.
|
||||||
Dir string
|
Dir string
|
||||||
|
|
@ -71,8 +72,9 @@ type InitOptions struct {
|
||||||
InventoryID string
|
InventoryID string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewInitOptions(ioStreams genericclioptions.IOStreams) *InitOptions {
|
func NewInitOptions(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *InitOptions {
|
||||||
return &InitOptions{
|
return &InitOptions{
|
||||||
|
factory: f,
|
||||||
ioStreams: ioStreams,
|
ioStreams: ioStreams,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -89,14 +91,13 @@ func (i *InitOptions) Complete(args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
i.Dir = dir
|
i.Dir = dir
|
||||||
if len(i.Namespace) == 0 {
|
|
||||||
// Returns default namespace if no namespace found.
|
ns, err := findNamespace(i.factory.ToRawKubeConfigLoader(), i.Dir)
|
||||||
namespace, err := calcPackageNamespace(i.Dir)
|
if err != nil {
|
||||||
if err != nil {
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
i.Namespace = namespace
|
|
||||||
}
|
}
|
||||||
|
i.Namespace = ns
|
||||||
|
|
||||||
// Set the default inventory label if one does not exist.
|
// Set the default inventory label if one does not exist.
|
||||||
if len(i.InventoryID) == 0 {
|
if len(i.InventoryID) == 0 {
|
||||||
inventoryID, err := i.defaultInventoryID()
|
inventoryID, err := i.defaultInventoryID()
|
||||||
|
|
@ -113,6 +114,35 @@ func (i *InitOptions) Complete(args []string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type namespaceLoader interface {
|
||||||
|
Namespace() (string, bool, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// findNamespace looks up the namespace that should be used for the
|
||||||
|
// inventory template of the package. If the namespace is specified with
|
||||||
|
// the --namespace flag, it will be used no matter what. If not, this
|
||||||
|
// will look at all the resource, and if all belong in the same namespace,
|
||||||
|
// it will return that namespace. Otherwise, it will return the namespace
|
||||||
|
// set in the context.
|
||||||
|
func findNamespace(loader namespaceLoader, dir string) (string, error) {
|
||||||
|
namespace, enforceNamespace, err := loader.Namespace()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if enforceNamespace {
|
||||||
|
return namespace, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ns, allInSameNs, err := allInSameNamespace(dir)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if allInSameNs {
|
||||||
|
return ns, nil
|
||||||
|
}
|
||||||
|
return namespace, nil
|
||||||
|
}
|
||||||
|
|
||||||
// normalizeDir returns full absolute directory path of the
|
// normalizeDir returns full absolute directory path of the
|
||||||
// passed directory or an error. This function cleans up paths
|
// passed directory or an error. This function cleans up paths
|
||||||
// such as current directory (.), relative directories (..), or
|
// such as current directory (.), relative directories (..), or
|
||||||
|
|
@ -136,35 +166,36 @@ func isDirectory(path string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// calcPackageNamespace returns the namespace of the package
|
// allInSameNamespace goes through all resources in the package and
|
||||||
// config files. Assumes all namespaced resources are in the
|
// checks the namespace for all of them. If they all have the namespace
|
||||||
// same namespace. Returns the default namespace if none of the
|
// set and they all have the same value, this will return that namespace
|
||||||
// config files has a namespace.
|
// and the second return value will be true. Otherwise, it will not return
|
||||||
func calcPackageNamespace(packageDir string) (string, error) {
|
// a namespace and the second return value will be false.
|
||||||
|
func allInSameNamespace(packageDir string) (string, bool, error) {
|
||||||
r := kio.LocalPackageReader{PackagePath: packageDir}
|
r := kio.LocalPackageReader{PackagePath: packageDir}
|
||||||
nodes, err := r.Read()
|
nodes, err := r.Read()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", false, err
|
||||||
}
|
}
|
||||||
// Return the non-empty unique namespace if found. Cluster-scoped
|
var ns string
|
||||||
// resources do not have namespace set.
|
|
||||||
currentNamespace := metav1.NamespaceDefault
|
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
rm, err := node.GetMeta()
|
rm, err := node.GetMeta()
|
||||||
if err != nil || len(rm.ObjectMeta.Namespace) == 0 {
|
if err != nil {
|
||||||
continue
|
return "", false, err
|
||||||
}
|
}
|
||||||
if currentNamespace == metav1.NamespaceDefault {
|
if rm.Namespace == "" {
|
||||||
currentNamespace = rm.ObjectMeta.Namespace
|
return "", false, nil
|
||||||
}
|
}
|
||||||
if currentNamespace != rm.ObjectMeta.Namespace {
|
if ns == "" {
|
||||||
return "", errors.Errorf(
|
ns = rm.Namespace
|
||||||
"resources belong to different namespaces, a namespace is required to create the resource " +
|
} else if rm.Namespace != ns {
|
||||||
"used for keeping track of past apply operations. Please specify ---inventory-namespace.")
|
return "", false, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Return the default namespace if none found.
|
if ns != "" {
|
||||||
return currentNamespace, nil
|
return ns, true, nil
|
||||||
|
}
|
||||||
|
return "", false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultInventoryID returns a UUID string as a default unique
|
// defaultInventoryID returns a UUID string as a default unique
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,9 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
|
cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ioStreams = genericclioptions.IOStreams{}
|
|
||||||
|
|
||||||
// writeFile writes a file under the test directory
|
// writeFile writes a file under the test directory
|
||||||
func writeFile(t *testing.T, path string, value []byte) {
|
func writeFile(t *testing.T, path string, value []byte) {
|
||||||
err := ioutil.WriteFile(path, value, 0600)
|
err := ioutil.WriteFile(path, value, 0600)
|
||||||
|
|
@ -42,50 +41,171 @@ metadata:
|
||||||
namespace: namespaceB
|
namespace: namespaceB
|
||||||
`)
|
`)
|
||||||
|
|
||||||
|
var readFileC = []byte(`
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: objC
|
||||||
|
`)
|
||||||
|
|
||||||
func TestComplete(t *testing.T) {
|
func TestComplete(t *testing.T) {
|
||||||
d1, err := ioutil.TempDir("", "test-dir")
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
assert.FailNow(t, err.Error())
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(d1)
|
|
||||||
|
|
||||||
writeFile(t, filepath.Join(d1, "a_test.yaml"), readFileA)
|
|
||||||
writeFile(t, filepath.Join(d1, "b_test.yaml"), readFileB)
|
|
||||||
|
|
||||||
tests := map[string]struct {
|
tests := map[string]struct {
|
||||||
args []string
|
args []string
|
||||||
isError bool
|
files map[string][]byte
|
||||||
|
isError bool
|
||||||
|
expectedErrMessage string
|
||||||
|
expectedNamespace string
|
||||||
}{
|
}{
|
||||||
"Empty args returns error": {
|
"Empty args returns error": {
|
||||||
args: []string{},
|
args: []string{},
|
||||||
isError: true,
|
isError: true,
|
||||||
|
expectedErrMessage: "need one 'directory' arg; have 0",
|
||||||
},
|
},
|
||||||
"More than one argument should fail": {
|
"More than one argument should fail": {
|
||||||
args: []string{"foo", "bar"},
|
args: []string{"foo", "bar"},
|
||||||
isError: true,
|
isError: true,
|
||||||
|
expectedErrMessage: "need one 'directory' arg; have 2",
|
||||||
},
|
},
|
||||||
"Non-directory arg should fail": {
|
"Non-directory arg should fail": {
|
||||||
args: []string{"foo"},
|
args: []string{"foo"},
|
||||||
isError: true,
|
isError: true,
|
||||||
|
expectedErrMessage: "invalid directory argument: foo",
|
||||||
},
|
},
|
||||||
"More than one namespace should fail": {
|
"More than one namespace should fail": {
|
||||||
args: []string{d1},
|
args: []string{},
|
||||||
isError: true,
|
files: map[string][]byte{
|
||||||
|
"a_test.yaml": readFileA,
|
||||||
|
"b_test.yaml": readFileB,
|
||||||
|
},
|
||||||
|
isError: true,
|
||||||
|
expectedErrMessage: "resources belong to different namespaces",
|
||||||
|
},
|
||||||
|
"If at least one resource doesn't have namespace, it should use the default": {
|
||||||
|
args: []string{},
|
||||||
|
files: map[string][]byte{
|
||||||
|
"b_test.yaml": readFileB,
|
||||||
|
"c_test.yaml": readFileC,
|
||||||
|
},
|
||||||
|
isError: false,
|
||||||
|
expectedNamespace: "foo",
|
||||||
|
},
|
||||||
|
"No resources without namespace should use the default namespace": {
|
||||||
|
args: []string{},
|
||||||
|
files: map[string][]byte{
|
||||||
|
"c_test.yaml": readFileC,
|
||||||
|
},
|
||||||
|
isError: false,
|
||||||
|
expectedNamespace: "foo",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for name, tc := range tests {
|
for name, tc := range tests {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
io := NewInitOptions(ioStreams)
|
var err error
|
||||||
err := io.Complete(tc.args)
|
dir, err := ioutil.TempDir("", "test-dir")
|
||||||
if tc.isError && err == nil {
|
if !assert.NoError(t, err) {
|
||||||
t.Errorf("Expected error, but did not receive one")
|
assert.FailNow(t, err.Error())
|
||||||
}
|
}
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
for fileName, fileContent := range tc.files {
|
||||||
|
writeFile(t, filepath.Join(dir, fileName), fileContent)
|
||||||
|
}
|
||||||
|
if len(tc.files) > 0 {
|
||||||
|
tc.args = append(tc.args, dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
tf := cmdtesting.NewTestFactory().WithNamespace("foo")
|
||||||
|
defer tf.Cleanup()
|
||||||
|
ioStreams, _, out, _ := genericclioptions.NewTestIOStreams()
|
||||||
|
io := NewInitOptions(tf, ioStreams)
|
||||||
|
err = io.Complete(tc.args)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if !tc.isError {
|
||||||
|
t.Errorf("Expected error, but did not receive one")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert.Contains(t, err.Error(), tc.expectedErrMessage)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert.Contains(t, out.String(), tc.expectedNamespace)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFindNamespace(t *testing.T) {
|
||||||
|
testCases := map[string]struct {
|
||||||
|
namespace string
|
||||||
|
enforceNamespace bool
|
||||||
|
files map[string][]byte
|
||||||
|
expectedNamespace string
|
||||||
|
}{
|
||||||
|
"fallback to default": {
|
||||||
|
namespace: "foo",
|
||||||
|
enforceNamespace: false,
|
||||||
|
files: map[string][]byte{
|
||||||
|
"a_test.yaml": readFileA,
|
||||||
|
"b_test.yaml": readFileB,
|
||||||
|
},
|
||||||
|
expectedNamespace: "foo",
|
||||||
|
},
|
||||||
|
"enforce namespace": {
|
||||||
|
namespace: "bar",
|
||||||
|
enforceNamespace: true,
|
||||||
|
files: map[string][]byte{
|
||||||
|
"a_test.yaml": readFileA,
|
||||||
|
},
|
||||||
|
expectedNamespace: "bar",
|
||||||
|
},
|
||||||
|
"use namespace from resource if all the same": {
|
||||||
|
namespace: "bar",
|
||||||
|
enforceNamespace: false,
|
||||||
|
files: map[string][]byte{
|
||||||
|
"a_test.yaml": readFileA,
|
||||||
|
},
|
||||||
|
expectedNamespace: "namespaceA",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for tn, tc := range testCases {
|
||||||
|
t.Run(tn, func(t *testing.T) {
|
||||||
|
var err error
|
||||||
|
dir, err := ioutil.TempDir("", "test-dir")
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
assert.FailNow(t, err.Error())
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
for fileName, fileContent := range tc.files {
|
||||||
|
writeFile(t, filepath.Join(dir, fileName), fileContent)
|
||||||
|
}
|
||||||
|
|
||||||
|
fakeLoader := &fakeNamespaceLoader{
|
||||||
|
namespace: tc.namespace,
|
||||||
|
enforceNamespace: tc.enforceNamespace,
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace, err := findNamespace(fakeLoader, dir)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tc.expectedNamespace, namespace)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type fakeNamespaceLoader struct {
|
||||||
|
namespace string
|
||||||
|
enforceNamespace bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fakeNamespaceLoader) Namespace() (string, bool, error) {
|
||||||
|
return f.namespace, f.enforceNamespace, nil
|
||||||
|
}
|
||||||
|
|
||||||
func TestDefaultInventoryID(t *testing.T) {
|
func TestDefaultInventoryID(t *testing.T) {
|
||||||
io := NewInitOptions(ioStreams)
|
tf := cmdtesting.NewTestFactory().WithNamespace("foo")
|
||||||
|
defer tf.Cleanup()
|
||||||
|
ioStreams, _, _, _ := genericclioptions.NewTestIOStreams() //nolint:dogsled
|
||||||
|
io := NewInitOptions(tf, ioStreams)
|
||||||
actual, err := io.defaultInventoryID()
|
actual, err := io.defaultInventoryID()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Unxpected error during UUID generation: %v", err)
|
t.Errorf("Unxpected error during UUID generation: %v", err)
|
||||||
|
|
@ -172,7 +292,10 @@ func TestFillInValues(t *testing.T) {
|
||||||
|
|
||||||
for name, tc := range tests {
|
for name, tc := range tests {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
io := NewInitOptions(ioStreams)
|
tf := cmdtesting.NewTestFactory().WithNamespace("foo")
|
||||||
|
defer tf.Cleanup()
|
||||||
|
ioStreams, _, _, _ := genericclioptions.NewTestIOStreams() //nolint:dogsled
|
||||||
|
io := NewInitOptions(tf, ioStreams)
|
||||||
io.Namespace = tc.namespace
|
io.Namespace = tc.namespace
|
||||||
io.InventoryID = tc.inventoryID
|
io.InventoryID = tc.inventoryID
|
||||||
actual := io.fillInValues()
|
actual := io.fillInValues()
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"k8s.io/cli-runtime/pkg/resource"
|
"k8s.io/cli-runtime/pkg/resource"
|
||||||
"k8s.io/kubectl/pkg/cmd/util"
|
"k8s.io/kubectl/pkg/cmd/util"
|
||||||
"sigs.k8s.io/cli-utils/pkg/apply/solver"
|
"sigs.k8s.io/cli-utils/pkg/apply/solver"
|
||||||
|
"sigs.k8s.io/cli-utils/pkg/inventory"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ManifestReader defines the interface for reading a set
|
// ManifestReader defines the interface for reading a set
|
||||||
|
|
@ -53,6 +54,13 @@ func setNamespaces(factory util.Factory, infos []*resource.Info,
|
||||||
|
|
||||||
for _, inf := range infos {
|
for _, inf := range infos {
|
||||||
accessor, _ := meta.Accessor(inf.Object)
|
accessor, _ := meta.Accessor(inf.Object)
|
||||||
|
|
||||||
|
// Exclude any inventory objects here since we don't want to change
|
||||||
|
// their namespace.
|
||||||
|
if inventory.IsInventoryObject(inf) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// if the resource already has the namespace set, we don't
|
// if the resource already has the namespace set, we don't
|
||||||
// need to do anything
|
// need to do anything
|
||||||
if ns := accessor.GetNamespace(); ns != "" {
|
if ns := accessor.GetNamespace(); ns != "" {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue