Automating Juniper Apstra: From Raw API to Terraform
Photo by Homa Appliances / Unsplash

Automating Juniper Apstra: From Raw API to Terraform

Introduction

When automating Juniper Apstra's Intent-Based Networking (IBN) platform, teams have several approaches: using the REST API directly, leveraging the Python SDK (pyapstra), using Ansible with the URI module, or implementing Infrastructure as Code with the Terraform provider. Let's explore each approach.

The Raw API Approach

What It Is

Direct interaction with Apstra's RESTful API endpoints, handling authentication, requests, and responses manually.

Example Implementation


import requests
import json

def create_blueprint():
    # Authentication
    auth_response = requests.post(
        'https://apstra.example.com/api/aaa/login',
        json={
            'username': 'admin',
            'password': 'password'
        },
        verify=False  # For self-signed certs
    )
    token = auth_response.json()['token']
    
    # Create blueprint
    headers = {
        'AuthToken': token,
        'Content-Type': 'application/json'
    }
    
    blueprint_data = {
        "label": "dc1_blueprint",
        "reference_architecture": "dc_template",
        "init_type": "template"
    }
    
    response = requests.post(
        'https://apstra.example.com/api/blueprints',
        headers=headers,
        json=blueprint_data
    )
    return response.json()
    

The Python SDK Approach

What It Is

The official Juniper Apstra Python SDK provides a Pythonic interface to Apstra's functionality, handling authentication and API interactions.

Pros (Additional to previous)

  • Purpose-built for Apstra
  • Handles authentication automatically
  • Built-in error handling for Apstra-specific cases
  • Maintains session management

Example Implementation

from pyapstra.client import Client

def create_blueprint():
    # Initialize client
    client = Client(
        server="apstra.example.com",
        port=443,
        user="admin",
        password="password",
        verify=False
    )
    
    # Create blueprint
    blueprint = client.blueprints.create(
        label="dc1_blueprint",
        reference_architecture="dc_template",
        init_type="template"
    )
    
    return blueprint.id

The Ansible Approach

What It Is

Using Ansible's URI module to interact with Apstra's API in a declarative way through playbooks.

Additional Pros

  • Integrates with existing Ansible workflows
  • Can combine with other network automation tasks
  • Reusable playbooks for common tasks

Example Implementation

---
- name: Create Apstra Blueprint
  hosts: localhost
  gather_facts: no
  vars:
    apstra_host: "https://apstra.example.com"
    blueprint_name: "dc1_blueprint"
    
  tasks:
    - name: Login to Apstra
      uri:
        url: "{{ apstra_host }}/api/aaa/login"
        method: POST
        body_format: json
        body:
          username: "admin"
          password: "password"
        validate_certs: no
      register: login_response
      
    - name: Create Blueprint
      uri:
        url: "{{ apstra_host }}/api/blueprints"
        method: POST
        body_format: json
        body:
          label: "{{ blueprint_name }}"
          reference_architecture: "dc_template"
          init_type: "template"
        headers:
          AuthToken: "{{ login_response.json.token }}"
        validate_certs: no
      register: blueprint_response

The Terraform Approach

What It Is

Using Juniper's official Terraform provider for Apstra to manage infrastructure as code.

Additional Pros

  • Purpose-built for Apstra
  • Handles API complexity
  • Built-in state management for Apstra resources
  • Declarative approach to network intent

Example Implementation

# Configure the Apstra Provider
provider "apstra" {
  url = "https://apstra.example.com"
  username = "admin"
  password = "password"
  tls_validation_disabled = true
}

# Create a Blueprint
resource "apstra_datacenter_blueprint" "dc1" {
  name = "dc1_blueprint"
  template = "dc_template"
  
  # Optional: Configure additional blueprint properties
  networks = {
    "spine_leaf_link" = {
      ipv4_enabled = true
      ipv4_pool = "spine_leaf_pool"
    }
  }
}

# Deploy the Blueprint
resource "apstra_blueprint_deployment" "dc1_deploy" {
  blueprint_id = apstra_datacenter_blueprint.dc1.id
  comment     = "Deployed via Terraform"
}

Real-World Decision Making for Apstra Automation

Consider these Apstra-specific factors when choosing:

  1. Use Case Complexity

    • Simple blueprint creation → Python SDK
    • Complex datacenter automation → Terraform
    • One-off tasks → Ansible
    • Custom integration needs → Raw API
  2. Team Skills

    • Network engineers familiar with Python → SDK
    • Infrastructure teams using Terraform → Terraform provider
    • Existing Ansible automation → Ansible URI approach
  3. Scale of Operation

    • Single datacenter → Any approach
    • Multiple datacenters → Terraform
    • Mixed with other automation → Ansible
    • Custom workflow needs → SDK
  4. Change Management Requirements

    • Strict change control → Terraform (plan/apply workflow)
    • Ad-hoc changes → SDK or Ansible
    • Integration with other systems → API
    • Audit requirements → Terraform

Conclusion

For Apstra automation, each approach has its merits:

  • Terraform provides the most robust infrastructure-as-code experience
  • The Python SDK offers the most programmatic control
  • Ansible integrates well with existing network automation
  • The raw API provides the most flexibility

Many organizations use a combination:

  • Terraform for infrastructure and blueprint management
  • SDK for custom tooling and integration
  • Ansible for operational tasks
  • API for specialized needs

The key is choosing the right tool for your specific requirements while maintaining consistency and reliability in your network automation strategy.