Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getAllUsers() is broken #175

Open
mlasevich opened this issue Apr 13, 2021 · 4 comments
Open

getAllUsers() is broken #175

mlasevich opened this issue Apr 13, 2021 · 4 comments

Comments

@mlasevich
Copy link

mlasevich commented Apr 13, 2021

There are many, many issues reporting this bug over course of years, and all are closed without a fix (#123 , #125, #126, #162, #163 and others) - all seem to be closed without a resolution - and yet the bug still exists with 1.5.0 and Python 3.9

There are many explanations proposed, but none seem to actual explain what is going on. This is definitely not a permissions issue and not exactly "a very large number of users issue". What it seems to be a is a pagination issue. for sake of testing, I have manually modified MAX_PAGESIZE from 500 to 1000 in the call, and it started working (our total user count is a but under 2600) I am going to go out on a limb and guess that if you reduce the page size, you will be able to reproduce it locally

Playing with it experimentally, it appears to breaks EXACTLY when number of pages exceeds 4 (which is why it will not break when number of users is below 2000). But you should be able to recreate it regardless. I am going to guess that if you take number of users you have and divide it by 4 and set the PAGESIZE to that number minus 1, it will break, while that number plus one will work.

@AjaxOdessa
Copy link
Contributor

Thanks for trick with MAX_PAGESIZE, it is a quick and dirty solution to my current needs!

@mlasevich
Copy link
Author

mlasevich commented Apr 19, 2021

@AjaxOdessa with getAllUsers() flat out broken, I found it is easier to bypass it and just query Rally more directly:

  USERS = Namespace(
      ALL='((Disabled = true) OR (Disabled = false))',
      ENABLED='(Disabled = false)',
      DISABLED='(Disabled = true)',
  )

  kind=USERS.ENABLED 
  user_attrs = ["UserName", "DisplayName",
                "FirstName", "LastName", "MiddleName",
                 "ShortDisplayName", "OnpremLdapUsername",
                 "CreationDate", "EmailAddress",
                 "LastPasswordUpdateDate", "Disabled",
                 "Subscription", "SubscriptionAdmin",
                 "Role", "TeamMemberships" ]
  #return rally.getAllUsers()
  return rally.get('User', fetch=",".join(user_attrs),
                   query=[kind], instance=False,
                   pagesize=500, start=0, limit=10000,
                   projectScopeUp=True, projectScopeDown=True,)

@rhgdas
Copy link

rhgdas commented Aug 20, 2021

Any resolution to this issue?

@rhgdas
Copy link

rhgdas commented Aug 31, 2021

Here is my solution to this:

import pyral
from pyral import Rally
class GetUser:
def init(self):
self.ds_instance = os.getenv('DS_INSTANCE')
self.ral_obj = Rally(server=os.getenv('RALLY_SERVER'), apikey=os.getenv('RALLY_APIKEY'),
workspace=os.getenv('RALLY_WORKSPACE'), project=self.project)
self.START_INDEX = 1
self.MAX_PAGESIZE = 2000
self.MAX_ITEMS = 1000000
self.SERVICE_REQUEST_TIMEOUT = 120
self.HTTP_REQUEST_SUCCESS_CODE = 200
self.PAGE_NOT_FOUND_CODE = 404

def get_user_details(self):
contextHelper = self.ral_obj.contextHelper
session = self.ral_obj.session
session.headers = pyral.config.RALLY_REST_HEADERS
service_url = "%s://%s/%s" % (
pyral.config.PROTOCOL, os.getenv("RALLY_SERVER"), pyral.config.WEB_SERVICE % pyral.config.WS_API_VERSION)
saved_workspace_name, saved_workspace_ref = contextHelper.getWorkspace()
workspace = saved_workspace_name
self.ral_obj.setWorkspace(os.getenv('RALLY_WORKSPACE'))

context, augments = contextHelper.identifyContext(workspace=workspace)
workspace_ref = contextHelper.currentWorkspaceRef()

user_attrs = ["UserName", "DisplayName",
              "FirstName", "LastName", "MiddleName",
              "ShortDisplayName", "OnpremLdapUsername",
              "CreationDate", "EmailAddress",
              "LastPasswordUpdateDate", "Disabled",
              "Subscription", "SubscriptionAdmin",
              "Role", "UserPermissions", "TeamMemberships",
              "UserProfile",
              "TimeZone",  # a UserProfile attribute
              # and other UserProfile attributes
              ]

user_inclusion = "((Disabled = true) OR (Disabled = false))"
users_resource = 'users?fetch=%s&query=%s&pagesize=%s&start=1&workspace=%s' % \
                 (",".join(user_attrs), user_inclusion , self.MAX_PAGESIZE, workspace_ref)
full_resource_url = '%s/%s' % (service_url, users_resource)
response = self.ral_obj.session.get(full_resource_url, timeout=self.SERVICE_REQUEST_TIMEOUT)
if response.status_code != self.HTTP_REQUEST_SUCCESS_CODE:
    return []
response = pyral.RallyRESTResponse(session, context, users_resource, response, "full", 0)
if not response.errors:
    users = [user for user in response]
return users

This method actually uses all components from pyral except the query builder, where we have issues when you have more than 4 pages. Increase the self.MAX_PAGESIZE in class initiation section and your issue will be resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants