本文整理匯總了Golang中k8s/io/kubernetes/pkg/admission.Attributes.GetOperation方法的典型用法代碼示例。如果您正苦於以下問題:Golang Attributes.GetOperation方法的具體用法?Golang Attributes.GetOperation怎麽用?Golang Attributes.GetOperation使用的例子?那麽, 這裏精選的方法代碼示例或許可以為您提供幫助。您也可以進一步了解該方法所在類k8s/io/kubernetes/pkg/admission.Attributes
的用法示例。
在下文中一共展示了Attributes.GetOperation方法的15個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的Golang代碼示例。
示例1: Admit
func (d *sccExecRestrictions) Admit(a admission.Attributes) (err error) {
if a.GetOperation() != admission.Connect {
return nil
}
if a.GetResource() != kapi.Resource("pods") {
return nil
}
if a.GetSubresource() != "attach" && a.GetSubresource() != "exec" {
return nil
}
pod, err := d.client.Pods(a.GetNamespace()).Get(a.GetName())
if err != nil {
return admission.NewForbidden(a, err)
}
// create a synthentic admission attribute to check SCC admission status for this pod
// clear the SA name, so that any permissions MUST be based on your user's power, not the SAs power.
pod.Spec.ServiceAccountName = ""
createAttributes := admission.NewAttributesRecord(pod, kapi.Kind("Pod"), a.GetNamespace(), a.GetName(), a.GetResource(), a.GetSubresource(), admission.Create, a.GetUserInfo())
if err := d.constraintAdmission.Admit(createAttributes); err != nil {
return admission.NewForbidden(a, err)
}
return nil
}
示例2: Admit
func (d *sccExecRestrictions) Admit(a admission.Attributes) (err error) {
if a.GetOperation() != admission.Connect {
return nil
}
if a.GetResource().GroupResource() != kapi.Resource("pods") {
return nil
}
if a.GetSubresource() != "attach" && a.GetSubresource() != "exec" {
return nil
}
pod, err := d.client.Core().Pods(a.GetNamespace()).Get(a.GetName())
if err != nil {
return admission.NewForbidden(a, err)
}
// TODO, if we want to actually limit who can use which service account, then we'll need to add logic here to make sure that
// we're allowed to use the SA the pod is using. Otherwise, user-A creates pod and user-B (who can't use the SA) can exec into it.
createAttributes := admission.NewAttributesRecord(pod, pod, kapi.Kind("Pod").WithVersion(""), a.GetNamespace(), a.GetName(), a.GetResource(), "", admission.Create, a.GetUserInfo())
if err := d.constraintAdmission.Admit(createAttributes); err != nil {
return admission.NewForbidden(a, err)
}
return nil
}
示例3: Evaluate
func (e *quotaEvaluator) Evaluate(a admission.Attributes) error {
e.init.Do(func() {
go e.run()
})
// if we do not know how to evaluate use for this kind, just ignore
evaluators := e.registry.Evaluators()
evaluator, found := evaluators[a.GetKind().GroupKind()]
if !found {
return nil
}
// for this kind, check if the operation could mutate any quota resources
// if no resources tracked by quota are impacted, then just return
op := a.GetOperation()
operationResources := evaluator.OperationResources(op)
if len(operationResources) == 0 {
return nil
}
waiter := newAdmissionWaiter(a)
e.addWork(waiter)
// wait for completion or timeout
select {
case <-waiter.finished:
case <-time.After(10 * time.Second):
return fmt.Errorf("timeout")
}
return waiter.result
}
示例4: Admit
// Admit determines if the service should be admitted based on the configured network CIDR.
func (r *externalIPRanger) Admit(a kadmission.Attributes) error {
if a.GetResource().GroupResource() != kapi.Resource("services") {
return nil
}
svc, ok := a.GetObject().(*kapi.Service)
// if we can't convert then we don't handle this object so just return
if !ok {
return nil
}
// Determine if an ingress ip address should be allowed as an
// external ip by checking the loadbalancer status of the previous
// object state. Only updates need to be validated against the
// ingress ip since the loadbalancer status cannot be set on
// create.
ingressIP := ""
retrieveIngressIP := a.GetOperation() == kadmission.Update &&
r.allowIngressIP && svc.Spec.Type == kapi.ServiceTypeLoadBalancer
if retrieveIngressIP {
old, ok := a.GetOldObject().(*kapi.Service)
ipPresent := ok && old != nil && len(old.Status.LoadBalancer.Ingress) > 0
if ipPresent {
ingressIP = old.Status.LoadBalancer.Ingress[0].IP
}
}
var errs field.ErrorList
switch {
// administrator disabled externalIPs
case len(svc.Spec.ExternalIPs) > 0 && len(r.admit) == 0:
onlyIngressIP := len(svc.Spec.ExternalIPs) == 1 && svc.Spec.ExternalIPs[0] == ingressIP
if !onlyIngressIP {
errs = append(errs, field.Forbidden(field.NewPath("spec", "externalIPs"), "externalIPs have been disabled"))
}
// administrator has limited the range
case len(svc.Spec.ExternalIPs) > 0 && len(r.admit) > 0:
for i, s := range svc.Spec.ExternalIPs {
ip := net.ParseIP(s)
if ip == nil {
errs = append(errs, field.Forbidden(field.NewPath("spec", "externalIPs").Index(i), "externalIPs must be a valid address"))
continue
}
notIngressIP := s != ingressIP
if (NetworkSlice(r.reject).Contains(ip) || !NetworkSlice(r.admit).Contains(ip)) && notIngressIP {
errs = append(errs, field.Forbidden(field.NewPath("spec", "externalIPs").Index(i), "externalIP is not allowed"))
continue
}
}
}
if len(errs) > 0 {
return apierrs.NewInvalid(a.GetKind().GroupKind(), a.GetName(), errs)
}
return nil
}
示例5: Admit
func (l *lifecycle) Admit(a admission.Attributes) (err error) {
// prevent deletion of immortal namespaces
if a.GetOperation() == admission.Delete && a.GetKind() == "Namespace" && l.immortalNamespaces.Has(a.GetName()) {
return errors.NewForbidden(a.GetKind(), a.GetName(), fmt.Errorf("this namespace may not be deleted"))
}
gvk, err := api.RESTMapper.KindFor(a.GetResource())
if err != nil {
return errors.NewInternalError(err)
}
mapping, err := api.RESTMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
if err != nil {
return errors.NewInternalError(err)
}
if mapping.Scope.Name() != meta.RESTScopeNameNamespace {
return nil
}
namespaceObj, exists, err := l.store.Get(&api.Namespace{
ObjectMeta: api.ObjectMeta{
Name: a.GetNamespace(),
Namespace: "",
},
})
if err != nil {
return errors.NewInternalError(err)
}
// refuse to operate on non-existent namespaces
if !exists {
// in case of latency in our caches, make a call direct to storage to verify that it truly exists or not
namespaceObj, err = l.client.Namespaces().Get(a.GetNamespace())
if err != nil {
if errors.IsNotFound(err) {
return err
}
return errors.NewInternalError(err)
}
}
// ensure that we're not trying to create objects in terminating namespaces
if a.GetOperation() == admission.Create {
namespace := namespaceObj.(*api.Namespace)
if namespace.Status.Phase != api.NamespaceTerminating {
return nil
}
// TODO: This should probably not be a 403
return admission.NewForbidden(a, fmt.Errorf("Unable to create new content in namespace %s because it is being terminated.", a.GetNamespace()))
}
return nil
}
示例6: Admit
func (l *lifecycle) Admit(a admission.Attributes) (err error) {
// prevent deletion of immortal namespaces
if a.GetOperation() == admission.Delete && a.GetKind() == api.Kind("Namespace") && l.immortalNamespaces.Has(a.GetName()) {
return errors.NewForbidden(a.GetResource(), a.GetName(), fmt.Errorf("this namespace may not be deleted"))
}
// if we're here, then we've already passed authentication, so we're allowed to do what we're trying to do
// if we're here, then the API server has found a route, which means that if we have a non-empty namespace
// its a namespaced resource.
if len(a.GetNamespace()) == 0 || a.GetKind() == api.Kind("Namespace") {
return nil
}
namespaceObj, exists, err := l.store.Get(&api.Namespace{
ObjectMeta: api.ObjectMeta{
Name: a.GetNamespace(),
Namespace: "",
},
})
if err != nil {
return errors.NewInternalError(err)
}
// refuse to operate on non-existent namespaces
if !exists {
// in case of latency in our caches, make a call direct to storage to verify that it truly exists or not
namespaceObj, err = l.client.Legacy().Namespaces().Get(a.GetNamespace())
if err != nil {
if errors.IsNotFound(err) {
return err
}
return errors.NewInternalError(err)
}
}
// ensure that we're not trying to create objects in terminating namespaces
if a.GetOperation() == admission.Create {
namespace := namespaceObj.(*api.Namespace)
if namespace.Status.Phase != api.NamespaceTerminating {
return nil
}
// TODO: This should probably not be a 403
return admission.NewForbidden(a, fmt.Errorf("Unable to create new content in namespace %s because it is being terminated.", a.GetNamespace()))
}
return nil
}
示例7: Admit
// Admit enforces that pod and its project node label selectors matches at least a node in the cluster.
func (p *podNodeEnvironment) Admit(a admission.Attributes) (err error) {
// ignore anything except create or update of pods
if !(a.GetOperation() == admission.Create || a.GetOperation() == admission.Update) {
return nil
}
resource := a.GetResource()
if resource != "pods" {
return nil
}
obj := a.GetObject()
pod, ok := obj.(*kapi.Pod)
if !ok {
return nil
}
name := pod.Name
projects, err := projectcache.GetProjectCache()
if err != nil {
return err
}
namespace, err := projects.GetNamespaceObject(a.GetNamespace())
if err != nil {
return apierrors.NewForbidden(resource, name, err)
}
projectNodeSelector, err := projects.GetNodeSelectorMap(namespace)
if err != nil {
return err
}
if labelselector.Conflicts(projectNodeSelector, pod.Spec.NodeSelector) {
return apierrors.NewForbidden(resource, name, fmt.Errorf("pod node label selector conflicts with its project node label selector"))
}
// modify pod node selector = project node selector + current pod node selector
pod.Spec.NodeSelector = labelselector.Merge(projectNodeSelector, pod.Spec.NodeSelector)
return nil
}
示例8: Admit
func (l *lifecycle) Admit(a admission.Attributes) (err error) {
// prevent deletion of immortal namespaces
if a.GetOperation() == admission.Delete {
if a.GetKind() == "Namespace" && l.immortalNamespaces.Has(a.GetName()) {
return errors.NewForbidden(a.GetKind(), a.GetName(), fmt.Errorf("namespace can never be deleted"))
}
return nil
}
defaultVersion, kind, err := api.RESTMapper.VersionAndKindForResource(a.GetResource())
if err != nil {
return admission.NewForbidden(a, err)
}
mapping, err := api.RESTMapper.RESTMapping(kind, defaultVersion)
if err != nil {
return admission.NewForbidden(a, err)
}
if mapping.Scope.Name() != meta.RESTScopeNameNamespace {
return nil
}
namespaceObj, exists, err := l.store.Get(&api.Namespace{
ObjectMeta: api.ObjectMeta{
Name: a.GetNamespace(),
Namespace: "",
},
})
if err != nil {
return admission.NewForbidden(a, err)
}
if !exists {
return nil
}
namespace := namespaceObj.(*api.Namespace)
if namespace.Status.Phase != api.NamespaceTerminating {
return nil
}
return admission.NewForbidden(a, fmt.Errorf("Unable to create new content in namespace %s because it is being terminated.", a.GetNamespace()))
}
示例9: Admit
// Admit attempts to apply the image policy to the incoming resource.
func (a *imagePolicyPlugin) Admit(attr admission.Attributes) error {
switch attr.GetOperation() {
case admission.Create, admission.Update:
if len(attr.GetSubresource()) > 0 {
return nil
}
// only create and update are tested, and only on core resources
// TODO: scan all resources
// TODO: Create a general equivalence map for admission - operation X on subresource Y is equivalent to reduced operation
default:
return nil
}
gr := attr.GetResource().GroupResource()
if !a.accepter.Covers(gr) {
return nil
}
m, err := meta.GetImageReferenceMutator(attr.GetObject())
if err != nil {
return apierrs.NewForbidden(gr, attr.GetName(), fmt.Errorf("unable to apply image policy against objects of type %T: %v", attr.GetObject(), err))
}
// load exclusion rules from the namespace cache
var excluded sets.String
if ns := attr.GetNamespace(); len(ns) > 0 {
if ns, err := a.projectCache.GetNamespace(ns); err == nil {
if value := ns.Annotations[api.IgnorePolicyRulesAnnotation]; len(value) > 0 {
excluded = sets.NewString(strings.Split(value, ",")...)
}
}
}
if err := accept(a.accepter, a.resolver, m, attr, excluded); err != nil {
return err
}
return nil
}
示例10: Admit
// Admit makes admission decisions while enforcing quota
func (q *quotaAdmission) Admit(a admission.Attributes) (err error) {
// ignore all operations that correspond to sub-resource actions
if a.GetSubresource() != "" {
return nil
}
// if we do not know how to evaluate use for this kind, just ignore
evaluators := q.evaluator.registry.Evaluators()
evaluator, found := evaluators[a.GetKind().GroupKind()]
if !found {
return nil
}
// for this kind, check if the operation could mutate any quota resources
// if no resources tracked by quota are impacted, then just return
op := a.GetOperation()
operationResources := evaluator.OperationResources(op)
if len(operationResources) == 0 {
return nil
}
return q.evaluator.evaluate(a)
}
示例11: Admit
func (o *podNodeConstraints) Admit(attr admission.Attributes) error {
switch {
case o.config == nil,
attr.GetSubresource() != "":
return nil
}
shouldCheck, err := shouldCheckResource(attr.GetResource().GroupResource(), attr.GetKind().GroupKind())
if err != nil {
return err
}
if !shouldCheck {
return nil
}
// Only check Create operation on pods
if attr.GetResource().GroupResource() == kapi.Resource("pods") && attr.GetOperation() != admission.Create {
return nil
}
ps, err := o.getPodSpec(attr)
if err == nil {
return o.admitPodSpec(attr, ps)
}
return err
}
示例12: Admit
// Admit admits resources into cluster that do not violate any defined LimitRange in the namespace
func (l *limitRanger) Admit(a admission.Attributes) (err error) {
// Ignore all calls to subresources
if a.GetSubresource() != "" {
return nil
}
obj := a.GetObject()
resource := a.GetResource()
name := "Unknown"
if obj != nil {
name, _ = meta.NewAccessor().Name(obj)
if len(name) == 0 {
name, _ = meta.NewAccessor().GenerateName(obj)
}
}
key := &api.LimitRange{
ObjectMeta: api.ObjectMeta{
Namespace: a.GetNamespace(),
Name: "",
},
}
items, err := l.indexer.Index("namespace", key)
if err != nil {
return admission.NewForbidden(a, fmt.Errorf("Unable to %s %s at this time because there was an error enforcing limit ranges", a.GetOperation(), resource))
}
if len(items) == 0 {
return nil
}
// ensure it meets each prescribed min/max
for i := range items {
limitRange := items[i].(*api.LimitRange)
err = l.limitFunc(limitRange, a.GetResource(), a.GetObject())
if err != nil {
return admission.NewForbidden(a, err)
}
}
return nil
}
示例13: Admit
func (q *quota) Admit(a admission.Attributes) (err error) {
if a.GetSubresource() != "" {
return nil
}
if a.GetOperation() == "DELETE" {
return nil
}
key := &api.ResourceQuota{
ObjectMeta: api.ObjectMeta{
Namespace: a.GetNamespace(),
Name: "",
},
}
// concurrent operations that modify quota tracked resources can cause a conflict when incrementing usage
// as a result, we will attempt to increment quota usage per request up to numRetries limit
// we fuzz each retry with an interval period to attempt to improve end-user experience during concurrent operations
numRetries := 10
interval := time.Duration(rand.Int63n(90)+int64(10)) * time.Millisecond
items, err := q.indexer.Index("namespace", key)
if err != nil {
return admission.NewForbidden(a, fmt.Errorf("unable to %s %s at this time because there was an error enforcing quota", a.GetOperation(), a.GetResource()))
}
if len(items) == 0 {
return nil
}
for i := range items {
quota := items[i].(*api.ResourceQuota)
for retry := 1; retry <= numRetries; retry++ {
// we cannot modify the value directly in the cache, so we copy
status := &api.ResourceQuotaStatus{
Hard: api.ResourceList{},
Used: api.ResourceList{},
}
for k, v := range quota.Status.Hard {
status.Hard[k] = *v.Copy()
}
for k, v := range quota.Status.Used {
status.Used[k] = *v.Copy()
}
dirty, err := IncrementUsage(a, status, q.client)
if err != nil {
return admission.NewForbidden(a, err)
}
if dirty {
// construct a usage record
usage := api.ResourceQuota{
ObjectMeta: api.ObjectMeta{
Name: quota.Name,
Namespace: quota.Namespace,
ResourceVersion: quota.ResourceVersion,
Labels: quota.Labels,
Annotations: quota.Annotations},
}
usage.Status = *status
_, err = q.client.ResourceQuotas(usage.Namespace).UpdateStatus(&usage)
if err == nil {
break
}
// we have concurrent requests to update quota, so look to retry if needed
if retry == numRetries {
return admission.NewForbidden(a, fmt.Errorf("unable to %s %s at this time because there are too many concurrent requests to increment quota", a.GetOperation(), a.GetResource()))
}
time.Sleep(interval)
// manually get the latest quota
quota, err = q.client.ResourceQuotas(usage.Namespace).Get(quota.Name)
if err != nil {
return admission.NewForbidden(a, err)
}
}
}
}
return nil
}
示例14: IncrementUsage
// IncrementUsage updates the supplied ResourceQuotaStatus object based on the incoming operation
// Return true if the usage must be recorded prior to admitting the new resource
// Return an error if the operation should not pass admission control
func IncrementUsage(a admission.Attributes, status *api.ResourceQuotaStatus, client client.Interface) (bool, error) {
var errs []error
dirty := true
set := map[api.ResourceName]bool{}
for k := range status.Hard {
set[k] = true
}
obj := a.GetObject()
// handle max counts for each kind of resource (pods, services, replicationControllers, etc.)
if a.GetOperation() == admission.Create {
resourceName := resourceToResourceName[a.GetResource()]
hard, hardFound := status.Hard[resourceName]
if hardFound {
used, usedFound := status.Used[resourceName]
if !usedFound {
return false, fmt.Errorf("quota usage stats are not yet known, unable to admit resource until an accurate count is completed.")
}
if used.Value() >= hard.Value() {
errs = append(errs, fmt.Errorf("limited to %s %s", hard.String(), resourceName))
dirty = false
} else {
status.Used[resourceName] = *resource.NewQuantity(used.Value()+int64(1), resource.DecimalSI)
}
}
}
if a.GetResource() == "pods" {
for _, resourceName := range []api.ResourceName{api.ResourceMemory, api.ResourceCPU} {
// ignore tracking the resource if it's not in the quota document
if !set[resourceName] {
continue
}
hard, hardFound := status.Hard[resourceName]
if !hardFound {
continue
}
// if we do not yet know how much of the current resource is used, we cannot accept any request
used, usedFound := status.Used[resourceName]
if !usedFound {
return false, fmt.Errorf("unable to admit pod until quota usage stats are calculated.")
}
// the amount of resource being requested, or an error if it does not make a request that is tracked
pod := obj.(*api.Pod)
delta, err := resourcequotacontroller.PodRequests(pod, resourceName)
if err != nil {
return false, fmt.Errorf("must make a non-zero request for %s since it is tracked by quota.", resourceName)
}
// if this operation is an update, we need to find the delta usage from the previous state
if a.GetOperation() == admission.Update {
oldPod, err := client.Pods(a.GetNamespace()).Get(pod.Name)
if err != nil {
return false, err
}
// if the previous version of the resource made a resource request, we need to subtract the old request
// from the current to get the actual resource request delta. if the previous version of the pod
// made no request on the resource, then we get an err value. we ignore the err value, and delta
// will just be equal to the total resource request on the pod since there is nothing to subtract.
oldRequest, err := resourcequotacontroller.PodRequests(oldPod, resourceName)
if err == nil {
err = delta.Sub(*oldRequest)
if err != nil {
return false, err
}
}
}
newUsage := used.Copy()
newUsage.Add(*delta)
// make the most precise comparison possible
newUsageValue := newUsage.Value()
hardUsageValue := hard.Value()
if newUsageValue <= resource.MaxMilliValue && hardUsageValue <= resource.MaxMilliValue {
newUsageValue = newUsage.MilliValue()
hardUsageValue = hard.MilliValue()
}
if newUsageValue > hardUsageValue {
errs = append(errs, fmt.Errorf("unable to admit pod without exceeding quota for resource %s: limited to %s but require %s to succeed.", resourceName, hard.String(), newUsage.String()))
dirty = false
} else {
status.Used[resourceName] = *newUsage
}
}
}
return dirty, utilerrors.NewAggregate(errs)
}
示例15: Admit
// Admit enforces that a namespace must exist in order to associate content with it.
// Admit enforces that a namespace that is terminating cannot accept new content being associated with it.
func (e *lifecycle) Admit(a admission.Attributes) (err error) {
if len(a.GetNamespace()) == 0 {
return nil
}
// always allow a SAR request through, the SAR will return information about
// the ability to take action on the object, no need to verify it here.
if isSubjectAccessReview(a) {
return nil
}
mapping, err := latest.RESTMapper.RESTMapping(a.GetKind())
if err != nil {
glog.V(4).Infof("Ignoring life-cycle enforcement for resource %v; no associated default version and kind could be found.", a.GetResource())
return nil
}
if mapping.Scope.Name() != meta.RESTScopeNameNamespace {
return nil
}
// we want to allow someone to delete something in case it was phantom created somehow
if a.GetOperation() == "DELETE" {
return nil
}
name := "Unknown"
obj := a.GetObject()
if obj != nil {
name, _ = meta.NewAccessor().Name(obj)
}
if !e.cache.Running() {
return admission.NewForbidden(a, err)
}
namespace, err := e.cache.GetNamespace(a.GetNamespace())
if err != nil {
return admission.NewForbidden(a, err)
}
if a.GetOperation() != "CREATE" {
return nil
}
if namespace.Status.Phase == kapi.NamespaceTerminating && !e.creatableResources.Has(strings.ToLower(a.GetResource().Resource)) {
return apierrors.NewForbidden(a.GetKind().Kind, name, fmt.Errorf("Namespace %s is terminating", a.GetNamespace()))
}
// in case of concurrency issues, we will retry this logic
numRetries := 10
interval := time.Duration(rand.Int63n(90)+int64(10)) * time.Millisecond
for retry := 1; retry <= numRetries; retry++ {
// associate this namespace with openshift
_, err = projectutil.Associate(e.client, namespace)
if err == nil {
break
}
// we have exhausted all reasonable efforts to retry so give up now
if retry == numRetries {
return admission.NewForbidden(a, err)
}
// get the latest namespace for the next pass in case of resource version updates
time.Sleep(interval)
// it's possible the namespace actually was deleted, so just forbid if this occurs
namespace, err = e.client.Namespaces().Get(a.GetNamespace())
if err != nil {
return admission.NewForbidden(a, err)
}
}
return nil
}