Coverage for scripts / list_assets.py: 22%

54 statements  

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

1#!/usr/bin/env python3 

2""" 

3List and search assets/CMDB objects with IQL filtering. 

4 

5Lists assets from Insight/Assets with optional IQL query filtering. 

6Requires JSM Premium license or Assets license. 

7 

8Usage: 

9 list_assets.py 

10 list_assets.py --type Server 

11 list_assets.py --iql 'Status="Active"' 

12 list_assets.py --type Server --iql 'Status="Active"' 

13 list_assets.py --output json 

14""" 

15 

16import argparse 

17import sys 

18import json 

19from pathlib import Path 

20 

21# Add shared lib to path 

22shared_lib_path = str(Path(__file__).parent.parent.parent.parent / 'shared' / 'scripts' / 'lib') 

23if shared_lib_path not in sys.path: 

24 sys.path.insert(0, shared_lib_path) 

25 

26from config_manager import get_jira_client 

27 

28 

29def list_assets(object_type: str = None, iql: str = None, max_results: int = 100): 

30 """ 

31 List assets with optional filtering. 

32 

33 Args: 

34 object_type: Optional object type name 

35 iql: Optional IQL query string 

36 max_results: Maximum results to return 

37 

38 Returns: 

39 List of asset objects 

40 """ 

41 with get_jira_client() as client: 

42 # Check license first 

43 if not client.has_assets_license(): 

44 print("ERROR: Assets/Insight not available. Requires JSM Premium license.", file=sys.stderr) 

45 sys.exit(1) 

46 

47 return client.list_assets(object_type, iql, max_results) 

48 

49 

50def format_text(assets: list) -> str: 

51 """Format assets as human-readable text.""" 

52 if not assets: 

53 return "No assets found matching criteria." 

54 

55 output = [f"Assets ({len(assets)} total):\n"] 

56 

57 for asset in assets: 

58 output.append(f"Key: {asset.get('objectKey', 'N/A')}") 

59 output.append(f"Label: {asset.get('label', 'N/A')}") 

60 

61 if 'objectType' in asset: 

62 output.append(f"Type: {asset['objectType'].get('name', 'N/A')}") 

63 

64 if 'attributes' in asset: 

65 for attr in asset['attributes'][:3]: # Show first 3 attributes 

66 attr_name = attr.get('objectTypeAttribute', {}).get('name', 'Unknown') 

67 values = attr.get('objectAttributeValues', []) 

68 if values: 

69 attr_value = values[0].get('value', 'N/A') 

70 output.append(f" {attr_name}: {attr_value}") 

71 

72 output.append("") 

73 

74 return "\n".join(output) 

75 

76 

77def format_json(assets: list) -> str: 

78 """Format assets as JSON.""" 

79 return json.dumps(assets, indent=2) 

80 

81 

82def main(): 

83 parser = argparse.ArgumentParser( 

84 description="List assets/CMDB objects", 

85 formatter_class=argparse.RawDescriptionHelpFormatter, 

86 epilog=__doc__ 

87 ) 

88 parser.add_argument('--type', help='Object type name filter') 

89 parser.add_argument('--iql', help='IQL query string for filtering') 

90 parser.add_argument('--max-results', type=int, default=100, 

91 help='Maximum results to return (default: 100)') 

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

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

94 parser.add_argument('--profile', help='JIRA profile to use') 

95 

96 args = parser.parse_args() 

97 

98 try: 

99 assets = list_assets(args.type, args.iql, args.max_results) 

100 

101 if args.output == 'json': 

102 print(format_json(assets)) 

103 else: 

104 print(format_text(assets)) 

105 

106 except SystemExit: 

107 raise 

108 except Exception as e: 

109 print(f"Error listing assets: {str(e)}", file=sys.stderr) 

110 sys.exit(1) 

111 

112 

113if __name__ == "__main__": 

114 main()