Best Python code snippet using pyatom_python
ReqMgrRESTModel.py
Source:ReqMgrRESTModel.py
1#!/usr/bin/env python2"""3ReqMgrRESTModel4This holds the methods for the REST model, all methods which5will be available via HTTP PUT/GET/POST commands from the interface,6the validation, the security for each, and the function calls for the7DB interfaces they execute.8https://twiki.cern.ch/twiki/bin/viewauth/CMS/ReqMgrSystemDesign9"""10import sys11import math12import cherrypy13import json14import threading15import urllib16import logging17import WMCore.Lexicon18from WMCore.Wrappers import JsonWrapper19from WMCore.WebTools.RESTModel import RESTModel20import WMCore.HTTPFrontEnd.RequestManager.ReqMgrWebTools as Utilities21from WMCore.WMException import WMException22import WMCore.RequestManager.RequestDB.Interface.User.Registration as Registration23import WMCore.RequestManager.RequestDB.Interface.User.Requests as UserRequests24import WMCore.RequestManager.RequestDB.Interface.Request.ListRequests as ListRequests25import WMCore.RequestManager.RequestDB.Interface.Request.GetRequest as GetRequest26import WMCore.RequestManager.RequestDB.Interface.Admin.RequestManagement as RequestAdmin27import WMCore.RequestManager.RequestDB.Interface.Admin.ProdManagement as ProdManagement28import WMCore.RequestManager.RequestDB.Interface.Admin.GroupManagement as GroupManagement29import WMCore.RequestManager.RequestDB.Interface.Admin.UserManagement as UserManagement30import WMCore.RequestManager.RequestDB.Interface.ProdSystem.ProdMgrRetrieve as ProdMgrRetrieve31import WMCore.RequestManager.RequestDB.Interface.Admin.SoftwareManagement as SoftwareAdmin32import WMCore.RequestManager.RequestDB.Interface.Request.ChangeState as ChangeState33import WMCore.RequestManager.RequestDB.Interface.Group.Information as GroupInfo34import WMCore.RequestManager.RequestDB.Interface.Request.Campaign as Campaign35class ReqMgrRESTModel(RESTModel):36 """ The REST interface to the ReqMgr database. Documentation may37 be found at https://twiki.cern.ch/twiki/bin/viewauth/CMS/ReqMgrSystemDesign """38 def __init__(self, config):39 RESTModel.__init__(self, config)40 self.couchUrl = config.couchUrl41 self.workloadDBName = config.workloadDBName42 self.configDBName = config.configDBName43 self.security_params = {'roles':config.security_roles}44 # Optional values for individual methods45 self.reqPriorityMax = getattr(config, 'maxReqPriority', 100)46 self._addMethod('GET', 'request', self.getRequest, 47 args = ['requestName'],48 secured=True, validation=[self.isalnum], expires = 0)49 self._addMethod('GET', 'assignment', self.getAssignment,50 args = ['teamName', 'request'],51 secured=True, validation = [self.isalnum], expires = 0)52 self._addMethod('GET', 'user', self.getUser,53 args = ['userName'], 54 secured=True, validation = [self.isalnum], expires = 0)55 self._addMethod('GET', 'group', self.getGroup,56 args = ['group', 'user'], secured=True, expires = 0)57 self._addMethod('GET', 'version', self.getVersion, args = [], 58 secured=True, expires = 0)59 self._addMethod('GET', 'team', self.getTeam, args = [], 60 secured=True, expires = 0)61 self._addMethod('GET', 'workQueue', self.getWorkQueue,62 args = ['request', 'workQueue'], 63 secured=True, validation = [self.isalnum], expires = 0)64 self._addMethod('GET', 'message', self.getMessage,65 args = ['request'], 66 secured=True, validation = [self.isalnum], expires = 0)67 self._addMethod('GET', 'inputdataset', self.getInputDataset,68 args = ['prim', 'proc', 'tier'],69 secured=True)70 self._addMethod('GET', 'outputdataset', self.getOutputDataset,71 args = ['prim', 'proc', 'tier'],72 secured=True)73 self._addMethod('GET', 'campaign', self.getCampaign,74 args = ['campaign'],75 secured=True, validation = [self.isalnum], expires = 0)76 self._addMethod('PUT', 'request', self.putRequest,77 args = ['requestName', 'status', 'priority'],78 secured=True, validation = [self.isalnum, self.reqPriority])79 self._addMethod('PUT', 'assignment', self.putAssignment,80 args = ['team', 'requestName'],81 secured=True, security_params=self.security_params,82 validation = [self.isalnum])83 self._addMethod('PUT', 'user', self.putUser,84 args = ['userName', 'email', 'dnName'],85 secured=True, security_params=self.security_params,86 validation = [self.validateUser])87 self._addMethod('PUT', 'group', self.putGroup,88 args = ['group', 'user'],89 secured=True, security_params=self.security_params,90 validation = [self.isalnum])91 self._addMethod('PUT', 'version', self.putVersion,92 args = ['version', 'scramArch'],93 secured=True, security_params=self.security_params,94 validation = [self.validateVersion])95 self._addMethod('PUT', 'team', self.putTeam,96 args = ['team'],97 secured=True, security_params=self.security_params,98 validation = [self.isalnum])99 self._addMethod('PUT', 'workQueue', self.putWorkQueue, 100 args = ['request', 'url'],101 secured=True, security_params=self.security_params,102 validation = [self.validatePutWorkQueue])103 self._addMethod('PUT', 'message', self.putMessage,104 args = ['request'],105 secured=True, security_params=self.security_params,106 validation = [self.isalnum])107 self._addMethod('PUT', 'campaign', self.putCampaign,108 args = ['campaign', 'request'],109 secured=True, 110 validation = [self.isalnum])111 self._addMethod('POST', 'request', self.postRequest,112 args = ['requestName', 'events_written', 113 'events_merged', 'files_written',114 'files_merged', 'percent_written', 115 'percent_success', 'dataset'],116 secured=True, validation = [self.validateUpdates])117 self._addMethod('POST', 'user', self.postUser,118 args = ['user', 'priority'],119 secured=True, security_params=self.security_params,120 validation = [self.isalnum, self.intpriority])121 self._addMethod('POST', 'group', self.postGroup,122 args = ['group', 'priority'],123 secured=True, security_params=self.security_params,124 validation = [self.isalnum, self.intpriority])125 self._addMethod('DELETE', 'request', self.deleteRequest,126 args = ['requestName'],127 secured=True, security_params=self.security_params,128 validation = [self.isalnum])129 self._addMethod('DELETE', 'user', self.deleteUser,130 args = ['user'],131 secured=True, security_params=self.security_params,132 validation = [self.isalnum])133 self._addMethod('DELETE', 'group', self.deleteGroup,134 args = ['group', 'user'],135 secured=True, security_params=self.security_params,136 validation = [self.isalnum])137 self._addMethod('DELETE', 'version', self.deleteVersion,138 args = ['version', 'scramArch'],139 secured=True, validation = [self.validateVersion])140 self._addMethod('DELETE', 'team', self.deleteTeam,141 args = ['team'],142 secured=True, security_params=self.security_params,143 validation = [self.isalnum])144 self._addMethod('DELETE', 'campaign', self.deleteCampaign,145 args = ['campaign'],146 secured=True, security_params=self.security_params,147 validation = [self.isalnum])148 self._addMethod('GET', 'requestnames', self.getRequestNames,149 args = [], secured=True, expires = 0)150 self._addMethod('GET', 'outputDatasetsByRequestName', self.getOutputForRequest,151 args = ['requestName'], secured=True,152 validation=[self.isalnum], expires = 0)153 self._addMethod('GET', 'outputDatasetsByPrepID', self.getOutputForPrepID,154 args = ['prepID'], secured=True, 155 validation=[self.isalnum], expires = 0) 156 self._addMethod('GET', 'mostRecentOutputDatasetsByPrepID', self.getMostRecentOutputForPrepID,157 args = ['prepID'], secured=True, 158 validation=[self.isalnum], expires = 0)159 cherrypy.engine.subscribe('start_thread', self.initThread)160 161 def initThread(self, thread_index):162 """ The ReqMgr expects the DBI to be contained in the Thread """163 myThread = threading.currentThread()164 #myThread = cherrypy.thread_data165 # Get it from the DBFormatter superclass166 myThread.dbi = self.dbi167 def isalnum(self, index):168 """ Validates that all input is alphanumeric, 169 with spaces and underscores tolerated"""170 for v in index.values():171 WMCore.Lexicon.identifier(v)172 return index173 def getDataset(self, prim, proc, tier):174 """ If only prim exists, assume it's urlquoted.175 If all three exists, assue it's /prim/proc/tier 176 """177 if not proc and not tier:178 dataset = urllib.unquote(prim)179 elif prim and proc and tier:180 dataset = "/%s/%s/%s" % (prim, proc, tier)181 WMCore.Lexicon.dataset(dataset) 182 return dataset183 def intpriority(self, index):184 """ Casts priority to an integer """185 if index.has_key('priority'):186 value = int(index['priority'])187 if math.fabs(value) >= sys.maxint:188 msg = "Invalid priority! Priority must have abs() less then MAXINT!" 189 raise cherrypy.HTTPError(400, msg)190 index['priority'] = value191 return index192 def reqPriority(self, index):193 """194 _reqPriority_195 Sets request priority to an integer.196 Also makes sure it's within a certain value.197 """198 if not index.has_key('priority'):199 return index200 201 index = self.intpriority(index = index)202 value = index['priority']203 if math.fabs(value) > self.reqPriorityMax:204 msg = "Invalid requestPriority! Request priority must have abs() less then %i!" % self.reqPriorityMax205 raise cherrypy.HTTPError(400, msg)206 207 return index208 209 def validateUser(self, index):210 assert index['userName'].isalnum()211 assert '@' in index['email']212 assert index['email'].replace('@','').replace('.','').isalnum()213 if 'dnName' in index:214 assert index['dnName'].replace(' ','').isalnum()215 return index216 def validateVersion(self, index):217 """ Make sure it's a legitimate CMSSW version format """218 WMCore.Lexicon.cmsswversion(index['version'])219 return index220 def findRequest(self, requestName):221 """ Either returns the request object, or None """222 requests = ListRequests.listRequests()223 for request in requests:224 if request['RequestName'] == requestName:225 return request226 return None227 def getRequest(self, requestName=None):228 """ If a request name is specified, return the details of the request. 229 Otherwise, return an overview of all requests """230 if requestName == None:231 return GetRequest.getRequests()232 else:233 result = Utilities.requestDetails(requestName)234 try:235 teamNames = GetRequest.getAssignmentsByName(requestName)236 result['teams'] = teamNames237 except:238 # Ignore errors, then we just don't have a team name239 pass240 return result241 def getRequestNames(self):242 """ return all the request names in RequestManager as list """243 #TODO this could me combined with getRequest244 return GetRequest.getOverview()245 def getOutputForRequest(self, requestName):246 """Return the datasets produced by this request."""247 return Utilities.getOutputForRequest(requestName)248 def getOutputForPrepID(self, prepID):249 """Return the datasets produced by this prep ID. in a dict of requestName:dataset list"""250 requestIDs = GetRequest.getRequestByPrepID(prepID)251 result = {}252 for requestID in requestIDs:253 request = GetRequest.getRequest(requestID)254 requestName = request["RequestName"]255 helper = Utilities.loadWorkload(request)256 result[requestName] = helper.listOutputDatasets()257 return result258 def getMostRecentOutputForPrepID(self, prepID):259 """Return the datasets produced by the most recently submitted request with this prep ID"""260 requestIDs = GetRequest.getRequestByPrepID(prepID)261 # most recent will have the largest ID262 requestID = max(requestIDs)263 request = GetRequest.getRequest(requestID)264 helper = Utilities.loadWorkload(request)265 return helper.listOutputDatasets()266 267 def getAssignment(self, teamName=None, request=None):268 """ If a team name is passed in, get all assignments for that team.269 If a request is passed in, return a list of teams the request is 270 assigned to 271 """272 # better to use ReqMgr/RequestDB/Interface/ProdSystem/ProdMgrRetrieve?273 #requestIDs = ProdMgrRetrieve.findAssignedRequests(teamName)274 # Maybe now assigned to team is same as assigned to ProdMgr275 result = []276 if teamName != None:277 requestIDs = ListRequests.listRequestsByTeam(teamName, "assigned").values()278 requests = [GetRequest.getRequest(reqID) for reqID in requestIDs]279 # put highest priorities first280 requests.sort(key=lambda r: r['RequestPriority'], reverse=True)281 # return list of tuples, since we need sorting282 result = [[req['RequestName'], req['RequestWorkflow']] for req in requests]283 elif request != None:284 result = GetRequest.getAssignmentsByName(request)285 return result286 def getUser(self, userName=None, group=None):287 """ No args returns a list of all users. Group returns groups this user is in. Username288 returs a JSON with information about the user """289 if userName != None:290 if not Registration.isRegistered(userName):291 raise cherrypy.HTTPError(404, "Cannot find user")292 result = {}293 result['groups'] = GroupInfo.groupsForUser(userName).keys()294 result['requests'] = UserRequests.listRequests(userName).keys()295 result['priority'] = UserManagement.getPriority(userName)296 result.update(Registration.userInfo(userName))297 return json.dumps(result)298 elif group != None:299 GroupInfo.usersInGroup(group) 300 else:301 return Registration.listUsers()302 303 def getGroup(self, group=None, user=None):304 """ No args lists all groups, one args returns JSON with users and priority """305 if group != None:306 result = {}307 result['users'] = GroupInfo.usersInGroup(group)308 try:309 result['priority'] = GroupManagement.getPriority(group)310 except IndexError:311 raise cherrypy.HTTPError(404, "Cannot find group/group priority")312 return json.dumps(result)313 elif user != None: 314 return GroupInfo.groupsForUser(user).keys()315 else:316 return GroupInfo.listGroups()317 def getVersion(self):318 """ Returns a list of all CMSSW versions registered with ReqMgr """319 archList = SoftwareAdmin.listSoftware()320 result = []321 for arch in archList.keys():322 for version in archList[arch]:323 if not version in result:324 result.append(version)325 return result326 327 def getTeam(self):328 """ Returns a list of all teams registered with ReqMgr """329 return ProdManagement.listTeams()330 def getWorkQueue(self, request=None, workQueue=None):331 """ If a request is passed in, return the URl of the workqueue.332 If a workqueue is passed in, return all requests acquired by it """333 if workQueue != None:334 return ProdMgrRetrieve.findAssignedRequests(workQueue)335 if request != None:336 return ProdManagement.getProdMgr(request)337 # return all the workqueue ulr338 return GetRequest.getGlobalQueues()339 def getMessage(self, request):340 """ Returns a list of messages attached to this request """341 return ChangeState.getMessages(request)342 def getInputDataset(self, prim, proc=None, tier=None):343 """ returns a list of requests with this input dataset 344 Input can either be a single urlquoted dataset, or a 345 /prim/proc/tier"""346 dataset = self.getDataset(prim, proc, tier)347 return GetRequest.getRequestsByCriteria("Datasets.GetRequestByInput", dataset) 348 def getOutputDataset(self, prim, proc=None, tier=None):349 """ returns a list of requests with this output dataset 350 Input can either be a single urlquoted dataset, or a351 /prim/proc/tier"""352 dataset = self.getDataset(prim, proc, tier)353 return GetRequest.getRequestsByCriteria("Datasets.GetRequestByOutput", dataset)354 def getCampaign(self, campaign=None):355 """ returns a list of all campaigns if no argument, and a list of356 all requests in a campaign if there is an argument """357 if campaign == None:358 return Campaign.listCampaigns()359 else:360 return Campaign.listRequestsByCampaign(campaign)361 def putWorkQueue(self, request, url):362 """ Registers the request as "acquired" by the workqueue with the given URL """363 Utilities.changeStatus(request, "acquired")364 return ProdManagement.associateProdMgr(request, urllib.unquote(url))365 def validatePutWorkQueue(self, index):366 assert index['request'].replace('_','').replace('-','').replace('.','').isalnum()367 assert index['url'].startswith('http')368 return index369 def putRequest(self, requestName=None, status=None, priority=None):370 """ Checks the request n the body with one arg, and changes the status with kwargs """371 request = None372 if requestName:373 request = self.findRequest(requestName)374 if request == None:375 """ Creates a new request, with a JSON-encoded schema that is sent in the376 body of the request """377 body = cherrypy.request.body.read()378 schema = Utilities.unidecode(JsonWrapper.loads(body))379 schema.setdefault('CouchURL', Utilities.removePasswordFromUrl(self.couchUrl))380 schema.setdefault('CouchDBName', self.configDBName)381 try:382 request = Utilities.makeRequest(schema, self.couchUrl, self.workloadDBName)383 except cherrypy.HTTPError:384 # Assume that this is a valid HTTPError385 raise386 except WMException, ex:387 raise cherrypy.HTTPError(400, ex._message)388 except Exception, ex:389 raise cherrypy.HTTPError(400, ex.message)390 # see if status & priority need to be upgraded391 if status != None:392 # forbid assignment here393 if status == 'assigned' and request['RequestStatus'] != 'ops-hold':394 raise cherrypy.HTTPError(403, "Cannot change status without a team. Please use PUT /reqmgr/rest/assignment/<team>/<requestName>")395 try:396 Utilities.changeStatus(requestName, status)397 except RuntimeError, e:398 # ignore some of these errors: https://svnweb.cern.ch/trac/CMSDMWM/ticket/2002399 if status != 'announced' and status != 'closed-out':400 raise cherrypy.HTTPError(403, "Failed to change status: %s" % str(e))401 if priority != None:402 Utilities.changePriority(requestName, priority) 403 return request404 def putAssignment(self, team, requestName):405 """ Assigns this request to this team """406 # see if it's already assigned407 team = urllib.unquote(team)408 if not team in ProdManagement.listTeams():409 raise cherrypy.HTTPError(404,"Cannot find this team")410 requestNamesAndIDs = ListRequests.listRequestsByTeam(team)411 if requestName in requestNamesAndIDs.keys():412 raise cherrypy.HTTPError(400,"Already assigned to this team")413 return ChangeState.assignRequest(requestName, team)414 def putUser(self, userName, email, dnName=None):415 """ Needs to be passed an e-mail address, maybe dnName """416 if Registration.isRegistered(userName):417 return "User already exists"418 result = Registration.registerUser(userName, email, dnName)419 def putGroup(self, group, user=None):420 """ Creates a group, or if a user is passed, adds that user to the group """421 if(user != None):422 # assume group exists and add user to it423 return GroupManagement.addUserToGroup(user, group)424 if GroupInfo.groupExists(group):425 return "Group already exists"426 GroupManagement.addGroup(group)427 def putVersion(self, version, scramArch = None):428 """ Registers a new CMSSW version with ReqMgr """429 return SoftwareAdmin.addSoftware(version, scramArch = scramArch)430 def putTeam(self, team):431 """ Registers a team with ReqMgr """432 return ProdManagement.addTeam(urllib.unquote(team))433 def putMessage(self, request):434 """ Attaches a message to this request """435 message = JsonWrapper.loads( cherrypy.request.body.read() )436 result = ChangeState.putMessage(request, message)437 return result438 def putCampaign(self, campaign, request=None):439 """ Adds a campaign if it doesn't already exist, and optionally440 associates a request with it """441 if request:442 requestID = GetRequest.requestID(request)443 if requestID:444 result = Campaign.associateCampaign(campaign, requestID)445 Utilities.associateCampaign(campaign = campaign,446 requestName = request,447 couchURL = self.couchUrl,448 couchDBName = self.workloadDBName)449 return result450 else:451 return False452 else:453 Campaign.addCampaign(campaign)454 455# def postRequest(self, requestName, events_written=None, events_merged=None, 456# files_written=None, files_merged = None, dataset=None):457 def postRequest(self, requestName, **kwargs):458 """459 Add a progress update to the request Id provided, params can460 optionally contain:461 - *events_written* Int462 - *events_merged* Int463 - *files_written* Int464 - *files_merged* int465 - *percent_success* float466 - *percent_complete float467 - *dataset* string (dataset name)468 """469 return ChangeState.updateRequest(requestName, kwargs)470 def validateUpdates(self, index):471 """ Check the values for the updates """472 for k in ['events_written', 'events_merged', 473 'files_written', 'files_merged']:474 if k in index:475 index[k] = int(index[k])476 for k in ['percent_success', 'percent_complete']:477 if k in index:478 index[k] = float(index[k])479 return index480 def postUser(self, user, priority):481 """ Change the user's priority """482 return UserManagement.setPriority(user, priority)483 def postGroup(self, group, priority):484 """ Change the group's priority """485 return GroupManagement.setPriority(group, priority)486 def deleteRequest(self, requestName):487 """ Deletes a request from the ReqMgr """488 request = self.findRequest(requestName)489 if request == None:490 raise cherrypy.HTTPError(404, "No such request")491 return RequestAdmin.deleteRequest(request['RequestID'])492 def deleteUser(self, user):493 """ Deletes a user, as well as deleting his requests and removing494 him from all groups """495 if user in self.getUser():496 requests = json.loads(self.getUser(user))['requests']497 for request in requests:498 self.deleteRequest(request)499 for group in GroupInfo.groupsForUser(user).keys():500 GroupManagement.removeUserFromGroup(user, group)501 return UserManagement.deleteUser(user)502 def deleteGroup(self, group, user=None):503 """ If no user is sent, delete the group. Otherwise, delete the user from the group """504 if user == None:505 return GroupManagement.deleteGroup(group)506 else:507 return GroupManagement.removeUserFromGroup(user, group) 508 def deleteVersion(self, version, scramArch):509 """ Un-register this software version with ReqMgr """510 SoftwareAdmin.removeSoftware(version, scramArch)511 def deleteTeam(self, team):512 """ Delete this team from ReqMgr """513 ProdManagement.removeTeam(urllib.unquote(team))514 def deleteCampaign(self, campaign):...
authorizer.py
Source:authorizer.py
1import jwt2import re3from os import environ4JWT_SECRET = environ.get('JWT_SECRET', 'm3chsh0p_4p1')5access_request = [6 {7 'method': 'GET',8 'resource': '/items'9 },10 {11 'method': 'POST',12 'resource': '/items'13 }14]15def handler(event, context):16 print('Authorization Token: ' + event['authorizationToken'])17 print('Method ARN: ' + event['methodArn'])18 if 'authorizationToken' not in event:19 raise Exception('Unauthorized')20 if not event['authorizationToken'].startswith('Bearer'):21 raise Exception('Unaunthorized')22 token = event['authorizationToken'].replace('Bearer', '').strip()23 try:24 payload = jwt.decode(token, JWT_SECRET, algorithm="HS256")25 # check the user belongs to the database26 except jwt.exceptions.InvalidTokenError:27 raise Exception('Token invalid or expired')28 aws_data = get_aws_data(event)29 policy = AuthPolicy(payload['user_id'], aws_data['awsAccountId'])30 policy.restApiId = aws_data['restApiId']31 policy.region = aws_data['region']32 policy.stage = aws_data['stage']33 for request in access_request:34 policy.allowMethod(request['method'], request['resource'])35 authResponse = policy.build()36 authResponse['context'] = {37 'userId': payload['user_id'],38 'jwtToken': token39 }40 return authResponse41def get_aws_data(event):42 tmp = event['methodArn'].split(':')43 awsAccountId = tmp[4]44 apiGatewayArnTmp = tmp[5].split('/')45 region = tmp[3]46 rest_api_id = apiGatewayArnTmp[0]47 stage = apiGatewayArnTmp[1]48 49 return { 'awsAccountId': awsAccountId, 'region': region, 'restApiId': rest_api_id, 'stage': stage }50class HttpVerb:51 GET = "GET"52 POST = "POST"53 PUT = "PUT"54 PATCH = "PATCH"55 HEAD = "HEAD"56 DELETE = "DELETE"57 OPTIONS = "OPTIONS"58 ALL = "*"59class AuthPolicy(object):60 awsAccountId = ""61 """The AWS account id the policy will be generated for. This is used to create the method ARNs."""62 principalId = ""63 """The principal used for the policy, this should be a unique identifier for the end user."""64 version = "2012-10-17"65 """The policy version used for the evaluation. This should always be '2012-10-17'"""66 pathRegex = "^[/.a-zA-Z0-9-\*]+$"67 """The regular expression used to validate resource paths for the policy"""68 """these are the internal lists of allowed and denied methods. These are lists69 of objects and each object has 2 properties: A resource ARN and a nullable70 conditions statement.71 the build method processes these lists and generates the approriate72 statements for the final policy"""73 allowMethods = []74 denyMethods = []75 restApiId = "*"76 """The API Gateway API id. By default this is set to '*'"""77 region = "*"78 """The region where the API is deployed. By default this is set to '*'"""79 stage = "*"80 """The name of the stage used in the policy. By default this is set to '*'"""81 def __init__(self, principal, awsAccountId):82 self.awsAccountId = awsAccountId83 self.principalId = principal84 self.allowMethods = []85 self.denyMethods = []86 def _addMethod(self, effect, verb, resource, conditions):87 """Adds a method to the internal lists of allowed or denied methods. Each object in88 the internal list contains a resource ARN and a condition statement. The condition89 statement can be null."""90 if verb != "*" and not hasattr(HttpVerb, verb):91 raise NameError("Invalid HTTP verb " + verb + ". Allowed verbs in HttpVerb class")92 resourcePattern = re.compile(self.pathRegex)93 if not resourcePattern.match(resource):94 raise NameError("Invalid resource path: " + resource + ". Path should match " + self.pathRegex)95 if resource[:1] == "/":96 resource = resource[1:]97 resourceArn = ("arn:aws:execute-api:" +98 self.region + ":" +99 self.awsAccountId + ":" +100 self.restApiId + "/" +101 self.stage + "/" +102 verb + "/" +103 resource)104 if effect.lower() == "allow":105 self.allowMethods.append({106 'resourceArn' : resourceArn,107 'conditions' : conditions108 })109 elif effect.lower() == "deny":110 self.denyMethods.append({111 'resourceArn' : resourceArn,112 'conditions' : conditions113 })114 def _getEmptyStatement(self, effect):115 """Returns an empty statement object prepopulated with the correct action and the116 desired effect."""117 statement = {118 'Action': 'execute-api:Invoke',119 'Effect': effect[:1].upper() + effect[1:].lower(),120 'Resource': []121 }122 return statement123 def _getStatementForEffect(self, effect, methods):124 """This function loops over an array of objects containing a resourceArn and125 conditions statement and generates the array of statements for the policy."""126 statements = []127 if len(methods) > 0:128 statement = self._getEmptyStatement(effect)129 for curMethod in methods:130 if curMethod['conditions'] is None or len(curMethod['conditions']) == 0:131 statement['Resource'].append(curMethod['resourceArn'])132 else:133 conditionalStatement = self._getEmptyStatement(effect)134 conditionalStatement['Resource'].append(curMethod['resourceArn'])135 conditionalStatement['Condition'] = curMethod['conditions']136 statements.append(conditionalStatement)137 statements.append(statement)138 return statements139 def allowAllMethods(self):140 """Adds a '*' allow to the policy to authorize access to all methods of an API"""141 self._addMethod("Allow", HttpVerb.ALL, "*", [])142 def denyAllMethods(self):143 """Adds a '*' allow to the policy to deny access to all methods of an API"""144 self._addMethod("Deny", HttpVerb.ALL, "*", [])145 def allowMethod(self, verb, resource):146 """Adds an API Gateway method (Http verb + Resource path) to the list of allowed147 methods for the policy"""148 self._addMethod("Allow", verb, resource, [])149 def denyMethod(self, verb, resource):150 """Adds an API Gateway method (Http verb + Resource path) to the list of denied151 methods for the policy"""152 self._addMethod("Deny", verb, resource, [])153 def allowMethodWithConditions(self, verb, resource, conditions):154 """Adds an API Gateway method (Http verb + Resource path) to the list of allowed155 methods and includes a condition for the policy statement. More on AWS policy156 conditions here: http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements.html#Condition"""157 self._addMethod("Allow", verb, resource, conditions)158 def denyMethodWithConditions(self, verb, resource, conditions):159 """Adds an API Gateway method (Http verb + Resource path) to the list of denied160 methods and includes a condition for the policy statement. More on AWS policy161 conditions here: http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements.html#Condition"""162 self._addMethod("Deny", verb, resource, conditions)163 def build(self):164 """Generates the policy document based on the internal lists of allowed and denied165 conditions. This will generate a policy with two main statements for the effect:166 one statement for Allow and one statement for Deny.167 Methods that includes conditions will have their own statement in the policy."""168 if ((self.allowMethods is None or len(self.allowMethods) == 0) and169 (self.denyMethods is None or len(self.denyMethods) == 0)):170 raise NameError("No statements defined for the policy")171 policy = {172 'principalId' : self.principalId,173 'policyDocument' : {174 'Version' : self.version,175 'Statement' : []176 }177 }178 policy['policyDocument']['Statement'].extend(self._getStatementForEffect("Allow", self.allowMethods))179 policy['policyDocument']['Statement'].extend(self._getStatementForEffect("Deny", self.denyMethods))...
CRABRESTModelMock.py
Source:CRABRESTModelMock.py
1from WMCore.WebTools.RESTModel import RESTModel2import WMCore3import threading4import cherrypy5import imp6import os7import uuid8import tempfile9SI_RESULT = {}10SI_RESULT['server_dn'] = ''11SI_RESULT['my_proxy'] = 'myproxy.cern.ch'12FILE_NAME = 'src_output.root'13goodLumisResult = '{"1":[ [1,15], [30,50] ], "3":[ [10,15], [30,50] ]}'14publishResult = {u'status': True, u'message': 'Publication completed for campaign ewv_crab_something_1_111229_140959', u'summary': {u'/primary/secondary-out1-v1/USER': {u'files': 10, u'blocks': 1, u'existingFiles': 10}, u'/primary/secondary-out2-v1/USER': {u'files': 10, u'blocks': 1, u'existingFiles': 10}}}15class CRABRESTModelMock(RESTModel):16 def __init__(self, config={}):17 RESTModel.__init__(self, config)18 self.mapme = imp.load_source('', os.path.join( os.path.dirname(__file__), "../../../data/mapper.py"))19 self.defaulturi = self.mapme.defaulturi20 self._addMethod('POST', 'user', self.addNewUser,21 args=[],22 validation=[self.isalnum])23 self._addMethod('POST', 'task', self.postRequest,24 args=['requestName'],25 validation=[self.isalnum])26 self._addMethod('DELETE', 'task', self.deleteRequest,27 args=['requestID'],28 validation=[self.isalnum])29 self._addMethod('GET', 'task', self.getTaskStatus,30 args=['requestID'],31 validation=[self.isalnum])32 #/data33 self._addMethod('GET', 'data', self.getDataLocation,34 args=['requestID','jobRange'], validation=[self.isalnum])35 self._addMethod('POST', 'publish', self.publish,36 args=['requestName'],37 validation=[self.isalnum])38 #/goodLumis39 self._addMethod('GET', 'goodLumis', self.getGoodLumis,40 args=['requestID'], validation=[self.isalnum])41 #42 self._addMethod('POST', 'lumiMask', self.postLumiMask,43 args=[], validation=[self.isalnum])44 # Server45 self._addMethod('GET', 'info', self.getServerInfo,46 args=[],47 validation=[self.isalnum])48 self._addMethod('GET', 'requestmapping', self.getClientMapping,49 args=[],50 validation=[self.isalnum])51 self._addMethod('GET', 'jobErrors', self.getJobErrors,52 args=['requestID'],53 validation=[self.isalnum])54 self._addMethod('POST', 'resubmit', self.reSubmit,55 args=['requestID'],56 validation=[self.isalnum])57 cherrypy.engine.subscribe('start_thread', self.initThread)58 #not sure if we really need to validate input.59 def isalnum(self, call_input):60 """61 Validates that all input is alphanumeric, with spaces and underscores62 tolerated.63 """64 for v in call_input.values():65 WMCore.Lexicon.identifier(v)66 return call_input67 def initThread(self, thread_index):68 """69 The ReqMgr expects the DBI to be contained in the Thread70 """71 myThread = threading.currentThread()72 #myThread = cherrypy.thread_data73 # Get it from the DBFormatter superclass74 myThread.dbi = self.dbi75 def getServerInfo(self):76 """77 Return information to allow client operations78 """79 return SI_RESULT80 def getTaskStatus(self, requestID):81 return {u'workflows': [{u'request': u'cinquilli.nocern_crab_TESTME_1_111025_181202',82 u'requestDetails': {u'RequestMessages': [], u'RequestStatus': u'aborted'},83 u'states': {u'/cinquilli.nocern_crab_TESTME_1_111025_181202/Analysis': {u'success': {u'count': 9, u'jobIDs': [117, 118, 119, 120, 121, 122, 123, 124, 125],84 u'jobs': [1, 2, 3, 4, 5, 6, 7, 8, 9]}},85 u'/cinquilli.nocern_crab_TESTME_1_111025_181202/Analysis/LogCollect': {u'success': {u'count': 1, u'jobIDs': [126], u'jobs': [10]}}},86 u'subOrder': 1},87 {u'request': u'cinquilli.nocern_crab_TESTME_1_resubmit_111028_000117',88 u'requestDetails': {u'RequestMessages': [['request failed']], u'RequestStatus': u'failed'},89 u'states': {},90 u'subOrder': 2}]}91 def getDataLocation(self, requestID, jobRange):92 f = open(FILE_NAME, 'w')93 f.close()94 return {u'data': [{u'output': {u'1': {u'pfn': unicode(FILE_NAME)}},95 u'request': u'cinquilli.nocern_crab_TESTME_1_111025_181202',96 u'subOrder': 1},97 {u'output': {},98 u'request': u'cinquilli.nocern_crab_TESTME_1_resubmit_111028_000117',99 u'subOrder': 2}]}100 def getGoodLumis(self, requestID):101 """102 Mockup to return the list of good lumis processed as generated103 by CouchDB104 """105 return goodLumisResult106 def publish(self, requestName):107 """108 Mockup to return the publication summary109 """110 return publishResult111 def getClientMapping(self):112 """113 Return the dictionary that allows the client to map the client configuration to the server request114 It also returns the URI for each API115 """116 return self.defaulturi117 def deleteRequest(self, requestID):118 return {"result": "ok"}119 def addNewUser(self):120 return { "hn_name" : "mmascher" }121 def postRequest(self, requestName):122 return {'ID': 'mmascher_crab_MyAnalysis26_110707_164957'}123 def postLumiMask(self):124 """125 Mock version of result of ACDC upload126 """127 result = {}128 result['DocID'] = uuid.uuid4().hex129 result['DocRev'] = uuid.uuid4().hex130 result['Name'] = "%s-cmsRun1" % params['RequestName']131 return result132 def getJobErrors(self, requestID):133 failed = {'1':134 {'0': {135 'step1': [ { "details": "Error in StageOut: 99109\n'x.z.root' does not match regular expression /store/temp/([a-zA-Z0-9\\-_]+).root",136 "type":"Misc. StageOut error: 99109\n",137 "exitCode":99109 }138 ],139 'step2': [ { "details": "Cannot find file in jobReport path: /x/y/z/job_134/Report.1.pkl",140 "type":"99999",141 "exitCode":84 }142 ]143 }144 },145 '2':146 {'0': {147 'step1': [ { "details": "Error in StageOut: 99109\n'x.z.root' does not match regular expression /store/temp/([a-zA-Z0-9\\-_]+).root",148 "type":"Misc. StageOut error: 99109\n",149 "exitCode":99109 }150 ]151 },152 '1': {153 'step1': [ { "details": "Error in StageOut: 99109\n'x.z.root' does not match regular expression /store/temp/([a-zA-Z0-9\\-_]+).root", "type":"Misc. StageOut error: 99109\n",154 "exitCode":99109 }155 ]156 }157 }158 }159 return {u'errors': [{u'details': failed, u'request': u'cinquilli.nocern_crab_TESTME_1_111025_181202', u'subOrder': 1},160 {u'details': {}, u'request': u'cinquilli.nocern_crab_TESTME_1_resubmit_111028_000117', u'subOrder': 2}]}161 def reSubmit(self, requestID):...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!