106 lines
3.6 KiB
Python
Executable File
106 lines
3.6 KiB
Python
Executable File
#! /usr/bin/env python3
|
|
|
|
"""
|
|
Command-line script to retrieve list of learners that have requested to be retired.
|
|
The script calls the appropriate LMS endpoint to get this list of learners.
|
|
"""
|
|
|
|
import io
|
|
import logging
|
|
import sys
|
|
from os import path
|
|
|
|
import click
|
|
import yaml
|
|
|
|
# Add top-level project path to sys.path before importing scripts code
|
|
sys.path.append(path.abspath(path.join(path.dirname(__file__), '../..')))
|
|
|
|
from scripts.user_retirement.utils.edx_api import LmsApi
|
|
from scripts.user_retirement.utils.jenkins import export_learner_job_properties
|
|
|
|
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
@click.command("get_learners_to_retire")
|
|
@click.option(
|
|
'--config_file',
|
|
help='File in which YAML config exists that overrides all other params.'
|
|
)
|
|
@click.option(
|
|
'--cool_off_days',
|
|
help='Number of days a learner should be in the retirement queue before being actually retired.',
|
|
default=7
|
|
)
|
|
@click.option(
|
|
'--output_dir',
|
|
help="Directory in which to write the Jenkins properties files.",
|
|
default='./jenkins_props'
|
|
)
|
|
@click.option(
|
|
'--user_count_error_threshold',
|
|
help="If more users than this number are returned we will error out instead of retiring. This is a failsafe"
|
|
"against attacks that somehow manage to add users to the retirement queue.",
|
|
default=300
|
|
)
|
|
@click.option(
|
|
'--max_user_batch_size',
|
|
help="This setting will only get at most X number of users. If this number is lower than the user_count_error_threshold"
|
|
"setting then it will not error.",
|
|
default=200
|
|
)
|
|
def get_learners_to_retire(config_file,
|
|
cool_off_days,
|
|
output_dir,
|
|
user_count_error_threshold,
|
|
max_user_batch_size):
|
|
"""
|
|
Retrieves a JWT token as the retirement service user, then calls the LMS
|
|
endpoint to retrieve the list of learners awaiting retirement.
|
|
"""
|
|
if not config_file:
|
|
click.echo('A config file is required.')
|
|
sys.exit(-1)
|
|
|
|
with io.open(config_file, 'r') as config:
|
|
config_yaml = yaml.safe_load(config)
|
|
|
|
user_count_error_threshold = int(user_count_error_threshold)
|
|
cool_off_days = int(cool_off_days)
|
|
|
|
client_id = config_yaml['client_id']
|
|
client_secret = config_yaml['client_secret']
|
|
lms_base_url = config_yaml['base_urls']['lms']
|
|
retirement_pipeline = config_yaml['retirement_pipeline']
|
|
end_states = [state[1] for state in retirement_pipeline]
|
|
states_to_request = ['PENDING'] + end_states
|
|
|
|
api = LmsApi(lms_base_url, lms_base_url, client_id, client_secret)
|
|
|
|
# Retrieve the learners to retire and export them to separate Jenkins property files.
|
|
learners_to_retire = api.learners_to_retire(states_to_request, cool_off_days, max_user_batch_size)
|
|
if max_user_batch_size:
|
|
learners_to_retire = learners_to_retire[:max_user_batch_size]
|
|
learners_to_retire_cnt = len(learners_to_retire)
|
|
|
|
if learners_to_retire_cnt > user_count_error_threshold:
|
|
click.echo(
|
|
'Too many learners to retire! Expected {} or fewer, got {}!'.format(
|
|
user_count_error_threshold,
|
|
learners_to_retire_cnt
|
|
)
|
|
)
|
|
sys.exit(-1)
|
|
|
|
export_learner_job_properties(
|
|
learners_to_retire,
|
|
output_dir
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# pylint: disable=unexpected-keyword-arg, no-value-for-parameter
|
|
# If using env vars to provide params, prefix them with "RETIREMENT_", e.g. RETIREMENT_CLIENT_ID
|
|
get_learners_to_retire(auto_envvar_prefix='RETIREMENT')
|