Candidate Push Models
Overview
The Candidate Push models provide a structured way to manage configuration commits in Palo Alto Networks' Strata Cloud Manager. These models handle the validation and processing of commit requests, including folder selection, admin authorization, and commit descriptions.
Attributes
Request Model Attributes
Attribute | Type | Required | Default | Description |
---|---|---|---|---|
folders | List[str] | Yes | None | List of folders to commit changes from |
admin | List[str] | Yes | None | List of admin email addresses for authorization |
description | str | Yes | None | Description of commit changes. Max length: 255 |
device_groups | List[str] | No | [] | List of device groups to commit changes to |
devices | List[str] | No | [] | List of devices to commit changes to |
include_uncommitted_changes | bool | No | False | Whether to include uncommitted changes |
Response Model Attributes
Attribute | Type | Required | Default | Description |
---|---|---|---|---|
success | bool | Yes | None | Whether commit operation was successfully started |
job_id | str | Yes | None | ID of the commit job |
id | str | Yes | None | ID of the commit job (alias for job_id) |
message | str | Yes | None | Detailed message about the commit operation |
Exceptions
The Candidate Push models can raise the following exceptions during validation:
- ValueError: Raised in several scenarios:
- When folders list is empty or contains invalid strings
- When admin list is empty or contains invalid email addresses
- When description validation fails (empty or exceeds max length)
- When device_groups or devices contain invalid entries
Model Validators
Folder Validation
The models enforce validation rules for the folders list:
from scm.models.operations import CandidatePushModel
# Initialize with valid folder datacommit_request = CandidatePushModel(
folders=["Texas", "Production"],
admin=["admin@example.com"],
description="Configuration update"
)
# Error: empty folders listtry:
invalid_request = CandidatePushModel(
folders=[],
admin=["admin@example.com"],
description="Test commit"
)
except ValueError as e:
print(e) # "At least one folder must be specified"
# Error: invalid folder stringstry:
invalid_request = CandidatePushModel(
folders=["", " "],
admin=["admin@example.com"],
description="Test commit"
)
except ValueError as e:
print(e) # "All folders must be non-empty strings"
# Initialize with valid folder datacommit_request = CandidatePushModel(
folders=["Texas", "Production"],
admin=["admin@example.com"],
description="Configuration update"
)
# Error: empty folders listtry:
invalid_request = CandidatePushModel(
folders=[],
admin=["admin@example.com"],
description="Test commit"
)
except ValueError as e:
print(e) # "At least one folder must be specified"
# Error: invalid folder stringstry:
invalid_request = CandidatePushModel(
folders=["", " "],
admin=["admin@example.com"],
description="Test commit"
)
except ValueError as e:
print(e) # "All folders must be non-empty strings"
Admin Validation
The models validate admin email addresses:
from scm.models.operations import CandidatePushModel
# Initialize with valid admin datacommit_request = CandidatePushModel(
folders=["Texas"],
admin=["admin@example.com"],
description="Configuration update"
)
# Special value "all" is allowed for all adminsall_admins_request = CandidatePushModel(
folders=["Texas"],
admin=["all"],
description="Configuration update"
)
# Error: empty admin listtry:
invalid_request = CandidatePushModel(
folders=["Production"],
admin=[],
description="Test commit"
)
except ValueError as e:
print(e) # "At least one admin must be specified"
# Error: invalid email addressestry:
invalid_request = CandidatePushModel(
folders=["Production"],
admin=["invalid-email", "also-invalid"],
description="Test commit"
)
except ValueError as e:
print(e) # "All admin entries must be valid email addresses"
# Initialize with valid admin datacommit_request = CandidatePushModel(
folders=["Texas"],
admin=["admin@example.com"],
description="Configuration update"
)
# Special value "all" is allowed for all adminsall_admins_request = CandidatePushModel(
folders=["Texas"],
admin=["all"],
description="Configuration update"
)
# Error: empty admin listtry:
invalid_request = CandidatePushModel(
folders=["Production"],
admin=[],
description="Test commit"
)
except ValueError as e:
print(e) # "At least one admin must be specified"
# Error: invalid email addressestry:
invalid_request = CandidatePushModel(
folders=["Production"],
admin=["invalid-email", "also-invalid"],
description="Test commit"
)
except ValueError as e:
print(e) # "All admin entries must be valid email addresses"
Description Validation
The models validate the commit description:
from scm.models.operations import CandidatePushModel
# Initialize with valid descriptioncommit_request = CandidatePushModel(
folders=["Texas"],
admin=["admin@example.com"],
description="Configuration update"
)
# Error: empty descriptiontry:
invalid_request = CandidatePushModel(
folders=["Production"],
admin=["admin@example.com"],
description=""
)
except ValueError as e:
print(e) # "Description cannot be empty"
# Error: description too longtry:
invalid_request = CandidatePushModel(
folders=["Production"],
admin=["admin@example.com"],
description="A" * 300 # Over 255 characters
)
except ValueError as e:
print(e) # "Description cannot exceed 255 characters"
# Initialize with valid descriptioncommit_request = CandidatePushModel(
folders=["Texas"],
admin=["admin@example.com"],
description="Configuration update"
)
# Error: empty descriptiontry:
invalid_request = CandidatePushModel(
folders=["Production"],
admin=["admin@example.com"],
description=""
)
except ValueError as e:
print(e) # "Description cannot be empty"
# Error: description too longtry:
invalid_request = CandidatePushModel(
folders=["Production"],
admin=["admin@example.com"],
description="A" * 300 # Over 255 characters
)
except ValueError as e:
print(e) # "Description cannot exceed 255 characters"
Usage Examples
Creating a Commit Request
from scm.client import ScmClient
from scm.models.operations import CandidatePushModel
# Initialize clientclient = ScmClient(
client_id="your_client_id",
client_secret="your_client_secret",
tsg_id="your_tsg_id"
)
# Create a commit request using a dictionarycommit_dict = {
"folders": ["Texas", "Production"],
"admin": ["admin@example.com"],
"description": "Updating security policies",
"include_uncommitted_changes": True
}
response = client.operations.commit(commit_dict)
# Using model directlycommit_request = CandidatePushModel(
folders=["Texas", "Production"],
admin=["admin@example.com"],
description="Updating security policies",
include_uncommitted_changes=True
)
payload = commit_request.model_dump(exclude_unset=True)
response = client.operations.commit(payload)
print(f"Commit job started with ID: {response.job_id}")
from scm.models.operations import CandidatePushModel
# Initialize clientclient = ScmClient(
client_id="your_client_id",
client_secret="your_client_secret",
tsg_id="your_tsg_id"
)
# Create a commit request using a dictionarycommit_dict = {
"folders": ["Texas", "Production"],
"admin": ["admin@example.com"],
"description": "Updating security policies",
"include_uncommitted_changes": True
}
response = client.operations.commit(commit_dict)
# Using model directlycommit_request = CandidatePushModel(
folders=["Texas", "Production"],
admin=["admin@example.com"],
description="Updating security policies",
include_uncommitted_changes=True
)
payload = commit_request.model_dump(exclude_unset=True)
response = client.operations.commit(payload)
print(f"Commit job started with ID: {response.job_id}")
Handling the Response
from scm.client import ScmClient
from scm.models.operations import CandidatePushResponseModel
# Initialize clientclient = ScmClient(
client_id="your_client_id",
client_secret="your_client_secret",
tsg_id="your_tsg_id"
)
# Create a commit requestcommit_dict = {
"folders": ["Texas"],
"admin": ["admin@example.com"],
"description": "Updating security policies"
}
response = client.operations.commit(commit_dict)
# Process the responseif response.success:
print(f"Commit job {response.job_id} started successfully")
print(f"Message: {response.message}")
# Track the job status
job_status = client.operations.get_job_status(response.job_id)
print(f"Job status: {job_status.data[0].status_str}")
else:
print(f"Commit failed: {response.message}")
from scm.models.operations import CandidatePushResponseModel
# Initialize clientclient = ScmClient(
client_id="your_client_id",
client_secret="your_client_secret",
tsg_id="your_tsg_id"
)
# Create a commit requestcommit_dict = {
"folders": ["Texas"],
"admin": ["admin@example.com"],
"description": "Updating security policies"
}
response = client.operations.commit(commit_dict)
# Process the responseif response.success:
print(f"Commit job {response.job_id} started successfully")
print(f"Message: {response.message}")
# Track the job status
job_status = client.operations.get_job_status(response.job_id)
print(f"Job status: {job_status.data[0].status_str}")
else:
print(f"Commit failed: {response.message}")
Commit with Unified Client
from scm.client import ScmClient
import time
# Initialize clientclient = ScmClient(
client_id="your_client_id",
client_secret="your_client_secret",
tsg_id="your_tsg_id"
)
# Perform configuration updatessecurity_rule = client.security_rule.create({
"name": "allow-web-traffic",
"source": ["any"],
"destination": ["any"],
"application": ["web-browsing"],
"service": ["application-default"],
"action": "allow",
"folder": "Security Policies"
})
# Commit the changescommit_result = client.operations.commit(
folders=["Security Policies"],
description="Added web traffic rule",
admin=["admin@example.com"]
)
# Monitor the job asynchronouslyjob_id = commit_result.job_id
print(f"Commit job initiated with ID: {job_id}")
# Poll for job completionstatus = "PENDING"
while status not in ["FIN", "FAIL"]:
time.sleep(5)
job_result = client.operations.get_job_status(job_id)
status = job_result.data[0].job_status
print(f"Current status: {job_result.data[0].status_str}")
if status == "FIN":
print("Commit completed successfully")
else:
print(f"Commit failed: {job_result.data[0].summary}")
import time
# Initialize clientclient = ScmClient(
client_id="your_client_id",
client_secret="your_client_secret",
tsg_id="your_tsg_id"
)
# Perform configuration updatessecurity_rule = client.security_rule.create({
"name": "allow-web-traffic",
"source": ["any"],
"destination": ["any"],
"application": ["web-browsing"],
"service": ["application-default"],
"action": "allow",
"folder": "Security Policies"
})
# Commit the changescommit_result = client.operations.commit(
folders=["Security Policies"],
description="Added web traffic rule",
admin=["admin@example.com"]
)
# Monitor the job asynchronouslyjob_id = commit_result.job_id
print(f"Commit job initiated with ID: {job_id}")
# Poll for job completionstatus = "PENDING"
while status not in ["FIN", "FAIL"]:
time.sleep(5)
job_result = client.operations.get_job_status(job_id)
status = job_result.data[0].job_status
print(f"Current status: {job_result.data[0].status_str}")
if status == "FIN":
print("Commit completed successfully")
else:
print(f"Commit failed: {job_result.data[0].summary}")