func (o *RemoveFromProjectOptions) Run() error {
	bindingList, err := o.Client.PolicyBindings(o.BindingNamespace).List(labels.Everything(), fields.Everything())
	if err != nil {
		return err
	}
	sort.Sort(authorizationapi.PolicyBindingSorter(bindingList.Items))

	usersRemoved := util.StringSet{}
	groupsRemoved := util.StringSet{}

	for _, currPolicyBinding := range bindingList.Items {
		for _, currBinding := range authorizationapi.SortRoleBindings(currPolicyBinding.RoleBindings, true) {
			bindingHasGroups := len(o.Groups) > 0 && currBinding.Groups.HasAny(o.Groups...)
			bindingHasUsers := len(o.Users) > 0 && currBinding.Users.HasAny(o.Users...)
			if !bindingHasGroups && !bindingHasUsers {
				continue
			}

			existingGroups := util.NewStringSet(currBinding.Groups.List()...)
			existingUsers := util.NewStringSet(currBinding.Users.List()...)

			currBinding.Groups.Delete(o.Groups...)
			currBinding.Users.Delete(o.Users...)

			_, err = o.Client.RoleBindings(o.BindingNamespace).Update(currBinding)
			if err != nil {
				return err
			}

			roleDisplayName := fmt.Sprintf("%s/%s", currBinding.RoleRef.Namespace, currBinding.RoleRef.Name)
			if len(currBinding.RoleRef.Namespace) == 0 {
				roleDisplayName = currBinding.RoleRef.Name
			}
			if diff := existingGroups.Difference(currBinding.Groups); len(diff) != 0 {
				fmt.Fprintf(o.Out, "Removing %s from groups %v in project %s.\n", roleDisplayName, diff.List(), o.BindingNamespace)
				groupsRemoved.Insert(diff.List()...)
			}
			if diff := existingUsers.Difference(currBinding.Users); len(diff) != 0 {
				fmt.Fprintf(o.Out, "Removing %s from users %v in project %s.\n", roleDisplayName, diff.List(), o.BindingNamespace)
				usersRemoved.Insert(diff.List()...)
			}
		}
	}

	if diff := util.NewStringSet(o.Groups...).Difference(groupsRemoved); len(diff) != 0 {
		fmt.Fprintf(o.Out, "Groups %v were not bound to roles in project %s.\n", diff.List(), o.BindingNamespace)
	}
	if diff := util.NewStringSet(o.Users...).Difference(usersRemoved); len(diff) != 0 {
		fmt.Fprintf(o.Out, "Users %v were not bound to roles in project %s.\n", diff.List(), o.BindingNamespace)
	}

	return nil
}
func (o *RemoveFromProjectOptions) Run() error {
	bindingList, err := o.Client.PolicyBindings(o.BindingNamespace).List(kapi.ListOptions{})
	if err != nil {
		return err
	}
	sort.Sort(authorizationapi.PolicyBindingSorter(bindingList.Items))

	usersRemoved := sets.String{}
	groupsRemoved := sets.String{}
	sasRemoved := sets.String{}
	othersRemoved := sets.String{}

	subjectsToRemove := authorizationapi.BuildSubjects(o.Users, o.Groups, uservalidation.ValidateUserName, uservalidation.ValidateGroupName)

	for _, currPolicyBinding := range bindingList.Items {
		for _, currBinding := range authorizationapi.SortRoleBindings(currPolicyBinding.RoleBindings, true) {
			originalSubjects := make([]kapi.ObjectReference, len(currBinding.Subjects))
			copy(originalSubjects, currBinding.Subjects)
			oldUsers, oldGroups, oldSAs, oldOthers := authorizationapi.SubjectsStrings(currBinding.Namespace, originalSubjects)
			oldUsersSet, oldGroupsSet, oldSAsSet, oldOtherSet := sets.NewString(oldUsers...), sets.NewString(oldGroups...), sets.NewString(oldSAs...), sets.NewString(oldOthers...)

			currBinding.Subjects = removeSubjects(currBinding.Subjects, subjectsToRemove)
			newUsers, newGroups, newSAs, newOthers := authorizationapi.SubjectsStrings(currBinding.Namespace, currBinding.Subjects)
			newUsersSet, newGroupsSet, newSAsSet, newOtherSet := sets.NewString(newUsers...), sets.NewString(newGroups...), sets.NewString(newSAs...), sets.NewString(newOthers...)

			if len(currBinding.Subjects) == len(originalSubjects) {
				continue
			}

			_, err = o.Client.RoleBindings(o.BindingNamespace).Update(currBinding)
			if err != nil {
				return err
			}

			roleDisplayName := fmt.Sprintf("%s/%s", currBinding.RoleRef.Namespace, currBinding.RoleRef.Name)
			if len(currBinding.RoleRef.Namespace) == 0 {
				roleDisplayName = currBinding.RoleRef.Name
			}

			if diff := oldUsersSet.Difference(newUsersSet); len(diff) != 0 {
				fmt.Fprintf(o.Out, "Removing %s from users %v in project %s.\n", roleDisplayName, diff.List(), o.BindingNamespace)
				usersRemoved.Insert(diff.List()...)
			}
			if diff := oldGroupsSet.Difference(newGroupsSet); len(diff) != 0 {
				fmt.Fprintf(o.Out, "Removing %s from groups %v in project %s.\n", roleDisplayName, diff.List(), o.BindingNamespace)
				groupsRemoved.Insert(diff.List()...)
			}
			if diff := oldSAsSet.Difference(newSAsSet); len(diff) != 0 {
				fmt.Fprintf(o.Out, "Removing %s from serviceaccounts %v in project %s.\n", roleDisplayName, diff.List(), o.BindingNamespace)
				sasRemoved.Insert(diff.List()...)
			}
			if diff := oldOtherSet.Difference(newOtherSet); len(diff) != 0 {
				fmt.Fprintf(o.Out, "Removing %s from subjects %v in project %s.\n", roleDisplayName, diff.List(), o.BindingNamespace)
				othersRemoved.Insert(diff.List()...)
			}
		}
	}

	if diff := sets.NewString(o.Users...).Difference(usersRemoved); len(diff) != 0 {
		fmt.Fprintf(o.Out, "Users %v were not bound to roles in project %s.\n", diff.List(), o.BindingNamespace)
	}
	if diff := sets.NewString(o.Groups...).Difference(groupsRemoved); len(diff) != 0 {
		fmt.Fprintf(o.Out, "Groups %v were not bound to roles in project %s.\n", diff.List(), o.BindingNamespace)
	}

	return nil
}