AtlassianJiraServiceManagement
Use this integration to manage Jira objects and attach files to Jira objects from Cortex XSOAR.
IT Services · Atlassian Jira Service Management
Details
| ID | AtlassianJiraServiceManagement |
|---|---|
| Provider | Atlassian |
| Category | IT Services |
| From Version | 6.10.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM |
README
Use this integration to manage Jira objects and attach files to Jira objects from Cortex XSOAR.
This integration was integrated and tested with version 5.4.15 of AtlassianJiraServiceManagement.
Configure Atlassian Jira Service Management in Cortex
| Parameter | Required |
|---|---|
| Server URL | True |
| API Token | True |
| Trust any certificate (not secure) | False |
| Use system proxy settings | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
jira-asset-object-schema-list
List all object schemas.
Base Command
jira-asset-object-schema-list
Input
| Argument Name | Description | Required |
|---|---|---|
| limit | The maximum amount of schemas to retrieve. Cannot be used alongside the page and page_size arguments. | Optional |
| all_results | Whether to retrieve all object schemas with no limit. Possible values are: true, false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| JiraAsset.Schema.ID | Number | The ID of the object schema. |
| JiraAsset.Schema.Name | String | The name of the object schema. |
| JiraAsset.Schema.Key | String | The key of the object schema. |
| JiraAsset.Schema.Status | String | The status of the object schema. |
| JiraAsset.Schema.Created | Date | The date in which this object schema was created. |
| JiraAsset.Schema.Updated | Date | The date in which this object schema was updated. |
| JiraAsset.Schema.ObjectCount | Number | The number of objects in the schema. |
| JiraAsset.Schema.ObjectTypeCount | Number | The number of different object types in the schema. |
jira-asset-object-type-list
List all object types.
Base Command
jira-asset-object-type-list
Input
| Argument Name | Description | Required |
|---|---|---|
| schema_id | The schema from which the command will retrieve object types. Values can be received by running the jira-asset-object-schema-list command. |
Required |
| exclude | Object types with that name will be excluded from the results. | Optional |
| limit | The maximum amount of object types to retrieve. | Optional |
| all_results | Whether to retrieve all object types with no limit. Possible values are: true, false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| JiraAsset.ObjectType.ID | Number | The ID of the object type. |
| JiraAsset.ObjectType.Name | String | The name of the object type. |
| JiraAsset.ObjectType.Type | Number | The type of the object type. |
| JiraAsset.ObjectType.Position | Number | The position of the object type among other object types with the same level in the schema hierarchy. |
| JiraAsset.ObjectType.Created | Date | The date the object type was created. |
| JiraAsset.ObjectType.Updated | Date | The date the object type was last updated. |
| JiraAsset.ObjectType.ObjectCount | Number | The amount of objects listed under this object type. |
| JiraAsset.ObjectType.ObjectSchemaId | Number | The ID of the schema this object type is listed under. |
| JiraAsset.ObjectType.Inherited | Boolean | Whether this object type inherits from a parent object type. |
| JiraAsset.ObjectType.AbstractObjectType | Boolean | Is this object type abstract (can only be inherited). |
| JiraAsset.ObjectType.ParentObjectTypeInherited | Boolean | Whether this object type inherits from a parent object type. |
jira-asset-object-type-attribute-list
List all attributes for an object type.
Base Command
jira-asset-object-type-attribute-list
Input
| Argument Name | Description | Required |
|---|---|---|
| object_type_id | The object type for which the command will retrieve attributes. Values can be received by running the jira-asset-object-type-list command. |
Required |
| is_editable | Whether to only return attributes that can be edited. Possible values are: true, false. | Optional |
| order_by_name | Whether to sort the results by the attribute name. Possible values are: true, false. | Optional |
| query | Query to filter on available object type attributes. Filter attributes that start with the query. | Optional |
| include_value_exist | Should the response only include attributes where attribute values exists. Possible values are: true, false. | Optional |
| exclude_parent_attributes | Should the response exclude parent attributes. Possible values are: true, false. | Optional |
| include_children | Should the response include child attributes. Possible values are: true, false. | Optional |
| order_by_required | Should the response be ordered by the number of required attributes. Possible values are: true, false. | Optional |
| limit | The maximum amount of object types to retrieve. | Optional |
| all_results | Whether to retrieve all object types with no limit. Possible values are: true, false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| JiraAsset.Attribute.ID | Number | The ID of the attribute. |
| JiraAsset.Attribute.Name | String | The name of the attribute. |
| JiraAsset.Attribute.Label | Boolean | Whether this attribute is used as the label for objects of that type. |
| JiraAsset.Attribute.Type | String | The type of the attribute (Default, Reference, User, Project etc.). |
| JiraAsset.Attribute.DefaultType.id | Number | ID for the sub-type of the default type. |
| JiraAsset.Attribute.DefaultType.name | String | Name for the sub-type of the default type. |
| JiraAsset.Attribute.Editable | Boolean | Whether this attribute is editable. |
| JiraAsset.Attribute.System | Boolean | Whether this attribute is a system attribute or a custom one. |
| JiraAsset.Attribute.Sortable | Boolean | Can the objects be sorted by that attribute. |
| JiraAsset.Attribute.Summable | Boolean | Can this attribute be summarized. |
| JiraAsset.Attribute.Indexed | Boolean | Is this attribute indexed. |
| JiraAsset.Attribute.MinimumCardinality | Number | The minimum amount of elements this attribute should populate. |
| JiraAsset.Attribute.MaximumCardinality | Number | The maximum amount of elements this attribute should populate. |
| JiraAsset.Attribute.Removable | Boolean | Whether this attribute can be removed from the object. |
| JiraAsset.Attribute.Hidden | Boolean | Whether this attribute is a hidden attribute. |
| JiraAsset.Attribute.IncludeChildObjectTypes | Boolean | Whether this attribute includes child object types. |
| JiraAsset.Attribute.UniqueAttribute | Boolean | Whether this attribute is unique to its object. |
| JiraAsset.Attribute.Options | String | Options for the attributes. |
| JiraAsset.Attribute.Position | Number | The position of the attribute in relation to other object attributes. |
jira-asset-object-create
Create a new object of the specified object type ID. Either attributes or attributes_json must be provided.
Base Command
jira-asset-object-create
Input
| Argument Name | Description | Required |
|---|---|---|
| object_type_id | The object type for which a new object will be created. | Required |
| attributes | Provide this field if attributes_json is not provided. A key-value map of object attributes. The structure of the field is: { “attributeId1”: [ “value1”, “value2”] , “attributeId2”:[“value1”, “value2”] }. You can run the jira-asset-object-type-attribute-list command to retrieve the list of available attributes. |
Optional |
| attributes_json | Provide this field if attributes is not provided. A JSON string of object attributes to be added to the new object. Take a look at https://docs.atlassian.com/assets/REST/10.7.0/#object-createObject for the structure of this field. You can use the jira-asset-object-type-attribute-list command to retrieve the list of available attributes. |
Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| JiraAsset.Object.ID | Number | ID of the newly created object. |
| JiraAsset.Object.Label | String | The value of the attribute that is marked as Label for this object type. |
| JiraAsset.Object.ObjectKey | String | The auto-generated object key. |
| JiraAsset.Object.Avatar.objectId | Number | ID of the newly created object. |
| JiraAsset.Object.Created | Date | The date in which this object was created. |
| JiraAsset.Object.Updated | Date | The date in which this object was last updated. |
| JiraAsset.Object.HasAvatar | Boolean | Does this object have an Avatar. |
| JiraAsset.Object.Timestamp | Date | Epoch version of the object’s creation date. |
| JiraAsset.Object.Links.self | String | The link to view this object in the Jira web app. |
| JiraAsset.Object.Name | String | The name of the newly created object. |
jira-asset-object-update
Updates an existing object of specified object type ID. Either attributes or attributes_json must be provided.
Base Command
jira-asset-object-update
Input
| Argument Name | Description | Required |
|---|---|---|
| object_id | ID of the object that will be updated. | Required |
| attributes | Provide this field if attributes_json is not provided. A key-value map of object attributes. The structure of the field is: { “attributeId1”: [ “value1”, “value2”] , “attributeId2”:[“value1”, “value2”] }. You can use the jira-asset-object-type-attribute-list command to retrieve the list of available attributes. |
Optional |
| attributes_json | Provide this field if attributes is not provided. A JSON string of object attributes to be added to the new object. Take a look at https://docs.atlassian.com/assets/REST/10.7.0/#object-createObject for the structure of this field. You can use the jira-asset-object-type-attribute-list command to retrieve the list of available attributes. |
Optional |
Context Output
There is no context output for this command.
jira-asset-object-delete
Deletes an existing object of the specified object ID.
Base Command
jira-asset-object-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| object_id | ID of the object that will be deleted. | Required |
Context Output
There is no context output for this command.
jira-asset-object-get
Retrieves the object with the specified object ID.
Base Command
jira-asset-object-get
Input
| Argument Name | Description | Required |
|---|---|---|
| object_id | ID of the object that will be retrieved. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| JiraAsset.Object.ID | Number | ID of the retrieved object. |
| JiraAsset.Object.Label | String | The value of the attribute that is marked as Label for this object type. |
| JiraAsset.Object.ObjectKey | String | The auto-generated object key. |
| JiraAsset.Object.Created | Date | The date in which this object was created. |
| JiraAsset.Object.Updated | Date | The date in which this object was last updated. |
| JiraAsset.Object.HasAvatar | Boolean | Does this object have an Avatar. |
| JiraAsset.Object.Timestamp | Date | Epoch version of the object’s creation date. |
| JiraAsset.Object.ExtendedInfo.openIssuesExists | Boolean | Does this object appear in any open issues. |
| JiraAsset.Object.ExtendedInfo.attachmentsExists | Boolean | Does this object have any attachments. |
| JiraAsset.Object.Links.self | String | The link to view this object in the Jira web app. |
| JiraAsset.Object.Name | String | The name of the object. |
jira-asset-object-search
Searches for objects of the specified object type.
Base Command
jira-asset-object-search
Input
| Argument Name | Description | Required |
|---|---|---|
| ql_query | An aql query to search objects by. View https://support.atlassian.com/jira-service-management-cloud/docs/use-assets-query-language-aql/ for further details. | Required |
| include_attributes | Whether to include the attributes structure in the response. Possible values are: true, false. | Optional |
| page | Page number. | Optional |
| page_size | Use this argument or limit, but not both. Size of the page. Defaults to 50. | Optional |
| limit | Use this argument or a combination of page and page_size, but not both. Limit the number of entries returned by the command. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| JiraAsset.Object.ID | Number | ID of the retrieved object. |
| JiraAsset.Object.Label | String | The value of the attribute that is marked as Label for this object type. |
| JiraAsset.Object.ObjectKey | String | The auto-generated object key. |
| JiraAsset.Object.Created | Date | The date in which this object was created. |
| JiraAsset.Object.Updated | Date | The date in which this object was last updated. |
| JiraAsset.Object.HasAvatar | Boolean | Does this object have an Avatar. |
| JiraAsset.Object.Timestamp | Date | Epoch version of the object’s creation date. |
| JiraAsset.Object.Attributes.id | Number | The ID of the attribute. |
| JiraAsset.Object.Attributes.objectTypeAttributeId | Number | The ID of the attribute, not relative to the object type. |
| JiraAsset.Object.Attributes.objectAttributeValues.value | String | The value of the specific attribute for this object. |
| JiraAsset.Object.Attributes.objectAttributeValues.referencedType | Boolean | Whether this attribute is referenced by other types. |
| JiraAsset.Object.Attributes.objectAttributeValues.displayValue | String | The display value for this attribute. |
| JiraAsset.Object.Attributes.objectAttributeValues.searchValue | String | The search value for this attribute. |
| JiraAsset.Object.Attributes.objectId | Number | The ID of the object this attribute is assigned to. |
| JiraAsset.Object.Links.self | String | The link to view this object in the Jira web app. |
| JiraAsset.Object.Name | String | The name of the object. |
jira-asset-attribute-json-create
Utility command used to create a JSON file with all attributes of the specified object type. All that is left is to fill in the values of each attribute.
Base Command
jira-asset-attribute-json-create
Input
| Argument Name | Description | Required |
|---|---|---|
| object_type_id | ID of the object type that attributes JSON will be created for. You could use the jira-asset-object-type-list command to find object types. | Required |
| is_editable | Whether to fetch only editable attributes. Possible values are: true, false. | Optional |
| is_required | Whether to fetch only required attributes. Possible values are: true, false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| InfoFile.Name | string | File name. |
| InfoFile.EntryID | string | The entry ID of the report. |
| InfoFile.Size | number | File size. |
| InfoFile.Type | string | File type, e.g., “PE”. |
| InfoFile.Info | string | Basic information of the file. |
jira-asset-comment-create
Creates a comment for the specified object.
Base Command
jira-asset-comment-create
Input
| Argument Name | Description | Required |
|---|---|---|
| object_id | ID of the object that the comment will be added to. You could use the jira-asset-object-search command to find objects. | Required |
| comment | Body of the comment that will be created. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| JiraAsset.Comment.Created | Date | The date in which this comment was created. |
| JiraAsset.Comment.Updated | Date | The date in which this object was last updated. |
| JiraAsset.Comment.Id | Number | The ID of the newly created comment. |
| JiraAsset.Comment.Actor.AvatarUrl | String | URL to the avatar of the author of the comment. |
| JiraAsset.Comment.Actor.DisplayName | String | Display name of the author of the comment. |
| JiraAsset.Comment.Actor.Name | String | Name of the author of the comment. |
| JiraAsset.Comment.Actor.Key | String | Key of the author of the comment. |
| JiraAsset.Comment.Actor.RenderedLink | String | A link to the author’s Jira profile. |
| JiraAsset.Comment.Actor.IsDeleted | Boolean | Is the author of the comment deleted. |
| JiraAsset.Comment.Role | Number | The role of the author of the comment. |
| JiraAsset.Comment.Comment | String | The body of the comment that was newly added. |
| JiraAsset.Comment.CommentOutput | String | The body of the comment that was newly added. |
| JiraAsset.Comment.ObjectId | Number | The ID of the object the new comment was added to. |
| JiraAsset.Comment.CanEdit | Boolean | Whether the comment is editable. |
| JiraAsset.Comment.CanDelete | Boolean | Whether the comment can be deleted. |
jira-asset-connected-ticket-list
Returns a list of all connected tickets for the specified object.
Base Command
jira-asset-connected-ticket-list
Input
| Argument Name | Description | Required |
|---|---|---|
| object_id | ID of the object for which connected tickets will be fetched. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| JiraAsset.ConnectedTicket.Tickets.Key | String | Key for the connected ticket. |
| JiraAsset.ConnectedTicket.Tickets.ID | Number | The ID of the connected ticket. |
| JiraAsset.ConnectedTicket.Tickets.Reporter | String | The user who reported the connected ticket. |
| JiraAsset.ConnectedTicket.Tickets.Created | Date | The date in which this connected ticket was created. |
| JiraAsset.ConnectedTicket.Tickets.Updated | Date | The date in which this connected ticket was last updated. |
| JiraAsset.ConnectedTicket.Tickets.Title | String | Title of the connected ticket. |
| JiraAsset.ConnectedTicket.Tickets.Status.Name | String | The name of the status of the connected ticket. |
| JiraAsset.ConnectedTicket.Tickets.Status.Colorname | String | The color of the connected tikcet. |
| JiraAsset.ConnectedTicket.Tickets.Type.Name | String | The type of the connected ticket. |
| JiraAsset.ConnectedTicket.Tickets.Type.Description | String | The description of the type of the connected ticket. |
| JiraAsset.ConnectedTicket.Tickets.Type.Iconurl | String | The URL to the icon representing the type of the connected ticket. |
| JiraAsset.ConnectedTicket.Tickets.Priority.Name | String | Priority of the connected ticket. |
| JiraAsset.ConnectedTicket.Tickets.Priority.Iconurl | String | The URL to the icon representing the priority of the connected ticket. |
| JiraAsset.ConnectedTicket.Allticketsquery | String | The query used to fetch the connected tickets. |
jira-asset-comment-list
Returns a list of comments for the specified object.
Base Command
jira-asset-comment-list
Input
| Argument Name | Description | Required |
|---|---|---|
| object_id | ID of the object that comments will be retrieved for. You could use the jira-asset-object-search command to find objects. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| JiraAsset.Comment.Created | Date | The date in which this comment was created. |
| JiraAsset.Comment.Updated | Date | The date in which this object was last updated. |
| JiraAsset.Comment.ID | Number | The ID of the newly created comment. |
| JiraAsset.Comment.Role | Number | The role of the author of the comment. |
| JiraAsset.Comment.Comment | String | The body of the comment that was newly added. |
| JiraAsset.Comment.CommentOutput | String | The body of the comment that was newly added. |
| JiraAsset.Comment.ObjectId | Number | The ID of the object the new comment was added to. |
| JiraAsset.Comment.CanEdit | Boolean | Whether the comment is editable. |
| JiraAsset.Comment.CanDelete | unknown | Whether the comment can be deleted. |
jira-asset-attachment-add
Uploads a file attachment to the specified object.
Base Command
jira-asset-attachment-add
Input
| Argument Name | Description | Required |
|---|---|---|
| object_id | ID of the object that the file will be attached to. | Required |
| entry_id | ID of the file to upload. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| JiraAsset.Attachment.ID | Number | ID of the attachment. |
| JiraAsset.Attachment.Author | String | Author of the attachment. |
| JiraAsset.Attachment.MimeType | String | The file’s MIME type. |
| JiraAsset.Attachment.Filename | String | The file’s name. |
| JiraAsset.Attachment.Filesize | String | The size of the file. |
| JiraAsset.Attachment.Created | Date | The date in which this attachment was created. |
| JiraAsset.Attachment.Comment | String | The comment attached to the attachment, if there is one. |
| JiraAsset.Attachment.CommentOutput | String | The comment output of the attachment, if there is one. |
| JiraAsset.Attachment.Url | String | URL to the attachment. |
jira-asset-attachment-list
Returns a list of attachments for the specified object. You can also download the files in a zipped format.
Base Command
jira-asset-attachment-list
Input
| Argument Name | Description | Required |
|---|---|---|
| object_id | ID of the object that attachments will be fetched for. | Required |
| download_file | Whether to download the attachments for this object in a zipped format. Possible values are: true, false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| JiraAsset.Attachment.ID | Number | ID of the attachment. |
| JiraAsset.Attachment.Author | String | Author of the attachment. |
| JiraAsset.Attachment.MimeType | String | The file’s MIME type. |
| JiraAsset.Attachment.Filename | String | The file’s name. |
| JiraAsset.Attachment.Filesize | String | The size of the file. |
| JiraAsset.Attachment.Created | Date | The date in which this attachment was created. |
| JiraAsset.Attachment.Comment | String | The comment attached to the attachment, if there is one. |
| JiraAsset.Attachment.CommentOutput | String | The comment output of the attachment, if there is one. |
| JiraAsset.Attachment.Url | String | URL to the attachment. |
jira-asset-attachment-remove
Removes an attachment from a specific object.
Base Command
jira-asset-attachment-remove
Input
| Argument Name | Description | Required |
|---|---|---|
| id | ID of the attachment that will be deleted. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| JiraAsset.Attachment.ID | Number | ID of the attachment that was deleted. |
| JiraAsset.Attachment.Author | String | Author of the attachment. |
| JiraAsset.Attachment.MimeType | String | The file’s MIME type. |
| JiraAsset.Attachment.Filename | String | The file’s name. |
| JiraAsset.Attachment.Filesize | String | The size of the file. |
| JiraAsset.Attachment.Created | Date | The date in which this attachment was created. |
| JiraAsset.Attachment.Comment | String | The comment attached to the attachment, if there is one. |
| JiraAsset.Attachment.CommentOutput | String | The comment output of the attachment, if there is one. |
| JiraAsset.Attachment.Url | String | URL to the attachment. |
Configuration parameters
url— Server URL (required)credentials— (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (15)
-
jira-asset-attachment-addUploads a file attachment to the specified object.
-
jira-asset-attachment-listReturns a list of attachments for the specified object. You can also download the files in a zipped format.
-
jira-asset-attachment-removeRemoves an attachment from a specific object.
-
jira-asset-attribute-json-createUtility command used to create a JSON file with all attributes of the specified object type. All that is left is to fill in the values of each attribute.
-
jira-asset-comment-createCreates a comment for the specified object.
-
jira-asset-comment-listReturns a list of comments for the specified object.
-
jira-asset-connected-ticket-listReturns a list of all connected tickets for the specified object.
-
jira-asset-object-createCreate a new object of the specified object type ID. Either attributes or attributes_json must be provided.
-
jira-asset-object-deleteDeletes an existing object of the specified object ID.
-
jira-asset-object-getRetrieves the object with the specified object ID.
-
jira-asset-object-schema-listList all object schemas.
-
jira-asset-object-searchSearches for objects of the specified object type.
-
jira-asset-object-type-attribute-listList all attributes for an object type.
-
jira-asset-object-type-listList all object types.
-
jira-asset-object-updateUpdates an existing object of specified object type ID. Either attributes or attributes_json must be provided.
import json import os from typing import Any from unittest.mock import Mock import AtlassianJiraServiceManagement as JSM import demistomock as demisto import pytest from CommonServerPython import CommandResults from pytest_mock import MockerFixture def util_load_json(path): with open(path, encoding="utf-8") as f: return json.loads(f.read()) command_test_data = util_load_json("./test_data/command_test_data.json") client = JSM.Client(base_url="https://url.com", verify=False, proxy=False, api_key="key123") def test_convert_keys_to_pascal_empty_list(): """ Given: - An empty list of objects to convert to pascal case. When: - Calling the convert_keys_to_pascal function. Then: - The function should return an empty list. """ objects = [] key_mapping = None expected_result = [] result = JSM.convert_keys_to_pascal(objects, key_mapping) assert result == expected_result def test_convert_keys_to_pascal_list_with_keys(): """ Given: - A list of objects with keys to convert to pascal case. When: - Calling the convert_keys_to_pascal function. Then: - The function should return the list with keys converted to pascal case. """ objects = [ {"key1": "value1", "key2": "value2"}, {"key3": "value3", "key4": "value4"}, ] key_mapping = None expected_result = [ {"Key1": "value1", "Key2": "value2"}, {"Key3": "value3", "Key4": "value4"}, ] result = JSM.convert_keys_to_pascal(objects, key_mapping) assert result == expected_result def test_convert_keys_to_pascal_list_with_keys_and_mapping(): """ Given: - A list of objects with keys to convert to pascal case. - A key mapping to apply to the keys. When: - Calling the convert_keys_to_pascal function. Then: - The function should return the list with keys converted to pascal case and mapping applied where specified. """ objects = [ {"key1": "value1", "key2": "value2"}, {"key3": "value3", "key4": "value4"}, ] key_mapping = {"key1": "MappedKey1", "key4": "MappedKey4"} expected_result = [ {"MappedKey1": "value1", "Key2": "value2"}, {"Key3": "value3", "MappedKey4": "value4"}, ] result = JSM.convert_keys_to_pascal(objects, key_mapping) assert result == expected_result def test_get_object_readable_outputs(): objects = [ {"objectType": {"name": "typeA"}, "avatar": "avatarA", "id": 123, "key": "value"}, {"objectType": {"name": "typeB"}, "avatar": "avatarB", "id": 456, "key": "value"}, ] expected_output = [{"ID": 123, "Key": "value", "Type": "typeA"}, {"ID": 456, "Key": "value", "Type": "typeB"}] assert JSM.get_object_readable_outputs(objects) == expected_output def test_clean_object_attributes_with_type_and_default_type(): """ Given: - An object with 'id', 'name', 'type', and 'defaultType' fields. When: - Cleaning the object attributes to match a certain format. Then: - The cleaned attributes should match the expected format with 'type' replaced by its string representation and keys in PascalCase. """ attributes = [{"id": 1, "name": "Test", "type": 0, "defaultType": {"name": "Text"}, "objectType": {"id": 1}}] expected = [{"id": 1, "name": "Test", "type": "Text", "defaultType": {"name": "Text"}}] result = JSM.clean_object_attributes(attributes) assert result == expected def test_clean_object_attributes_with_type(): """ Given: - An object with 'id', 'value', and 'type' fields. When: - Cleaning the object attributes to match a certain format. Then: - The cleaned attributes should match the expected format with 'type' replaced by its string representation and keys in PascalCase. """ attributes = [{"id": 2, "value": "Hello", "type": 1}] expected = [{"id": 2, "value": "Hello", "type": "Object Reference"}] result = JSM.clean_object_attributes(attributes) assert result == expected def test_clean_object_attributes_empty(): """ Given: - An empty list of object attributes. When: - Cleaning the object attributes to match a certain format. Then: - The function should return an empty list as no attributes are present to clean. """ attributes = [] expected = [] result = JSM.clean_object_attributes(attributes) assert result == expected def test_convert_attributes_multiple_values(): """ Given: - A dictionary with one attribute having multiple values. When: - The convert_attributes function is called with the dictionary. Then: - The function should return a list with a dictionary containing 'objectTypeAttributeId' set to the attribute ID and 'objectAttributeValues' as a list of dictionaries with 'value' keys. """ attributes = {"attr1": ["value1", "value2"]} expected = [{"objectTypeAttributeId": "attr1", "objectAttributeValues": [{"value": "value1"}, {"value": "value2"}]}] result = JSM.convert_attributes(attributes) assert result == expected def test_convert_attributes_single_value(): """ Given: - A dictionary with one attribute having a single value. When: - The convert_attributes function is called with the dictionary. Then: - The function should return a list with a dictionary containing 'objectTypeAttributeId' set to the attribute ID and 'objectAttributeValues' as a list with a single dictionary with the 'value' key. """ attributes = {"attr2": ["hello"]} expected = [{"objectTypeAttributeId": "attr2", "objectAttributeValues": [{"value": "hello"}]}] result = JSM.convert_attributes(attributes) assert result == expected def test_convert_attributes_empty(): """ Given: - An empty dictionary of attributes. When: - The convert_attributes function is called with the dictionary. Then: - The function should return an empty list as there are no attributes to convert. """ attributes = {} expected = [] result = JSM.convert_attributes(attributes) assert result == expected def test_convert_attributes_empty_values(): """ Given: A dictionary with an attribute ID and an empty list of values When: The convert_attributes function is called with the dictionary Then: The function should return a list with a dictionary containing an empty list for objectAttributeValues """ attributes = {"attr4": []} expected = [{"objectTypeAttributeId": "attr4", "objectAttributeValues": []}] result = JSM.convert_attributes(attributes) assert result == expected def test_get_attributes_json_data_with_attributes(): """ Given: An object type ID and a string representation of attributes When: The get_attributes_json_data function is called with the object type ID and attributes Then: The function should return a dictionary with the object type ID and converted attributes """ object_type_id = "test_object_type" attributes = {"attr1": ["value1", "value2"], "attr2": ["hello"]} expected = { "objectTypeId": object_type_id, "attributes": [ {"objectTypeAttributeId": "attr1", "objectAttributeValues": [{"value": "value1"}, {"value": "value2"}]}, {"objectTypeAttributeId": "attr2", "objectAttributeValues": [{"value": "hello"}]}, ], } result = JSM.get_attributes_json_data(object_type_id, attributes=attributes) assert result == expected def test_get_attributes_json_data_with_attributes_json(): """ Given: An object type ID and a JSON string representation of attributes When: The get_attributes_json_data function is called with the object type ID and attributes_json Then: The function should return a dictionary with the object type ID and converted attributes """ object_type_id = "test_object_type" attributes_json = ( "{" '"attributes": [' '{"objectTypeAttributeId": "attr1", "objectAttributeValues": [{"value": "value1"},{"value": "value2"}]},' '{"objectTypeAttributeId": "attr2", "objectAttributeValues": [{"value": "hello"}]}]}' ) expected = { "objectTypeId": object_type_id, "attributes": [ {"objectTypeAttributeId": "attr1", "objectAttributeValues": [{"value": "value1"}, {"value": "value2"}]}, {"objectTypeAttributeId": "attr2", "objectAttributeValues": [{"value": "hello"}]}, ], } result = JSM.get_attributes_json_data(object_type_id, attributes_json=attributes_json) assert result == expected def test_get_attributes_json_data_no_input(): """ Given: An object type ID, but no attributes or attributes_json When: The get_attributes_json_data function is called without providing attributes or attributes_json Then: The function should raise a ValueError """ object_type_id = "test_object_type" with pytest.raises(ValueError): JSM.get_attributes_json_data(object_type_id) def test_get_attributes_json_data_both_inputs(): """ Given: An object type ID, and both attributes and attributes_json When: The get_attributes_json_data function is called with both attributes and attributes_json Then: The function should raise a ValueError """ object_type_id = "test_object_type" attributes = '{"attr1": ["value1", "value2"]}' attributes_json = '{"attributes": [{"attr2": ["hello"]}]}' with pytest.raises(ValueError): JSM.get_attributes_json_data(object_type_id, attributes=attributes, attributes_json=attributes_json) def test_parse_object_results_basic(): """ Given: An object with multiple fields, but no object type. When: The parse_object_results function is called with the object. Then: The function should return a dictionary with the object ID and the object name. """ res = {"id": 123, "name": "TestObject"} expected_output = {"outputs": [{"id": 123, "name": "TestObject"}], "objectId": 123} assert JSM.parse_object_results(res) == expected_output def test_parse_object_results_with_object_type(): """ Given: An object with multiple fields and an object type. When: The parse_object_results function is called with the object. Then: The function should return a dict with the object ID and name converted to PascalCase but delete the object type. """ res = {"id": 123, "name": "TestObject", "objectType": "TestType"} expected_output = {"outputs": [{"id": 123, "name": "TestObject"}], "objectId": 123} assert JSM.parse_object_results(res) == expected_output def test_parse_object_results_empty(): """ Given: An empty object. When: The parse_object_results function is called with the object. Then: The function should return a dictionary with an empty dictionary for outputs and no ID. """ res = {} expected_output = {"outputs": [{}], "objectId": None} assert JSM.parse_object_results(res) == expected_output def test_jira_asset_object_schema_list_command_with_limit(mocker: MockerFixture): """ Given: - An args dict with a 'limit' argument. When: - Calling the jira_asset_object_schema_list_command with the args dict. Then: - The command returns a limited number of results as specified by the 'limit' argument. """ args = {"limit": "2"} expected_len = 2 mocked_return_value = command_test_data["object_schema_list"]["response"] mocked_client = mocker.patch.object(client, "get_schema_list", return_value=mocked_return_value) command_results = JSM.jira_asset_object_schema_list_command(client, args) mocked_client.assert_called() assert len(command_results.outputs) == expected_len def test_jira_asset_object_schema_list_command_all_results(mocker: MockerFixture): """ Given: - An args dict with 'all_results' set to 'true'. When: - Calling the jira_asset_object_schema_list_command with the args dict. Then: - The command returns all results, ignoring any 'limit' argument. """ args = {"all_results": "true"} expected_len = 3 mocked_return_value = command_test_data["object_schema_list"]["response"] mocked_client = mocker.patch.object(client, "get_schema_list", return_value=mocked_return_value) command_results = JSM.jira_asset_object_schema_list_command(client, args) mocked_client.assert_called() assert len(command_results.outputs) == expected_len def test_jira_asset_object_schema_list_command_all_results_with_limit(mocker: MockerFixture): """ Given: - An args dict with 'all_results' set to 'true' and a 'limit' argument. When: - Calling the jira_asset_object_schema_list_command with the args dict. Then: - The command returns all results, taking into account the 'limit' only if 'all_results' is false. """ args = {"all_results": "true", "limit": 2} expected_len = 3 mocked_return_value = command_test_data["object_schema_list"]["response"] mocked_client = mocker.patch.object(client, "get_schema_list", return_value=mocked_return_value) command_results = JSM.jira_asset_object_schema_list_command(client, args) mocked_client.assert_called() assert len(command_results.outputs) == expected_len def test_jira_asset_object_type_list_command_with_limit_2(mocker: MockerFixture): """ Given: - An arguments dictionary with 'limit' set to '2' and 'schema_id' set to '1'. When: - Calling the jira_asset_object_type_list_command with the given arguments. Then: - The command should return exactly 2 results as specified by the 'limit' argument. """ args = {"limit": "2", "schema_id": "1"} expected_len = 2 mocked_return_value = command_test_data["object_type_list"]["response"] mocked_client = mocker.patch.object(client, "get_object_type_list", return_value=mocked_return_value) command_results = JSM.jira_asset_object_type_list_command(client, args) mocked_client.assert_called_with("1", None) assert len(command_results.outputs) == expected_len def test_jira_asset_object_type_list_command_with_limit_4(mocker: MockerFixture): """ Given: - An arguments dictionary with 'limit' set to '4' and 'schema_id' set to '1'. When: - Calling the jira_asset_object_type_list_command with the given arguments. Then: - The command should return exactly 4 results as specified by the 'limit' argument. """ args = {"limit": "4", "schema_id": "1"} expected_len = 4 mocked_return_value = command_test_data["object_type_list"]["response"] mocked_client = mocker.patch.object(client, "get_object_type_list", return_value=mocked_return_value) command_results = JSM.jira_asset_object_type_list_command(client, args) mocked_client.assert_called_with("1", None) assert len(command_results.outputs) == expected_len def test_jira_asset_object_type_list_command_all_results(mocker: MockerFixture): """ Given: - An arguments dictionary with 'all_results' set to 'true' and 'schema_id' set to '1'. When: - Calling the jira_asset_object_type_list_command with the given arguments. Then: - The command should return all available results, ignoring the 'limit' argument. """ args = {"all_results": "true", "schema_id": "1"} expected_len = 5 mocked_return_value = command_test_data["object_type_list"]["response"] mocked_client = mocker.patch.object(client, "get_object_type_list", return_value=mocked_return_value) command_results = JSM.jira_asset_object_type_list_command(client, args) mocked_client.assert_called_with("1", None) assert len(command_results.outputs) == expected_len def test_jira_asset_object_type_list_command_all_results_with_limit(mocker: MockerFixture): """ Given: - An arguments dictionary with 'all_results' set to 'true', a 'limit' of 2, and 'schema_id' set to '1'. When: - Calling the jira_asset_object_type_list_command with the given arguments. Then: - The command should return all available results, as 'all_results' takes precedence over the 'limit'. """ args = {"all_results": "true", "limit": 2, "schema_id": "1"} expected_len = 5 mocked_return_value = command_test_data["object_type_list"]["response"] mocked_client = mocker.patch.object(client, "get_object_type_list", return_value=mocked_return_value) command_results = JSM.jira_asset_object_type_list_command(client, args) mocked_client.assert_called_with("1", None) assert len(command_results.outputs) == expected_len @pytest.mark.parametrize( "args, expected_len", [ ({"limit": "2", "object_type_id": "1"}, 2), ({"limit": "4", "object_type_id": "1"}, 4), ({"all_results": "true", "object_type_id": "1"}, 6), ({"all_results": "true", "limit": 2, "object_type_id": "1"}, 6), ], ) def test_jira_asset_object_type_attribute_list_command(mocker: MockerFixture, args: dict[str, Any], expected_len: int): """ Given: An args dict with limit and/or all_results When: Calling the jira_asset_object_type_list_command with the args dict Then: The command returns results, taking into account the limit, only if all_results is false """ mocked_return_value = command_test_data["object_type_attributes"]["response"] mocked_client = mocker.patch.object(client, "get_object_type_attributes", return_value=mocked_return_value) command_results = JSM.jira_asset_object_type_attribute_list_command(client, args) assert len(command_results.outputs) == expected_len mocked_client.assert_called_with( object_type_id=args["object_type_id"], order_by_name=False, query=None, include_value_exist=False, exclude_parent_attributes=False, include_children=False, order_by_required=False, ) def test_jira_asset_object_create_command(mocker: MockerFixture): """ Given: An object_type_id and a string of attributes When: The object_create command is called with said arguments Then: The client's create_object function is called with said arguments in the format that the get_attributes_json_data function returns """ object_type_id = "1" attributes = {"1": ["value1"], "2": ["value1", "value2"]} attributes_json_data = JSM.get_attributes_json_data(object_type_id, attributes) mocked_client = mocker.patch.object(client, "create_object", return_value=command_test_data["object_create"]["response"]) JSM.jira_asset_object_create_command(client, {"object_type_id": object_type_id, "attributes": attributes}) mocked_client.assert_called_with(attributes_json_data) def test_jira_asset_object_update_command(mocker: MockerFixture): """ Given: An object_id and a string of attributes When: The object_update command is called with said arguments Then: The client's update_object function is called with said arguments in the format that the get_attributes_json_data function returns """ object_id = "1" object_type_id = "3" attributes = {"1": ["value1"], "2": ["value1", "value2"]} attributes_json_data = JSM.get_attributes_json_data(object_type_id, attributes) mocker.patch.object(client, "get_object", return_value=command_test_data["get_object"]["response"]) mocked_update_object = mocker.patch.object( client, "update_object", return_value=command_test_data["object_update"]["response"] ) JSM.jira_asset_object_update_command(client, {"object_id": object_id, "attributes": attributes}) mocked_update_object.assert_called_with(object_id, attributes_json_data) def test_jira_asset_object_delete_command(mocker: MockerFixture): """ Given: An object id When: The jira_asset_object_delete_command function is called Then: The client's delete_object function is called with said object id """ object_id = "1" mocked_client = mocker.patch.object(client, "delete_object", return_value={}) JSM.jira_asset_object_delete_command(client, {"object_id": object_id}) mocked_client.assert_called_with(object_id) def test_jira_asset_object_delete_non_exising_object(mocker: MockerFixture): """ Given: A non-existing object id When: The client's delete_object function returns None Then: The jira_asset_object_delete_command function returns a specific hr response """ object_id = "-1" mock_delete = mocker.patch.object(client, "delete_object", return_value=None) command_result = JSM.jira_asset_object_delete_command(client, {"object_id": object_id}) mock_delete.assert_called_with(object_id) assert command_result.readable_output == f"Object with id: {object_id} does not exist" def test_jira_object_get_command(mocker: MockerFixture): """ Given: An object id When: The jira_asset_object_get_command function is called Then: The client's get_object function is called with said object id """ object_id = "1" mocked_client = mocker.patch.object(client, "get_object", return_value=command_test_data["get_object"]["response"]) JSM.jira_asset_object_get_command(client, {"object_id": object_id}) mocked_client.assert_called_with(object_id) def test_jira_asset_object_get_non_exising_object(mocker: MockerFixture): """ Given: A non-existing object id When: The client's get_object function returns None Then: The jira_asset_object_get_command function returns a specific hr response """ object_id = "-1" mock_delete = mocker.patch.object(client, "get_object", return_value=None) command_result = JSM.jira_asset_object_get_command(client, {"object_id": object_id}) mock_delete.assert_called_with(object_id) assert command_result.readable_output == f"Object with id: {object_id} does not exist" def test_jira_asset_object_search_command(mocker: MockerFixture): """ Given: A ql_query When: The jira_asset_object_search_command function is called Then: The client's search_objects function is called with said ql_query, with the default values for the rest of the arguments """ ql_query = "objectType = SW_engineer" mocked_client = mocker.patch.object(client, "search_objects", return_value=command_test_data["search_objects"]["response"]) JSM.jira_asset_object_search_command(client, {"ql_query": ql_query}) mocked_client.assert_called_with(ql_query, False, 1, 50, None) def test_jira_asset_object_search_command_no_results(mocker: MockerFixture): """ Given: A ql_query that matches no objects (API returns a response without 'objectEntries' key, e.g. a 404 error body such as {"errorMessages": [...], "errors": {}}). When: The jira_asset_object_search_command function is called. Then: The command returns a human-readable "No objects found." message instead of raising a KeyError. """ ql_query = '"Hostname" in ("NONEXISTENT")' mocker.patch.object(client, "search_objects", return_value={"errorMessages": ["No resource found"], "errors": {}}) result = JSM.jira_asset_object_search_command(client, {"ql_query": ql_query}) assert result.readable_output == "No objects found." def test_jira_asset_object_search_command_empty_object_entries(mocker: MockerFixture): """ Given: A ql_query that matches no objects (API returns {"objectEntries": [], "total": 0}). When: The jira_asset_object_search_command function is called. Then: The command returns a human-readable "No objects found." message. """ ql_query = '"Hostname" in ("NONEXISTENT")' mocker.patch.object(client, "search_objects", return_value={"objectEntries": [], "total": 0}) result = JSM.jira_asset_object_search_command(client, {"ql_query": ql_query}) assert result.readable_output == "No objects found." @pytest.mark.parametrize( "args, expected_len", [({"object_type_id": "1"}, 6), ({"object_type_id": "1", "is_required": "true"}, 4)] ) def test_jira_asset_attribute_json_create_command(mocker: MockerFixture, args, expected_len): """ Given: An args dictionary with the object_type_id and an optional is_required argument When: The jira_asset_attribute_json_create_command function is called Then: The client's get_object_type_attributes function is called with the right parameters and returns only required objects if the is_required argument is set to true """ object_type_id = "1" mocked_attributes_response = command_test_data["object_type_attributes"]["response"] mock_attributes_call = mocker.patch.object(client, "get_object_type_attributes", return_value=mocked_attributes_response) command_results = JSM.jira_asset_attribute_json_create_command(client, args) mock_attributes_call.assert_called_with(object_type_id=object_type_id, is_editable=False) _, command_results = command_results os.remove(f"1_{_.get('FileID')}") attributes = json.loads(command_results.readable_output).get("attributes") assert len(attributes) == expected_len def test_jira_asset_comment_create_command(mocker: MockerFixture): """ Given: An object id and a comment When: The jira_asset_comment_create_command function is called Then: The client's create_comment function is called with the object_id and the comment """ object_id = "1" comment = "comment body" mocked_client = mocker.patch.object(client, "create_comment", return_value={"id": 1}) JSM.jira_asset_comment_create_command(client, {"object_id": object_id, "comment": comment}) mocked_client.assert_called_with(object_id, comment) def test_jira_asset_comment_list_command(mocker: MockerFixture): """ Given: An object id When: The jira_asset_comment_list_command function is called Then: The client's get_comment_list function is called with the object_id """ object_id = "1" mocked_client = mocker.patch.object(client, "get_comment_list", return_value=[{"id": 1}]) JSM.jira_asset_comment_list_command(client, {"object_id": object_id}) mocked_client.assert_called_with(object_id) def test_jira_asset_connected_ticket_list_command(mocker: MockerFixture): """ Given: An object id When: The jira_asset_connected_ticket_list_command function is called Then: The client's get_object_connected_tickets function is called with the object_id """ object_id = "1" mocked_client = mocker.patch.object(client, "get_object_connected_tickets", return_value={"tickets": [{"id": 1}]}) JSM.jira_asset_connected_ticket_list_command(client, {"object_id": object_id}) mocked_client.assert_called_with(object_id) def test_jira_asset_attachment_add_command(mocker: MockerFixture): object_id = "1" entry_id = None mocker.patch.object(demisto, "getFilePath", return_value={"path": "test_data/test_file.txt"}) mocked_client = mocker.patch.object(client, "send_file", return_value=[{"id": 1}]) JSM.jira_asset_attachment_add_command(client, {"object_id": object_id, "entry_id": entry_id}) mocked_client.assert_called_with(object_id=object_id, file_path="test_data/test_file.txt") def test_jira_asset_attachment_list_command_no_download(mocker: MockerFixture): object_id = "1" path = f"/attachments/object/{object_id}" mocked_client = mocker.patch.object(client, "get_object_attachment_list", return_value=[{"id": 1}]) JSM.jira_asset_attachment_list_command(client, {"object_id": object_id, "download_file": "false"}) mocked_client.assert_called_with(path) def test_jira_asset_attachment_list_command_with_download(mocker: MockerFixture): object_id = "1" file_list = command_test_data["attachment_list"]["response"] path = f"/attachments/object/{object_id}" mocked_client = mocker.patch.object(client, "get_object_attachment_list", return_value=file_list) mocker.patch.object(client, "get_file", return_value=Mock(content=b"file content")) mocker.patch("os.remove") mocker.patch("builtins.open", mocker.mock_open()) mocker.patch("zipfile.ZipFile") result = JSM.jira_asset_attachment_list_command(client, {"object_id": object_id, "download_file": "true"}) mocked_client.assert_called_with(path) assert isinstance(result, list) assert isinstance(result[0], dict) # fileResult returns a dict assert result[0]["File"] == "ObjectAttachments.zip" assert isinstance(result[1], CommandResults) def test_jira_asset_attachment_remove_command(mocker: MockerFixture): file_id = "1" mocked_client = mocker.patch.object(client, "remove_file", return_value={"id": 1}) JSM.jira_asset_attachment_remove_command(client, {"id": file_id}) mocked_client.assert_called_with(file_id)