...

Source file src/k8s.io/kubectl/pkg/util/prune/prune.go

Documentation: k8s.io/kubectl/pkg/util/prune

     1  /*
     2  Copyright 2017 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package prune
    18  
    19  import (
    20  	"fmt"
    21  	"strings"
    22  
    23  	"k8s.io/apimachinery/pkg/api/meta"
    24  	"k8s.io/apimachinery/pkg/runtime/schema"
    25  	"k8s.io/klog/v2"
    26  )
    27  
    28  // default allowlist of namespaced resources
    29  var defaultNamespacedPruneResources = []Resource{
    30  	{"", "v1", "ConfigMap", true},
    31  	{"", "v1", "Endpoints", true},
    32  	{"", "v1", "PersistentVolumeClaim", true},
    33  	{"", "v1", "Pod", true},
    34  	{"", "v1", "ReplicationController", true},
    35  	{"", "v1", "Secret", true},
    36  	{"", "v1", "Service", true},
    37  	{"batch", "v1", "Job", true},
    38  	{"batch", "v1", "CronJob", true},
    39  	{"networking.k8s.io", "v1", "Ingress", true},
    40  	{"apps", "v1", "DaemonSet", true},
    41  	{"apps", "v1", "Deployment", true},
    42  	{"apps", "v1", "ReplicaSet", true},
    43  	{"apps", "v1", "StatefulSet", true},
    44  }
    45  
    46  // default allowlist of non-namespaced resources
    47  var defaultNonNamespacedPruneResources = []Resource{
    48  	{"", "v1", "Namespace", false},
    49  	{"", "v1", "PersistentVolume", false},
    50  }
    51  
    52  type Resource struct {
    53  	group      string
    54  	version    string
    55  	kind       string
    56  	namespaced bool
    57  }
    58  
    59  func (pr Resource) String() string {
    60  	return fmt.Sprintf("%v/%v, Kind=%v, Namespaced=%v", pr.group, pr.version, pr.kind, pr.namespaced)
    61  }
    62  
    63  // if namespace is explicitly specified, the default allow list should not include non-namespaced resources.
    64  // if pruneResources is specified by user, respect the user setting.
    65  func GetRESTMappings(mapper meta.RESTMapper, pruneResources []Resource, namespaceSpecified bool) (namespaced, nonNamespaced []*meta.RESTMapping, err error) {
    66  	if len(pruneResources) == 0 {
    67  		pruneResources = defaultNamespacedPruneResources
    68  		// TODO in kubectl v1.29, add back non-namespaced resource only if namespace is not specified
    69  		pruneResources = append(pruneResources, defaultNonNamespacedPruneResources...)
    70  		if namespaceSpecified {
    71  			klog.Warning("Deprecated: kubectl apply will no longer prune non-namespaced resources by default when used with the --namespace flag in a future release. To preserve the current behaviour, list the resources you want to target explicitly in the --prune-allowlist flag.")
    72  		}
    73  	}
    74  
    75  	for _, resource := range pruneResources {
    76  		addedMapping, err := mapper.RESTMapping(schema.GroupKind{Group: resource.group, Kind: resource.kind}, resource.version)
    77  		if err != nil {
    78  			return nil, nil, fmt.Errorf("invalid resource %v: %v", resource, err)
    79  		}
    80  		if resource.namespaced {
    81  			namespaced = append(namespaced, addedMapping)
    82  		} else {
    83  			nonNamespaced = append(nonNamespaced, addedMapping)
    84  		}
    85  	}
    86  
    87  	return namespaced, nonNamespaced, nil
    88  }
    89  
    90  func ParseResources(mapper meta.RESTMapper, gvks []string) ([]Resource, error) {
    91  	pruneResources := []Resource{}
    92  	for _, groupVersionKind := range gvks {
    93  		gvk := strings.Split(groupVersionKind, "/")
    94  		if len(gvk) != 3 {
    95  			return nil, fmt.Errorf("invalid GroupVersionKind format: %v, please follow <group/version/kind>", groupVersionKind)
    96  		}
    97  
    98  		if gvk[0] == "core" {
    99  			gvk[0] = ""
   100  		}
   101  		mapping, err := mapper.RESTMapping(schema.GroupKind{Group: gvk[0], Kind: gvk[2]}, gvk[1])
   102  		if err != nil {
   103  			return pruneResources, err
   104  		}
   105  		var namespaced bool
   106  		namespaceScope := mapping.Scope.Name()
   107  		switch namespaceScope {
   108  		case meta.RESTScopeNameNamespace:
   109  			namespaced = true
   110  		case meta.RESTScopeNameRoot:
   111  			namespaced = false
   112  		default:
   113  			return pruneResources, fmt.Errorf("Unknown namespace scope: %q", namespaceScope)
   114  		}
   115  
   116  		pruneResources = append(pruneResources, Resource{gvk[0], gvk[1], gvk[2], namespaced})
   117  	}
   118  	return pruneResources, nil
   119  }
   120  

View as plain text