From c1ed95556edc123a8ea2261e6af8d3522eaa7c50 Mon Sep 17 00:00:00 2001 From: magodo Date: Fri, 8 Aug 2025 10:49:48 +1000 Subject: [PATCH 1/3] New option: `--include-managed-resource` --- flag.go | 4 ++++ internal/meta/meta_query.go | 3 +++ internal/meta/meta_res.go | 25 ++++++++++++++----------- internal/meta/meta_rg.go | 18 +++++++++++------- main.go | 31 ++++++++++++++++++++----------- pkg/config/config.go | 3 +++ 6 files changed, 55 insertions(+), 29 deletions(-) diff --git a/flag.go b/flag.go index b7b67abf..f5dc1dce 100644 --- a/flag.go +++ b/flag.go @@ -99,6 +99,7 @@ type FlagSet struct { flagResName string flagResType string flagIncludeRoleAssignment bool + flagIncludeManagedResource bool flagIncludeResourceGroup bool flagARGTable string flagARGAuthorizationScopeFilter string @@ -231,6 +232,9 @@ func (flag FlagSet) DescribeCLI(mode Mode) string { if flag.flagIncludeRoleAssignment { args = append(args, "--include-role-assignment=true") } + if flag.flagIncludeManagedResource { + args = append(args, "--include-managed-resource=true") + } switch mode { case ModeResource: diff --git a/internal/meta/meta_query.go b/internal/meta/meta_query.go index a19e03b8..5bf16a6b 100644 --- a/internal/meta/meta_query.go +++ b/internal/meta/meta_query.go @@ -18,6 +18,7 @@ type MetaQuery struct { resourceNamePrefix string resourceNameSuffix string includeRoleAssignment bool + includeManagedResource bool includeResourceGroup bool argTable string argAuthenticationScopeFilter armresourcegraph.AuthorizationScopeFilter @@ -35,6 +36,7 @@ func NewMetaQuery(cfg config.Config) (*MetaQuery, error) { argPredicate: cfg.ARGPredicate, recursiveQuery: cfg.RecursiveQuery, includeRoleAssignment: cfg.IncludeRoleAssignment, + includeManagedResource: cfg.IncludeManagedResource, includeResourceGroup: cfg.IncludeResourceGroup, argTable: cfg.ARGTable, argAuthenticationScopeFilter: armresourcegraph.AuthorizationScopeFilter(cfg.ARGAuthorizationScopeFilter), @@ -115,6 +117,7 @@ func (meta MetaQuery) queryResourceSet(ctx context.Context, predicate string, re Recursive: recursive, IncludeResourceGroup: meta.includeResourceGroup, ExtensionResourceTypes: extBuilder{includeRoleAssignment: meta.includeRoleAssignment}.Build(), + IncludeManaged: meta.includeManagedResource, ARGTable: meta.argTable, ARGAuthorizationScopeFilter: meta.argAuthenticationScopeFilter, } diff --git a/internal/meta/meta_res.go b/internal/meta/meta_res.go index b98bcc4b..4d999446 100644 --- a/internal/meta/meta_res.go +++ b/internal/meta/meta_res.go @@ -15,12 +15,13 @@ import ( type MetaResource struct { baseMeta - AzureIds []armid.ResourceId - ResourceName string - ResourceType string - resourceNamePrefix string - resourceNameSuffix string - includeRoleAssignment bool + AzureIds []armid.ResourceId + ResourceName string + ResourceType string + resourceNamePrefix string + resourceNameSuffix string + includeRoleAssignment bool + includeManagedResource bool } func NewMetaResource(cfg config.Config) (*MetaResource, error) { @@ -41,11 +42,12 @@ func NewMetaResource(cfg config.Config) (*MetaResource, error) { } meta := &MetaResource{ - baseMeta: *baseMeta, - AzureIds: ids, - ResourceName: cfg.TFResourceName, - ResourceType: cfg.TFResourceType, - includeRoleAssignment: cfg.IncludeRoleAssignment, + baseMeta: *baseMeta, + AzureIds: ids, + ResourceName: cfg.TFResourceName, + ResourceType: cfg.TFResourceType, + includeRoleAssignment: cfg.IncludeRoleAssignment, + includeManagedResource: cfg.IncludeManagedResource, } meta.resourceNamePrefix, meta.resourceNameSuffix = resourceNamePattern(cfg.ResourceNamePattern) @@ -178,6 +180,7 @@ func (meta MetaResource) queryResourceSet(ctx context.Context, resources []resou ClientOpt: meta.azureSDKClientOpt, Parallelism: meta.parallelism, ExtensionResourceTypes: extBuilder{includeRoleAssignment: meta.includeRoleAssignment}.Build(), + IncludeManaged: meta.includeManagedResource, } lister, err := azlist.NewLister(opt) diff --git a/internal/meta/meta_rg.go b/internal/meta/meta_rg.go index e61c8022..006f1233 100644 --- a/internal/meta/meta_rg.go +++ b/internal/meta/meta_rg.go @@ -12,10 +12,11 @@ import ( type MetaResourceGroup struct { baseMeta - resourceGroup string - resourceNamePrefix string - resourceNameSuffix string - includeRoleAssignment bool + resourceGroup string + resourceNamePrefix string + resourceNameSuffix string + includeRoleAssignment bool + includeManagedResource bool } func NewMetaResourceGroup(cfg config.Config) (*MetaResourceGroup, error) { @@ -26,9 +27,10 @@ func NewMetaResourceGroup(cfg config.Config) (*MetaResourceGroup, error) { } meta := &MetaResourceGroup{ - baseMeta: *baseMeta, - resourceGroup: cfg.ResourceGroupName, - includeRoleAssignment: cfg.IncludeRoleAssignment, + baseMeta: *baseMeta, + resourceGroup: cfg.ResourceGroupName, + includeRoleAssignment: cfg.IncludeRoleAssignment, + includeManagedResource: cfg.IncludeManagedResource, } meta.resourceNamePrefix, meta.resourceNameSuffix = resourceNamePattern(cfg.ResourceNamePattern) @@ -101,6 +103,7 @@ func (meta MetaResourceGroup) queryResourceSet(ctx context.Context, rg string) ( ClientOpt: meta.azureSDKClientOpt, Parallelism: meta.parallelism, ExtensionResourceTypes: extBuilder{includeRoleAssignment: meta.includeRoleAssignment}.Build(), + IncludeManaged: meta.includeManagedResource, ARGTable: "ResourceContainers", } lister, err := azlist.NewLister(opt) @@ -132,6 +135,7 @@ func (meta MetaResourceGroup) queryResourceSet(ctx context.Context, rg string) ( ClientOpt: meta.azureSDKClientOpt, Parallelism: meta.parallelism, ExtensionResourceTypes: extBuilder{includeRoleAssignment: meta.includeRoleAssignment}.Build(), + IncludeManaged: meta.includeManagedResource, Recursive: true, } lister, err = azlist.NewLister(opt) diff --git a/main.go b/main.go index 7b4dcb9d..59aa6317 100644 --- a/main.go +++ b/main.go @@ -264,6 +264,12 @@ func main() { Usage: `Whether to include role assignments assigned to the resources exported`, Destination: &flagset.flagIncludeRoleAssignment, }, + &cli.BoolFlag{ + Name: "include-managed-resource", + EnvVars: []string{"AZTFEXPORT_INCLUDE_MANAGED_RESOURCE"}, + Usage: `Whether to allow resources managed by service team/3rd party to be exported`, + Destination: &flagset.flagIncludeManagedResource, + }, // Common flags (auth) &cli.StringFlag{ @@ -577,12 +583,13 @@ func main() { // Initialize the config cfg := config.Config{ - CommonConfig: commonConfig, - ResourceIds: resIds, - TFResourceName: flagset.flagResName, - TFResourceType: flagset.flagResType, - ResourceNamePattern: flagset.flagPattern, - IncludeRoleAssignment: flagset.flagIncludeRoleAssignment, + CommonConfig: commonConfig, + ResourceIds: resIds, + TFResourceName: flagset.flagResName, + TFResourceType: flagset.flagResType, + ResourceNamePattern: flagset.flagPattern, + IncludeRoleAssignment: flagset.flagIncludeRoleAssignment, + IncludeManagedResource: flagset.flagIncludeManagedResource, } return realMain(c.Context, cfg, flagset.flagNonInteractive, flagset.hflagMockClient, flagset.flagPlainUI, flagset.flagGenerateMappingFile, flagset.hflagProfile, flagset.DescribeCLI(ModeResource), flagset.hflagTFClientPluginPath) @@ -612,11 +619,12 @@ func main() { // Initialize the config cfg := config.Config{ - CommonConfig: commonConfig, - ResourceGroupName: rg, - ResourceNamePattern: flagset.flagPattern, - RecursiveQuery: true, - IncludeRoleAssignment: flagset.flagIncludeRoleAssignment, + CommonConfig: commonConfig, + ResourceGroupName: rg, + ResourceNamePattern: flagset.flagPattern, + RecursiveQuery: true, + IncludeRoleAssignment: flagset.flagIncludeRoleAssignment, + IncludeManagedResource: flagset.flagIncludeManagedResource, } return realMain(c.Context, cfg, flagset.flagNonInteractive, flagset.hflagMockClient, flagset.flagPlainUI, flagset.flagGenerateMappingFile, flagset.hflagProfile, flagset.DescribeCLI(ModeResourceGroup), flagset.hflagTFClientPluginPath) @@ -650,6 +658,7 @@ func main() { ResourceNamePattern: flagset.flagPattern, RecursiveQuery: flagset.flagRecursive, IncludeRoleAssignment: flagset.flagIncludeRoleAssignment, + IncludeManagedResource: flagset.flagIncludeManagedResource, IncludeResourceGroup: flagset.flagIncludeResourceGroup, ARGTable: flagset.flagARGTable, ARGAuthorizationScopeFilter: flagset.flagARGAuthorizationScopeFilter, diff --git a/pkg/config/config.go b/pkg/config/config.go index d5bd7d26..9f93fa7d 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -119,6 +119,9 @@ type Config struct { // IncludeRoleAssignment specifies whether to include the role assignments assigned to the exported resources IncludeRoleAssignment bool + // IncludeManagedResource specifies whether to allow service team/3rd party managed resources to be exported + IncludeManagedResource bool + ///////////////////////// // Scope: rg, res (multi), query From 632b2066a4c1c45861b5d1effa16dc3e74381341 Mon Sep 17 00:00:00 2001 From: magodo Date: Fri, 8 Aug 2025 12:27:44 +1000 Subject: [PATCH 2/3] comment --- flag.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/flag.go b/flag.go index f5dc1dce..eafca163 100644 --- a/flag.go +++ b/flag.go @@ -82,15 +82,19 @@ type FlagSet struct { // flagResName (for single resource) // flagResType (for single resource) // flagPattern (for multi resources) + // flagIncludeRoleAssignment + // flagIncludeManagedResource // // rg: // flagPattern // flagIncludeRoleAssignment + // flagIncludeManagedResource // // query: // flagPattern // flagRecursive // flagIncludeRoleAssignment + // flagIncludeManagedResource // flagIncludeResourceGroup // flagARGTable // flagARGAuthorizationScopeFilter From c94df7c8665f7b13e538990decdef971c30315e8 Mon Sep 17 00:00:00 2001 From: magodo Date: Fri, 8 Aug 2025 12:57:38 +1000 Subject: [PATCH 3/3] Resource mode: Support `--recursive`, `--include-resource-group` --- flag.go | 54 ++++++++++++++++----------------------- internal/meta/meta_res.go | 15 ++++++----- main.go | 25 +++++++++++++++++- pkg/config/config.go | 21 +++++++++------ 4 files changed, 68 insertions(+), 47 deletions(-) diff --git a/flag.go b/flag.go index eafca163..4a17f8c8 100644 --- a/flag.go +++ b/flag.go @@ -82,8 +82,10 @@ type FlagSet struct { // flagResName (for single resource) // flagResType (for single resource) // flagPattern (for multi resources) + // flagRecursive // flagIncludeRoleAssignment // flagIncludeManagedResource + // flagIncludeResourceGroup // // rg: // flagPattern @@ -239,38 +241,26 @@ func (flag FlagSet) DescribeCLI(mode Mode) string { if flag.flagIncludeManagedResource { args = append(args, "--include-managed-resource=true") } - - switch mode { - case ModeResource: - if flag.flagResName != "" { - args = append(args, "--name="+flag.flagResName) - } - if flag.flagResType != "" { - args = append(args, "--type="+flag.flagResType) - } - if flag.flagPattern != "" { - args = append(args, "--name-pattern="+flag.flagPattern) - } - case ModeResourceGroup: - if flag.flagPattern != "" { - args = append(args, "--name-pattern="+flag.flagPattern) - } - case ModeQuery: - if flag.flagPattern != "" { - args = append(args, "--name-pattern="+flag.flagPattern) - } - if flag.flagRecursive { - args = append(args, "--recursive=true") - } - if flag.flagIncludeResourceGroup { - args = append(args, "--include-resource-group=true") - } - if flag.flagARGTable != "" { - args = append(args, "--arg-table="+flag.flagARGTable) - } - if flag.flagARGAuthorizationScopeFilter != "" { - args = append(args, "--arg-authorization-scope-filter="+flag.flagARGAuthorizationScopeFilter) - } + if flag.flagIncludeResourceGroup { + args = append(args, "--include-resource-group=true") + } + if flag.flagResName != "" { + args = append(args, "--name="+flag.flagResName) + } + if flag.flagResType != "" { + args = append(args, "--type="+flag.flagResType) + } + if flag.flagPattern != "" { + args = append(args, "--name-pattern="+flag.flagPattern) + } + if flag.flagRecursive { + args = append(args, "--recursive=true") + } + if flag.flagARGTable != "" { + args = append(args, "--arg-table="+flag.flagARGTable) + } + if flag.flagARGAuthorizationScopeFilter != "" { + args = append(args, "--arg-authorization-scope-filter="+flag.flagARGAuthorizationScopeFilter) } return "aztfexport " + strings.Join(args, " ") } diff --git a/internal/meta/meta_res.go b/internal/meta/meta_res.go index 1799e083..2bbc4d90 100644 --- a/internal/meta/meta_res.go +++ b/internal/meta/meta_res.go @@ -21,6 +21,8 @@ type MetaResource struct { resourceNameSuffix string includeRoleAssignment bool includeManagedResource bool + includeResourceGroup bool + recursive bool } func NewMetaResource(cfg config.Config) (*MetaResource, error) { @@ -45,8 +47,10 @@ func NewMetaResource(cfg config.Config) (*MetaResource, error) { AzureIds: ids, ResourceName: cfg.TFResourceName, ResourceType: cfg.TFResourceType, + recursive: cfg.RecursiveQuery, includeRoleAssignment: cfg.IncludeRoleAssignment, includeManagedResource: cfg.IncludeManagedResource, + includeResourceGroup: cfg.IncludeResourceGroup, } meta.resourceNamePrefix, meta.resourceNameSuffix = resourceNamePattern(cfg.ResourceNamePattern) @@ -68,12 +72,9 @@ func (meta *MetaResource) ListResource(ctx context.Context) (ImportList, error) rl = append(rl, resourceset.AzureResource{Id: id}) } - if meta.includeRoleAssignment { - var err error - rl, err = meta.listByIds(ctx, rl) - if err != nil { - return nil, fmt.Errorf("querying extension resources: %v", err) - } + rl, err := meta.listByIds(ctx, rl) + if err != nil { + return nil, fmt.Errorf("querying extension resources: %v", err) } meta.Logger().Debug("Azure Resource set map to TF resource set") @@ -186,6 +187,8 @@ func (meta MetaResource) listByIds(ctx context.Context, resources []resourceset. Parallelism: meta.parallelism, ExtensionResourceTypes: extBuilder{includeRoleAssignment: meta.includeRoleAssignment}.Build(), IncludeManaged: meta.includeManagedResource, + IncludeResourceGroup: meta.includeResourceGroup, + Recursive: meta.recursive, } lister, err := azlist.NewLister(opt) diff --git a/main.go b/main.go index 59aa6317..4493020a 100644 --- a/main.go +++ b/main.go @@ -424,6 +424,19 @@ func main() { Value: "res-", Destination: &flagset.flagPattern, }, + &cli.BoolFlag{ + Name: "recursive", + EnvVars: []string{"AZTFEXPORT_RECURSIVE"}, + Aliases: []string{"r"}, + Usage: "Recursively lists child resources of the resulting query resources", + Destination: &flagset.flagRecursive, + }, + &cli.BoolFlag{ + Name: "include-resource-group", + EnvVars: []string{"AZTFEXPORT_INCLUDE_RESOURCE_GROUP"}, + Usage: "Include the resource groups that the exported resources belong to", + Destination: &flagset.flagIncludeResourceGroup, + }, }, commonFlags...) resourceGroupFlags := append([]cli.Flag{ @@ -438,6 +451,14 @@ func main() { }, commonFlags...) queryFlags := append([]cli.Flag{ + &cli.StringFlag{ + Name: "name-pattern", + EnvVars: []string{"AZTFEXPORT_NAME_PATTERN"}, + Aliases: []string{"p"}, + Usage: `The pattern of the resource name. The semantic of a pattern is the same as Go's os.CreateTemp()`, + Value: "res-", + Destination: &flagset.flagPattern, + }, &cli.BoolFlag{ Name: "recursive", EnvVars: []string{"AZTFEXPORT_RECURSIVE"}, @@ -463,7 +484,7 @@ func main() { Usage: `The Azure Resource Graph Authorization Scope Filter parameter. Possible values are: "AtScopeAndBelow", "AtScopeAndAbove", "AtScopeAboveAndBelow" and "AtScopeExact"`, Destination: &flagset.flagARGAuthorizationScopeFilter, }, - }, resourceGroupFlags...) + }, commonFlags...) mappingFileFlags := append([]cli.Flag{}, commonFlags...) @@ -588,6 +609,8 @@ func main() { TFResourceName: flagset.flagResName, TFResourceType: flagset.flagResType, ResourceNamePattern: flagset.flagPattern, + RecursiveQuery: flagset.flagRecursive, + IncludeResourceGroup: flagset.flagIncludeResourceGroup, IncludeRoleAssignment: flagset.flagIncludeRoleAssignment, IncludeManagedResource: flagset.flagIncludeManagedResource, } diff --git a/pkg/config/config.go b/pkg/config/config.go index 9f93fa7d..b51d4e61 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -116,18 +116,18 @@ type Config struct { // MappingFile specifies the path of mapping file, this indicates the map file mode. MappingFile string - // IncludeRoleAssignment specifies whether to include the role assignments assigned to the exported resources - IncludeRoleAssignment bool - - // IncludeManagedResource specifies whether to allow service team/3rd party managed resources to be exported - IncludeManagedResource bool - ///////////////////////// // Scope: rg, res (multi), query // ResourceNamePattern specifies the resource name pattern ResourceNamePattern string + // IncludeRoleAssignment specifies whether to include the role assignments assigned to the exported resources + IncludeRoleAssignment bool + + // IncludeManagedResource specifies whether to allow service team/3rd party managed resources to be exported + IncludeManagedResource bool + ///////////////////////// // Scope: res (single) @@ -137,12 +137,17 @@ type Config struct { TFResourceType string ///////////////////////// - // Scope: query + // Scope: res, query - // RecursiveQuery specifies whether to recursively list the child/proxy resources of the ARG resulted resource list + // RecursiveQuery specifies whether to recursively list the child/proxy resources of the ARG resulted or user specified resource list RecursiveQuery bool + // IncludeResourceGroup specifies whether to include the resource groups that the exported resources belong to IncludeResourceGroup bool + + ///////////////////////// + // Scope: query + // ARGTable specifies the ARG table name, which defaults to the "Resources" table ARGTable string // ARGAuthorizationScopeFilter specifies the AuthorizationScopeFilter parameter. Possible values are: "AtScopeAndBelow", "AtScopeAndAbove", "AtScopeAboveAndBelow" and "AtScopeExact"