Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add table azure_recovery_services_backup_job Closes #663 #681

Merged
merged 13 commits into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions azure/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ func Plugin(ctx context.Context) *plugin.Plugin {
"azure_private_dns_zone": tableAzurePrivateDNSZone(ctx),
"azure_provider": tableAzureProvider(ctx),
"azure_public_ip": tableAzurePublicIP(ctx),
"azure_recovery_services_backup_job": tableAzureRecoveryServicesBackupJob(ctx),
"azure_recovery_services_vault": tableAzureRecoveryServicesVault(ctx),
"azure_redis_cache": tableAzureRedisCache(ctx),
"azure_resource_group": tableAzureResourceGroup(ctx),
Expand Down
230 changes: 230 additions & 0 deletions azure/table_azure_recovery_services_backup_job.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
package azure

import (
"context"
"strings"

"github.com/Azure/azure-sdk-for-go/profiles/latest/recoveryservices/mgmt/recoveryservices"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/recoveryservices/armrecoveryservicesbackup/v3"
"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"
)

//// TABLE DEFINITION ////

func tableAzureRecoveryServicesBackupJob(_ context.Context) *plugin.Table {
return &plugin.Table{
Name: "azure_recovery_services_backup_job",
Description: "Azure Recovery Services Backup Job",
List: &plugin.ListConfig{
ParentHydrate: listRecoveryServicesVaults,
Hydrate: listRecoveryServicesBackupJobs,
IgnoreConfig: &plugin.IgnoreConfig{
ShouldIgnoreErrorFunc: isNotFoundError([]string{"ResourceNotFound", "404"}),
},
KeyColumns: plugin.KeyColumnSlice{
{
Name: "vault_name",
Require: plugin.Optional,
},
{
Name: "resource_group",
Require: plugin.Optional,
},
},
},
Columns: azureColumns([]*plugin.Column{
{
Name: "name",
Description: "Resource name associated with the resource.",
Type: proto.ColumnType_STRING,
},
{
Name: "vault_name",
Description: "The recovery vault name.",
Type: proto.ColumnType_STRING,
},
{
Name: "id",
Description: "Resource ID represents the complete path to the resource.",
Type: proto.ColumnType_STRING,
Transform: transform.FromGo(),
},
{
Name: "type",
Description: "Resource type represents the complete path of the form Namespace/ResourceType/ResourceType/...",
Type: proto.ColumnType_STRING,
},
{
Name: "etag",
Description: "Optional ETag.",
Type: proto.ColumnType_STRING,
Transform: transform.FromField("ETag"),
},

// JSON fields
{
Name: "properties",
Description: "JobResource properties.",
Type: proto.ColumnType_JSON,
Transform: transform.From(backupJobProperties),
},

// Steampipe standard columns
{
Name: "title",
Description: ColumnDescriptionTitle,
Type: proto.ColumnType_STRING,
Transform: transform.FromField("Name"),
},
{
Name: "tags",
Description: ColumnDescriptionTags,
Type: proto.ColumnType_JSON,
},
{
Name: "akas",
Description: ColumnDescriptionAkas,
Type: proto.ColumnType_JSON,
Transform: transform.FromField("ID").Transform(idToAkas),
},

// Azure standard columns
{
Name: "region",
Description: ColumnDescriptionRegion,
Type: proto.ColumnType_STRING,
Transform: transform.FromField("Location").Transform(toLower),
},
{
Name: "resource_group",
Description: ColumnDescriptionResourceGroup,
Type: proto.ColumnType_STRING,
Transform: transform.FromField("ID").Transform(extractResourceGroupFromID),
},
}),
}
}

type JobInfo struct {
VaultName *string
ETag *string
Location *string
Properties armrecoveryservicesbackup.JobClassification
Tags map[string]*string
ID *string
Name *string
Type *string
}

//// LIST FUNCTION ////

func listRecoveryServicesBackupJobs(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
session, err := GetNewSession(ctx, d, "MANAGEMENT")
if err != nil {
return nil, err
}

cred, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
plugin.Logger(ctx).Error("azure_backup_job.listAzureBackupJobs", "NewDefaultAzureCredential", err)
madhushreeray30 marked this conversation as resolved.
Show resolved Hide resolved
return nil, err
}

vault := h.Item.(recoveryservices.Vault)

plugin.Logger(ctx).Error("Parameter ====>>", vault.Name, strings.Split(*vault.ID, "/")[4])

vaultName := d.EqualsQualString("vault_name")
rgName := d.EqualsQualString("resource_group")

if vaultName != "" {
if vaultName != *vault.Name {
return nil, nil
}
}

if rgName != "" {
if rgName != strings.Split(*vault.ID, "/")[4] {
return nil, nil
}
}

subscriptionID := session.SubscriptionID
clientFactory, err := armrecoveryservicesbackup.NewBackupJobsClient(subscriptionID, cred, nil)
if err != nil {
plugin.Logger(ctx).Error("azure_recovery_services_backup_job.listRecoveryServicesBackupJobs", "client_error", err)
return nil, nil
}
pager := clientFactory.NewListPager(*vault.Name, strings.Split(*vault.ID, "/")[4], &armrecoveryservicesbackup.BackupJobsClientListOptions{Filter: nil,
SkipToken: nil,
})
for pager.More() {
page, err := pager.NextPage(ctx)
if err != nil {
plugin.Logger(ctx).Error("azure_recovery_services_backup_job.listRecoveryServicesBackupJobs", "api_error", err)
return nil, nil
}

for _, v := range page.Value {
d.StreamListItem(ctx, JobInfo{
ETag: v.ETag,
Location: v.Location,
Properties: v.Properties,
Tags: v.Tags,
ID: v.ID,
Name: v.Name,
Type: v.Type,
VaultName: vault.Name,
})

// Check if context has been cancelled or if the limit has been hit (if specified)
// if there is a limit, it will return the number of rows required to reach this limit
if d.RowsRemaining(ctx) == 0 {
return nil, nil
}
}
}

return nil, nil
}

//// TRANSFORM FUNCTION

func backupJobProperties(ctx context.Context, d *transform.TransformData) (interface{}, error) {
data := d.HydrateItem.(JobInfo)

output := make(map[string]interface{})

if data.Properties != nil {
if data.Properties.GetJob() != nil {
if data.Properties.GetJob().ActivityID != nil {
output["ActivityID"] = data.Properties.GetJob().ActivityID
}
if data.Properties.GetJob().BackupManagementType != nil {
output["BackupManagementType"] = data.Properties.GetJob().BackupManagementType
}
if data.Properties.GetJob().JobType != nil {
output["JobType"] = data.Properties.GetJob().JobType
}
if data.Properties.GetJob().EndTime != nil {
output["EndTime"] = data.Properties.GetJob().EndTime
}
if data.Properties.GetJob().EntityFriendlyName != nil {
output["EntityFriendlyName"] = data.Properties.GetJob().EntityFriendlyName
}
if data.Properties.GetJob().Operation != nil {
output["Operation"] = data.Properties.GetJob().Operation
}
if data.Properties.GetJob().StartTime != nil {
output["StartTime"] = data.Properties.GetJob().StartTime
}
if data.Properties.GetJob().Status != nil {
output["Status"] = data.Properties.GetJob().Status
}
}
}
return output, nil
}
38 changes: 38 additions & 0 deletions docs/tables/azure_recovery_services_backup_job.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Table: azure_recovery_services_backup_job

An Azure Backup job is a task that you can define and run to perform data protection operations on your Azure resources. These jobs are typically used to back up and restore data from various Azure services, such as virtual machines, databases, and files.

## Examples

### Basic info

```sql
select
name,
id,
type,
vault_name,
region
from
azure_recovery_services_backup_job
where
vault_name = 'my-vault';
```

### Get job properties of jobs

```sql
select
name,
id,
properties ->> 'JobType' as job_type,
properties ->> 'ActivityID' as activity_id,
properties ->> 'BackupManagementType' as backup_management_type,
properties ->> 'EndTime' as end_time,
properties ->> 'EntityFriendlyName' as entity_friendly_name,
properties ->> 'Operation' as Operation,
properties ->> 'StartTime' as start_time,
properties ->> 'Status' as Status
from
azure_recovery_services_backup_job;
```
16 changes: 11 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.21
require (
github.com/Azure/azure-sdk-for-go v58.0.0+incompatible
github.com/Azure/azure-sdk-for-go/sdk/data/aztables v1.0.1
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/recoveryservices/armrecoveryservicesbackup/v3 v3.0.0
github.com/Azure/azure-storage-blob-go v0.12.0
github.com/Azure/go-autorest/autorest v0.11.17
github.com/Azure/go-autorest/autorest/azure/auth v0.5.6
Expand All @@ -22,14 +23,16 @@ require (
cloud.google.com/go/iam v1.1.1 // indirect
cloud.google.com/go/storage v1.30.1 // indirect
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.0.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.10 // indirect
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
github.com/Azure/go-autorest/autorest/validation v0.3.0 // indirect
github.com/Azure/go-autorest/logger v0.2.0 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 // indirect
github.com/XiaoMi/pegasus-go-client v0.0.0-20210427083443-f3b6b08bc4c2 // indirect
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
github.com/agext/levenshtein v1.2.2 // indirect
Expand Down Expand Up @@ -58,6 +61,7 @@ require (
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect
github.com/gofrs/uuid v4.0.0+incompatible // indirect
github.com/golang-jwt/jwt/v5 v5.0.0 // indirect
github.com/golang/glog v1.1.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
Expand All @@ -78,6 +82,7 @@ require (
github.com/iancoleman/strcase v0.3.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/klauspost/compress v1.15.11 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-ieproxy v0.0.1 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
Expand All @@ -90,6 +95,7 @@ require (
github.com/oklog/run v1.0.0 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/pegasus-kv/thrift v0.13.0 // indirect
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.14.0 // indirect
Expand Down Expand Up @@ -117,13 +123,13 @@ require (
go.opentelemetry.io/otel/sdk/metric v0.40.0 // indirect
go.opentelemetry.io/otel/trace v1.17.0 // indirect
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
golang.org/x/crypto v0.11.0 // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
golang.org/x/net v0.12.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/oauth2 v0.10.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/api v0.126.0 // indirect
Expand Down
Loading