BIG-IP Next – Introduction to the Blueprints API

If you have ever attempted to automate the BIG-IP configuration, you are probably familiar with F5’s AS3 extension. Although AS3 is supported in BIG-IP Next, there is another API that might be the better option if you haven’t started your migration journey up until now. This is called the Blueprints API. In this article, I want to show you how to use it to automate your applications with AS3. 

 

Overview

When you use the BIG-IP Next GUI, you instantly see the benefits of having a centrally managed configuration across all your BIG-IP instances. The steps to create an application service in the GUI now have a siloed setup where you define 4 main sections separately:

  1. Application Properties
  2. Virtual Server Properties
  3. Pool Properties
  4. Deployment Properties

Each one of these sections allows you to adjust areas of your application service while still having a way to manage configurations across multiple BIG-IP instances. In other words, you can define one pool under the pool properties, but still have different pool members under the deployment properties for each of your BIG-IP instances. This creates a centrally managed application service that does not require the exact same configuration in each environment.

When you perform these tasks in the GUI, BIG-IP Next is generating its own API calls internally. It takes each of your configuration items outlined in the 4 sections above and defines the application service as a Blueprint. This Blueprint is then used to modify anything about the configuration/deployment moving forward. If you aren’t a fan of using a GUI and you are trying to automate, this same exact API is exposed to you as well. This means we get to use the same centrally managed configuration in our API calls. It also means that we can easily automate existing application services by simply using the API to manage them moving forward.

So what does this Blueprint API look like? Below is sample JSON used to create a Blueprint called “bobs-blueprint”:

{
    "name":"bobs-blueprint",
    "set_name": "Examples",
    "template_name": "http",
    "parameters": {
        "application_description": "",
        "application_name": "bobs-blueprint",
        "enable_Global_Resiliency": false,
        "pools": [
            {
                "loadBalancingMode": "round-robin",
                "monitorType": [
                    "http"
                ],
                "poolName": "juice",
                "servicePort": 8080
            }
        ],
        "virtuals": [
            {
                "FastL4_TOS": 0,
                "FastL4_idleTimeout": 600,
                "FastL4_looseClose": true,
                "FastL4_looseInitialization": true,
                "FastL4_pvaAcceleration": "full",
                "FastL4_pvaDynamicClientPackets": 1,
                "FastL4_pvaDynamicServerPackets": 0,
                "FastL4_resetOnTimeout": true,
                "FastL4_tcpCloseTimeout": 43200,
                "FastL4_tcpHandshakeTimeout": 43200,
                "InspectionServicesEnum": [],
                "TCP_idle_timeout": 60,
                "UDP_idle_timeout": 60,
                "ciphers": "DEFAULT",
                "ciphers_server": "DEFAULT",
                "enable_Access": false,
                "enable_FastL4": false,
                "enable_FastL4_DSR": false,
                "enable_HTTP2_Profile": false,
                "enable_HTTP_Profile": false,
                "enable_InspectionServices": false,
                "enable_SsloPolicy": false,
                "enable_TCP_Profile": false,
                "enable_TLS_Client": false,
                "enable_TLS_Server": false,
                "enable_UDP_Profile": false,
                "enable_WAF": false,
                "enable_iRules": false,
                "enable_mirroring": true,
                "enable_snat": true,
                "iRulesEnum": [],
                "multiCertificatesEnum": [],
                "perRequestAccessPolicyEnum": "",
                "pool": "juice",
                "snat_addresses": [],
                "snat_automap": true,
                "tls_c_1_1": false,
                "tls_c_1_2": true,
                "tls_c_1_3": false,
                "tls_s_1_2": true,
                "tls_s_1_3": false,
                "trustCACertificate": "",
                "virtualName": "bobs-vs",
                "virtualPort": 80
            }
        ]
    }
}

 

As you can see, the structure of this JSON is siloed in a very similar way to the GUI:

Note: For those readers who are wondering where the Deployment section is, that is handled in a separate API call after the blueprint has been created. I’ll discuss that in more detail later.

In the sections below, I’ll review a few of the API endpoints you can use with some steps on how to perform the following common tasks:

  • Viewing an existing Blueprint
  • Creating a new Blueprint
  • Deploying a Blueprint

 

Viewing an Existing Blueprint

Before we start creating a new Blueprint from scratch, it is probably a good idea to explain how we can view a list of our current Blueprints. To do so, we simply make a GET request to the following API endpoint:

GET https://{{bigip_next_cm_mgmt_ip}}/api/v1/spaces/default/appsvcs/blueprints

 

This will return a list of every Blueprint created by the GUI and/or API. Below is an example output:

{
    "_embedded": {
        "appsvcs": [
            {
                "_links": {
                    "self": {
                        "href": "/api/v1/spaces/default/appsvcs/blueprints//3f2ef264-cf09-45c8-a925-f2c8fccf09f6"
                    }
                },
                "created": "2024-06-25T13:32:22.160399Z",
                "deployments": [
                    {
                        "id": "1e5f9c06-8800-4ab7-ad5e-648d55b83b68",
                        "instance_id": "ce179e66-b075-4068-bc4e-8e212954da49",
                        "target": {
                            "address": "10.2.1.3"
                        },
                        "parameters": {
                            "pools": [
                                {
                                    "isServicePool": false,
                                    "poolMembers": [
                                        {
                                            "address": "10.1.3.100",
                                            "name": "old"
                                        },
                                        {
                                            "address": "10.2.3.100",
                                            "name": "new"
                                        }
                                    ],
                                    "poolName": "juice"
                                }
                            ],
                            "virtuals": [
                                {
                                    "allow_networks": [],
                                    "enable_allow_networks": false,
                                    "virtualAddress": "10.2.2.11",
                                    "virtualName": "juice-shop"
                                }
                            ]
                        },
                        "last_successful_deploy_time": "2024-06-25T17:46:00.193649Z",
                        "modified": "2024-06-25T17:46:00.193649Z",
                        "last_record": {
                            "id": "cb6a06a1-c66d-41c3-a747-9a27b101a0f1",
                            "task_id": "6a65642d-810b-4194-9693-91a15f6d1ef0",
                            "created_application_path": "/applications/tenantSrLEVevFQnWwXT90590F3USQ/juice-shop",
                            "start_time": "2024-06-25T17:45:55.392732Z",
                            "end_time": "2024-06-25T17:46:00.193649Z",
                            "status": "completed"
                        }
                    },
                    {
                        "id": "001e14e8-7900-482a-bdd4-aca35967a5cc",
                        "instance_id": "0546acf5-3b88-422d-a948-28bbf0973212",
                        "target": {
                            "address": "10.2.1.4"
                        },
                        "parameters": {
                            "pools": [
                                {
                                    "isServicePool": false,
                                    "poolMembers": [
                                        {
                                            "address": "10.1.3.100",
                                            "name": "old"
                                        },
                                        {
                                            "address": "10.2.3.100",
                                            "name": "new"
                                        }
                                    ],
                                    "poolName": "juice"
                                }
                            ],
                            "virtuals": [
                                {
                                    "allow_networks": [],
                                    "enable_allow_networks": false,
                                    "virtualAddress": "10.2.2.12",
                                    "virtualName": "juice-shop"
                                }
                            ]
                        },
                        "last_successful_deploy_time": "2024-06-25T17:46:07.94836Z",
                        "modified": "2024-06-25T17:46:07.94836Z",
                        "last_record": {
                            "id": "8a8a29be-e56b-4ef1-bf6a-92f7ccc9e9b7",
                            "task_id": "0632cc18-9f0f-4a5e-875a-0d769b02e19b",
                            "created_application_path": "/applications/tenantSrLEVevFQnWwXT90590F3USQ/juice-shop",
                            "start_time": "2024-06-25T17:45:55.406377Z",
                            "end_time": "2024-06-25T17:46:07.94836Z",
                            "status": "completed"
                        }
                    }
                ],
                "deployments_count": {
                    "total": 2,
                    "completed": 2
                },
                "description": "",
                "fqdn": "",
                "gslb_enabled": false,
                "id": "3f2ef264-cf09-45c8-a925-f2c8fccf09f6",
                "modified": "2024-06-25T17:32:09.174243Z",
                "name": "juice-shop",
                "set_name": "Examples",
                "successful_instances": 2,
                "template_name": "http",
                "tenant_name": "tenantSrLEVevFQnWwXT90590F3USQ",
                "type": "FAST"
            }
        ]
    },
    "_links": {
        "self": {
            "href": "/api/v1/spaces/default/appsvcs/blueprints/"
        }
    },
    "count": 1,
    "total": 1
}

 

In the example above, I only have one Blueprint in my BIG-IP Next CM instance. If we look deeper into the output, we can start to see some detail around the configuration parameters as well as the deployment parameters for each BIG-IP. There is also an ID field in the JSON that we can use to reference a specific Blueprint. In the example above, we have:

"id": "3f2ef264-cf09-45c8-a925-f2c8fccf09f6"

 

This is important because as we start to modify, deploy, or delete our existing blueprints, we will need this ID to be able to make changes. We can also use this ID to view more detail on a specific Blueprint rather than an entire list of all Blueprints. To do so, we simply follow make a request to the endpoint below:

GET https://{{bigip_next_cm_mgmt_ip}}/api/v1/spaces/default/appsvcs/blueprints/{{Blueprint_id}}

 

In our example, this would be:

GET https://{{bigip_next_cm_mgmt_ip}}/api/v1/spaces/default/appsvcs/blueprints/3f2ef264-cf09-45c8-a925-f2c8fccf09f6 

 

The output from this API call provides robust detail on the Blueprint. It is probably too much detail to paste in an article like this, but there are some examples here if interested: https://clouddocs.f5.com/products/bigip-next/mgmt-api/latest/ApiReferences/bigip_public_api_ref/r_openapi-next.html#tag/Application-Services/operation/GetApplicationByID

Viewing a Blueprint like this can provide us with the latest configuration of our application service so that we can ensure we are using the most up-to-date files. It also can provide us with some templates/example configurations that we can use to create new application services moving forward. 

 

Creating a new Blueprint

Now that we have a pretty good understanding of the JSON structure and we know how to view some examples of Blueprints that have already been created, we can simply use them as a reference and create our own Blueprint from scratch. The basic format for creating a new Blueprint is below:

{
    "name": <blueprint_name>,
    "set_name": <template_set>
    "template_name": <template_name>,
    "parameters": {
        "application_description": <simple_description>,
        "application_name": <blueprint_name>,
        "enable_Global_Resiliency": false,
        "pools": [
            {
	          <pool_configuration_parameters>
            }
        ],
        "virtuals": [
            {
	          <virtual_server_configuration parameters>
            }
        ]
    }
}

 

More detail on each of the variable values below:

  • <blueprint_name> - This is the name you choose for your blueprint. I generally recommend this name be the same in both the “name” field and the “application_name” field which is why in the JSON above you’ll see this in both.
  • <template_set> - This is going to be the template set containing your FAST template. If you are using the default templates provided to you, this value would be “Examples”
  • <template_name> - This is the specific FAST template you are going to use for the configuration. If you are using the default template provided to you, this value would be “http”
  • <simple_description> - This can be any short description you would like to use for your application service.
  • <pool_configuration_parameters> - This will be the list of parameters that you are going to define for your pool. You do not have to fill in every single value if the FAST template contains values for that field. 
  • <virtual_server_configuration parameters> - This will be the list of parameters that you are going to define for your virtual server. You do not have to fill in every single value if the FAST template contains values for that field. 

Important Note: When creating your JSON, you will be defining a FAST template to use along with your application service (just like you would in the GUI). This means that you do not have to fill out every value under your pool and virtual server configuration. It will take in the values provided from your FAST template.

With our guide above, we can now make a new Blueprint for the “bobs-blueprint” example I referenced earlier:

{
    "name":"bobs-blueprint",
    "set_name": "Examples",
    "template_name": "http",
    "parameters": {
        "application_description":"This is a test of the blueprints api",
        "application_name": "bobs-blueprint",
        "pools": [
            {
                "loadBalancingMode": "round-robin",
                "monitorType": [
                    "http"
                ],
                "poolName": "juice_pool",
                "servicePort": 3000
            }
        ],
        "virtuals": [
            {
                "pool": "juice_pool",
                "virtualName": "blueprint_vs",
                "virtualPort": 80
            }
        ]
    }
}

 

As you can see, this is a much more condensed version of the original JSON I had for the example shown in the beginning of this article. Again, this is because we are referencing the FAST template “Examples/http” and taking in those values to configure the rest of the application service.

With our newly created JSON, the last step to creating this Blueprint is to send this in a POST request to the following API endpoint:

POST https://{{bigip_next_cm_mgmt_ip}}/api/v1/spaces/default/appsvcs/blueprints

 

After sending our POST, you'll notice we are given the "id" of the Blueprint in the response. As mentioned above, we can use this ID to modify, deploy, etc. 

{
    "_links": {
        "self": {
            "href": "/api/v1/spaces/default/appsvcs/blueprints/9c35a614-65ac-4d18-8082-589ea9bc78d9/deployments"
        }
    },
    "deployments": [
        {
            "deploymentID": "1a153f44-acaf-4487-81c7-61b8b5498627",
            "instanceID": "4ef739d1-9ef1-4eb7-a5bb-36c6d1334b16",
            "status": "pending",
            "taskID": "518534c8-9368-48dd-b399-94f55e72d5a7",
            "task_type": "CREATE"
        },
        {
            "deploymentID": "82ca8d6d-dbfd-43a8-a604-43f170d9f190",
            "instanceID": "0546acf5-3b88-422d-a948-28bbf0973212",
            "status": "pending",
            "taskID": "7ea24157-1412-4963-9560-56fb0ab78d8c",
            "task_type": "CREATE"
        }
    ],
    "id": "9c35a614-65ac-4d18-8082-589ea9bc78d9"
}

 

Now that the Blueprint has been created, we can go into our BIG-IP Next CM GUI and see our newly created application service:

 

You’ll notice that our newly created application service is in Draft mode. This is because we have not deployed the service yet. We’ll discuss that in the next section.

 

Deploying a Blueprint

Once we have our Blueprint created, the final step is to configure the deployment. As discussed above, this is done through a separate API Call. The format for a deployment is as follows:

{
    "deployments": [
        {
            "parameters": {
                "pools": [
                    {
                        "poolName": <pool_name>
                        "poolMembers": [
                            {
                                "name": <node1_name>,
                                "address": <node1_ip_address>
                            },
                            {
                                "name": <node2_name>,
                                "address": <node2_ip_address>
                            }
                        ]
                    }
                ],
                "virtuals": [
                    {
                        "virtualName": <virtual_server_name>,
                        "virtualAddress": <virtual_server_ip_address>
                    }
                ]
            },
            "target": {
                "address": <bigip_instance_ip_address>
            },
            "allow_overwrite": true
        }
    ]
}

 

Keep in mind that some of these values above are referencing names from your Blueprint configuration. These names need to be exactly the same. See below for more detail on each of these values:

  • <pool_name> - This references the pool from your Blueprint. This value must match what was used for “poolName” in the pool configuration of the Blueprint.
  • <node1_name> - This is any name you choose to describe your node in the pool
  • <node1_ip_address> - This is the specific IP address for your node
  • <node2_name> - If you are using more than one node, this would be the name you choose to represent your second node in the pool. This format can repeat for 3 nodes, 4 nodes, etc.
  • <node2_ip_address> - If you are using more than one node, this would be the IP address of your second node. This format can repeat for 3 nodes, 4 nodes, etc.
  • <virtual_server_name> - This references the virtual server from your Blueprint. This value must match what was used for “virtualName” in the virtuals configuration of the Blueprint.
  • <virtual_server_ip_address> - This would be the IP address of the Virtual Server being deployed on the BIG-IP
  • <bigip_instance_ip_address> - This is the IP address of the BIG-IP instance we are deploying to

Important Note: If you are deploying the same application to more than one BIG-IP instance, you can include multiple deployment blocks in your API call. 

Using the format above, we can now create our deployment for “bobs-blueprint”:

{
    "deployments": [
        {
            "parameters": {
                "pools": [
                    {
                        "poolName": "juice_pool",
                        "poolMembers": [
                            {
                                "name": "node1",
                                "address": "10.1.3.100"
                            }
                        ]
                    }
                ],
                "virtuals": [
                    {
                        "virtualName": "blueprint_vs",
                        "virtualAddress": "10.2.2.15"
                    }
                ]
            },
            "target": {
                "address": "10.2.1.3"
            },
            "allow_overwrite": true
        },
        {
            "parameters": {
                "pools": [
                    {
                        "poolName": "juice_pool",
                        "poolMembers": [
                            {
                                "name": "node1",
                                "address": "10.2.3.100"
                            }
                        ]
                    }
                ],
                "virtuals": [
                    {
                        "virtualName": "blueprint_vs",
                        "virtualAddress": "10.2.2.20"
                    }
                ]
            },
            "target": {
                "address": "10.2.1.4"
            },
            "allow_overwrite": true
        }
    ]
}

In this example deployment, I am deploying to two separate BIG-IP instances (10.2.1.3 and 10.2.1.4). This is where we can really start to see the value of the Blueprints API. With this structure, I can use the same pool and virtual server setup from our Blueprint, while still using different Virtual Server and Node IP addresses for the deployment at each instance. All of this is done with one API call.

The final step is to send this in a POST request to our deployments endpoint. The endpoint is very similar to viewing a blueprint as it uses our same Blueprint ID. See the format below:

POST https://{{bigip_next_cm_mgmt_ip}}/api/v1/spaces/default/appsvcs/blueprints/{{Blueprint_id}}/deployments

 

Using the ID from the response we received after creating our example blueprint, our endpoint would be:

POST https://{{bigip_next_cm_mgmt_ip}}/api/v1/spaces/default/appsvcs/blueprints/9c35a614-65ac-4d18-8082-589ea9bc78d9/deployments 

 

After sending our POST, we can go back to the BIG-IP Next CM GUI and see our application service is no longer considered a Draft. If we click into the application service, we’ll see our two deployments are up and healthy:

Conclusion

Hopefully after reading this article, you can see the value of using the Blueprints API for your automation. I think as an alternative to other automation methods, this can provide benefits such as:

  • Same centrally managed format/structure as GUI created applications
  • Since the BIG-IP Next CM GUI is already creating these JSON files under the hood, we can easily automate existing applications by using the Blueprints API for them moving forward
  • Deployments are handled separately from your application configuration
  • You can deploy your application service to multiple BIG-IP instances at once
  • Combining the Blueprints API with FAST templates allows you make application on-boarding much more streamlined. 

If you liked this article and are looking for more information our our Blueprints API, please visit the API documentation here: https://clouddocs.f5.com/products/bigip-next/mgmt-api/latest/ApiReferences/bigip_public_api_ref/r_openapi-next.html#tag/Application-Services/operation/GetAllApplications

Published Sep 30, 2024
Version 1.0
  • Thanks for sharing this.

    Blueprints are filling out existing FAST-Templates? Do I understand it correctly?

    • Michael_Everett's avatar
      Michael_Everett
      Icon for Employee rankEmployee

      Yes, that is correct. The blueprints API pushes the inputs provided into the declaration into the referenced template (in this case, a FAST template). You can also perform lightweight customization of the template at deployment time using the parameters block. In Bob's example above, the only customization on a per-deployment basis was the virtual server and pool details, but you can also make other customizations.