Example #1
0
func (w *userProjectWatcher) GroupMembershipChanged(namespaceName string, users, groups sets.String) {
	if !w.visibleNamespaces.Has("*") && !w.visibleNamespaces.Has(namespaceName) {
		// this user is scoped to a level that shouldn't see this update
		return
	}

	hasAccess := users.Has(w.user.GetName()) || groups.HasAny(w.user.GetGroups()...)
	_, known := w.knownProjects[namespaceName]

	switch {
	// this means that we were removed from the project
	case !hasAccess && known:
		delete(w.knownProjects, namespaceName)

		select {
		case w.cacheIncoming <- watch.Event{
			Type:   watch.Deleted,
			Object: projectutil.ConvertNamespace(&kapi.Namespace{ObjectMeta: kapi.ObjectMeta{Name: namespaceName}}),
		}:
		default:
			// remove the watcher so that we wont' be notified again and block
			w.authCache.RemoveWatcher(w)
			w.cacheError <- errors.New("delete notification timeout")
		}

	case hasAccess:
		namespace, err := w.projectCache.GetNamespace(namespaceName)
		if err != nil {
			utilruntime.HandleError(err)
			return
		}

		event := watch.Event{
			Type:   watch.Added,
			Object: projectutil.ConvertNamespace(namespace),
		}

		// if we already have this in our list, then we're getting notified because the object changed
		if lastResourceVersion, known := w.knownProjects[namespaceName]; known {
			event.Type = watch.Modified

			// if we've already notified for this particular resourceVersion, there's no work to do
			if lastResourceVersion == namespace.ResourceVersion {
				return
			}
		}
		w.knownProjects[namespaceName] = namespace.ResourceVersion

		select {
		case w.cacheIncoming <- event:
		default:
			// remove the watcher so that we won't be notified again and block
			w.authCache.RemoveWatcher(w)
			w.cacheError <- errors.New("add notification timeout")
		}

	}

}
Example #2
0
func (w *userProjectWatcher) GroupMembershipChanged(namespaceName string, latestUsers, lastestGroups, removedUsers, removedGroups, addedUsers, addedGroups sets.String) {
	hasAccess := latestUsers.Has(w.username) || lastestGroups.HasAny(w.groups...)
	removed := !hasAccess && (removedUsers.Has(w.username) || removedGroups.HasAny(w.groups...))

	switch {
	case removed:
		if _, known := w.knownProjects[namespaceName]; !known {
			return
		}
		delete(w.knownProjects, namespaceName)

		select {
		case w.cacheIncoming <- watch.Event{
			Type:   watch.Deleted,
			Object: projectutil.ConvertNamespace(&kapi.Namespace{ObjectMeta: kapi.ObjectMeta{Name: namespaceName}}),
		}:
		default:
			// remove the watcher so that we wont' be notified again and block
			w.authCache.RemoveWatcher(w)
			w.cacheError <- errors.New("delete notification timeout")
		}

	case hasAccess:
		namespace, err := w.projectCache.GetNamespace(namespaceName)
		if err != nil {
			utilruntime.HandleError(err)
			return
		}

		event := watch.Event{
			Type:   watch.Added,
			Object: projectutil.ConvertNamespace(namespace),
		}

		// if we already have this in our list, then we're getting notified because the object changed
		if lastResourceVersion, known := w.knownProjects[namespaceName]; known {
			event.Type = watch.Modified

			// if we've already notified for this particular resourceVersion, there's no work to do
			if lastResourceVersion == namespace.ResourceVersion {
				return
			}
		}
		w.knownProjects[namespaceName] = namespace.ResourceVersion

		select {
		case w.cacheIncoming <- event:
		default:
			// remove the watcher so that we won't be notified again and block
			w.authCache.RemoveWatcher(w)
			w.cacheError <- errors.New("add notification timeout")
		}

	}

}
Example #3
0
func (s *REST) Update(ctx kapi.Context, name string, objInfo rest.UpdatedObjectInfo) (runtime.Object, bool, error) {
	oldObj, err := s.Get(ctx, name)
	if err != nil {
		return nil, false, err
	}

	obj, err := objInfo.UpdatedObject(ctx, oldObj)
	if err != nil {
		return nil, false, err
	}

	project, ok := obj.(*api.Project)
	if !ok {
		return nil, false, fmt.Errorf("not a project: %#v", obj)
	}

	s.updateStrategy.PrepareForUpdate(obj, oldObj)
	if errs := s.updateStrategy.ValidateUpdate(ctx, obj, oldObj); len(errs) > 0 {
		return nil, false, kerrors.NewInvalid(projectapi.Kind("Project"), project.Name, errs)
	}

	namespace, err := s.client.Update(projectutil.ConvertProject(project))
	if err != nil {
		return nil, false, err
	}

	return projectutil.ConvertNamespace(namespace), false, nil
}
Example #4
0
// Get retrieves a Project by name
func (s *REST) Get(ctx kapi.Context, name string) (runtime.Object, error) {
	namespace, err := s.client.Get(name)
	if err != nil {
		return nil, err
	}
	return projectutil.ConvertNamespace(namespace), nil
}
Example #5
0
// Create registers the given Project.
func (s *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) {
	project, ok := obj.(*api.Project)
	if !ok {
		return nil, fmt.Errorf("not a project: %#v", obj)
	}
	kapi.FillObjectMetaSystemFields(ctx, &project.ObjectMeta)
	s.createStrategy.PrepareForCreate(obj)
	if errs := s.createStrategy.Validate(ctx, obj); len(errs) > 0 {
		return nil, kerrors.NewInvalid(projectapi.Kind("Project"), project.Name, errs)
	}
	namespace, err := s.client.Create(projectutil.ConvertProject(project))
	if err != nil {
		return nil, err
	}
	return projectutil.ConvertNamespace(namespace), nil
}
Example #6
0
// Watch pulls stuff from etcd, converts, and pushes out the outgoing channel. Meant to be
// called as a goroutine.
func (w *userProjectWatcher) Watch() {
	defer close(w.outgoing)
	defer func() {
		// when the watch ends, always remove the watcher from the cache to avoid leaking.
		w.authCache.RemoveWatcher(w)
	}()
	defer utilruntime.HandleCrash()

	// start by emitting all the `initialProjects`
	for i := range w.initialProjects {
		// keep this check here to sure we don't keep this open in the case of failures
		select {
		case err := <-w.cacheError:
			w.emit(makeErrorEvent(err))
			return
		default:
		}

		w.emit(watch.Event{
			Type:   watch.Added,
			Object: projectutil.ConvertNamespace(&w.initialProjects[i]),
		})
	}

	for {
		select {
		case err := <-w.cacheError:
			w.emit(makeErrorEvent(err))
			return

		case <-w.userStop:
			return

		case event := <-w.cacheIncoming:
			if curLen := int64(len(w.cacheIncoming)); watchChannelHWM.Update(curLen) {
				// Monitor if this gets backed up, and how much.
				glog.V(2).Infof("watch: %v objects queued in project cache watching channel.", curLen)
			}

			w.emit(event)
		}
	}
}