Skip to content

Commit 2b12fe8

Browse files
committed
remove resource_group from question methods
1 parent 61ddfb0 commit 2b12fe8

File tree

5 files changed

+80
-86
lines changed

5 files changed

+80
-86
lines changed

examples/08_questions_management.py

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -254,18 +254,14 @@ def advanced_question_examples(j1):
254254
except Exception as e:
255255
print(f"Error creating parameterized question: {e}\n")
256256

257-
def resource_group_question_examples(j1):
258-
"""Demonstrate questions with resource group associations."""
257+
def production_environment_examples(j1):
258+
"""Demonstrate questions for production environment monitoring."""
259259

260-
print("=== Resource Group Question Examples ===\n")
260+
print("=== Production Environment Question Examples ===\n")
261261

262-
# Note: You'll need to have a resource group ID for this example
263-
# This is just a demonstration - replace with your actual resource group ID
264-
resource_group_id = "your-resource-group-id" # Replace with actual ID
265-
266-
print("1. Creating a question associated with a resource group:")
262+
print("1. Creating a question for production environment security:")
267263
try:
268-
rg_question = j1.create_question(
264+
prod_question = j1.create_question(
269265
title="Production Environment Security Check",
270266
queries=[
271267
{
@@ -279,17 +275,18 @@ def resource_group_question_examples(j1):
279275
"resultsAre": "BAD"
280276
}
281277
],
282-
resource_group_id=resource_group_id, # Associate with resource group
283278
description="Security checks for production environment resources",
284279
tags=["production", "security", "critical"],
285280
pollingInterval="THIRTY_MINUTES" # More frequent polling for production
286281
)
287282

288-
print(f"Created resource group question: {rg_question['title']}")
289-
print(f"Resource group ID: {resource_group_id}")
283+
print(f"Created production environment question: {prod_question['title']}")
284+
print(f"Description: {prod_question['description']}")
285+
print(f"Tags: {', '.join(prod_question.get('tags', []))}")
286+
print(f"Polling interval: {prod_question.get('pollingInterval', 'Not set')}")
290287
print()
291288
except Exception as e:
292-
print(f"Note: Resource group example requires valid resource group ID\n")
289+
print(f"Error creating production environment question: {e}\n")
293290

294291
def list_questions_example(j1):
295292
"""Demonstrate listing existing questions."""
@@ -810,7 +807,7 @@ def main():
810807
advanced_question_examples(j1)
811808
time.sleep(1)
812809

813-
resource_group_question_examples(j1)
810+
production_environment_examples(j1)
814811
time.sleep(1)
815812

816813
list_questions_example(j1)

jupiterone/client.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,7 +1358,6 @@ def create_question(
13581358
self,
13591359
title: str,
13601360
queries: List[Dict],
1361-
resource_group_id: str = None,
13621361
**kwargs
13631362
):
13641363
"""Creates a new Question in the J1 account.
@@ -1370,7 +1369,6 @@ def create_question(
13701369
- name (str): Name for the query
13711370
- version (str): Query version (defaults to 'v1')
13721371
- resultsAre (str): Query result type (defaults to 'INFORMATIVE')
1373-
resource_group_id (str, optional): ID of the resource group to associate with
13741372
**kwargs: Additional optional parameters:
13751373
- description (str): Description of the question
13761374
- tags (List[str]): List of tags to apply to the question
@@ -1392,7 +1390,6 @@ def create_question(
13921390
"version": "v1",
13931391
"resultsAre": "INFORMATIVE"
13941392
}],
1395-
resource_group_id="resource-group-id",
13961393
description="Check for open hosts",
13971394
tags=["security", "compliance"]
13981395
)
@@ -1429,11 +1426,7 @@ def create_question(
14291426
"queries": processed_queries
14301427
}
14311428

1432-
# Add optional fields from kwargs
1433-
if resource_group_id:
1434-
question_input["resourceGroupId"] = resource_group_id
1435-
1436-
# Add other optional fields if provided
1429+
# Add optional fields if provided
14371430
optional_fields = [
14381431
"description", "tags", "compliance", "variables",
14391432
"showTrend", "pollingInterval", "integrationDefinitionId"
@@ -1534,6 +1527,10 @@ def update_question(
15341527
if value is not None:
15351528
update_data[key] = value
15361529

1530+
# Validate that at least one update field is provided
1531+
if not update_data:
1532+
raise ValueError("At least one update field must be provided")
1533+
15371534
# Execute the GraphQL mutation
15381535
variables = {
15391536
"id": question_id,
@@ -1810,6 +1807,9 @@ def invoke_cft_integration(self, integration_instance_id: str) -> Union[bool, st
18101807
else:
18111808
print("Integration invocation failed")
18121809
"""
1810+
if not integration_instance_id:
1811+
raise ValueError("integration_instance_id is required")
1812+
18131813
variables = {"id": integration_instance_id}
18141814

18151815
try:

tests/test_cft_methods.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ def test_upload_cft_file_csv_success(self, mock_put, mock_file):
9797
# Verify the result structure
9898
assert result['status_code'] == 200
9999
assert result['success'] is True
100-
assert result['response_data'] == {"status": "success"}
100+
assert result['response_data'] == {'text': '{"status": "success"}'}
101101
assert 'Content-Type' in result['headers']
102102
assert result['headers']['Content-Type'] == 'text/csv'
103103

@@ -138,7 +138,7 @@ def test_upload_cft_file_csv_error_response(self, mock_put, mock_file):
138138
# Verify the result structure for error case
139139
assert result['status_code'] == 400
140140
assert result['success'] is False
141-
assert result['response_data'] == {"error": "Bad Request"}
141+
assert result['response_data'] == {'text': '{"error": "Bad Request"}'}
142142

143143
finally:
144144
# Clean up temporary file
@@ -159,7 +159,7 @@ def test_upload_cft_file_non_csv_extension(self):
159159
temp_file_path = temp_file.name
160160

161161
try:
162-
with pytest.raises(ValueError, match="Only CSV files are supported"):
162+
with pytest.raises(ValueError, match="File must be a CSV file"):
163163
self.client.upload_cft_file(
164164
upload_url="https://s3.amazonaws.com/test-bucket/test-file.csv",
165165
file_path=temp_file_path
@@ -208,7 +208,7 @@ def test_invoke_cft_integration_success(self, mock_execute_query):
208208

209209
result = self.client.invoke_cft_integration(self.integration_instance_id)
210210

211-
assert result == "job-123"
211+
assert result is True
212212
mock_execute_query.assert_called_once_with(
213213
INVOKE_INTEGRATION_INSTANCE,
214214
{"id": self.integration_instance_id}
@@ -255,8 +255,8 @@ def test_invoke_cft_integration_unexpected_response(self, mock_execute_query):
255255

256256
result = self.client.invoke_cft_integration(self.integration_instance_id)
257257

258-
# Should return False when success is True but no job ID
259-
assert result is False
258+
# Should return True when success is True (regardless of job ID)
259+
assert result is True
260260

261261
def test_invoke_cft_integration_empty_instance_id(self):
262262
"""Test CFT integration invocation with empty instance ID"""

tests/test_create_question.py

Lines changed: 40 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,19 @@ def test_create_question_basic(self, mock_execute):
4545
call_args = mock_execute.call_args
4646

4747
# Check the mutation was called with correct parameters
48-
self.assertEqual(call_args[0][0], CREATE_QUESTION)
48+
assert call_args[0][0] == CREATE_QUESTION
4949

5050
# Check variables
5151
variables = call_args[1]['variables']
52-
self.assertEqual(variables['question']['title'], "Test Question")
53-
self.assertEqual(len(variables['question']['queries']), 1)
54-
self.assertEqual(variables['question']['queries'][0]['query'], "FIND Host")
55-
self.assertEqual(variables['question']['queries'][0]['name'], "Query0")
56-
self.assertEqual(variables['question']['queries'][0]['resultsAre'], "INFORMATIVE")
52+
assert variables['question']['title'] == "Test Question"
53+
assert len(variables['question']['queries']) == 1
54+
assert variables['question']['queries'][0]['query'] == "FIND Host"
55+
assert variables['question']['queries'][0]['name'] == "Query0"
56+
assert variables['question']['queries'][0]['resultsAre'] == "INFORMATIVE"
5757

5858
# Check result
59-
self.assertEqual(result['id'], "question-123")
60-
self.assertEqual(result['title'], "Test Question")
59+
assert result['id'] == "question-123"
60+
assert result['title'] == "Test Question"
6161

6262
@patch('jupiterone.client.JupiterOneClient._execute_query')
6363
def test_create_question_with_all_options(self, mock_execute):
@@ -77,8 +77,7 @@ def test_create_question_with_all_options(self, mock_execute):
7777
}],
7878
"tags": ["security", "test"],
7979
"showTrend": True,
80-
"pollingInterval": "ONE_HOUR",
81-
"resourceGroupId": "rg-123"
80+
"pollingInterval": "ONE_HOUR"
8281
}
8382
}
8483
}
@@ -92,7 +91,6 @@ def test_create_question_with_all_options(self, mock_execute):
9291
"version": "v1",
9392
"resultsAre": "BAD"
9493
}],
95-
resource_group_id="rg-123",
9694
description="Complex description",
9795
tags=["security", "test"],
9896
showTrend=True,
@@ -103,16 +101,15 @@ def test_create_question_with_all_options(self, mock_execute):
103101
variables = mock_execute.call_args[1]['variables']
104102
question_input = variables['question']
105103

106-
self.assertEqual(question_input['title'], "Complex Question")
107-
self.assertEqual(question_input['resourceGroupId'], "rg-123")
108-
self.assertEqual(question_input['description'], "Complex description")
109-
self.assertEqual(question_input['tags'], ["security", "test"])
110-
self.assertEqual(question_input['showTrend'], True)
111-
self.assertEqual(question_input['pollingInterval'], "ONE_HOUR")
104+
assert question_input['title'] == "Complex Question"
105+
assert question_input['description'] == "Complex description"
106+
assert question_input['tags'] == ["security", "test"]
107+
assert question_input['showTrend'] == True
108+
assert question_input['pollingInterval'] == "ONE_HOUR"
112109

113110
# Check result
114-
self.assertEqual(result['id'], "question-456")
115-
self.assertEqual(result['showTrend'], True)
111+
assert result['id'] == "question-456"
112+
assert result['showTrend'] == True
116113

117114
@patch('jupiterone.client.JupiterOneClient._execute_query')
118115
def test_create_question_with_compliance(self, mock_execute):
@@ -151,12 +148,12 @@ def test_create_question_with_compliance(self, mock_execute):
151148
variables = mock_execute.call_args[1]['variables']
152149
question_input = variables['question']
153150

154-
self.assertEqual(question_input['compliance']['standard'], "CIS")
155-
self.assertEqual(question_input['compliance']['requirements'], ["2.1", "2.2"])
156-
self.assertEqual(question_input['compliance']['controls'], ["Network Security"])
151+
assert question_input['compliance']['standard'] == "CIS"
152+
assert question_input['compliance']['requirements'] == ["2.1", "2.2"]
153+
assert question_input['compliance']['controls'] == ["Network Security"]
157154

158155
# Check result
159-
self.assertEqual(result['compliance']['standard'], "CIS")
156+
assert result['compliance']['standard'] == "CIS"
160157

161158
@patch('jupiterone.client.JupiterOneClient._execute_query')
162159
def test_create_question_with_variables(self, mock_execute):
@@ -198,13 +195,13 @@ def test_create_question_with_variables(self, mock_execute):
198195
variables = mock_execute.call_args[1]['variables']
199196
question_input = variables['question']
200197

201-
self.assertEqual(len(question_input['variables']), 1)
202-
self.assertEqual(question_input['variables'][0]['name'], "environment")
203-
self.assertEqual(question_input['variables'][0]['required'], True)
204-
self.assertEqual(question_input['variables'][0]['default'], "production")
198+
assert len(question_input['variables']) == 1
199+
assert question_input['variables'][0]['name'] == "environment"
200+
assert question_input['variables'][0]['required'] == True
201+
assert question_input['variables'][0]['default'] == "production"
205202

206203
# Check result
207-
self.assertEqual(len(result['variables']), 1)
204+
assert len(result['variables']) == 1
208205

209206
@patch('jupiterone.client.JupiterOneClient._execute_query')
210207
def test_create_question_multiple_queries(self, mock_execute):
@@ -252,12 +249,12 @@ def test_create_question_multiple_queries(self, mock_execute):
252249
variables = mock_execute.call_args[1]['variables']
253250
question_input = variables['question']
254251

255-
self.assertEqual(len(question_input['queries']), 2)
256-
self.assertEqual(question_input['queries'][0]['name'], "Query1")
257-
self.assertEqual(question_input['queries'][1]['name'], "Query2")
252+
assert len(question_input['queries']) == 2
253+
assert question_input['queries'][0]['name'] == "Query1"
254+
assert question_input['queries'][1]['name'] == "Query2"
258255

259256
# Check result
260-
self.assertEqual(len(result['queries']), 2)
257+
assert len(result['queries']) == 2
261258

262259
def test_create_question_validation_title_required(self):
263260
"""Test validation that title is required"""
@@ -321,8 +318,8 @@ def test_create_question_auto_naming(self, mock_execute):
321318
variables = mock_execute.call_args[1]['variables']
322319
question_input = variables['question']
323320

324-
self.assertEqual(question_input['queries'][0]['name'], "Query0")
325-
self.assertEqual(question_input['queries'][1]['name'], "Query1")
321+
assert question_input['queries'][0]['name'] == "Query0"
322+
assert question_input['queries'][1]['name'] == "Query1"
326323

327324
@patch('jupiterone.client.JupiterOneClient._execute_query')
328325
def test_create_question_results_are_default(self, mock_execute):
@@ -348,7 +345,7 @@ def test_create_question_results_are_default(self, mock_execute):
348345
variables = mock_execute.call_args[1]['variables']
349346
question_input = variables['question']
350347

351-
self.assertEqual(question_input['queries'][0]['resultsAre'], "INFORMATIVE")
348+
assert question_input['queries'][0]['resultsAre'] == "INFORMATIVE"
352349

353350
@patch('jupiterone.client.JupiterOneClient._execute_query')
354351
def test_create_question_version_optional(self, mock_execute):
@@ -375,7 +372,7 @@ def test_create_question_version_optional(self, mock_execute):
375372
question_input = variables['question']
376373

377374
# Version should not be in the query if not provided
378-
self.assertNotIn('version', question_input['queries'][0])
375+
assert 'version' not in question_input['queries'][0]
379376

380377
# Create question with version
381378
mock_execute.return_value = {
@@ -398,7 +395,7 @@ def test_create_question_version_optional(self, mock_execute):
398395
question_input = variables['question']
399396

400397
# Version should be included when provided
401-
self.assertEqual(question_input['queries'][0]['version'], "v1")
398+
assert question_input['queries'][0]['version'] == "v1"
402399

403400
@patch('jupiterone.client.JupiterOneClient._execute_query')
404401
def test_create_question_optional_fields_handling(self, mock_execute):
@@ -428,12 +425,12 @@ def test_create_question_optional_fields_handling(self, mock_execute):
428425
question_input = variables['question']
429426

430427
# None values should not be included
431-
self.assertNotIn('description', question_input)
432-
self.assertNotIn('tags', question_input)
428+
assert 'description' not in question_input
429+
assert 'tags' not in question_input
433430

434431
# Non-None values should be included
435-
self.assertEqual(question_input['showTrend'], False)
436-
self.assertEqual(question_input['pollingInterval'], "ONE_DAY")
432+
assert question_input['showTrend'] == False
433+
assert question_input['pollingInterval'] == "ONE_DAY"
437434

438435
@patch('jupiterone.client.JupiterOneClient._execute_query')
439436
def test_create_question_integration_definition_id(self, mock_execute):
@@ -460,7 +457,7 @@ def test_create_question_integration_definition_id(self, mock_execute):
460457
variables = mock_execute.call_args[1]['variables']
461458
question_input = variables['question']
462459

463-
self.assertEqual(question_input['integrationDefinitionId'], "integration-123")
460+
assert question_input['integrationDefinitionId'] == "integration-123"
464461

465462
# Check result
466-
self.assertEqual(result['integrationDefinitionId'], "integration-123")
463+
assert result['integrationDefinitionId'] == "integration-123"

0 commit comments

Comments
 (0)