From dcae814974375ffe660230400c18c71430b3734f Mon Sep 17 00:00:00 2001 From: ParthaI <47887552+ParthaI@users.noreply.github.com> Date: Sat, 15 Jun 2024 02:03:40 +0530 Subject: [PATCH] Add table azure_cdn_frontdoor_profile Closes #764 (#777) Co-authored-by: Ved misra <47312748+misraved@users.noreply.github.com> --- .../dependencies.txt | 0 .../test-get-expected.json | 9 + .../test-get-query.sql | 3 + .../test-list-expected.json | 9 + .../test-list-query.sql | 3 + .../test-not-found-expected.json | 1 + .../test-not-found-query.sql | 3 + .../test-turbot-expected.json | 10 + .../test-turbot-query.sql | 3 + .../variables.json | 1 + .../azure_cdn_frontdoor_profile/variables.tf | 69 ++++++ azure/plugin.go | 1 + azure/table_azure_cdn_frontdoor_profile.go | 196 ++++++++++++++++++ docs/tables/azure_cdn_frontdoor_profile.md | 102 +++++++++ 14 files changed, 410 insertions(+) create mode 100644 azure-test/tests/azure_cdn_frontdoor_profile/dependencies.txt create mode 100644 azure-test/tests/azure_cdn_frontdoor_profile/test-get-expected.json create mode 100644 azure-test/tests/azure_cdn_frontdoor_profile/test-get-query.sql create mode 100644 azure-test/tests/azure_cdn_frontdoor_profile/test-list-expected.json create mode 100644 azure-test/tests/azure_cdn_frontdoor_profile/test-list-query.sql create mode 100644 azure-test/tests/azure_cdn_frontdoor_profile/test-not-found-expected.json create mode 100644 azure-test/tests/azure_cdn_frontdoor_profile/test-not-found-query.sql create mode 100644 azure-test/tests/azure_cdn_frontdoor_profile/test-turbot-expected.json create mode 100644 azure-test/tests/azure_cdn_frontdoor_profile/test-turbot-query.sql create mode 100644 azure-test/tests/azure_cdn_frontdoor_profile/variables.json create mode 100644 azure-test/tests/azure_cdn_frontdoor_profile/variables.tf create mode 100644 azure/table_azure_cdn_frontdoor_profile.go create mode 100644 docs/tables/azure_cdn_frontdoor_profile.md diff --git a/azure-test/tests/azure_cdn_frontdoor_profile/dependencies.txt b/azure-test/tests/azure_cdn_frontdoor_profile/dependencies.txt new file mode 100644 index 00000000..e69de29b diff --git a/azure-test/tests/azure_cdn_frontdoor_profile/test-get-expected.json b/azure-test/tests/azure_cdn_frontdoor_profile/test-get-expected.json new file mode 100644 index 00000000..97aabe61 --- /dev/null +++ b/azure-test/tests/azure_cdn_frontdoor_profile/test-get-expected.json @@ -0,0 +1,9 @@ +[ + { + "id": "{{ output.resource_id.value }}", + "name": "{{ resourceName }}", + "resource_group": "{{ resourceName }}", + "subscription_id": "{{ output.subscription_id.value }}", + "type": "Microsoft.Cdn/profiles" + } +] diff --git a/azure-test/tests/azure_cdn_frontdoor_profile/test-get-query.sql b/azure-test/tests/azure_cdn_frontdoor_profile/test-get-query.sql new file mode 100644 index 00000000..7d0743ad --- /dev/null +++ b/azure-test/tests/azure_cdn_frontdoor_profile/test-get-query.sql @@ -0,0 +1,3 @@ +select name, id, type, resource_group, subscription_id +from azure.azure_cdn_frontdoor_profile +where name = '{{ resourceName }}' and resource_group = '{{ resourceName }}'; diff --git a/azure-test/tests/azure_cdn_frontdoor_profile/test-list-expected.json b/azure-test/tests/azure_cdn_frontdoor_profile/test-list-expected.json new file mode 100644 index 00000000..97aabe61 --- /dev/null +++ b/azure-test/tests/azure_cdn_frontdoor_profile/test-list-expected.json @@ -0,0 +1,9 @@ +[ + { + "id": "{{ output.resource_id.value }}", + "name": "{{ resourceName }}", + "resource_group": "{{ resourceName }}", + "subscription_id": "{{ output.subscription_id.value }}", + "type": "Microsoft.Cdn/profiles" + } +] diff --git a/azure-test/tests/azure_cdn_frontdoor_profile/test-list-query.sql b/azure-test/tests/azure_cdn_frontdoor_profile/test-list-query.sql new file mode 100644 index 00000000..4a412913 --- /dev/null +++ b/azure-test/tests/azure_cdn_frontdoor_profile/test-list-query.sql @@ -0,0 +1,3 @@ +select name, id, type, resource_group, subscription_id +from azure.azure_cdn_frontdoor_profile +where id = '{{ output.resource_id.value }}'; diff --git a/azure-test/tests/azure_cdn_frontdoor_profile/test-not-found-expected.json b/azure-test/tests/azure_cdn_frontdoor_profile/test-not-found-expected.json new file mode 100644 index 00000000..fe51488c --- /dev/null +++ b/azure-test/tests/azure_cdn_frontdoor_profile/test-not-found-expected.json @@ -0,0 +1 @@ +[] diff --git a/azure-test/tests/azure_cdn_frontdoor_profile/test-not-found-query.sql b/azure-test/tests/azure_cdn_frontdoor_profile/test-not-found-query.sql new file mode 100644 index 00000000..b7eeb1b3 --- /dev/null +++ b/azure-test/tests/azure_cdn_frontdoor_profile/test-not-found-query.sql @@ -0,0 +1,3 @@ +select name, id, type +from azure.azure_cdn_frontdoor_profile +where name = 'dummy-test{{ resourceName }}' and resource_group = '{{ resourceName }}'; diff --git a/azure-test/tests/azure_cdn_frontdoor_profile/test-turbot-expected.json b/azure-test/tests/azure_cdn_frontdoor_profile/test-turbot-expected.json new file mode 100644 index 00000000..02cd3c76 --- /dev/null +++ b/azure-test/tests/azure_cdn_frontdoor_profile/test-turbot-expected.json @@ -0,0 +1,10 @@ +[ + { + "akas": [ + "{{ output.resource_aka.value }}", + "{{ output.resource_aka_lower.value }}" + ], + "name": "{{ resourceName }}", + "title": "{{ resourceName }}" + } +] diff --git a/azure-test/tests/azure_cdn_frontdoor_profile/test-turbot-query.sql b/azure-test/tests/azure_cdn_frontdoor_profile/test-turbot-query.sql new file mode 100644 index 00000000..32dc2d8c --- /dev/null +++ b/azure-test/tests/azure_cdn_frontdoor_profile/test-turbot-query.sql @@ -0,0 +1,3 @@ +select name, akas, title +from azure.azure_cdn_frontdoor_profile +where name = '{{ resourceName }}' and resource_group = '{{ resourceName }}'; diff --git a/azure-test/tests/azure_cdn_frontdoor_profile/variables.json b/azure-test/tests/azure_cdn_frontdoor_profile/variables.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/azure-test/tests/azure_cdn_frontdoor_profile/variables.json @@ -0,0 +1 @@ +{} diff --git a/azure-test/tests/azure_cdn_frontdoor_profile/variables.tf b/azure-test/tests/azure_cdn_frontdoor_profile/variables.tf new file mode 100644 index 00000000..bf992d2b --- /dev/null +++ b/azure-test/tests/azure_cdn_frontdoor_profile/variables.tf @@ -0,0 +1,69 @@ +variable "resource_name" { + type = string + default = "turbot-test-20200930-create-update" + description = "Name of the resource used throughout the test." +} + +variable "azure_environment" { + type = string + default = "public" + description = "Azure environment used for the test." +} + +variable "azure_subscription" { + type = string + default = "3510ae4d-530b-497d-8f30-53b9616fc6c1" + description = "Azure environment used for the test." +} + +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "=3.107.0" + } + } +} + +provider "azurerm" { + # Cannot be passed as a variable + environment = var.azure_environment + subscription_id = var.azure_subscription + features {} +} + +resource "azurerm_resource_group" "named_test_resource" { + name = var.resource_name + location = "East US" +} + +resource "azurerm_cdn_frontdoor_profile" "named_test_resource" { + name = var.resource_name + resource_group_name = azurerm_resource_group.named_test_resource.name + sku_name = "Standard_AzureFrontDoor" + + tags = { + environment = "Production" + } +} + +output "resource_id" { + depends_on = [azurerm_cdn_frontdoor_profile.named_test_resource] + value = replace(replace(azurerm_cdn_frontdoor_profile.named_test_resource.id, "resourceGroups", "resourcegroups"), "Profiles", "profiles") +} + +output "resource_aka" { + value = "azure://${replace(replace(azurerm_cdn_frontdoor_profile.named_test_resource.id, "resourceGroups", "resourcegroups"), "Profiles", "profiles")}" +} + +output "resource_aka_lower" { + value = "azure://${lower(azurerm_cdn_frontdoor_profile.named_test_resource.id)}" +} + +output "resource_name" { + value = "${var.resource_name}" +} + +output "subscription_id" { + value = var.azure_subscription +} diff --git a/azure/plugin.go b/azure/plugin.go index 69178693..818de3c5 100644 --- a/azure/plugin.go +++ b/azure/plugin.go @@ -53,6 +53,7 @@ func Plugin(ctx context.Context) *plugin.Plugin { "azure_backup_policy": tableAzureBackupPolicy(ctx), "azure_bastion_host": tableAzureBastionHost(ctx), "azure_batch_account": tableAzureBatchAccount(ctx), + "azure_cdn_frontdoor_profile": tableAzureCDNFrontDoorProfile(ctx), "azure_cognitive_account": tableAzureCognitiveAccount(ctx), "azure_compute_availability_set": tableAzureComputeAvailabilitySet(ctx), "azure_compute_disk": tableAzureComputeDisk(ctx), diff --git a/azure/table_azure_cdn_frontdoor_profile.go b/azure/table_azure_cdn_frontdoor_profile.go new file mode 100644 index 00000000..0745af60 --- /dev/null +++ b/azure/table_azure_cdn_frontdoor_profile.go @@ -0,0 +1,196 @@ +package azure + +import ( + "context" + + "github.com/Azure/azure-sdk-for-go/profiles/latest/cdn/mgmt/cdn" + "github.com/turbot/steampipe-plugin-sdk/v5/grpc/proto" + "github.com/turbot/steampipe-plugin-sdk/v5/plugin" + "github.com/turbot/steampipe-plugin-sdk/v5/plugin/transform" +) + +func tableAzureCDNFrontDoorProfile(_ context.Context) *plugin.Table { + return &plugin.Table{ + Name: "azure_cdn_frontdoor_profile", + Description: "Azure CDN Front Door Profile", + Get: &plugin.GetConfig{ + KeyColumns: plugin.AllColumns([]string{"name", "resource_group"}), + Hydrate: getAzureCDNFrontDoorProfile, + IgnoreConfig: &plugin.IgnoreConfig{ + ShouldIgnoreErrorFunc: isNotFoundError([]string{"ResourceNotFound", "ResourceGroupNotFound", "404"}), + }, + }, + List: &plugin.ListConfig{ + Hydrate: listAzureCDNFrontDoorProfiles, + }, + Columns: azureColumns([]*plugin.Column{ + { + Name: "name", + Description: "The name of the CDN front door profile.", + Type: proto.ColumnType_STRING, + Transform: transform.FromField("Name"), + }, + { + Name: "id", + Description: "The resource identifier.", + Type: proto.ColumnType_STRING, + Transform: transform.FromGo(), + }, + { + Name: "type", + Description: "The resource type.", + Type: proto.ColumnType_STRING, + }, + { + Name: "location", + Description: "The location of the CDN front door profile.", + Type: proto.ColumnType_STRING, + Transform: transform.FromField("Location").Transform(toLower), + }, + { + Name: "sku_name", + Description: "Name of the pricing tier.", + Type: proto.ColumnType_STRING, + Transform: transform.FromField("Sku.Name"), + }, + { + Name: "kind", + Description: "Kind of the profile. Used by portal to differentiate traditional CDN profile and new AFD profile.", + Type: proto.ColumnType_STRING, + }, + { + Name: "resource_state", + Description: "Resource status of the CDN front door profile.", + Type: proto.ColumnType_STRING, + Transform: transform.FromField("ProfileProperties.ResourceState").Transform(transform.ToString), + }, + { + Name: "provisioning_state", + Description: "Provisioning status of the CDN front door profile.", + Type: proto.ColumnType_STRING, + Transform: transform.FromField("ProfileProperties.ProvisioningState"), + }, + { + Name: "front_door_id", + Description: "The ID of the front door.", + Type: proto.ColumnType_STRING, + Transform: transform.FromField("ProfileProperties.FrontDoorID"), + }, + { + Name: "origin_response_timeout_seconds", + Description: "Send and receive timeout on forwarding request to the origin. When timeout is reached, the request fails and returns.", + Type: proto.ColumnType_INT, + Transform: transform.FromField("ProfileProperties.OriginResponseTimeoutSeconds"), + }, + + // Steampipe standard columns + { + Name: "title", + Description: "Title of the resource.", + Type: proto.ColumnType_STRING, + Transform: transform.FromField("Name"), + }, + { + Name: "tags", + Description: "Tags associated with the resource.", + Type: proto.ColumnType_JSON, + }, + { + Name: "akas", + Description: "Array of globally unique identifier strings (also known as) for the resource.", + Type: proto.ColumnType_JSON, + Transform: transform.FromField("ID").Transform(idToAkas), + }, + + // Azure standard columns + { + Name: "region", + Description: "The Azure region where the resource is located.", + Type: proto.ColumnType_STRING, + Transform: transform.FromField("Location").Transform(toLower), + }, + { + Name: "resource_group", + Description: "The resource group in which the resource is located.", + Type: proto.ColumnType_STRING, + Transform: transform.FromField("ID").Transform(extractResourceGroupFromID), + }, + }), + } +} + +//// LIST FUNCTION + +func listAzureCDNFrontDoorProfiles(ctx context.Context, d *plugin.QueryData, _ *plugin.HydrateData) (interface{}, error) { + session, err := GetNewSession(ctx, d, "MANAGEMENT") + if err != nil { + plugin.Logger(ctx).Error("azure_cdn_frontdoor_profile.listAzureCDNFrontDoorProfiles", "session_error", err) + return nil, err + } + + subscriptionID := session.SubscriptionID + client := cdn.NewProfilesClientWithBaseURI(session.ResourceManagerEndpoint, subscriptionID) + client.Authorizer = session.Authorizer + result, err := client.List(ctx) + if err != nil { + plugin.Logger(ctx).Error("azure_cdn_frontdoor_profile.listAzureCDNFrontDoorProfiles", "api_error", err) + return nil, err + } + + for _, profile := range result.Values() { + d.StreamListItem(ctx, profile) + if d.RowsRemaining(ctx) == 0 { + return nil, nil + } + } + + for result.NotDone() { + err = result.NextWithContext(ctx) + if err != nil { + plugin.Logger(ctx).Error("azure_cdn_frontdoor_profile.listAzureCDNFrontDoorProfiles", "paging_error", err) + return nil, err + } + for _, profile := range result.Values() { + d.StreamListItem(ctx, profile) + if d.RowsRemaining(ctx) == 0 { + return nil, nil + } + } + } + + return nil, nil +} + +//// HYDRATE FUNCTION + +func getAzureCDNFrontDoorProfile(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) { + + name := d.EqualsQuals["name"].GetStringValue() + resourceGroup := d.EqualsQuals["resource_group"].GetStringValue() + + // Return nil if no input provided + if name == "" || resourceGroup == "" { + return nil, nil + } + + session, err := GetNewSession(ctx, d, "MANAGEMENT") + if err != nil { + plugin.Logger(ctx).Error("azure_cdn_frontdoor_profile.getAzureCDNFrontDoorProfile", "session_error", err) + return nil, err + } + subscriptionID := session.SubscriptionID + client := cdn.NewProfilesClientWithBaseURI(session.ResourceManagerEndpoint, subscriptionID) + client.Authorizer = session.Authorizer + + profile, err := client.Get(ctx, resourceGroup, name) + if err != nil { + plugin.Logger(ctx).Error("azure_cdn_frontdoor_profile.getAzureCDNFrontDoorProfile", "api_error", err) + return nil, err + } + + if profile.ID != nil { + return profile, nil + } + + return nil, nil +} diff --git a/docs/tables/azure_cdn_frontdoor_profile.md b/docs/tables/azure_cdn_frontdoor_profile.md new file mode 100644 index 00000000..3585dde5 --- /dev/null +++ b/docs/tables/azure_cdn_frontdoor_profile.md @@ -0,0 +1,102 @@ +--- +title: "Steampipe Table: azure_cdn_frontdoor_profile - Query Azure CDN Front Door Profiles using SQL" +description: "Allows users to query CDN Front Door Profiles in Azure, providing detailed information about each profile, including its endpoint configurations, origin groups, and routing rules." +--- + +# Table: azure_cdn_frontdoor_profile - Query Azure CDN Front Door Profiles using SQL + +An Azure CDN Front Door Profile is a collection of settings and configurations for a content delivery network (CDN) front door, which is used to accelerate the delivery of web content to users globally. + +## Table Usage Guide + +The `azure_cdn_frontdoor_profile` table provides insights into CDN Front Door Profiles within Azure. As an Infrastructure Engineer, explore detailed information about each front door profile through this table, including its endpoint configurations, origin groups, and routing rules. Use this table to manage and optimize your CDN profiles, ensuring fast and reliable content delivery for your applications. + +## Examples + +### Basic front door profile information +Retrieve basic information about your Azure CDN Front Door Profiles, including their names, locations, and provisioning states. + +```sql+postgres +select + name, + location, + provisioning_state +from + azure_cdn_frontdoor_profile; +``` + +```sql+sqlite +select + name, + location, + provisioning_state +from + azure_cdn_frontdoor_profile; +``` + +### SKU name and kind +Explore the SKU names and kinds of your Azure CDN Front Door Profiles, which can help in understanding the pricing tiers and types of profiles in use. + +```sql+postgres +select + name, + sku_name, + kind +from + azure_cdn_frontdoor_profile; +``` + +```sql+sqlite +select + name, + sku_name, + kind +from + azure_cdn_frontdoor_profile; +``` + +### Profiles in failed provisioning state +Retrieve information about front door profiles that are in a failed provisioning state. This can help in identifying and troubleshooting issues with profile deployment. + +```sql+postgres +select + name, + location, + provisioning_state +from + azure_cdn_frontdoor_profile +where + provisioning_state = 'Failed'; +``` + +```sql+sqlite +select + name, + location, + provisioning_state +from + azure_cdn_frontdoor_profile +where + provisioning_state = 'Failed'; +``` + +### Front door IDs and origin response timeout +Explore the IDs of the front doors and the origin response timeout settings of your CDN profiles. + +```sql+postgres +select + name, + front_door_id, + origin_response_timeout_seconds +from + azure_cdn_frontdoor_profile; +``` + +```sql+sqlite +select + name, + front_door_id, + origin_response_timeout_seconds +from + azure_cdn_frontdoor_profile; +```