ClusterRoles

// ClusterRoles returns the cluster roles to bootstrap an API server with
func ClusterRoles() []rbacv1.ClusterRole {
	roles := []rbacv1.ClusterRole{
		{
			// a "root" role which can do absolutely anything
			ObjectMeta: metav1.ObjectMeta{Name: "cluster-admin"},
			Rules: []rbacv1.PolicyRule{
				rbacv1helpers.NewRule("*").Groups("*").Resources("*").RuleOrDie(),
				rbacv1helpers.NewRule("*").URLs("*").RuleOrDie(),
			},
		},
		{
			// a role which provides just enough power to determine if the server is
			// ready and discover API versions for negotiation
			ObjectMeta: metav1.ObjectMeta{Name: "system:discovery"},
			Rules: []rbacv1.PolicyRule{
				rbacv1helpers.NewRule("get").URLs(
					"/livez", "/readyz", "/healthz",
					"/version", "/version/",
					"/openapi", "/openapi/*",
					"/api", "/api/*",
					"/apis", "/apis/*",
				).RuleOrDie(),
			},
		},
		{
			// a role which provides minimal read access to the monitoring endpoints
			// (i.e. /metrics, /livez/*, /readyz/*, /healthz/*, /livez, /readyz, /healthz)
			// The splatted health check endpoints allow read access to individual health check
			// endpoints which may contain more sensitive cluster information information
			ObjectMeta: metav1.ObjectMeta{Name: "system:monitoring"},
			Rules: []rbacv1.PolicyRule{
				rbacv1helpers.NewRule("get").URLs(
					"/metrics", "/metrics/slis",
					"/livez", "/readyz", "/healthz",
					"/livez/*", "/readyz/*", "/healthz/*",
				).RuleOrDie(),
			},
		},
	}

	basicUserRules := []rbacv1.PolicyRule{
		rbacv1helpers.NewRule("create").Groups(authorizationGroup).Resources("selfsubjectaccessreviews", "selfsubjectrulesreviews").RuleOrDie(),
	}

	if utilfeature.DefaultFeatureGate.Enabled(features.APISelfSubjectReview) {
		basicUserRules = append(basicUserRules, rbacv1helpers.NewRule("create").Groups(authenticationGroup).Resources("selfsubjectreviews").RuleOrDie())
	}

	roles = append(roles, []rbacv1.ClusterRole{
		{
			// a role which provides minimal resource access to allow a "normal" user to learn information about themselves
			ObjectMeta: metav1.ObjectMeta{Name: "system:basic-user"},
			Rules:      basicUserRules,
		},
		{
			// a role which provides just enough power read insensitive cluster information
			ObjectMeta: metav1.ObjectMeta{Name: "system:public-info-viewer"},
			Rules: []rbacv1.PolicyRule{
				rbacv1helpers.NewRule("get").URLs(
					"/livez", "/readyz", "/healthz", "/version", "/version/",
				).RuleOrDie(),
			},
		},
		{
			// a role for a namespace level admin.  It is `edit` plus the power to grant permissions to other users.
			ObjectMeta: metav1.ObjectMeta{Name: "admin"},
			AggregationRule: &rbacv1.AggregationRule{
				ClusterRoleSelectors: []metav1.LabelSelector{
					{MatchLabels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-admin": "true"}},
				},
			},
		},
		{
			// a role for a namespace level editor.  It grants access to all user level actions in a namespace.
			// It does not grant powers for "privileged" resources which are domain of the system: `/status`
			// subresources or `quota`/`limits` which are used to control namespaces
			ObjectMeta: metav1.ObjectMeta{Name: "edit", Labels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-admin": "true"}},
			AggregationRule: &rbacv1.AggregationRule{
				ClusterRoleSelectors: []metav1.LabelSelector{
					{MatchLabels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-edit": "true"}},
				},
			},
		},
		{
			// a role for namespace level viewing.  It grants Read-only access to non-escalating resources in
			// a namespace.
			ObjectMeta: metav1.ObjectMeta{Name: "view", Labels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-edit": "true"}},
			AggregationRule: &rbacv1.AggregationRule{
				ClusterRoleSelectors: []metav1.LabelSelector{
					{MatchLabels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-view": "true"}},
				},
			},
		},
		{
			// a role for a namespace level admin.  It is `edit` plus the power to grant permissions to other users.
			ObjectMeta: metav1.ObjectMeta{Name: "system:aggregate-to-admin", Labels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-admin": "true"}},
			Rules: []rbacv1.PolicyRule{
				// additional admin powers
				rbacv1helpers.NewRule("create").Groups(authorizationGroup).Resources("localsubjectaccessreviews").RuleOrDie(),
				rbacv1helpers.NewRule(ReadWrite...).Groups(rbacGroup).Resources("roles", "rolebindings").RuleOrDie(),
			},
		},
		{
			// a role for a namespace level editor.  It grants access to all user level actions in a namespace.
			// It does not grant powers for "privileged" resources which are domain of the system: `/status`
			// subresources or `quota`/`limits` which are used to control namespaces
			ObjectMeta: metav1.ObjectMeta{Name: "system:aggregate-to-edit", Labels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-edit": "true"}},
			Rules: []rbacv1.PolicyRule{
				// Allow read on escalating resources
				rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("pods/attach", "pods/proxy", "pods/exec", "pods/portforward", "secrets", "services/proxy").RuleOrDie(),
				rbacv1helpers.NewRule("impersonate").Groups(legacyGroup).Resources("serviceaccounts").RuleOrDie(),

				rbacv1helpers.NewRule(Write...).Groups(legacyGroup).Resources("pods", "pods/attach", "pods/proxy", "pods/exec", "pods/portforward").RuleOrDie(),
				rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("pods/eviction").RuleOrDie(),
				rbacv1helpers.NewRule(Write...).Groups(legacyGroup).Resources("replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts",
					"services", "services/proxy", "persistentvolumeclaims", "configmaps", "secrets", "events").RuleOrDie(),
				rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("serviceaccounts/token").RuleOrDie(),

				rbacv1helpers.NewRule(Write...).Groups(appsGroup).Resources(
					"statefulsets", "statefulsets/scale",
					"daemonsets",
					"deployments", "deployments/scale", "deployments/rollback",
					"replicasets", "replicasets/scale").RuleOrDie(),

				rbacv1helpers.NewRule(Write...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(),

				rbacv1helpers.NewRule(Write...).Groups(batchGroup).Resources("jobs", "cronjobs").RuleOrDie(),

				rbacv1helpers.NewRule(Write...).Groups(extensionsGroup).Resources("daemonsets",
					"deployments", "deployments/scale", "deployments/rollback", "ingresses",
					"replicasets", "replicasets/scale", "replicationcontrollers/scale",
					"networkpolicies").RuleOrDie(),

				rbacv1helpers.NewRule(Write...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(),

				rbacv1helpers.NewRule(Write...).Groups(networkingGroup).Resources("networkpolicies", "ingresses").RuleOrDie(),

				rbacv1helpers.NewRule(ReadWrite...).Groups(coordinationGroup).Resources("leases").RuleOrDie(),
			},
		},
		{
			// a role for namespace level viewing.  It grants Read-only access to non-escalating resources in
			// a namespace.
			ObjectMeta: metav1.ObjectMeta{Name: "system:aggregate-to-view", Labels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-view": "true"}},
			Rules: []rbacv1.PolicyRule{
				rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("pods", "replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts",
					"services", "services/status", "endpoints", "persistentvolumeclaims", "persistentvolumeclaims/status", "configmaps").RuleOrDie(),
				rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("limitranges", "resourcequotas", "bindings", "events",
					"pods/status", "resourcequotas/status", "namespaces/status", "replicationcontrollers/status", "pods/log").RuleOrDie(),
				// read access to namespaces at the namespace scope means you can read *this* namespace.  This can be used as an
				// indicator of which namespaces you have access to.
				rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("namespaces").RuleOrDie(),

				rbacv1helpers.NewRule(Read...).Groups(discoveryGroup).Resources("endpointslices").RuleOrDie(),

				rbacv1helpers.NewRule(Read...).Groups(appsGroup).Resources(
					"controllerrevisions",
					"statefulsets", "statefulsets/status", "statefulsets/scale",
					"daemonsets", "daemonsets/status",
					"deployments", "deployments/status", "deployments/scale",
					"replicasets", "replicasets/status", "replicasets/scale").RuleOrDie(),

				rbacv1helpers.NewRule(Read...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers", "horizontalpodautoscalers/status").RuleOrDie(),

				rbacv1helpers.NewRule(Read...).Groups(batchGroup).Resources("jobs", "cronjobs", "cronjobs/status", "jobs/status").RuleOrDie(),

				rbacv1helpers.NewRule(Read...).Groups(extensionsGroup).Resources("daemonsets", "daemonsets/status", "deployments", "deployments/scale", "deployments/status",
					"ingresses", "ingresses/status", "replicasets", "replicasets/scale", "replicasets/status", "replicationcontrollers/scale",
					"networkpolicies").RuleOrDie(),

				rbacv1helpers.NewRule(Read...).Groups(policyGroup).Resources("poddisruptionbudgets", "poddisruptionbudgets/status").RuleOrDie(),

				rbacv1helpers.NewRule(Read...).Groups(networkingGroup).Resources("networkpolicies", "ingresses", "ingresses/status").RuleOrDie(),
			},
		},
		{
			// a role to use for heapster's connections back to the API server
			ObjectMeta: metav1.ObjectMeta{Name: "system:heapster"},
			Rules: []rbacv1.PolicyRule{
				rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("events", "pods", "nodes", "namespaces").RuleOrDie(),
				rbacv1helpers.NewRule(Read...).Groups(extensionsGroup).Resources("deployments").RuleOrDie(),
			},
		},
		{
			// a role for nodes to use to have the access they need for running pods
			ObjectMeta: metav1.ObjectMeta{Name: systemNodeRoleName},
			Rules:      NodeRules(),
		},
		{
			// a role to use for node-problem-detector access.  It does not get bound to default location since
			// deployment locations can reasonably vary.
			ObjectMeta: metav1.ObjectMeta{Name: "system:node-problem-detector"},
			Rules: []rbacv1.PolicyRule{
				rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
				rbacv1helpers.NewRule("patch").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(),
				eventsRule(),
			},
		},
		{
			// a role to use for full access to the kubelet API
			ObjectMeta: metav1.ObjectMeta{Name: "system:kubelet-api-admin"},
			Rules: []rbacv1.PolicyRule{
				// Allow read-only access to the Node API objects
				rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
				// Allow all API calls to the nodes
				rbacv1helpers.NewRule("proxy").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
				rbacv1helpers.NewRule("*").Groups(legacyGroup).Resources("nodes/proxy", "nodes/metrics", "nodes/stats", "nodes/log").RuleOrDie(),
			},
		},
		{
			// a role to use for bootstrapping a node's client certificates
			ObjectMeta: metav1.ObjectMeta{Name: "system:node-bootstrapper"},
			Rules: []rbacv1.PolicyRule{
				// used to create a certificatesigningrequest for a node-specific client certificate, and watch for it to be signed
				rbacv1helpers.NewRule("create", "get", "list", "watch").Groups(certificatesGroup).Resources("certificatesigningrequests").RuleOrDie(),
			},
		},
		{
			// a role to use for allowing authentication and authorization delegation
			ObjectMeta: metav1.ObjectMeta{Name: "system:auth-delegator"},
			Rules: []rbacv1.PolicyRule{
				// These creates are non-mutating
				rbacv1helpers.NewRule("create").Groups(authenticationGroup).Resources("tokenreviews").RuleOrDie(),
				rbacv1helpers.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews").RuleOrDie(),
			},
		},
		{
			// a role to use for the API registry, summarization, and proxy handling
			ObjectMeta: metav1.ObjectMeta{Name: "system:kube-aggregator"},
			Rules: []rbacv1.PolicyRule{
				// it needs to see all services so that it knows whether the ones it points to exist or not
				rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(),
			},
		},
		{
			// a role to use for bootstrapping the kube-controller-manager so it can create the shared informers
			// service accounts, and secrets that we need to create separate identities for other controllers
			ObjectMeta: metav1.ObjectMeta{Name: "system:kube-controller-manager"},
			Rules: []rbacv1.PolicyRule{
				eventsRule(),
				// Needed for leader election.
				rbacv1helpers.NewRule("create").Groups(coordinationGroup).Resources("leases").RuleOrDie(),
				rbacv1helpers.NewRule("get", "update").Groups(coordinationGroup).Resources("leases").Names("kube-controller-manager").RuleOrDie(),
				// TODO: Remove once we fully migrate to lease in leader-election.
				rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("endpoints").RuleOrDie(),
				rbacv1helpers.NewRule("get", "update").Groups(legacyGroup).Resources("endpoints").Names("kube-controller-manager").RuleOrDie(),
				// Fundamental resources.
				rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("secrets", "serviceaccounts").RuleOrDie(),
				rbacv1helpers.NewRule("delete").Groups(legacyGroup).Resources("secrets").RuleOrDie(),
				rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("namespaces", "secrets", "serviceaccounts", "configmaps").RuleOrDie(),
				rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("secrets", "serviceaccounts").RuleOrDie(),
				// Needed to check API access.  These creates are non-mutating
				rbacv1helpers.NewRule("create").Groups(authenticationGroup).Resources("tokenreviews").RuleOrDie(),
				rbacv1helpers.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews").RuleOrDie(),
				// Needed for all shared informers
				rbacv1helpers.NewRule("list", "watch").Groups("*").Resources("*").RuleOrDie(),
				rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("serviceaccounts/token").RuleOrDie(),
			},
		},
		{
			// a role to use for the kube-dns pod
			ObjectMeta: metav1.ObjectMeta{Name: "system:kube-dns"},
			Rules: []rbacv1.PolicyRule{
				rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("endpoints", "services").RuleOrDie(),
			},
		},
		{
			// a role for an external/out-of-tree persistent volume provisioner
			ObjectMeta: metav1.ObjectMeta{Name: "system:persistent-volume-provisioner"},
			Rules: []rbacv1.PolicyRule{
				rbacv1helpers.NewRule("get", "list", "watch", "create", "delete").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(),
				// update is needed in addition to read access for setting lock annotations on PVCs
				rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(),
				rbacv1helpers.NewRule(Read...).Groups(storageGroup).Resources("storageclasses").RuleOrDie(),

				// Needed for watching provisioning success and failure events
				rbacv1helpers.NewRule("watch").Groups(legacyGroup).Resources("events").RuleOrDie(),

				eventsRule(),
			},
		},
		{
			// a role making the csrapprover controller approve a node client CSR
			ObjectMeta: metav1.ObjectMeta{Name: "system:certificates.k8s.io:certificatesigningrequests:nodeclient"},
			Rules: []rbacv1.PolicyRule{
				rbacv1helpers.NewRule("create").Groups(certificatesGroup).Resources("certificatesigningrequests/nodeclient").RuleOrDie(),
			},
		},
		{
			// a role making the csrapprover controller approve a node client CSR requested by the node itself
			ObjectMeta: metav1.ObjectMeta{Name: "system:certificates.k8s.io:certificatesigningrequests:selfnodeclient"},
			Rules: []rbacv1.PolicyRule{
				rbacv1helpers.NewRule("create").Groups(certificatesGroup).Resources("certificatesigningrequests/selfnodeclient").RuleOrDie(),
			},
		},
		{
			ObjectMeta: metav1.ObjectMeta{Name: "system:volume-scheduler"},
			Rules: []rbacv1.PolicyRule{
				rbacv1helpers.NewRule(ReadUpdate...).Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(),
				rbacv1helpers.NewRule(Read...).Groups(storageGroup).Resources("storageclasses").RuleOrDie(),
				rbacv1helpers.NewRule(ReadUpdate...).Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(),
			},
		},
		{
			ObjectMeta: metav1.ObjectMeta{Name: "system:certificates.k8s.io:legacy-unknown-approver"},
			Rules: []rbacv1.PolicyRule{
				rbacv1helpers.NewRule("approve").Groups(certificatesGroup).Resources("signers").Names(capi.LegacyUnknownSignerName).RuleOrDie(),
			},
		},
		{
			ObjectMeta: metav1.ObjectMeta{Name: "system:certificates.k8s.io:kubelet-serving-approver"},
			Rules: []rbacv1.PolicyRule{
				rbacv1helpers.NewRule("approve").Groups(certificatesGroup).Resources("signers").Names(capi.KubeletServingSignerName).RuleOrDie(),
			},
		},
		{
			ObjectMeta: metav1.ObjectMeta{Name: "system:certificates.k8s.io:kube-apiserver-client-approver"},
			Rules: []rbacv1.PolicyRule{
				rbacv1helpers.NewRule("approve").Groups(certificatesGroup).Resources("signers").Names(capi.KubeAPIServerClientSignerName).RuleOrDie(),
			},
		},
		{
			ObjectMeta: metav1.ObjectMeta{Name: "system:certificates.k8s.io:kube-apiserver-client-kubelet-approver"},
			Rules: []rbacv1.PolicyRule{
				rbacv1helpers.NewRule("approve").Groups(certificatesGroup).Resources("signers").Names(capi.KubeAPIServerClientKubeletSignerName).RuleOrDie(),
			},
		},
	}...)

	// Add the cluster role for reading the ServiceAccountIssuerDiscovery endpoints
	roles = append(roles, rbacv1.ClusterRole{
		ObjectMeta: metav1.ObjectMeta{Name: "system:service-account-issuer-discovery"},
		Rules: []rbacv1.PolicyRule{
			rbacv1helpers.NewRule("get").URLs(
				"/.well-known/openid-configuration",
				"/openid/v1/jwks",
			).RuleOrDie(),
		},
	})

	// node-proxier role is used by kube-proxy.
	nodeProxierRules := []rbacv1.PolicyRule{
		rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(),
		rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),

		eventsRule(),
	}
	nodeProxierRules = append(nodeProxierRules, rbacv1helpers.NewRule("list", "watch").Groups(discoveryGroup).Resources("endpointslices").RuleOrDie())
	roles = append(roles, rbacv1.ClusterRole{
		ObjectMeta: metav1.ObjectMeta{Name: "system:node-proxier"},
		Rules:      nodeProxierRules,
	})

	kubeSchedulerRules := []rbacv1.PolicyRule{
		eventsRule(),
		// This is for leaderlease access
		// TODO: scope this to the kube-system namespace
		rbacv1helpers.NewRule("create").Groups(coordinationGroup).Resources("leases").RuleOrDie(),
		rbacv1helpers.NewRule("get", "update").Groups(coordinationGroup).Resources("leases").Names("kube-scheduler").RuleOrDie(),
		// TODO: Remove once we fully migrate to lease in leader-election.
		rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("endpoints").RuleOrDie(),
		rbacv1helpers.NewRule("get", "update").Groups(legacyGroup).Resources("endpoints").Names("kube-scheduler").RuleOrDie(),

		// Fundamental resources
		rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("nodes").RuleOrDie(),
		rbacv1helpers.NewRule("get", "list", "watch", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(),
		rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("pods/binding", "bindings").RuleOrDie(),
		rbacv1helpers.NewRule("patch", "update").Groups(legacyGroup).Resources("pods/status").RuleOrDie(),
		// Things that select pods
		rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("services", "replicationcontrollers").RuleOrDie(),
		rbacv1helpers.NewRule(Read...).Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(),
		rbacv1helpers.NewRule(Read...).Groups(appsGroup).Resources("statefulsets").RuleOrDie(),
		// Things that pods use or applies to them
		rbacv1helpers.NewRule(Read...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(),
		rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("persistentvolumeclaims", "persistentvolumes").RuleOrDie(),
		// Needed to check API access. These creates are non-mutating
		rbacv1helpers.NewRule("create").Groups(authenticationGroup).Resources("tokenreviews").RuleOrDie(),
		rbacv1helpers.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews").RuleOrDie(),
		// Needed for volume limits
		rbacv1helpers.NewRule(Read...).Groups(storageGroup).Resources("csinodes").RuleOrDie(),
		// Needed for namespaceSelector feature in pod affinity
		rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("namespaces").RuleOrDie(),
		rbacv1helpers.NewRule(Read...).Groups(storageGroup).Resources("csidrivers").RuleOrDie(),
		rbacv1helpers.NewRule(Read...).Groups(storageGroup).Resources("csistoragecapacities").RuleOrDie(),
	}
	// Needed for dynamic resource allocation.
	if utilfeature.DefaultFeatureGate.Enabled(features.DynamicResourceAllocation) {
		kubeSchedulerRules = append(kubeSchedulerRules,
			rbacv1helpers.NewRule(Read...).Groups(resourceGroup).Resources("resourceclaims", "resourceclasses").RuleOrDie(),
			rbacv1helpers.NewRule(ReadUpdate...).Groups(resourceGroup).Resources("resourceclaims/status").RuleOrDie(),
			rbacv1helpers.NewRule(ReadWrite...).Groups(resourceGroup).Resources("podschedulingcontexts").RuleOrDie(),
			rbacv1helpers.NewRule(Read...).Groups(resourceGroup).Resources("podschedulingcontexts/status").RuleOrDie(),
		)
	}
	roles = append(roles, rbacv1.ClusterRole{
		// a role to use for the kube-scheduler
		ObjectMeta: metav1.ObjectMeta{Name: "system:kube-scheduler"},
		Rules:      kubeSchedulerRules,
	})

	// Default ClusterRole to allow reading ClusterTrustBundle objects
	if utilfeature.DefaultFeatureGate.Enabled(features.ClusterTrustBundle) {
		roles = append(roles, rbacv1.ClusterRole{
			ObjectMeta: metav1.ObjectMeta{Name: "system:cluster-trust-bundle-discovery"},
			Rules: []rbacv1.PolicyRule{
				rbacv1helpers.NewRule(Read...).Groups(certificatesGroup).Resources("clustertrustbundles").RuleOrDie(),
			},
		})
	}

	addClusterRoleLabel(roles)
	return roles
}


ClusterRoleBindings

// ClusterRoleBindings return default rolebindings to the default roles
func ClusterRoleBindings() []rbacv1.ClusterRoleBinding {
	rolebindings := []rbacv1.ClusterRoleBinding{
		rbacv1helpers.NewClusterBinding("cluster-admin").Groups(user.SystemPrivilegedGroup).BindingOrDie(),
		rbacv1helpers.NewClusterBinding("system:monitoring").Groups(user.MonitoringGroup).BindingOrDie(),
		rbacv1helpers.NewClusterBinding("system:discovery").Groups(user.AllAuthenticated).BindingOrDie(),
		rbacv1helpers.NewClusterBinding("system:basic-user").Groups(user.AllAuthenticated).BindingOrDie(),
		rbacv1helpers.NewClusterBinding("system:public-info-viewer").Groups(user.AllAuthenticated, user.AllUnauthenticated).BindingOrDie(),
		rbacv1helpers.NewClusterBinding("system:node-proxier").Users(user.KubeProxy).BindingOrDie(),
		rbacv1helpers.NewClusterBinding("system:kube-controller-manager").Users(user.KubeControllerManager).BindingOrDie(),
		rbacv1helpers.NewClusterBinding("system:kube-dns").SAs("kube-system", "kube-dns").BindingOrDie(),
		rbacv1helpers.NewClusterBinding("system:kube-scheduler").Users(user.KubeScheduler).BindingOrDie(),
		rbacv1helpers.NewClusterBinding("system:volume-scheduler").Users(user.KubeScheduler).BindingOrDie(),

		// This default binding of the system:node role to the system:nodes group is deprecated in 1.7 with the availability of the Node authorizer.
		// This leaves the binding, but with an empty set of subjects, so that tightening reconciliation can remove the subject.
		{
			ObjectMeta: metav1.ObjectMeta{Name: systemNodeRoleName},
			RoleRef:    rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "ClusterRole", Name: systemNodeRoleName},
		},
	}

	// Allow all in-cluster workloads (via their service accounts) to read the OIDC discovery endpoints.
	// Users with certain forms of write access (create pods, create secrets, create service accounts, etc)
	// can gain access to a service account identity which would allow them to access this information.
	// This includes the issuer URL, which is already present in the SA token JWT.  Similarly, SAs can
	// already gain this same info via introspection of their own token.  Since this discovery endpoint
	// points to what issued all service account tokens, it seems fitting for SAs to have this access.
	// Defer to the cluster admin with regard to binding directly to all authenticated and/or
	// unauthenticated users.
	rolebindings = append(rolebindings,
		rbacv1helpers.NewClusterBinding("system:service-account-issuer-discovery").Groups(serviceaccount.AllServiceAccountsGroup).BindingOrDie(),
	)

	// Service accounts can read ClusterTrustBundle objects.
	if utilfeature.DefaultFeatureGate.Enabled(features.ClusterTrustBundle) {
		rolebindings = append(rolebindings, rbacv1helpers.NewClusterBinding("system:cluster-trust-bundle-discovery").Groups(serviceaccount.AllServiceAccountsGroup).BindingOrDie())
	}

	addClusterRoleBindingLabel(rolebindings)

	return rolebindings
}


ClusterRolesToAggregate

// ClusterRolesToAggregate maps from previous clusterrole name to the new clusterrole name
func ClusterRolesToAggregate() map[string]string {
	return map[string]string{
		"admin": "system:aggregate-to-admin",
		"edit":  "system:aggregate-to-edit",
		"view":  "system:aggregate-to-view",
	}
}


ClusterRoleBindingsToSplit

// ClusterRoleBindingsToSplit returns a map of Names of source ClusterRoleBindings
// to copy Subjects, Annotations, and Labels to destination ClusterRoleBinding templates.
func ClusterRoleBindingsToSplit() map[string]rbacv1.ClusterRoleBinding {
	bindingsToSplit := map[string]rbacv1.ClusterRoleBinding{}
	for _, defaultClusterRoleBinding := range ClusterRoleBindings() {
		switch defaultClusterRoleBinding.Name {
		case "system:public-info-viewer":
			bindingsToSplit["system:discovery"] = defaultClusterRoleBinding
		}
	}
	return bindingsToSplit
}


visit

func (v *authorizingVisitor) visit(source fmt.Stringer, rule *rbacv1.PolicyRule, err error) bool {
	if rule != nil && RuleAllows(v.requestAttributes, rule) {
		v.allowed = true
		v.reason = fmt.Sprintf("RBAC: allowed by %s", source.String())
		return false
	}
	if err != nil {
		v.errors = append(v.errors, err)
	}
	return true
}


Authorize

func (r *RBACAuthorizer) Authorize(ctx context.Context, requestAttributes authorizer.Attributes) (authorizer.Decision, string, error) {
	ruleCheckingVisitor := &authorizingVisitor{requestAttributes: requestAttributes}

	r.authorizationRuleResolver.VisitRulesFor(requestAttributes.GetUser(), requestAttributes.GetNamespace(), ruleCheckingVisitor.visit)
	if ruleCheckingVisitor.allowed {
		return authorizer.DecisionAllow, ruleCheckingVisitor.reason, nil
	}

	// Build a detailed log of the denial.
	// Make the whole block conditional so we don't do a lot of string-building we won't use.
	if klogV := klog.V(5); klogV.Enabled() {
		var operation string
		if requestAttributes.IsResourceRequest() {
			b := &bytes.Buffer{}
			b.WriteString(`"`)
			b.WriteString(requestAttributes.GetVerb())
			b.WriteString(`" resource "`)
			b.WriteString(requestAttributes.GetResource())
			if len(requestAttributes.GetAPIGroup()) > 0 {
				b.WriteString(`.`)
				b.WriteString(requestAttributes.GetAPIGroup())
			}
			if len(requestAttributes.GetSubresource()) > 0 {
				b.WriteString(`/`)
				b.WriteString(requestAttributes.GetSubresource())
			}
			b.WriteString(`"`)
			if len(requestAttributes.GetName()) > 0 {
				b.WriteString(` named "`)
				b.WriteString(requestAttributes.GetName())
				b.WriteString(`"`)
			}
			operation = b.String()
		} else {
			operation = fmt.Sprintf("%q nonResourceURL %q", requestAttributes.GetVerb(), requestAttributes.GetPath())
		}

		var scope string
		if ns := requestAttributes.GetNamespace(); len(ns) > 0 {
			scope = fmt.Sprintf("in namespace %q", ns)
		} else {
			scope = "cluster-wide"
		}

		klogV.Infof("RBAC: no rules authorize user %q with groups %q to %s %s", requestAttributes.GetUser().GetName(), requestAttributes.GetUser().GetGroups(), operation, scope)
	}

	reason := ""
	if len(ruleCheckingVisitor.errors) > 0 {
		reason = fmt.Sprintf("RBAC: %v", utilerrors.NewAggregate(ruleCheckingVisitor.errors))
	}
	return authorizer.DecisionNoOpinion, reason, nil
}


RulesFor

func (r *RBACAuthorizer) RulesFor(user user.Info, namespace string) ([]authorizer.ResourceRuleInfo, []authorizer.NonResourceRuleInfo, bool, error) {
	var (
		resourceRules    []authorizer.ResourceRuleInfo
		nonResourceRules []authorizer.NonResourceRuleInfo
	)

	policyRules, err := r.authorizationRuleResolver.RulesFor(user, namespace)
	for _, policyRule := range policyRules {
		if len(policyRule.Resources) > 0 {
			r := authorizer.DefaultResourceRuleInfo{
				Verbs:         policyRule.Verbs,
				APIGroups:     policyRule.APIGroups,
				Resources:     policyRule.Resources,
				ResourceNames: policyRule.ResourceNames,
			}
			var resourceRule authorizer.ResourceRuleInfo = &r
			resourceRules = append(resourceRules, resourceRule)
		}
		if len(policyRule.NonResourceURLs) > 0 {
			r := authorizer.DefaultNonResourceRuleInfo{
				Verbs:           policyRule.Verbs,
				NonResourceURLs: policyRule.NonResourceURLs,
			}
			var nonResourceRule authorizer.NonResourceRuleInfo = &r
			nonResourceRules = append(nonResourceRules, nonResourceRule)
		}
	}
	return resourceRules, nonResourceRules, false, err
}


New

func New(roles rbacregistryvalidation.RoleGetter, roleBindings rbacregistryvalidation.RoleBindingLister, clusterRoles rbacregistryvalidation.ClusterRoleGetter, clusterRoleBindings rbacregistryvalidation.ClusterRoleBindingLister) *RBACAuthorizer {
	authorizer := &RBACAuthorizer{
		authorizationRuleResolver: rbacregistryvalidation.NewDefaultRuleResolver(
			roles, roleBindings, clusterRoles, clusterRoleBindings,
		),
	}
	return authorizer
}


RulesAllow

func RulesAllow(requestAttributes authorizer.Attributes, rules ...rbacv1.PolicyRule) bool {
	for i := range rules {
		if RuleAllows(requestAttributes, &rules[i]) {
			return true
		}
	}

	return false
}


RuleAllows

func RuleAllows(requestAttributes authorizer.Attributes, rule *rbacv1.PolicyRule) bool {
	if requestAttributes.IsResourceRequest() {
		combinedResource := requestAttributes.GetResource()
		if len(requestAttributes.GetSubresource()) > 0 {
			combinedResource = requestAttributes.GetResource() + "/" + requestAttributes.GetSubresource()
		}

		return rbacv1helpers.VerbMatches(rule, requestAttributes.GetVerb()) &&
			rbacv1helpers.APIGroupMatches(rule, requestAttributes.GetAPIGroup()) &&
			rbacv1helpers.ResourceMatches(rule, combinedResource, requestAttributes.GetSubresource()) &&
			rbacv1helpers.ResourceNameMatches(rule, requestAttributes.GetName())
	}

	return rbacv1helpers.VerbMatches(rule, requestAttributes.GetVerb()) &&
		rbacv1helpers.NonResourceURLMatches(rule, requestAttributes.GetPath())
}


GetRole

func (g *RoleGetter) GetRole(namespace, name string) (*rbacv1.Role, error) {
	return g.Lister.Roles(namespace).Get(name)
}


ListRoleBindings

func (l *RoleBindingLister) ListRoleBindings(namespace string) ([]*rbacv1.RoleBinding, error) {
	return l.Lister.RoleBindings(namespace).List(labels.Everything())
}


GetClusterRole

func (g *ClusterRoleGetter) GetClusterRole(name string) (*rbacv1.ClusterRole, error) {
	return g.Lister.Get(name)
}


ListClusterRoleBindings

func (l *ClusterRoleBindingLister) ListClusterRoleBindings() ([]*rbacv1.ClusterRoleBinding, error) {
	return l.Lister.List(labels.Everything())
}


NewSubjectAccessEvaluator

func NewSubjectAccessEvaluator(roles rbacregistryvalidation.RoleGetter, roleBindings rbacregistryvalidation.RoleBindingLister, clusterRoles rbacregistryvalidation.ClusterRoleGetter, clusterRoleBindings rbacregistryvalidation.ClusterRoleBindingLister, superUser string) *SubjectAccessEvaluator {
	subjectLocator := &SubjectAccessEvaluator{
		superUser:                superUser,
		roleBindingLister:        roleBindings,
		clusterRoleBindingLister: clusterRoleBindings,
		roleToRuleMapper: rbacregistryvalidation.NewDefaultRuleResolver(
			roles, roleBindings, clusterRoles, clusterRoleBindings,
		),
	}
	return subjectLocator
}


AllowedSubjects

// AllowedSubjects returns the subjects that can perform an action and any errors encountered while computing the list.
// It is possible to have both subjects and errors returned if some rolebindings couldn't be resolved, but others could be.
func (r *SubjectAccessEvaluator) AllowedSubjects(requestAttributes authorizer.Attributes) ([]rbacv1.Subject, error) {
	subjects := []rbacv1.Subject{{Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: user.SystemPrivilegedGroup}}
	if len(r.superUser) > 0 {
		subjects = append(subjects, rbacv1.Subject{Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: r.superUser})
	}
	errorlist := []error{}

	if clusterRoleBindings, err := r.clusterRoleBindingLister.ListClusterRoleBindings(); err != nil {
		errorlist = append(errorlist, err)

	} else {
		for _, clusterRoleBinding := range clusterRoleBindings {
			rules, err := r.roleToRuleMapper.GetRoleReferenceRules(clusterRoleBinding.RoleRef, "")
			if err != nil {
				// if we have an error, just keep track of it and keep processing.  Since rules are additive,
				// missing a reference is bad, but we can continue with other rolebindings and still have a list
				// that does not contain any invalid values
				errorlist = append(errorlist, err)
			}
			if RulesAllow(requestAttributes, rules...) {
				subjects = append(subjects, clusterRoleBinding.Subjects...)
			}
		}
	}

	if namespace := requestAttributes.GetNamespace(); len(namespace) > 0 {
		if roleBindings, err := r.roleBindingLister.ListRoleBindings(namespace); err != nil {
			errorlist = append(errorlist, err)

		} else {
			for _, roleBinding := range roleBindings {
				rules, err := r.roleToRuleMapper.GetRoleReferenceRules(roleBinding.RoleRef, namespace)
				if err != nil {
					// if we have an error, just keep track of it and keep processing.  Since rules are additive,
					// missing a reference is bad, but we can continue with other rolebindings and still have a list
					// that does not contain any invalid values
					errorlist = append(errorlist, err)
				}
				if RulesAllow(requestAttributes, rules...) {
					subjects = append(subjects, roleBinding.Subjects...)
				}
			}
		}
	}

	dedupedSubjects := []rbacv1.Subject{}
	for _, subject := range subjects {
		found := false
		for _, curr := range dedupedSubjects {
			if curr == subject {
				found = true
				break
			}
		}

		if !found {
			dedupedSubjects = append(dedupedSubjects, subject)
		}
	}

	return subjects, utilerrors.NewAggregate(errorlist)
}


Resource

// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
	return SchemeGroupVersion.WithResource(resource).GroupResource()
}


addKnownTypes

// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&AdmissionReview{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&ValidatingWebhookConfiguration{},
		&ValidatingWebhookConfigurationList{},
		&MutatingWebhookConfiguration{},
		&MutatingWebhookConfigurationList{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&ValidatingAdmissionPolicy{},
		&ValidatingAdmissionPolicyList{},
		&ValidatingAdmissionPolicyBinding{},
		&ValidatingAdmissionPolicyBindingList{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


Kind

// Kind takes an unqualified kind and returns a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {
	return SchemeGroupVersion.WithKind(kind).GroupKind()
}


addKnownTypes

// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&APIGroupDiscoveryList{},
		&APIGroupDiscovery{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&StorageVersion{},
		&StorageVersionList{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&Deployment{},
		&DeploymentList{},
		&StatefulSet{},
		&StatefulSetList{},
		&DaemonSet{},
		&DaemonSetList{},
		&ReplicaSet{},
		&ReplicaSetList{},
		&ControllerRevision{},
		&ControllerRevisionList{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&Deployment{},
		&DeploymentList{},
		&DeploymentRollback{},
		&Scale{},
		&StatefulSet{},
		&StatefulSetList{},
		&ControllerRevision{},
		&ControllerRevisionList{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&Deployment{},
		&DeploymentList{},
		&Scale{},
		&StatefulSet{},
		&StatefulSetList{},
		&DaemonSet{},
		&DaemonSetList{},
		&ReplicaSet{},
		&ReplicaSetList{},
		&ControllerRevision{},
		&ControllerRevisionList{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&TokenReview{},
		&TokenRequest{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


String

func (t ExtraValue) String() string {
	return fmt.Sprintf("%v", []string(t))
}


addKnownTypes

// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&SelfSubjectReview{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&SelfSubjectReview{},
		&TokenReview{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&SelfSubjectRulesReview{},
		&SelfSubjectAccessReview{},
		&SubjectAccessReview{},
		&LocalSubjectAccessReview{},
	)

	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&HorizontalPodAutoscaler{},
		&HorizontalPodAutoscalerList{},
		&Scale{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&HorizontalPodAutoscaler{},
		&HorizontalPodAutoscalerList{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


Resource

// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
	return SchemeGroupVersion.WithResource(resource).GroupResource()
}


addKnownTypes

// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&Job{},
		&JobList{},
		&CronJob{},
		&CronJobList{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&CronJob{},
		&CronJobList{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&CertificateSigningRequest{},
		&CertificateSigningRequestList{},
	)

	// Add the watch version that applies
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


Kind

// Kind takes an unqualified kind and returns a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {
	return SchemeGroupVersion.WithKind(kind).GroupKind()
}


addKnownTypes

// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&ClusterTrustBundle{},
		&ClusterTrustBundleList{},
	)

	// Add the watch version that applies
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&Lease{},
		&LeaseList{},
	)

	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


APILifecycleIntroduced

// APILifecycleIntroduced returns the release in which the API struct was introduced as int versions of major and minor for comparison.
func (in *ComponentStatus) APILifecycleIntroduced() (major, minor int) {
	return 1, 0
}


APILifecycleDeprecated

// APILifecycleDeprecated returns the release in which the API struct was or will be deprecated as int versions of major and minor for comparison.
func (in *ComponentStatus) APILifecycleDeprecated() (major, minor int) {
	return 1, 19
}


APILifecycleIntroduced

// APILifecycleIntroduced returns the release in which the API struct was introduced as int versions of major and minor for comparison.
func (in *ComponentStatusList) APILifecycleIntroduced() (major, minor int) {
	return 1, 0
}


APILifecycleDeprecated

// APILifecycleDeprecated returns the release in which the API struct was or will be deprecated as int versions of major and minor for comparison.
func (in *ComponentStatusList) APILifecycleDeprecated() (major, minor int) {
	return 1, 19
}


SetGroupVersionKind

// IsAnAPIObject allows clients to preemptively get a reference to an API object and pass it to places that
// intend only to get a reference to that object. This simplifies the event recording interface.
func (obj *ObjectReference) SetGroupVersionKind(gvk schema.GroupVersionKind) {
	obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind()
}


GroupVersionKind

func (obj *ObjectReference) GroupVersionKind() schema.GroupVersionKind {
	return schema.FromAPIVersionAndKind(obj.APIVersion, obj.Kind)
}


GetObjectKind

func (obj *ObjectReference) GetObjectKind() schema.ObjectKind { return obj }


addKnownTypes

// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&Pod{},
		&PodList{},
		&PodStatusResult{},
		&PodTemplate{},
		&PodTemplateList{},
		&ReplicationController{},
		&ReplicationControllerList{},
		&Service{},
		&ServiceProxyOptions{},
		&ServiceList{},
		&Endpoints{},
		&EndpointsList{},
		&Node{},
		&NodeList{},
		&NodeProxyOptions{},
		&Binding{},
		&Event{},
		&EventList{},
		&List{},
		&LimitRange{},
		&LimitRangeList{},
		&ResourceQuota{},
		&ResourceQuotaList{},
		&Namespace{},
		&NamespaceList{},
		&Secret{},
		&SecretList{},
		&ServiceAccount{},
		&ServiceAccountList{},
		&PersistentVolume{},
		&PersistentVolumeList{},
		&PersistentVolumeClaim{},
		&PersistentVolumeClaimList{},
		&PodAttachOptions{},
		&PodLogOptions{},
		&PodExecOptions{},
		&PodPortForwardOptions{},
		&PodProxyOptions{},
		&ComponentStatus{},
		&ComponentStatusList{},
		&SerializedReference{},
		&RangeAllocation{},
		&ConfigMap{},
		&ConfigMapList{},
	)

	// Add common types
	scheme.AddKnownTypes(SchemeGroupVersion, &metav1.Status{})

	// Add the watch version that applies
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


String

// Returns string version of ResourceName.
func (rn ResourceName) String() string {
	return string(rn)
}


Cpu

// Cpu returns the Cpu limit if specified.
func (rl *ResourceList) Cpu() *resource.Quantity {
	return rl.Name(ResourceCPU, resource.DecimalSI)
}


Memory

// Memory returns the Memory limit if specified.
func (rl *ResourceList) Memory() *resource.Quantity {
	return rl.Name(ResourceMemory, resource.BinarySI)
}


Storage

// Storage returns the Storage limit if specified.
func (rl *ResourceList) Storage() *resource.Quantity {
	return rl.Name(ResourceStorage, resource.BinarySI)
}


Pods

// Pods returns the list of pods
func (rl *ResourceList) Pods() *resource.Quantity {
	return rl.Name(ResourcePods, resource.DecimalSI)
}


StorageEphemeral

// StorageEphemeral returns the list of ephemeral storage volumes, if any
func (rl *ResourceList) StorageEphemeral() *resource.Quantity {
	return rl.Name(ResourceEphemeralStorage, resource.BinarySI)
}


Name

// Name returns the resource with name if specified, otherwise it returns a nil quantity with default format.
func (rl *ResourceList) Name(name ResourceName, defaultFormat resource.Format) *resource.Quantity {
	if val, ok := (*rl)[name]; ok {
		return &val
	}
	return &resource.Quantity{Format: defaultFormat}
}


MatchTaint

// MatchTaint checks if the taint matches taintToMatch. Taints are unique by key:effect,
// if the two taints have same key:effect, regard as they match.
func (t *Taint) MatchTaint(taintToMatch *Taint) bool {
	return t.Key == taintToMatch.Key && t.Effect == taintToMatch.Effect
}


ToString

// taint.ToString() converts taint struct to string in format '<key>=<value>:<effect>', '<key>=<value>:', '<key>:<effect>', or '<key>'.
func (t *Taint) ToString() string {
	if len(t.Effect) == 0 {
		if len(t.Value) == 0 {
			return fmt.Sprintf("%v", t.Key)
		}
		return fmt.Sprintf("%v=%v:", t.Key, t.Value)
	}
	if len(t.Value) == 0 {
		return fmt.Sprintf("%v:%v", t.Key, t.Effect)
	}
	return fmt.Sprintf("%v=%v:%v", t.Key, t.Value, t.Effect)
}


MatchToleration

// MatchToleration checks if the toleration matches tolerationToMatch. Tolerations are unique by <key,effect,operator,value>,
// if the two tolerations have same <key,effect,operator,value> combination, regard as they match.
// TODO: uniqueness check for tolerations in api validations.
func (t *Toleration) MatchToleration(tolerationToMatch *Toleration) bool {
	return t.Key == tolerationToMatch.Key &&
		t.Effect == tolerationToMatch.Effect &&
		t.Operator == tolerationToMatch.Operator &&
		t.Value == tolerationToMatch.Value
}


ToleratesTaint

// ToleratesTaint checks if the toleration tolerates the taint.
// The matching follows the rules below:
//
//  1. Empty toleration.effect means to match all taint effects,
//     otherwise taint effect must equal to toleration.effect.
//  2. If toleration.operator is 'Exists', it means to match all taint values.
//  3. Empty toleration.key means to match all taint keys.
//     If toleration.key is empty, toleration.operator must be 'Exists';
//     this combination means to match all taint values and all taint keys.
func (t *Toleration) ToleratesTaint(taint *Taint) bool {
	if len(t.Effect) > 0 && t.Effect != taint.Effect {
		return false
	}

	if len(t.Key) > 0 && t.Key != taint.Key {
		return false
	}

	// TODO: Use proper defaulting when Toleration becomes a field of PodSpec
	switch t.Operator {
	// empty operator means Equal
	case "", TolerationOpEqual:
		return t.Value == taint.Value
	case TolerationOpExists:
		return true
	default:
		return false
	}
}


Kind

// Kind takes an unqualified kind and returns a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {
	return SchemeGroupVersion.WithKind(kind).GroupKind()
}


Resource

// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
	return SchemeGroupVersion.WithResource(resource).GroupResource()
}


addKnownTypes

// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&EndpointSlice{},
		&EndpointSliceList{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&Event{},
		&EventList{},
	)

	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&Deployment{},
		&DeploymentList{},
		&DeploymentRollback{},
		&Scale{},
		&DaemonSetList{},
		&DaemonSet{},
		&Ingress{},
		&IngressList{},
		&ReplicaSet{},
		&ReplicaSetList{},
		&NetworkPolicy{},
		&NetworkPolicyList{},
	)
	// Add the watch version that applies
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&FlowSchema{},
		&FlowSchemaList{},
		&PriorityLevelConfiguration{},
		&PriorityLevelConfigurationList{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&ImageReview{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&Ingress{},
		&IngressList{},
		&IngressClass{},
		&IngressClassList{},
		&NetworkPolicy{},
		&NetworkPolicyList{},
	)

	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


Kind

// Kind takes an unqualified kind and returns a Group qualified GroupKind.
func Kind(kind string) schema.GroupKind {
	return SchemeGroupVersion.WithKind(kind).GroupKind()
}


Resource

// Resource takes an unqualified resource and returns a Group qualified GroupResource.
func Resource(resource string) schema.GroupResource {
	return SchemeGroupVersion.WithResource(resource).GroupResource()
}


addKnownTypes

// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&ClusterCIDR{},
		&ClusterCIDRList{},
		&IPAddress{},
		&IPAddressList{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&Ingress{},
		&IngressList{},
		&IngressClass{},
		&IngressClassList{},
	)
	// Add the watch version that applies
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// addKnownTypes adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&RuntimeClass{},
		&RuntimeClassList{},
	)

	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&PodDisruptionBudget{},
		&PodDisruptionBudgetList{},
		&Eviction{},
	)
	// Add the watch version that applies
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&PodDisruptionBudget{},
		&PodDisruptionBudgetList{},
		&PodSecurityPolicy{},
		&PodSecurityPolicyList{},
		&Eviction{},
	)
	// Add the watch version that applies
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&Role{},
		&RoleBinding{},
		&RoleBindingList{},
		&RoleList{},

		&ClusterRole{},
		&ClusterRoleBinding{},
		&ClusterRoleBindingList{},
		&ClusterRoleList{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&ResourceClass{},
		&ResourceClassList{},
		&ResourceClaim{},
		&ResourceClaimList{},
		&ResourceClaimTemplate{},
		&ResourceClaimTemplateList{},
		&PodSchedulingContext{},
		&PodSchedulingContextList{},
	)

	// Add common types
	scheme.AddKnownTypes(SchemeGroupVersion, &metav1.Status{})

	// Add the watch version that applies
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&PriorityClass{},
		&PriorityClassList{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


Resource

// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
	return SchemeGroupVersion.WithResource(resource).GroupResource()
}


addKnownTypes

// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&StorageClass{},
		&StorageClassList{},

		&VolumeAttachment{},
		&VolumeAttachmentList{},

		&CSINode{},
		&CSINodeList{},

		&CSIDriver{},
		&CSIDriverList{},

		&CSIStorageCapacity{},
		&CSIStorageCapacityList{},
	)

	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&VolumeAttachment{},
		&VolumeAttachmentList{},
		&CSIStorageCapacity{},
		&CSIStorageCapacityList{},
	)

	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&StorageClass{},
		&StorageClassList{},

		&VolumeAttachment{},
		&VolumeAttachmentList{},

		&CSIDriver{},
		&CSIDriverList{},

		&CSINode{},
		&CSINodeList{},

		&CSIStorageCapacity{},
		&CSIStorageCapacityList{},
	)

	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


main

func main() {
	stopCh := genericapiserver.SetupSignalHandler()
	cmd := server.NewServerCommand(os.Stdout, os.Stderr, stopCh)
	code := cli.Run(cmd)
	os.Exit(code)
}


IsProtectedCommunityGroup

// IsProtectedCommunityGroup returns whether or not a group specified for a CRD is protected for the community and needs
// to have the v1beta1.KubeAPIApprovalAnnotation set.
func IsProtectedCommunityGroup(group string) bool {
	switch {
	case group == "k8s.io" || strings.HasSuffix(group, ".k8s.io"):
		return true
	case group == "kubernetes.io" || strings.HasSuffix(group, ".kubernetes.io"):
		return true
	default:
		return false
	}

}


GetAPIApprovalState

// GetAPIApprovalState returns the state of the API approval and reason for that state
func GetAPIApprovalState(annotations map[string]string) (state APIApprovalState, reason string) {
	annotation := annotations[apiextensionsv1.KubeAPIApprovedAnnotation]

	// we use the result of this parsing in the switch/case below
	url, annotationURLParseErr := url.ParseRequestURI(annotation)
	switch {
	case len(annotation) == 0:
		return APIApprovalMissing, fmt.Sprintf("protected groups must have approval annotation %q, see https://github.com/kubernetes/enhancements/pull/1111", apiextensionsv1.KubeAPIApprovedAnnotation)
	case strings.HasPrefix(annotation, "unapproved"):
		return APIApprovalBypassed, fmt.Sprintf("not approved: %q", annotation)
	case annotationURLParseErr == nil && url != nil && len(url.Host) > 0 && len(url.Scheme) > 0:
		return APIApproved, fmt.Sprintf("approved in %v", annotation)
	default:
		return APIApprovalInvalid, fmt.Sprintf("protected groups must have approval annotation %q with either a URL or a reason starting with \"unapproved\", see https://github.com/kubernetes/enhancements/pull/1111", apiextensionsv1.KubeAPIApprovedAnnotation)
	}
}


SetCRDCondition

// SetCRDCondition sets the status condition. It either overwrites the existing one or creates a new one.
func SetCRDCondition(crd *apiextensionsv1.CustomResourceDefinition, newCondition apiextensionsv1.CustomResourceDefinitionCondition) {
	newCondition.LastTransitionTime = metav1.NewTime(time.Now())

	existingCondition := FindCRDCondition(crd, newCondition.Type)
	if existingCondition == nil {
		crd.Status.Conditions = append(crd.Status.Conditions, newCondition)
		return
	}

	if existingCondition.Status != newCondition.Status || existingCondition.LastTransitionTime.IsZero() {
		existingCondition.LastTransitionTime = newCondition.LastTransitionTime
	}

	existingCondition.Status = newCondition.Status
	existingCondition.Reason = newCondition.Reason
	existingCondition.Message = newCondition.Message
}


RemoveCRDCondition

// RemoveCRDCondition removes the status condition.
func RemoveCRDCondition(crd *apiextensionsv1.CustomResourceDefinition, conditionType apiextensionsv1.CustomResourceDefinitionConditionType) {
	newConditions := []apiextensionsv1.CustomResourceDefinitionCondition{}
	for _, condition := range crd.Status.Conditions {
		if condition.Type != conditionType {
			newConditions = append(newConditions, condition)
		}
	}
	crd.Status.Conditions = newConditions
}


FindCRDCondition

// FindCRDCondition returns the condition you're looking for or nil.
func FindCRDCondition(crd *apiextensionsv1.CustomResourceDefinition, conditionType apiextensionsv1.CustomResourceDefinitionConditionType) *apiextensionsv1.CustomResourceDefinitionCondition {
	for i := range crd.Status.Conditions {
		if crd.Status.Conditions[i].Type == conditionType {
			return &crd.Status.Conditions[i]
		}
	}

	return nil
}


IsCRDConditionTrue

// IsCRDConditionTrue indicates if the condition is present and strictly true.
func IsCRDConditionTrue(crd *apiextensionsv1.CustomResourceDefinition, conditionType apiextensionsv1.CustomResourceDefinitionConditionType) bool {
	return IsCRDConditionPresentAndEqual(crd, conditionType, apiextensionsv1.ConditionTrue)
}


IsCRDConditionFalse

// IsCRDConditionFalse indicates if the condition is present and false.
func IsCRDConditionFalse(crd *apiextensionsv1.CustomResourceDefinition, conditionType apiextensionsv1.CustomResourceDefinitionConditionType) bool {
	return IsCRDConditionPresentAndEqual(crd, conditionType, apiextensionsv1.ConditionFalse)
}


IsCRDConditionPresentAndEqual

// IsCRDConditionPresentAndEqual indicates if the condition is present and equal to the given status.
func IsCRDConditionPresentAndEqual(crd *apiextensionsv1.CustomResourceDefinition, conditionType apiextensionsv1.CustomResourceDefinitionConditionType, status apiextensionsv1.ConditionStatus) bool {
	for _, condition := range crd.Status.Conditions {
		if condition.Type == conditionType {
			return condition.Status == status
		}
	}
	return false
}


IsCRDConditionEquivalent

// IsCRDConditionEquivalent returns true if the lhs and rhs are equivalent except for times.
func IsCRDConditionEquivalent(lhs, rhs *apiextensionsv1.CustomResourceDefinitionCondition) bool {
	if lhs == nil && rhs == nil {
		return true
	}
	if lhs == nil || rhs == nil {
		return false
	}

	return lhs.Message == rhs.Message && lhs.Reason == rhs.Reason && lhs.Status == rhs.Status && lhs.Type == rhs.Type
}


CRDHasFinalizer

// CRDHasFinalizer returns true if the finalizer is in the list.
func CRDHasFinalizer(crd *apiextensionsv1.CustomResourceDefinition, needle string) bool {
	for _, finalizer := range crd.Finalizers {
		if finalizer == needle {
			return true
		}
	}

	return false
}


CRDRemoveFinalizer

// CRDRemoveFinalizer removes the finalizer if present.
func CRDRemoveFinalizer(crd *apiextensionsv1.CustomResourceDefinition, needle string) {
	newFinalizers := []string{}
	for _, finalizer := range crd.Finalizers {
		if finalizer != needle {
			newFinalizers = append(newFinalizers, finalizer)
		}
	}
	crd.Finalizers = newFinalizers
}


HasServedCRDVersion

// HasServedCRDVersion returns true if the given version is in the list of CRD's versions and the Served flag is set.
func HasServedCRDVersion(crd *apiextensionsv1.CustomResourceDefinition, version string) bool {
	for _, v := range crd.Spec.Versions {
		if v.Name == version {
			return v.Served
		}
	}
	return false
}


GetCRDStorageVersion

// GetCRDStorageVersion returns the storage version for given CRD.
func GetCRDStorageVersion(crd *apiextensionsv1.CustomResourceDefinition) (string, error) {
	for _, v := range crd.Spec.Versions {
		if v.Storage {
			return v.Name, nil
		}
	}
	// This should not happened if crd is valid
	return "", fmt.Errorf("invalid apiextensionsv1.CustomResourceDefinition, no storage version")
}


IsStoredVersion

// IsStoredVersion returns whether the given version is the storage version of the CRD.
func IsStoredVersion(crd *apiextensionsv1.CustomResourceDefinition, version string) bool {
	for _, v := range crd.Status.StoredVersions {
		if version == v {
			return true
		}
	}
	return false
}


GetSchemaForVersion

// GetSchemaForVersion returns the validation schema for the given version or nil.
func GetSchemaForVersion(crd *apiextensionsv1.CustomResourceDefinition, version string) (*apiextensionsv1.CustomResourceValidation, error) {
	for _, v := range crd.Spec.Versions {
		if version == v.Name {
			return v.Schema, nil
		}
	}
	return nil, fmt.Errorf("version %s not found in apiextensionsv1.CustomResourceDefinition: %v", version, crd.Name)
}


GetSubresourcesForVersion

// GetSubresourcesForVersion returns the subresources for given version or nil.
func GetSubresourcesForVersion(crd *apiextensionsv1.CustomResourceDefinition, version string) (*apiextensionsv1.CustomResourceSubresources, error) {
	for _, v := range crd.Spec.Versions {
		if version == v.Name {
			return v.Subresources, nil
		}
	}
	return nil, fmt.Errorf("version %s not found in apiextensionsv1.CustomResourceDefinition: %v", version, crd.Name)
}


HasPerVersionSchema

// HasPerVersionSchema returns true if a CRD uses per-version schema.
func HasPerVersionSchema(versions []apiextensionsv1.CustomResourceDefinitionVersion) bool {
	for _, v := range versions {
		if v.Schema != nil {
			return true
		}
	}
	return false
}


HasPerVersionSubresources

// HasPerVersionSubresources returns true if a CRD uses per-version subresources.
func HasPerVersionSubresources(versions []apiextensionsv1.CustomResourceDefinitionVersion) bool {
	for _, v := range versions {
		if v.Subresources != nil {
			return true
		}
	}
	return false
}


HasPerVersionColumns

// HasPerVersionColumns returns true if a CRD uses per-version columns.
func HasPerVersionColumns(versions []apiextensionsv1.CustomResourceDefinitionVersion) bool {
	for _, v := range versions {
		if len(v.AdditionalPrinterColumns) > 0 {
			return true
		}
	}
	return false
}


HasVersionServed

// HasVersionServed returns true if given CRD has given version served.
func HasVersionServed(crd *apiextensionsv1.CustomResourceDefinition, version string) bool {
	for _, v := range crd.Spec.Versions {
		if !v.Served || v.Name != version {
			continue
		}
		return true
	}
	return false
}


DeepCopy

// TODO: Update this after a tag is created for interface fields in DeepCopy
func (in *JSONSchemaProps) DeepCopy() *JSONSchemaProps {
	if in == nil {
		return nil
	}
	out := new(JSONSchemaProps)

	*out = *in

	if in.Default != nil {
		defaultJSON := JSON(runtime.DeepCopyJSONValue(*(in.Default)))
		out.Default = &(defaultJSON)
	} else {
		out.Default = nil
	}

	if in.Example != nil {
		exampleJSON := JSON(runtime.DeepCopyJSONValue(*(in.Example)))
		out.Example = &(exampleJSON)
	} else {
		out.Example = nil
	}

	if in.Ref != nil {
		in, out := &in.Ref, &out.Ref
		if *in == nil {
			*out = nil
		} else {
			*out = new(string)
			**out = **in
		}
	}

	if in.Maximum != nil {
		in, out := &in.Maximum, &out.Maximum
		if *in == nil {
			*out = nil
		} else {
			*out = new(float64)
			**out = **in
		}
	}

	if in.Minimum != nil {
		in, out := &in.Minimum, &out.Minimum
		if *in == nil {
			*out = nil
		} else {
			*out = new(float64)
			**out = **in
		}
	}

	if in.MaxLength != nil {
		in, out := &in.MaxLength, &out.MaxLength
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.MinLength != nil {
		in, out := &in.MinLength, &out.MinLength
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}
	if in.MaxItems != nil {
		in, out := &in.MaxItems, &out.MaxItems
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.MinItems != nil {
		in, out := &in.MinItems, &out.MinItems
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.MultipleOf != nil {
		in, out := &in.MultipleOf, &out.MultipleOf
		if *in == nil {
			*out = nil
		} else {
			*out = new(float64)
			**out = **in
		}
	}

	if in.Enum != nil {
		out.Enum = make([]JSON, len(in.Enum))
		for i := range in.Enum {
			out.Enum[i] = runtime.DeepCopyJSONValue(in.Enum[i])
		}
	}

	if in.MaxProperties != nil {
		in, out := &in.MaxProperties, &out.MaxProperties
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.MinProperties != nil {
		in, out := &in.MinProperties, &out.MinProperties
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.Required != nil {
		in, out := &in.Required, &out.Required
		*out = make([]string, len(*in))
		copy(*out, *in)
	}

	if in.Items != nil {
		in, out := &in.Items, &out.Items
		if *in == nil {
			*out = nil
		} else {
			*out = new(JSONSchemaPropsOrArray)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.AllOf != nil {
		in, out := &in.AllOf, &out.AllOf
		*out = make([]JSONSchemaProps, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}

	if in.OneOf != nil {
		in, out := &in.OneOf, &out.OneOf
		*out = make([]JSONSchemaProps, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
	if in.AnyOf != nil {
		in, out := &in.AnyOf, &out.AnyOf
		*out = make([]JSONSchemaProps, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}

	if in.Not != nil {
		in, out := &in.Not, &out.Not
		if *in == nil {
			*out = nil
		} else {
			*out = new(JSONSchemaProps)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.Properties != nil {
		in, out := &in.Properties, &out.Properties
		*out = make(map[string]JSONSchemaProps, len(*in))
		for key, val := range *in {
			(*out)[key] = *val.DeepCopy()
		}
	}

	if in.AdditionalProperties != nil {
		in, out := &in.AdditionalProperties, &out.AdditionalProperties
		if *in == nil {
			*out = nil
		} else {
			*out = new(JSONSchemaPropsOrBool)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.PatternProperties != nil {
		in, out := &in.PatternProperties, &out.PatternProperties
		*out = make(map[string]JSONSchemaProps, len(*in))
		for key, val := range *in {
			(*out)[key] = *val.DeepCopy()
		}
	}

	if in.Dependencies != nil {
		in, out := &in.Dependencies, &out.Dependencies
		*out = make(JSONSchemaDependencies, len(*in))
		for key, val := range *in {
			(*out)[key] = *val.DeepCopy()
		}
	}

	if in.AdditionalItems != nil {
		in, out := &in.AdditionalItems, &out.AdditionalItems
		if *in == nil {
			*out = nil
		} else {
			*out = new(JSONSchemaPropsOrBool)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.Definitions != nil {
		in, out := &in.Definitions, &out.Definitions
		*out = make(JSONSchemaDefinitions, len(*in))
		for key, val := range *in {
			(*out)[key] = *val.DeepCopy()
		}
	}

	if in.ExternalDocs != nil {
		in, out := &in.ExternalDocs, &out.ExternalDocs
		if *in == nil {
			*out = nil
		} else {
			*out = new(ExternalDocumentation)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.XPreserveUnknownFields != nil {
		in, out := &in.XPreserveUnknownFields, &out.XPreserveUnknownFields
		if *in == nil {
			*out = nil
		} else {
			*out = new(bool)
			**out = **in
		}
	}

	if in.XListMapKeys != nil {
		in, out := &in.XListMapKeys, &out.XListMapKeys
		*out = make([]string, len(*in))
		copy(*out, *in)
	}

	if in.XListType != nil {
		in, out := &in.XListType, &out.XListType
		if *in == nil {
			*out = nil
		} else {
			*out = new(string)
			**out = **in
		}
	}

	if in.XMapType != nil {
		in, out := &in.XMapType, &out.XMapType
		*out = new(string)
		**out = **in
	}

	if in.XValidations != nil {
		in, out := &in.XValidations, &out.XValidations
		*out = make([]ValidationRule, len(*in))
		copy(*out, *in)
	}

	return out
}


Funcs

// Funcs returns the fuzzer functions for the apiextensions apis.
func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
	return []interface{}{
		func(obj *apiextensions.CustomResourceDefinitionSpec, c fuzz.Continue) {
			c.FuzzNoCustom(obj)

			// match our defaulter
			if len(obj.Scope) == 0 {
				obj.Scope = apiextensions.NamespaceScoped
			}
			if len(obj.Names.Singular) == 0 {
				obj.Names.Singular = strings.ToLower(obj.Names.Kind)
			}
			if len(obj.Names.ListKind) == 0 && len(obj.Names.Kind) > 0 {
				obj.Names.ListKind = obj.Names.Kind + "List"
			}
			if len(obj.Versions) == 0 && len(obj.Version) == 0 {
				// internal object must have a version to roundtrip all fields
				obj.Version = "v1"
			}
			if len(obj.Versions) == 0 && len(obj.Version) != 0 {
				obj.Versions = []apiextensions.CustomResourceDefinitionVersion{
					{
						Name:    obj.Version,
						Served:  true,
						Storage: true,
					},
				}
			} else if len(obj.Versions) != 0 {
				obj.Version = obj.Versions[0].Name
			}
			if len(obj.AdditionalPrinterColumns) == 0 {
				obj.AdditionalPrinterColumns = []apiextensions.CustomResourceColumnDefinition{
					{Name: "Age", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"], JSONPath: ".metadata.creationTimestamp"},
				}
			}
			if obj.Conversion == nil {
				obj.Conversion = &apiextensions.CustomResourceConversion{
					Strategy: apiextensions.NoneConverter,
				}
			}
			if obj.Conversion.Strategy == apiextensions.WebhookConverter && len(obj.Conversion.ConversionReviewVersions) == 0 {
				obj.Conversion.ConversionReviewVersions = []string{"v1beta1"}
			}
			if obj.PreserveUnknownFields == nil {
				obj.PreserveUnknownFields = pointer.BoolPtr(true)
			}

			// Move per-version schema, subresources, additionalPrinterColumns to the top-level.
			// This is required by validation in v1beta1, and by round-tripping in v1.
			if len(obj.Versions) == 1 {
				if obj.Versions[0].Schema != nil {
					obj.Validation = obj.Versions[0].Schema
					obj.Versions[0].Schema = nil
				}
				if obj.Versions[0].AdditionalPrinterColumns != nil {
					obj.AdditionalPrinterColumns = obj.Versions[0].AdditionalPrinterColumns
					obj.Versions[0].AdditionalPrinterColumns = nil
				}
				if obj.Versions[0].Subresources != nil {
					obj.Subresources = obj.Versions[0].Subresources
					obj.Versions[0].Subresources = nil
				}
			}
		},
		func(obj *apiextensions.CustomResourceDefinition, c fuzz.Continue) {
			c.FuzzNoCustom(obj)

			if len(obj.Status.StoredVersions) == 0 {
				for _, v := range obj.Spec.Versions {
					if v.Storage && !apiextensions.IsStoredVersion(obj, v.Name) {
						obj.Status.StoredVersions = append(obj.Status.StoredVersions, v.Name)
					}
				}
			}
		},
		func(obj *apiextensions.JSONSchemaProps, c fuzz.Continue) {
			// we cannot use c.FuzzNoCustom because of the interface{} fields. So let's loop with reflection.
			vobj := reflect.ValueOf(obj).Elem()
			tobj := reflect.TypeOf(obj).Elem()
			for i := 0; i < tobj.NumField(); i++ {
				field := tobj.Field(i)
				switch field.Name {
				case "Default", "Enum", "Example", "Ref":
					continue
				default:
					isValue := true
					switch field.Type.Kind() {
					case reflect.Interface, reflect.Map, reflect.Slice, reflect.Pointer:
						isValue = false
					}
					if isValue || c.Intn(10) == 0 {
						c.Fuzz(vobj.Field(i).Addr().Interface())
					}
				}
			}
			if c.RandBool() {
				validJSON := apiextensions.JSON(`{"some": {"json": "test"}, "string": 42}`)
				obj.Default = &validJSON
			}
			if c.RandBool() {
				obj.Enum = []apiextensions.JSON{c.Float64(), c.RandString(), c.RandBool()}
			}
			if c.RandBool() {
				validJSON := apiextensions.JSON(`"foobarbaz"`)
				obj.Example = &validJSON
			}
			if c.RandBool() {
				validRef := "validRef"
				obj.Ref = &validRef
			}
			if len(obj.Type) == 0 {
				obj.Nullable = false // because this does not roundtrip through go-openapi
			}
			if obj.XIntOrString {
				obj.Type = ""
			}
		},
		func(obj *apiextensions.JSONSchemaPropsOrBool, c fuzz.Continue) {
			if c.RandBool() {
				obj.Allows = true
				obj.Schema = &apiextensions.JSONSchemaProps{}
				c.Fuzz(obj.Schema)
			} else {
				obj.Allows = c.RandBool()
			}
		},
		func(obj *apiextensions.JSONSchemaPropsOrArray, c fuzz.Continue) {
			// disallow both Schema and JSONSchemas to be nil.
			if c.RandBool() {
				obj.Schema = &apiextensions.JSONSchemaProps{}
				c.Fuzz(obj.Schema)
			} else {
				obj.JSONSchemas = make([]apiextensions.JSONSchemaProps, c.Intn(3)+1)
				for i := range obj.JSONSchemas {
					c.Fuzz(&obj.JSONSchemas[i])
				}
			}
		},
		func(obj *apiextensions.JSONSchemaPropsOrStringArray, c fuzz.Continue) {
			if c.RandBool() {
				obj.Schema = &apiextensions.JSONSchemaProps{}
				c.Fuzz(obj.Schema)
			} else {
				c.Fuzz(&obj.Property)
			}
		},
		func(obj *int64, c fuzz.Continue) {
			// JSON only supports 53 bits because everything is a float
			*obj = int64(c.Uint64()) & ((int64(1) << 53) - 1)
		},
	}
}


SetCRDCondition

// SetCRDCondition sets the status condition. It either overwrites the existing one or creates a new one.
func SetCRDCondition(crd *CustomResourceDefinition, newCondition CustomResourceDefinitionCondition) {
	newCondition.LastTransitionTime = metav1.NewTime(time.Now())

	existingCondition := FindCRDCondition(crd, newCondition.Type)
	if existingCondition == nil {
		crd.Status.Conditions = append(crd.Status.Conditions, newCondition)
		return
	}

	if existingCondition.Status != newCondition.Status || existingCondition.LastTransitionTime.IsZero() {
		existingCondition.LastTransitionTime = newCondition.LastTransitionTime
	}

	existingCondition.Status = newCondition.Status
	existingCondition.Reason = newCondition.Reason
	existingCondition.Message = newCondition.Message
}


RemoveCRDCondition

// RemoveCRDCondition removes the status condition.
func RemoveCRDCondition(crd *CustomResourceDefinition, conditionType CustomResourceDefinitionConditionType) {
	newConditions := []CustomResourceDefinitionCondition{}
	for _, condition := range crd.Status.Conditions {
		if condition.Type != conditionType {
			newConditions = append(newConditions, condition)
		}
	}
	crd.Status.Conditions = newConditions
}


FindCRDCondition

// FindCRDCondition returns the condition you're looking for or nil.
func FindCRDCondition(crd *CustomResourceDefinition, conditionType CustomResourceDefinitionConditionType) *CustomResourceDefinitionCondition {
	for i := range crd.Status.Conditions {
		if crd.Status.Conditions[i].Type == conditionType {
			return &crd.Status.Conditions[i]
		}
	}

	return nil
}


IsCRDConditionTrue

// IsCRDConditionTrue indicates if the condition is present and strictly true.
func IsCRDConditionTrue(crd *CustomResourceDefinition, conditionType CustomResourceDefinitionConditionType) bool {
	return IsCRDConditionPresentAndEqual(crd, conditionType, ConditionTrue)
}


IsCRDConditionFalse

// IsCRDConditionFalse indicates if the condition is present and false.
func IsCRDConditionFalse(crd *CustomResourceDefinition, conditionType CustomResourceDefinitionConditionType) bool {
	return IsCRDConditionPresentAndEqual(crd, conditionType, ConditionFalse)
}


IsCRDConditionPresentAndEqual

// IsCRDConditionPresentAndEqual indicates if the condition is present and equal to the given status.
func IsCRDConditionPresentAndEqual(crd *CustomResourceDefinition, conditionType CustomResourceDefinitionConditionType, status ConditionStatus) bool {
	for _, condition := range crd.Status.Conditions {
		if condition.Type == conditionType {
			return condition.Status == status
		}
	}
	return false
}


IsCRDConditionEquivalent

// IsCRDConditionEquivalent returns true if the lhs and rhs are equivalent except for times.
func IsCRDConditionEquivalent(lhs, rhs *CustomResourceDefinitionCondition) bool {
	if lhs == nil && rhs == nil {
		return true
	}
	if lhs == nil || rhs == nil {
		return false
	}

	return lhs.Message == rhs.Message && lhs.Reason == rhs.Reason && lhs.Status == rhs.Status && lhs.Type == rhs.Type
}


CRDHasFinalizer

// CRDHasFinalizer returns true if the finalizer is in the list.
func CRDHasFinalizer(crd *CustomResourceDefinition, needle string) bool {
	for _, finalizer := range crd.Finalizers {
		if finalizer == needle {
			return true
		}
	}

	return false
}


CRDRemoveFinalizer

// CRDRemoveFinalizer removes the finalizer if present.
func CRDRemoveFinalizer(crd *CustomResourceDefinition, needle string) {
	newFinalizers := []string{}
	for _, finalizer := range crd.Finalizers {
		if finalizer != needle {
			newFinalizers = append(newFinalizers, finalizer)
		}
	}
	crd.Finalizers = newFinalizers
}


HasServedCRDVersion

// HasServedCRDVersion returns true if the given version is in the list of CRD's versions and the Served flag is set.
func HasServedCRDVersion(crd *CustomResourceDefinition, version string) bool {
	for _, v := range crd.Spec.Versions {
		if v.Name == version {
			return v.Served
		}
	}
	return false
}


GetCRDStorageVersion

// GetCRDStorageVersion returns the storage version for given CRD.
func GetCRDStorageVersion(crd *CustomResourceDefinition) (string, error) {
	for _, v := range crd.Spec.Versions {
		if v.Storage {
			return v.Name, nil
		}
	}
	// This should not happened if crd is valid
	return "", fmt.Errorf("invalid CustomResourceDefinition, no storage version")
}


IsStoredVersion

// IsStoredVersion returns whether the given version is the storage version of the CRD.
func IsStoredVersion(crd *CustomResourceDefinition, version string) bool {
	for _, v := range crd.Status.StoredVersions {
		if version == v {
			return true
		}
	}
	return false
}


GetSchemaForVersion

// GetSchemaForVersion returns the validation schema for the given version or nil.
func GetSchemaForVersion(crd *CustomResourceDefinition, version string) (*CustomResourceValidation, error) {
	if !HasPerVersionSchema(crd.Spec.Versions) {
		return crd.Spec.Validation, nil
	}
	if crd.Spec.Validation != nil {
		return nil, fmt.Errorf("malformed CustomResourceDefinition %s version %s: top-level and per-version schemas must be mutual exclusive", crd.Name, version)
	}
	for _, v := range crd.Spec.Versions {
		if version == v.Name {
			return v.Schema, nil
		}
	}
	return nil, fmt.Errorf("version %s not found in CustomResourceDefinition: %v", version, crd.Name)
}


GetSubresourcesForVersion

// GetSubresourcesForVersion returns the subresources for given version or nil.
func GetSubresourcesForVersion(crd *CustomResourceDefinition, version string) (*CustomResourceSubresources, error) {
	if !HasPerVersionSubresources(crd.Spec.Versions) {
		return crd.Spec.Subresources, nil
	}
	if crd.Spec.Subresources != nil {
		return nil, fmt.Errorf("malformed CustomResourceDefinition %s version %s: top-level and per-version subresources must be mutual exclusive", crd.Name, version)
	}
	for _, v := range crd.Spec.Versions {
		if version == v.Name {
			return v.Subresources, nil
		}
	}
	return nil, fmt.Errorf("version %s not found in CustomResourceDefinition: %v", version, crd.Name)
}


GetColumnsForVersion

// GetColumnsForVersion returns the columns for given version or nil.
// NOTE: the newly logically-defaulted columns is not pointing to the original CRD object.
// One cannot mutate the original CRD columns using the logically-defaulted columns. Please iterate through
// the original CRD object instead.
func GetColumnsForVersion(crd *CustomResourceDefinition, version string) ([]CustomResourceColumnDefinition, error) {
	if !HasPerVersionColumns(crd.Spec.Versions) {
		return serveDefaultColumnsIfEmpty(crd.Spec.AdditionalPrinterColumns), nil
	}
	if len(crd.Spec.AdditionalPrinterColumns) > 0 {
		return nil, fmt.Errorf("malformed CustomResourceDefinition %s version %s: top-level and per-version additionalPrinterColumns must be mutual exclusive", crd.Name, version)
	}
	for _, v := range crd.Spec.Versions {
		if version == v.Name {
			return serveDefaultColumnsIfEmpty(v.AdditionalPrinterColumns), nil
		}
	}
	return nil, fmt.Errorf("version %s not found in CustomResourceDefinition: %v", version, crd.Name)
}


HasPerVersionSchema

// HasPerVersionSchema returns true if a CRD uses per-version schema.
func HasPerVersionSchema(versions []CustomResourceDefinitionVersion) bool {
	for _, v := range versions {
		if v.Schema != nil {
			return true
		}
	}
	return false
}


HasPerVersionSubresources

// HasPerVersionSubresources returns true if a CRD uses per-version subresources.
func HasPerVersionSubresources(versions []CustomResourceDefinitionVersion) bool {
	for _, v := range versions {
		if v.Subresources != nil {
			return true
		}
	}
	return false
}


HasPerVersionColumns

// HasPerVersionColumns returns true if a CRD uses per-version columns.
func HasPerVersionColumns(versions []CustomResourceDefinitionVersion) bool {
	for _, v := range versions {
		if len(v.AdditionalPrinterColumns) > 0 {
			return true
		}
	}
	return false
}


serveDefaultColumnsIfEmpty

// serveDefaultColumnsIfEmpty applies logically defaulting to columns, if the input columns is empty.
// NOTE: in this way, the newly logically-defaulted columns is not pointing to the original CRD object.
// One cannot mutate the original CRD columns using the logically-defaulted columns. Please iterate through
// the original CRD object instead.
func serveDefaultColumnsIfEmpty(columns []CustomResourceColumnDefinition) []CustomResourceColumnDefinition {
	if len(columns) > 0 {
		return columns
	}
	return []CustomResourceColumnDefinition{
		{Name: "Age", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"], JSONPath: ".metadata.creationTimestamp"},
	}
}


HasVersionServed

// HasVersionServed returns true if given CRD has given version served.
func HasVersionServed(crd *CustomResourceDefinition, version string) bool {
	for _, v := range crd.Spec.Versions {
		if !v.Served || v.Name != version {
			continue
		}
		return true
	}
	return false
}


Install

// Install registers the API group and adds types to a scheme
func Install(scheme *runtime.Scheme) {
	utilruntime.Must(apiextensions.AddToScheme(scheme))
	utilruntime.Must(v1beta1.AddToScheme(scheme))
	utilruntime.Must(v1.AddToScheme(scheme))
	utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion, v1beta1.SchemeGroupVersion))
}


Kind

// Kind takes an unqualified kind and returns back a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {
	return SchemeGroupVersion.WithKind(kind).GroupKind()
}


Resource

// Resource takes an unqualified resource and returns back a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
	return SchemeGroupVersion.WithResource(resource).GroupResource()
}


addKnownTypes

// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&CustomResourceDefinition{},
		&CustomResourceDefinitionList{},
	)
	return nil
}


func Convert_apiextensions_JSONSchemaProps_To_v1_JSONSchemaProps(in *apiextensions.JSONSchemaProps, out *JSONSchemaProps, s conversion.Scope) error {
	if err := autoConvert_apiextensions_JSONSchemaProps_To_v1_JSONSchemaProps(in, out, s); err != nil {
		return err
	}
	if in.Default != nil && *(in.Default) == nil {
		out.Default = nil
	}
	if in.Example != nil && *(in.Example) == nil {
		out.Example = nil
	}
	return nil
}


func Convert_apiextensions_JSON_To_v1_JSON(in *apiextensions.JSON, out *JSON, s conversion.Scope) error {
	raw, err := json.Marshal(*in)
	if err != nil {
		return err
	}
	if len(raw) == 0 || bytes.Equal(raw, nullLiteral) {
		// match JSON#UnmarshalJSON treatment of literal nulls
		out.Raw = nil
	} else {
		out.Raw = raw
	}
	return nil
}


func Convert_v1_JSON_To_apiextensions_JSON(in *JSON, out *apiextensions.JSON, s conversion.Scope) error {
	if in != nil {
		var i interface{}
		if len(in.Raw) > 0 && !bytes.Equal(in.Raw, nullLiteral) {
			if err := json.Unmarshal(in.Raw, &i); err != nil {
				return err
			}
		}
		*out = i
	} else {
		out = nil
	}
	return nil
}


func Convert_apiextensions_CustomResourceDefinitionSpec_To_v1_CustomResourceDefinitionSpec(in *apiextensions.CustomResourceDefinitionSpec, out *CustomResourceDefinitionSpec, s conversion.Scope) error {
	if err := autoConvert_apiextensions_CustomResourceDefinitionSpec_To_v1_CustomResourceDefinitionSpec(in, out, s); err != nil {
		return err
	}

	if len(out.Versions) == 0 && len(in.Version) > 0 {
		// no versions were specified, and a version name was specified
		out.Versions = []CustomResourceDefinitionVersion{{Name: in.Version, Served: true, Storage: true}}
	}

	// If spec.{subresources,validation,additionalPrinterColumns} exists, move to versions
	if in.Subresources != nil {
		subresources := &CustomResourceSubresources{}
		if err := Convert_apiextensions_CustomResourceSubresources_To_v1_CustomResourceSubresources(in.Subresources, subresources, s); err != nil {
			return err
		}
		for i := range out.Versions {
			out.Versions[i].Subresources = subresources
		}
	}
	if in.Validation != nil {
		schema := &CustomResourceValidation{}
		if err := Convert_apiextensions_CustomResourceValidation_To_v1_CustomResourceValidation(in.Validation, schema, s); err != nil {
			return err
		}
		for i := range out.Versions {
			out.Versions[i].Schema = schema
		}
	}
	if in.AdditionalPrinterColumns != nil {
		additionalPrinterColumns := make([]CustomResourceColumnDefinition, len(in.AdditionalPrinterColumns))
		for i := range in.AdditionalPrinterColumns {
			if err := Convert_apiextensions_CustomResourceColumnDefinition_To_v1_CustomResourceColumnDefinition(&in.AdditionalPrinterColumns[i], &additionalPrinterColumns[i], s); err != nil {
				return err
			}
		}
		for i := range out.Versions {
			out.Versions[i].AdditionalPrinterColumns = additionalPrinterColumns
		}
	}
	return nil
}


func Convert_v1_CustomResourceDefinitionSpec_To_apiextensions_CustomResourceDefinitionSpec(in *CustomResourceDefinitionSpec, out *apiextensions.CustomResourceDefinitionSpec, s conversion.Scope) error {
	if err := autoConvert_v1_CustomResourceDefinitionSpec_To_apiextensions_CustomResourceDefinitionSpec(in, out, s); err != nil {
		return err
	}

	if len(out.Versions) == 0 {
		return nil
	}

	// Copy versions[0] to version
	out.Version = out.Versions[0].Name

	// If versions[*].{subresources,schema,additionalPrinterColumns} are identical, move to spec
	subresources := out.Versions[0].Subresources
	subresourcesIdentical := true
	validation := out.Versions[0].Schema
	validationIdentical := true
	additionalPrinterColumns := out.Versions[0].AdditionalPrinterColumns
	additionalPrinterColumnsIdentical := true

	// Detect if per-version fields are identical
	for _, v := range out.Versions {
		if subresourcesIdentical && !apiequality.Semantic.DeepEqual(v.Subresources, subresources) {
			subresourcesIdentical = false
		}
		if validationIdentical && !apiequality.Semantic.DeepEqual(v.Schema, validation) {
			validationIdentical = false
		}
		if additionalPrinterColumnsIdentical && !apiequality.Semantic.DeepEqual(v.AdditionalPrinterColumns, additionalPrinterColumns) {
			additionalPrinterColumnsIdentical = false
		}
	}

	// If they are, set the top-level fields and clear the per-version fields
	if subresourcesIdentical {
		out.Subresources = subresources
	}
	if validationIdentical {
		out.Validation = validation
	}
	if additionalPrinterColumnsIdentical {
		out.AdditionalPrinterColumns = additionalPrinterColumns
	}
	for i := range out.Versions {
		if subresourcesIdentical {
			out.Versions[i].Subresources = nil
		}
		if validationIdentical {
			out.Versions[i].Schema = nil
		}
		if additionalPrinterColumnsIdentical {
			out.Versions[i].AdditionalPrinterColumns = nil
		}
	}

	return nil
}


func Convert_v1_CustomResourceConversion_To_apiextensions_CustomResourceConversion(in *CustomResourceConversion, out *apiextensions.CustomResourceConversion, s conversion.Scope) error {
	if err := autoConvert_v1_CustomResourceConversion_To_apiextensions_CustomResourceConversion(in, out, s); err != nil {
		return err
	}

	out.WebhookClientConfig = nil
	out.ConversionReviewVersions = nil
	if in.Webhook != nil {
		out.ConversionReviewVersions = in.Webhook.ConversionReviewVersions
		if in.Webhook.ClientConfig != nil {
			out.WebhookClientConfig = &apiextensions.WebhookClientConfig{}
			if err := Convert_v1_WebhookClientConfig_To_apiextensions_WebhookClientConfig(in.Webhook.ClientConfig, out.WebhookClientConfig, s); err != nil {
				return err
			}
		}
	}
	return nil
}


func Convert_apiextensions_CustomResourceConversion_To_v1_CustomResourceConversion(in *apiextensions.CustomResourceConversion, out *CustomResourceConversion, s conversion.Scope) error {
	if err := autoConvert_apiextensions_CustomResourceConversion_To_v1_CustomResourceConversion(in, out, s); err != nil {
		return err
	}

	out.Webhook = nil
	if in.WebhookClientConfig != nil || in.ConversionReviewVersions != nil {
		out.Webhook = &WebhookConversion{}
		out.Webhook.ConversionReviewVersions = in.ConversionReviewVersions
		if in.WebhookClientConfig != nil {
			out.Webhook.ClientConfig = &WebhookClientConfig{}
			if err := Convert_apiextensions_WebhookClientConfig_To_v1_WebhookClientConfig(in.WebhookClientConfig, out.Webhook.ClientConfig, s); err != nil {
				return err
			}
		}
	}
	return nil
}


func Convert_apiextensions_ValidationRules_To_v1_ValidationRules(in *apiextensions.ValidationRules, out *ValidationRules, s conversion.Scope) error {
	*out = *(*ValidationRules)(unsafe.Pointer(in))
	return nil
}


DeepCopy

// TODO: Update this after a tag is created for interface fields in DeepCopy
func (in *JSONSchemaProps) DeepCopy() *JSONSchemaProps {
	if in == nil {
		return nil
	}
	out := new(JSONSchemaProps)
	*out = *in

	if in.Ref != nil {
		in, out := &in.Ref, &out.Ref
		if *in == nil {
			*out = nil
		} else {
			*out = new(string)
			**out = **in
		}
	}

	if in.Maximum != nil {
		in, out := &in.Maximum, &out.Maximum
		if *in == nil {
			*out = nil
		} else {
			*out = new(float64)
			**out = **in
		}
	}

	if in.Minimum != nil {
		in, out := &in.Minimum, &out.Minimum
		if *in == nil {
			*out = nil
		} else {
			*out = new(float64)
			**out = **in
		}
	}

	if in.MaxLength != nil {
		in, out := &in.MaxLength, &out.MaxLength
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.MinLength != nil {
		in, out := &in.MinLength, &out.MinLength
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}
	if in.MaxItems != nil {
		in, out := &in.MaxItems, &out.MaxItems
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.MinItems != nil {
		in, out := &in.MinItems, &out.MinItems
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.MultipleOf != nil {
		in, out := &in.MultipleOf, &out.MultipleOf
		if *in == nil {
			*out = nil
		} else {
			*out = new(float64)
			**out = **in
		}
	}

	if in.MaxProperties != nil {
		in, out := &in.MaxProperties, &out.MaxProperties
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.MinProperties != nil {
		in, out := &in.MinProperties, &out.MinProperties
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.Required != nil {
		in, out := &in.Required, &out.Required
		*out = make([]string, len(*in))
		copy(*out, *in)
	}

	if in.Items != nil {
		in, out := &in.Items, &out.Items
		if *in == nil {
			*out = nil
		} else {
			*out = new(JSONSchemaPropsOrArray)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.AllOf != nil {
		in, out := &in.AllOf, &out.AllOf
		*out = make([]JSONSchemaProps, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}

	if in.OneOf != nil {
		in, out := &in.OneOf, &out.OneOf
		*out = make([]JSONSchemaProps, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
	if in.AnyOf != nil {
		in, out := &in.AnyOf, &out.AnyOf
		*out = make([]JSONSchemaProps, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}

	if in.Not != nil {
		in, out := &in.Not, &out.Not
		if *in == nil {
			*out = nil
		} else {
			*out = new(JSONSchemaProps)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.Properties != nil {
		in, out := &in.Properties, &out.Properties
		*out = make(map[string]JSONSchemaProps, len(*in))
		for key, val := range *in {
			(*out)[key] = *val.DeepCopy()
		}
	}

	if in.AdditionalProperties != nil {
		in, out := &in.AdditionalProperties, &out.AdditionalProperties
		if *in == nil {
			*out = nil
		} else {
			*out = new(JSONSchemaPropsOrBool)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.PatternProperties != nil {
		in, out := &in.PatternProperties, &out.PatternProperties
		*out = make(map[string]JSONSchemaProps, len(*in))
		for key, val := range *in {
			(*out)[key] = *val.DeepCopy()
		}
	}

	if in.Dependencies != nil {
		in, out := &in.Dependencies, &out.Dependencies
		*out = make(JSONSchemaDependencies, len(*in))
		for key, val := range *in {
			(*out)[key] = *val.DeepCopy()
		}
	}

	if in.AdditionalItems != nil {
		in, out := &in.AdditionalItems, &out.AdditionalItems
		if *in == nil {
			*out = nil
		} else {
			*out = new(JSONSchemaPropsOrBool)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.Definitions != nil {
		in, out := &in.Definitions, &out.Definitions
		*out = make(JSONSchemaDefinitions, len(*in))
		for key, val := range *in {
			(*out)[key] = *val.DeepCopy()
		}
	}

	if in.ExternalDocs != nil {
		in, out := &in.ExternalDocs, &out.ExternalDocs
		if *in == nil {
			*out = nil
		} else {
			*out = new(ExternalDocumentation)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.XPreserveUnknownFields != nil {
		in, out := &in.XPreserveUnknownFields, &out.XPreserveUnknownFields
		if *in == nil {
			*out = nil
		} else {
			*out = new(bool)
			**out = **in
		}
	}

	if in.XMapType != nil {
		in, out := &in.XMapType, &out.XMapType
		*out = new(string)
		**out = **in
	}

	if in.XValidations != nil {
		in, out := &in.XValidations, &out.XValidations
		*out = make([]ValidationRule, len(*in))
		copy(*out, *in)
	}

	return out
}


addDefaultingFuncs

func addDefaultingFuncs(scheme *runtime.Scheme) error {
	return RegisterDefaults(scheme)
}


func SetDefaults_CustomResourceDefinition(obj *CustomResourceDefinition) {
	SetDefaults_CustomResourceDefinitionSpec(&obj.Spec)
	if len(obj.Status.StoredVersions) == 0 {
		for _, v := range obj.Spec.Versions {
			if v.Storage {
				obj.Status.StoredVersions = append(obj.Status.StoredVersions, v.Name)
				break
			}
		}
	}
}


func SetDefaults_CustomResourceDefinitionSpec(obj *CustomResourceDefinitionSpec) {
	if len(obj.Names.Singular) == 0 {
		obj.Names.Singular = strings.ToLower(obj.Names.Kind)
	}
	if len(obj.Names.ListKind) == 0 && len(obj.Names.Kind) > 0 {
		obj.Names.ListKind = obj.Names.Kind + "List"
	}
	if obj.Conversion == nil {
		obj.Conversion = &CustomResourceConversion{
			Strategy: NoneConverter,
		}
	}
}


// SetDefaults_ServiceReference sets defaults for Webhook's ServiceReference
func SetDefaults_ServiceReference(obj *ServiceReference) {
	if obj.Port == nil {
		obj.Port = utilpointer.Int32Ptr(443)
	}
}


MarshalJSON

func (s JSONSchemaPropsOrBool) MarshalJSON() ([]byte, error) {
	if s.Schema != nil {
		return json.Marshal(s.Schema)
	}

	if s.Schema == nil && !s.Allows {
		return jsFalse, nil
	}
	return jsTrue, nil
}


UnmarshalJSON

func (s *JSONSchemaPropsOrBool) UnmarshalJSON(data []byte) error {
	var nw JSONSchemaPropsOrBool
	switch {
	case len(data) == 0:
	case data[0] == '{':
		var sch JSONSchemaProps
		if err := json.Unmarshal(data, &sch); err != nil {
			return err
		}
		nw.Allows = true
		nw.Schema = &sch
	case len(data) == 4 && string(data) == "true":
		nw.Allows = true
	case len(data) == 5 && string(data) == "false":
		nw.Allows = false
	default:
		return errors.New("boolean or JSON schema expected")
	}
	*s = nw
	return nil
}


MarshalJSON

func (s JSONSchemaPropsOrStringArray) MarshalJSON() ([]byte, error) {
	if len(s.Property) > 0 {
		return json.Marshal(s.Property)
	}
	if s.Schema != nil {
		return json.Marshal(s.Schema)
	}
	return []byte("null"), nil
}


UnmarshalJSON

func (s *JSONSchemaPropsOrStringArray) UnmarshalJSON(data []byte) error {
	var first byte
	if len(data) > 1 {
		first = data[0]
	}
	var nw JSONSchemaPropsOrStringArray
	if first == '{' {
		var sch JSONSchemaProps
		if err := json.Unmarshal(data, &sch); err != nil {
			return err
		}
		nw.Schema = &sch
	}
	if first == '[' {
		if err := json.Unmarshal(data, &nw.Property); err != nil {
			return err
		}
	}
	*s = nw
	return nil
}


MarshalJSON

func (s JSONSchemaPropsOrArray) MarshalJSON() ([]byte, error) {
	if len(s.JSONSchemas) > 0 {
		return json.Marshal(s.JSONSchemas)
	}
	return json.Marshal(s.Schema)
}


UnmarshalJSON

func (s *JSONSchemaPropsOrArray) UnmarshalJSON(data []byte) error {
	var nw JSONSchemaPropsOrArray
	var first byte
	if len(data) > 1 {
		first = data[0]
	}
	if first == '{' {
		var sch JSONSchemaProps
		if err := json.Unmarshal(data, &sch); err != nil {
			return err
		}
		nw.Schema = &sch
	}
	if first == '[' {
		if err := json.Unmarshal(data, &nw.JSONSchemas); err != nil {
			return err
		}
	}
	*s = nw
	return nil
}


MarshalJSON

func (s JSON) MarshalJSON() ([]byte, error) {
	if len(s.Raw) > 0 {
		return s.Raw, nil
	}
	return []byte("null"), nil

}


UnmarshalJSON

func (s *JSON) UnmarshalJSON(data []byte) error {
	if len(data) > 0 && !bytes.Equal(data, nullLiteral) {
		s.Raw = data
	}
	return nil
}


Kind

// Kind takes an unqualified kind and returns back a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {
	return SchemeGroupVersion.WithKind(kind).GroupKind()
}


Resource

// Resource takes an unqualified resource and returns back a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
	return SchemeGroupVersion.WithResource(resource).GroupResource()
}


addKnownTypes

// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&CustomResourceDefinition{},
		&CustomResourceDefinitionList{},
		&ConversionReview{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


init

func init() {
	// We only register manually written functions here. The registration of the
	// generated functions takes place in the generated files. The separation
	// makes the code compile even when the generated files are missing.
	localSchemeBuilder.Register(addDefaultingFuncs)
}