Skip to content

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"

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"

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"

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}")

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}")

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}")