Coverage for scripts / create_request.py: 15%

92 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2025-12-25 18:08 -0500

1#!/usr/bin/env python3 

2""" 

3Create a JSM service request. 

4 

5Usage: 

6 python create_request.py --service-desk 1 --request-type 10 --summary "Email not working" --description "Cannot send emails" 

7 python create_request.py --service-desk "IT Support" --request-type "Incident" --summary "Server down" 

8 python create_request.py --service-desk 1 --request-type 10 --summary "Test" --field priority=High --dry-run 

9""" 

10 

11import sys 

12import os 

13import argparse 

14import json 

15from pathlib import Path 

16from typing import Optional, Dict, Any, List 

17 

18sys.path.insert(0, str(Path(__file__).parent.parent.parent / 'shared' / 'scripts' / 'lib')) 

19 

20from config_manager import get_jira_client 

21from error_handler import print_error, JiraError, NotFoundError 

22from formatters import print_success 

23 

24 

25def create_service_request(service_desk_id: str, request_type_id: str, 

26 summary: str, description: str, 

27 custom_fields: Optional[Dict[str, Any]] = None, 

28 participants: Optional[List[str]] = None, 

29 on_behalf_of: Optional[str] = None, 

30 profile: Optional[str] = None) -> Dict[str, Any]: 

31 """ 

32 Create a service request. 

33 

34 Args: 

35 service_desk_id: Service desk ID or key 

36 request_type_id: Request type ID 

37 summary: Request summary 

38 description: Request description 

39 custom_fields: Additional custom fields 

40 participants: List of participant email addresses 

41 on_behalf_of: Create on behalf of user email 

42 profile: JIRA profile to use 

43 

44 Returns: 

45 Created request data 

46 

47 Raises: 

48 ValueError: If required fields are missing 

49 NotFoundError: If service desk or request type not found 

50 """ 

51 if not summary or not summary.strip(): 

52 raise ValueError("summary is required") 

53 

54 if not description or not description.strip(): 

55 raise ValueError("description is required") 

56 

57 # Build request field values 

58 fields = { 

59 'summary': summary, 

60 'description': description 

61 } 

62 

63 # Add custom fields 

64 if custom_fields: 

65 fields.update(custom_fields) 

66 

67 with get_jira_client(profile) as client: 

68 return client.create_request( 

69 service_desk_id=service_desk_id, 

70 request_type_id=request_type_id, 

71 fields=fields, 

72 participants=participants, 

73 on_behalf_of=on_behalf_of 

74 ) 

75 

76 

77def parse_custom_fields(field_args: List[str]) -> Dict[str, Any]: 

78 """ 

79 Parse custom field arguments from command line. 

80 

81 Args: 

82 field_args: List of field=value strings 

83 

84 Returns: 

85 Dictionary of field values 

86 """ 

87 fields = {} 

88 for arg in field_args: 

89 if '=' not in arg: 

90 raise ValueError(f"Invalid field format: {arg}. Use field=value") 

91 

92 key, value = arg.split('=', 1) 

93 fields[key.strip()] = value.strip() 

94 

95 return fields 

96 

97 

98def main(): 

99 """Main entry point.""" 

100 parser = argparse.ArgumentParser( 

101 description='Create a JSM service request', 

102 formatter_class=argparse.RawDescriptionHelpFormatter, 

103 epilog=""" 

104Examples: 

105 Basic usage: 

106 %(prog)s --service-desk 1 --request-type 10 --summary "Email not working" --description "Cannot send emails" 

107 

108 With custom fields: 

109 %(prog)s --service-desk 1 --request-type 10 --summary "Server down" --description "Production server not responding" --field priority=High --field impact="Multiple Users" 

110 

111 With participants: 

112 %(prog)s --service-desk 1 --request-type 10 --summary "Team access" --description "Need access for team" --participants "alice@example.com,bob@example.com" 

113 

114 On behalf of customer: 

115 %(prog)s --service-desk 1 --request-type 10 --summary "Password reset" --description "User needs reset" --on-behalf-of "customer@example.com" 

116 

117 Dry-run: 

118 %(prog)s --service-desk 1 --request-type 10 --summary "Test" --description "Test" --dry-run 

119 """ 

120 ) 

121 

122 parser.add_argument('--service-desk', required=True, 

123 help='Service desk ID or key') 

124 parser.add_argument('--request-type', required=True, 

125 help='Request type ID') 

126 parser.add_argument('--summary', required=True, 

127 help='Request summary') 

128 parser.add_argument('--description', required=True, 

129 help='Request description') 

130 parser.add_argument('--field', action='append', default=[], 

131 help='Custom field (format: field=value)') 

132 parser.add_argument('--participants', 

133 help='Comma-separated list of participant emails') 

134 parser.add_argument('--on-behalf-of', 

135 help='Create request on behalf of user email') 

136 parser.add_argument('--output', choices=['text', 'json'], default='text', 

137 help='Output format (default: text)') 

138 parser.add_argument('--dry-run', action='store_true', 

139 help='Show what would be created without creating') 

140 parser.add_argument('--profile', 

141 help='JIRA profile to use from config') 

142 

143 args = parser.parse_args() 

144 

145 try: 

146 # Parse custom fields 

147 custom_fields = parse_custom_fields(args.field) if args.field else None 

148 

149 # Parse participants 

150 participants = None 

151 if args.participants: 

152 participants = [p.strip() for p in args.participants.split(',')] 

153 

154 if args.dry_run: 

155 print("DRY RUN MODE - No changes will be made\n") 

156 print("Would create request:") 

157 print(f" Service Desk: {args.service_desk}") 

158 print(f" Request Type: {args.request_type}") 

159 print(f" Summary: {args.summary}") 

160 print(f" Description: {args.description}") 

161 if custom_fields: 

162 print(f" Custom Fields: {json.dumps(custom_fields, indent=2)}") 

163 if participants: 

164 print(f" Participants: {', '.join(participants)}") 

165 if args.on_behalf_of: 

166 print(f" On Behalf Of: {args.on_behalf_of}") 

167 return 0 

168 

169 request = create_service_request( 

170 service_desk_id=args.service_desk, 

171 request_type_id=args.request_type, 

172 summary=args.summary, 

173 description=args.description, 

174 custom_fields=custom_fields, 

175 participants=participants, 

176 on_behalf_of=args.on_behalf_of, 

177 profile=args.profile 

178 ) 

179 

180 if args.output == 'json': 

181 print(json.dumps(request, indent=2)) 

182 else: 

183 print_success("Service request created successfully!\n") 

184 print(f"Request Key: {request.get('issueKey')}") 

185 

186 req_type = request.get('requestType', {}) 

187 print(f"Request Type: {req_type.get('name', 'N/A')}") 

188 

189 status = request.get('currentStatus', {}) 

190 print(f"Status: {status.get('status', 'N/A')}") 

191 

192 print(f"\nSummary: {args.summary}") 

193 print(f"Description: {args.description}") 

194 

195 reporter = request.get('reporter', {}) 

196 print(f"\nReporter: {reporter.get('emailAddress', 'N/A')}") 

197 

198 created = request.get('createdDate', {}) 

199 print(f"Created: {created.get('friendly', 'N/A')}") 

200 

201 links = request.get('_links', {}) 

202 if 'web' in links: 

203 print(f"\nCustomer Portal: {links['web']}") 

204 if 'agent' in links: 

205 print(f"Agent View: {links['agent']}") 

206 

207 return 0 

208 

209 except ValueError as e: 

210 print_error(str(e)) 

211 return 1 

212 except (JiraError, NotFoundError) as e: 

213 print_error(f"Failed to create request: {e}") 

214 return 1 

215 except Exception as e: 

216 print_error(f"Unexpected error: {e}") 

217 return 1 

218 

219 

220if __name__ == '__main__': 

221 sys.exit(main())