Testing a BIG-IP AS3 declaration

There are two primary ways to test an AS3 declaration for compatibility with BIG-IP Next: the action=dry-run and validation=lazy query parameters. The main difference between the two is that dry-run validates – but does not deploy – any configuration while lazy validation attempts to deploy the configuration, noting any properties that were ignored.

These examples use a declaration from the BIG-IP AS3 Core example declarations, because it contains items not currently supported in BIG-IP Next.

Also see Using Debug Mode in Application Troubleshooting for an additional option for testing declarations.

Using the dry-run query parameter

The dry-run query parameter sends the declaration through all validation checks but does not attempt to deploy the configuration on the target device. You are able to tell if certain properties or classes in the declaration were not accepted by looking at any errors displayed in the response. Even if there are no errors, the configuration is not deployed to BIG-IP Next.

To use this parameter, use the following syntax with the HTTP POST method: https://{{host}}/api/v1/application-services/declare?action=dry-run

The following is a snippet from a successful dry-run:

{
    "code": 200,
    "message": "success",
    "declaration": {
        "class": "ADC",
        "schemaVersion": "3.0.0",
        ...
    }
}

The following is a snippet from an unsuccessful dry-run, where you can see that the DOS_Profile class is not yet supported in AS3 on BIG-IP Next:

    {
        "code": 422,
        "message": "declaration is invalid",
        "errors": [
            {
                "instancePath": "/class",
                "schemaPath": "#/properties/class/const",
                "keyword": "const",
                "params": {
                    "allowedValue": "AS3"
                },
                "message": "must be equal to constant"
            },
            {
                "instancePath": "/Sample_DOS_NetVector/Application/DOS_NetVector/class",
                "schemaPath": "#/properties/class/enum",
                "keyword": "enum",
                "params": {
                    "allowedValues": [
                        "Analytics_Profile",
                        "Analytics_TCP_Profile",
                        "Certificate",
                        "HTTP_Compress",
                        "HTTP_Acceleration_Profile",
                        "HTTP2_Profile",
                        "iRule",
                        "L4_Profile",
                        "Monitor",
                        "Multiplex_Profile",
                        "Persist",
                        "Pool",
                        "Service_HTTP",
                        "Service_HTTPS",
                        "Service_Intercept_Inline",
                        "Service_L4",
                        "Service_TCP",
                        "Service_UDP",
                        "Service_Tap",
                        "SNAT_Pool",
                        "TCP_Profile",
                        "TLS_Client",
                        "TLS_Server",
                        "UDP_Profile",
                        "WAF_Policy"
                    ]
                },
                "message": "must be equal to one of the allowed values"
            },
            ...
        ]
    }

You can also use the traceResponse property with dry-run for more visibility into what AS3 would be configuring. The traceResponse property is part of the Controls class, and can either be set at the ADC class level (to include all tenants), or the tenant class level to include only a specific tenant in the trace.

For example, if you send the following HTTP canonical example with the Controls class to https://{{host}}/api/v1/application-services/declare?action=dry-run

   {
        "class": "ADC",
        "id": "adc-http-canonical",
        "schemaVersion": "3.0.0",
        "controls": {
            "class": "Controls",
            "logLevel": "debug",
            "traceResponse": true
        },
        "my_tenant": {
            "class": "Tenant",
            "my_app": {
                "class": "Application",
                "my_pool": {
                    "class": "Pool",
                    "loadBalancingMode": "least-connections-member",
                    "members": [
                        {
                            "serverAddresses": [
                            "192.168.0.2"
                            ],
                            "servicePort": 80
                        }
                    ]
                },
                "my_service": {
                    "class": "Service_HTTP",
                    "pool": "my_pool",
                    "virtualAddresses": [
                    "192.168.0.107"
                    ],
                    "virtualPort": 80
                }
            }
        }
    }

You receive a response similar to the following, which contains the trace response, including the systemConfig key, which is the translated configuration to be applied to the system, and the systemOperations key which contains a list of specific API requests that will be made with request/response details (response details only made if action=execute):

    {
        "results": [
            {
                "code": 200,
                "host": "bigip-as3.example.com",
                "message": "success",
                "runTime": 0,
                "tenant": "my_tenant"
            }
        ],
        "declaration": {
            "class": "ADC",
            "schemaVersion": "3.0.0",
            "id": "adc-http-canonical",
            "tenant01": {
                "class": "Tenant",
                "app01": {
                    "class": "Application"
                }
            },
            "controls": {
                "class": "Controls",
                "logLevel": "debug",
                "traceResponse": true
            },
            "my_tenant": {
                "class": "Tenant",
                "my_app": {
                    "class": "Application",
                    "my_pool": {
                        "class": "Pool",
                        "loadBalancingMode": "least-connections-member",
                        "members": [
                            {
                                "serverAddresses": [
                                    "198.168.0.2"
                                ],
                                "servicePort": 80
                            }
                        ]
                    },
                    "my_service": {
                        "class": "Service_HTTP",
                        "pool": "my_pool",
                        "virtualAddresses": [
                            "198.168.0.107"
                        ],
                        "virtualPort": 80
                    }
                }
            }
        },
        "traces": [
            {
                "tenant": "my_tenant",
                "systemConfig": {
                    "applications": [
                        {
                            "name": "my_tenant:my_app",
                            "stacks": [
                                {
                                    "clientSide": {
                                        "l4ClientSide": "my_tenant:my_app:my_service",
                                        "persistence": {
                                            "template": "SOURCE_ADDR_TEMPLATE"
                                        }
                                    },
                                    "enabled": true,
                                    "name": "my_tenant:my_app:my_service",
                                    "serverSide": {
                                        "l4ServerSide": "my_tenant:my_app:my_service",
                                        "loadBalancing": "least-connections"
                                    },
                                    "stackType": "HttpRevProxy"
                                }
                            ]
                        }
                    ],
                    "files": [],
                    "L4-clientsides": [
                        {
                            "destinations": [
                                "198.18.1.107"
                            ],
                            "l3Networks": [
                                "appsvcs:all-networks"
                            ],
                            "name": "my_tenant:my_app:my_service",
                            "ports": [
                                "80"
                            ]
                        }
                    ],
                    "L4-serversides": [
                        {
                            "endpoints": [
                                {
                                    "endpointType": "L4BasicEndpoint",
                                    "address": "198.18.10.101:80"
                                }
                            ],
                            "l3Networks": [
                                "appsvcs:all-networks"
                            ],
                            "name": "my_tenant:my_app:my_service"
                        }
                    ],
                    "waf-policies": []
                },
                "systemOperations": [
                    {
                        "request": {
                            "name": "my_tenant:my_app",
                            "stacks": [
                                {
                                    "clientSide": {
                                        "l4ClientSide": "my_tenant:my_app:my_service",
                                        "persistence": {
                                            "template": "SOURCE_ADDR_TEMPLATE"
                                        }
                                    },
                                    "enabled": true,
                                    "name": "my_tenant:my_app:my_service",
                                    "serverSide": {
                                        "l4ServerSide": "my_tenant:my_app:my_service",
                                        "loadBalancing": "least-connections"
                                    },
                                    "stackType": "HttpRevProxy"
                                }
                            ]
                        },
                        "resourceId": "/applications"
                    },
                    {
                        "request": {
                            "destinations": [
                                "198.18.1.107"
                            ],
                            "l3Networks": [
                                "appsvcs:all-networks"
                            ],
                            "name": "my_tenant:my_app:my_service",
                            "ports": [
                                "80"
                            ]
                        },
                        "resourceId": "/L4-clientsides"
                    },
                    {
                        "request": {
                            "endpoints": [
                                {
                                    "endpointType": "L4BasicEndpoint",
                                    "address": "198.18.10.101:80"
                                }
                            ],
                            "l3Networks": [
                                "appsvcs:all-networks"
                            ],
                            "name": "my_tenant:my_app:my_service"
                        },
                        "resourceId": "/L4-serversides"
                    }
                ]
            }
        ]
    }

Using the lazy validation query parameter

The validation=lazy query parameter attempts to ignore any properties that are not supported on BIG-IP Next, and then submit the remaining items. Any items that were ignored show in the bottom of the response as ignoredAttributes. Using this query parameter does deploy the configuration to BIG-IP Next if the declaration is otherwise successful.

If there are no ignoredAttributes, the entire declaration deploys to BIG-IP Next.

To use this parameter, use the following syntax with the HTTP POST method: https://{{host}}/api/v1/application-services/declare?validation=lazy

The following is the response to validation=lazy, where you can see the DOS_Profile class in the ignoredAttributes, as it is not yet supported in AS3 on BIG-IP Next:

    {
        "results": [
            {
                "code": 200,
                "message": "success",
                "host": "f5-appsvcs",
                "tenant": "Sample_DOS_NetVector",
                "runTime": 340
            }
        ],
        "declaration": {
            "class": "ADC",
            "schemaVersion": "3.16.0",
            "id": "DOS_Profile",
            "Sample_DOS_NetVector": {
                "class": "Tenant",
                "Application": {
                    "class": "Application",
                    "DOS_NetVector": {
                        "class": "DOS_Profile",
                        "network": {
                            "vectors": [
                                {
                                    "type": "ip-low-ttl",
                                    "state": "learn-only",
                                    "thresholdMode": "manual",
                                    "rateThreshold": 40000,
                                    "rateIncreaseThreshold": 600,
                                    "rateLimit": 1000000,
                                    "simulateAutoThresholdEnabled": true
                                },
                                {
                                    "type": "non-tcp-connection",
                                    "state": "learn-only",
                                    "thresholdMode": "manual",
                                    "rateThreshold": 40000,
                                    "rateIncreaseThreshold": 600,
                                    "rateLimit": 1000000,
                                    "simulateAutoThresholdEnabled": true
                                }
                            ]
                        }
                    }
                }
            }
        },
        "ignoredAttributes": [
            "/Sample_DOS_NetVector/Application/DOS_NetVector/class",
            "/Sample_DOS_NetVector/Application/DOS_NetVector"
        ]
    }