Skip to content

Commit

Permalink
feat(process): honor cluster-wide for k8s default objects (#320)
Browse files Browse the repository at this point in the history
No longer attaches namespaces to known cluster-wide objects. This is done by maintaining a static list of those in the source code. This is limited to those objects included in a clean, stock install of the latest Kubernetes version. 
For CRDs, the annotation must be used.
  • Loading branch information
captncraig authored Jul 16, 2020
1 parent 70c2cb3 commit 651e020
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 6 deletions.
11 changes: 6 additions & 5 deletions docs/docs/namespaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ legit cases where it's handy to have them span multiple namespaces, for example:

Some resources in Kubernetes are cluster-wide, meaning they don't belong to a single namespace at all.

To Tanka these appear as _Scenario 1 (see above)_, so it will set the default
namespace. In reality however, this is **not a problem**, because `kubectl`
discards this information silently. We made this design-choice, because it
simplifies our code a lot.
Tanka will make an attempt to not add namespaces to *known* cluster-wide types.
It does this with a short list of types in [the source code](https://github.com/grafana/tanka/blob/master/pkg/process/namespace.go).

In case this ever becomes a problem, you can **override this** behavior
Tanka cannot feasably maintain this list for all known custom resource types. In those cases, resources will have namespaces added to their manifests,
and kubectl should happily apply them as non-namespaced resources.

If this presents a problem for your workflow, you can **override this** behavior
per-resource, by setting the `tanka.dev/namespaced` annotation to `"false"`
(must be of `string` type):

Expand Down
34 changes: 33 additions & 1 deletion pkg/process/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,36 @@ const (
AnnotationNamespaced = MetadataPrefix + "/namespaced"
)

// This is a list of "cluster-wide" resources harvested from `kubectl api-resources --namespaced=false`
// This helps us to know which objects we should NOT apply namespaces to automatically.
// We can add to this list periodically if new types are added.
// This only applies to built-in kubernetes types. CRDs will need to be handled with annotations.
var clusterWideKinds = map[string]bool{
"APIService": true,
"CertificateSigningRequest": true,
"ClusterRole": true,
"ClusterRoleBinding": true,
"ComponentStatus": true,
"CSIDriver": true,
"CSINode": true,
"CustomResourceDefinition": true,
"MutatingWebhookConfiguration": true,
"Namespace": true,
"Node": true,
"NodeMetrics": true,
"PersistentVolume": true,
"PodSecurityPolicy": true,
"PriorityClass": true,
"RuntimeClass": true,
"SelfSubjectAccessReview": true,
"SelfSubjectRulesReview": true,
"StorageClass": true,
"SubjectAccessReview": true,
"TokenReview": true,
"ValidatingWebhookConfiguration": true,
"VolumeAttachment": true,
}

// Namespace injects the default namespace of the environment into each
// resources, that does not already define one. AnnotationNamespaced can be used
// to disable this per resource
Expand All @@ -20,7 +50,9 @@ func Namespace(list manifest.List, def string) manifest.List {

for i, m := range list {
namespaced := true

if clusterWideKinds[m.Kind()] {
namespaced = false
}
// check for annotation override
if s, ok := m.Metadata().Annotations()[AnnotationNamespaced]; ok {
namespaced = s == "true"
Expand Down

0 comments on commit 651e020

Please sign in to comment.