From e6ee03e3e3e054e452ef87576da907f2f5232e80 Mon Sep 17 00:00:00 2001 From: jregan Date: Wed, 19 Aug 2020 06:29:09 -0700 Subject: [PATCH] Add TypeMeta.IsNamespaceable --- kyaml/yaml/types.go | 40 +++++++++++++++++++++ kyaml/yaml/types_test.go | 75 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) diff --git a/kyaml/yaml/types.go b/kyaml/yaml/types.go index 7b46203c8..348085035 100644 --- a/kyaml/yaml/types.go +++ b/kyaml/yaml/types.go @@ -97,6 +97,46 @@ type TypeMeta struct { Kind string `json:"kind,omitempty" yaml:"kind,omitempty"` } +// Hardcoded list. +// TODO: replace this with data acquired from openapi. +var notNamespaceableKinds = []string{ + "APIService", + "CSIDriver", + "CSINode", + "CertificateSigningRequest", + "Cluster", + "ClusterRole", + "ClusterRoleBinding", + "ComponentStatus", + "CustomResourceDefinition", + "MutatingWebhookConfiguration", + "Namespace", + "Node", + "PersistentVolume", + "PodSecurityPolicy", + "PriorityClass", + "RuntimeClass", + "SelfSubjectAccessReview", + "SelfSubjectRulesReview", + "StorageClass", + "SubjectAccessReview", + "TokenReview", + "ValidatingWebhookConfiguration", + "VolumeAttachment", +} + +// IsNamespaceable returns true if this TypeMeta is for an object +// that can be placed in a namespace. +// Implements https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/#not-all-objects-are-in-a-namespace +func (tm TypeMeta) IsNamespaceable() bool { + for _, k := range notNamespaceableKinds { + if k == tm.Kind { + return false + } + } + return true +} + // NameMeta contains name information. type NameMeta struct { // Name is the metadata.name field of a Resource diff --git a/kyaml/yaml/types_test.go b/kyaml/yaml/types_test.go index 1bf8c96a5..8358fcd46 100644 --- a/kyaml/yaml/types_test.go +++ b/kyaml/yaml/types_test.go @@ -61,3 +61,78 @@ func TestIsYNodeEmptySeq(t *testing.T) { t.Fatalf("a node with content isn't empty") } } + +func TestIsNameSpaceable1(t *testing.T) { + testCases := []struct { + tm TypeMeta + isNamespaceable bool + }{ + { + tm: TypeMeta{Kind: "ClusterRole"}, + isNamespaceable: false, + }, + { + tm: TypeMeta{Kind: "Namespace"}, + isNamespaceable: false, + }, + { + tm: TypeMeta{Kind: "Deployment"}, + isNamespaceable: true, + }, + } + for _, tc := range testCases { + if tc.tm.IsNamespaceable() { + if !tc.isNamespaceable { + t.Fatalf("%v is namespaceable, but shouldn't be", tc.tm) + } + } else { + if tc.isNamespaceable { + t.Fatalf("%v is not namespaceable, but should be", tc.tm) + } + } + } +} + +func TestIsNameSpaceable2(t *testing.T) { + testCases := []struct { + yammy string + isNamespaceable bool + }{ + { + yammy: `apiVersion: apps/v1 +kind: Deployment +metadata: + name: bilbo + namespace: middleEarth +`, + isNamespaceable: true, + }, + { + yammy: `apiVersion: v1 +kind: Namespace +metadata: + name: middleEarth +`, + isNamespaceable: false, + }, + } + for _, tc := range testCases { + rn, err := Parse(tc.yammy) + if err != nil { + t.Fatalf("unexpected parse error %v from json: %s", err, tc.yammy) + } + meta, err := rn.GetMeta() + if err != nil { + t.Fatalf("unexpected meta error %v", err) + } + if meta.IsNamespaceable() { + if !tc.isNamespaceable { + t.Fatalf("%v is namespaceable, but shouldn't be", meta) + } + } else { + if tc.isNamespaceable { + t.Fatalf("%v is not namespaceable, but should be", meta) + } + } + } +}