azproviderlint

command module
v0.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 10, 2026 License: GPL-3.0 Imports: 7 Imported by: 0

README

azproviderlint

GitHub release Go Version License build lint CodeQL

Lint rules for the Terraform AzureRM provider. Each rule catches one mistake that comes up in provider code, from schema fields that break at plan time to pointer dereferences that panic when Azure leaves a field out. Most rules can fix what they find.

It runs on its own or as a golangci-lint plugin. The rules are ordinary Go analysis passes.

Quick start

go install github.com/katbyte/azproviderlint@latest
azproviderlint ./...

That runs every rule. To run some of them, name them. A category on its own (-AZG) means every rule in it.

azproviderlint -AZG001 ./...
azproviderlint -AZR001 -AZR003 ./...
azproviderlint -AZG ./...
azproviderlint -AZG -AZR001 ./...

Add -fix to apply the suggested fixes. Read the diff afterwards. Each rule's README says what its fix does and when to be careful.

Rules

Rules are named AZ, a category letter, and a number. The letters follow tfproviderlint where the categories overlap.

AZG - General Go Style / Readability
Rule Description
AZG000 azignore directives must give a reason
AZG001 combine err assignment and check into one if
AZG002 use new() instead of a single-use temporary's address
AZG003 use pointer.ToEnum for enum conversions
AZG004 use pointer.From instead of nil-check dereference
AZG005 inline single-use variable only used in a later assignment or return
AZG006 inline single-use variable only used in a later function call
AZG007 omit struct literal fields explicitly set to their zero value
AZG008 pointer dereferences must have a nil guard or use pointer.From
AZR - Resource Implementation
Rule Description
AZR001 SetId must use a resource id formatter/parser
AZR002 separate Create and Update methods
AZR003 no d.Get in Delete functions
AZR004 compare resource id types with resourceids.Match
AZR005 do not set the case-insensitive segments feature flag
AZR006 use timeouts wrappers, not StopContext
AZR007 use custom pollers instead of StateChangeConf
AZR008 flatten functions must return empty slices/maps, not nil
AZR009 no lifecycle narration logging in Create/Read/Update/Delete
AZR010 flatten functions handle nil input themselves, not their callers
AZD - Data Sources
Rule Description
AZD001 data sources must error when not found, not SetId("")
AZD002 data sources must error when not found, not MarkAsGone
AZS - Schema & Typed SDK Models
Rule Description
AZS001 typed SDK model numeric fields must be 64-bit (int64/float64)
AZS002 schema Default values must match the declared Type
AZS003 TypeList blocks must not allow empty blocks
AZS004 enum validation must use the SDK's possible-values helper
AZS005 registered resources must have a same-named data source
AZS006 data sources must expose their same-named resource's properties
AZS007 optional+computed fields must have a Note: O+C comment
AZS008 registration entries must be sorted alphabetically
AZS009 computed-only fields must not set input-only schema attributes
AZC - Clients & SDK Usage
Rule Description
AZC001 clients must set an explicit resource manager endpoint
AZT - Acceptance Testing
Rule Description
AZT001 acceptance tests must use a _test package
AZT002 acceptance tests must not read credentials from the environment
AZN - Naming Conventions

No rules yet. Reserved for property naming rules, such as percentages using a _percentage suffix rather than _in_percent.

AZV - Validation
Rule Description
AZV001 'invalid format' error messages must describe the expected format

Terms the rule docs use

If you are new to the provider, these come up a lot:

  • Untyped resource: the original plugin SDK style. A map[string]*pluginsdk.Schema, and d.Get / d.Set to move values in and out of state.
  • Typed resource: the newer internal/sdk style. A Go struct with tfschema tags, Arguments() / Attributes() for the schema, and metadata.Decode / metadata.Encode instead of Get / Set.
  • Framework resource: the Terraform Plugin Framework style, registered through FrameworkResources().
  • Expand / flatten: expandFoo turns config into an SDK request. flattenFoo turns an SDK response into what goes in state.
  • Resource ID: the provider's own parsed form of an Azure resource ID, with a generated formatter and parser per type. See AZR001.
  • go-azure-sdk / go-azure-helpers: the SDK the provider calls Azure with, and the helper library that provides pointer.To, pointer.From, and friends.

Ignoring reports

To skip one rule on one line, add a comment at the end of the line or on the line above it. Say why. A directive without a reason is reported by AZG000.

d.SetId(*read.ID) //azignore:AZR001 - legacy resource, ID formatter tracked in #1234

//azignore:AZG001,AZR003 combined form obscures the retry loop here
err := client.Delete(ctx, id)

Several rules can be listed with commas. The - before the reason is optional. This works under every driver, standalone or golangci-lint.

Under golangci-lint, //nolint:azproviderlint in the same place also works, but it silences every azproviderlint rule on that line, so prefer //azignore when you can.

Using it with golangci-lint

The plugin has to be compiled into a custom golangci-lint binary. Add it to .custom-gcl.yml:

version: v2.12.2
plugins:
  - module: "github.com/katbyte/azproviderlint"
    import: "github.com/katbyte/azproviderlint/plugin"
    version: v0.1.0

Build the binary and enable the linter:

golangci-lint custom
linters:
  enable:
    - azproviderlint
  settings:
    custom:
      azproviderlint:
        type: module

To run only azproviderlint through the custom binary:

custom-gcl run --enable-only azproviderlint ./...
Choosing rules

Every rule runs by default. Under settings, enable narrows that to a list and disable removes from whatever is enabled. Both accept rule names or whole categories.

linters:
  settings:
    custom:
      azproviderlint:
        type: module
        settings:
          enable: [AZG]         # only the AZG rules...
          disable: [AZG005]     # ...except AZG005

There is no per-rule flag on the golangci-lint command line. Use the settings above, or the standalone binary.

Options

Some rules take options. Each rule's README lists them. In golangci-lint they go under the rule's name in the same settings block. On the standalone binary they are -<RULE>.<option> flags.

        settings:
          AZS004: {allow-extra-values: true}
          AZG005: {max-gap: 50}
azproviderlint -AZG005 -AZG005.max-gap=50 ./...
Why bother with the plugin?

Building a custom binary is a one-time cost, and on a codebase the size of azurerm it pays off:

  • Loading the provider once, not twice. Type-checking azurerm and its vendor tree takes minutes. A separate binary does it all over again. Inside golangci-lint it is shared, and the result cache makes warm re-runs fast.
  • One config, one output. The path exclusions already in the provider's .golangci.yml (generated files, /sdk/, third_party) apply for free. So do SARIF, annotations, and --new-from-rev, which lets a rule be enforced on new code while a decade of existing findings is left alone.
  • //nolint works alongside //azignore.

The standalone binary is still the right tool for a quick one-rule run, for editors that expect a plain analysis vet tool, and for developing new rules.

Documentation

Overview

Command azproviderlint runs the analyzers in checks/ over Go packages, as a standalone multichecker; the same analyzers ship as a golangci-lint module plugin (see plugin/).

Directories

Path Synopsis
Package checks exposes all azproviderlint analyzers, grouped by category.
Package checks exposes all azproviderlint analyzers, grouped by category.
AZC
Package AZC collects the client & SDK usage checks.
Package AZC collects the client & SDK usage checks.
AZC/AZC001_client_missing_resource_manager_endpoint
Package AZC001 defines an analyzer that reports Azure SDK clients being created without the resource manager endpoint explicitly specified.
Package AZC001 defines an analyzer that reports Azure SDK clients being created without the resource manager endpoint explicitly specified.
AZD
Package AZD collects the data source checks.
Package AZD collects the data source checks.
AZD/AZD001_data_source_empty_set_id
Package AZD001 defines an analyzer that reports data sources calling SetId with an empty string instead of returning an error when the resource cannot be found.
Package AZD001 defines an analyzer that reports data sources calling SetId with an empty string instead of returning an error when the resource cannot be found.
AZD/AZD002_data_source_mark_as_gone
Package AZD002 defines an analyzer that reports data sources using MarkAsGone instead of returning an error when the resource cannot be found.
Package AZD002 defines an analyzer that reports data sources using MarkAsGone instead of returning an error when the resource cannot be found.
AZG
Package AZG collects the general Go style & readability checks.
Package AZG collects the general Go style & readability checks.
AZG/AZG000_azignore_missing_reason
Package AZG000 defines an analyzer that reports '//azignore:' directives that do not carry a reason explaining why the check is suppressed.
Package AZG000 defines an analyzer that reports '//azignore:' directives that do not carry a reason explaining why the check is suppressed.
AZG/AZG001_combine_err_assignment_and_check
Package AZG001 defines an analyzer that reports 'err := SomeFunc()' and '_, err := SomeFunc()' assignments that should be combined with the following 'if err != nil' into a single 'if' init statement.
Package AZG001 defines an analyzer that reports 'err := SomeFunc()' and '_, err := SomeFunc()' assignments that should be combined with the following 'if err != nil' into a single 'if' init statement.
AZG/AZG002_address_of_single_use_temporary
Package AZG002 defines an analyzer that reports single-use temporaries whose only use is taking their address — `v := <expr>` followed by `&v` in a later statement — which should be `new(<expr>)` (or `pointer.To(<expr>)`) at the address-of site.
Package AZG002 defines an analyzer that reports single-use temporaries whose only use is taking their address — `v := <expr>` followed by `&v` in a later statement — which should be `new(<expr>)` (or `pointer.To(<expr>)`) at the address-of site.
AZG/AZG003_pointer_to_enum_conversion
Package AZG003 defines an analyzer that reports pointer.To being used with an explicit go-azure-sdk enum type conversion (pointer.To(sdk.Enum(v))) where the generic pointer.ToEnum[sdk.Enum](v) helper should be used instead.
Package AZG003 defines an analyzer that reports pointer.To being used with an explicit go-azure-sdk enum type conversion (pointer.To(sdk.Enum(v))) where the generic pointer.ToEnum[sdk.Enum](v) helper should be used instead.
AZG/AZG004_zero_value_init_pointer_from
Package AZG004 defines an analyzer that reports a zero-value initialization immediately followed by a nil check and pointer dereference — `y := <zero>; if x != nil { y = *x }` — where the generic pointer.From(x) helper should be used instead.
Package AZG004 defines an analyzer that reports a zero-value initialization immediately followed by a nil check and pointer dereference — `y := <zero>; if x != nil { y = *x }` — where the generic pointer.From(x) helper should be used instead.
AZG/AZG005_single_use_temporary
Package AZG005 defines an analyzer that reports single-use temporaries consumed by a later statement in the same block — `x := <expr>` followed by `y = x` or `return x` where x has no other use — which should be inlined.
Package AZG005 defines an analyzer that reports single-use temporaries consumed by a later statement in the same block — `x := <expr>` followed by `y = x` or `return x` where x has no other use — which should be inlined.
AZG/AZG006_single_use_call_argument
Package AZG006 defines an analyzer that reports single-use variables whose only use is an argument of a later call whose other arguments are all literals — `x := flatten(...)` followed by `d.Set("key", x)` — which should be inlined.
Package AZG006 defines an analyzer that reports single-use variables whose only use is an argument of a later call whose other arguments are all literals — `x := flatten(...)` followed by `d.Set("key", x)` — which should be inlined.
AZG/AZG007_redundant_zero_value_field
Package AZG007 defines an analyzer that reports redundant zero-value assignments to struct literal fields, where the field should be omitted instead.
Package AZG007 defines an analyzer that reports redundant zero-value assignments to struct literal fields, where the field should be omitted instead.
AZG/AZG008_unchecked_nil_dereference
Package AZG008 defines an analyzer that reports pointer dereferences with no reachable nil guard — `string(*props.Status)` where nothing established `props.Status != nil` — which panic when an optional SDK field is absent.
Package AZG008 defines an analyzer that reports pointer dereferences with no reachable nil guard — `string(*props.Status)` where nothing established `props.Status != nil` — which panic when an optional SDK field is absent.
AZR
Package AZR collects the resource implementation checks.
Package AZR collects the resource implementation checks.
AZR/AZR001_set_id_dereferenced_pointer
Package AZR001 defines an analyzer that reports SetId being called with a dereferenced pointer (typically the raw Azure API resource ID) instead of a generated Resource ID Formatter/Parser's id.ID().
Package AZR001 defines an analyzer that reports SetId being called with a dereferenced pointer (typically the raw Azure API resource ID) instead of a generated Resource ID Formatter/Parser's id.ID().
AZR/AZR002_combined_create_update_method
Package AZR002 defines an analyzer that reports resources registering a combined CreateUpdate method instead of separate Create and Update methods.
Package AZR002 defines an analyzer that reports resources registering a combined CreateUpdate method instead of separate Create and Update methods.
AZR/AZR003_resource_data_get_in_delete
Package AZR003 defines an analyzer that reports ResourceData.Get being used inside a resource's Delete function, where it does not work as expected.
Package AZR003 defines an analyzer that reports ResourceData.Get being used inside a resource's Delete function, where it does not work as expected.
AZR/AZR004_resource_id_equality_comparison
Package AZR004 defines an analyzer that reports Resource IDs being compared with the == or != operators instead of resourceids.Match.
Package AZR004 defines an analyzer that reports Resource IDs being compared with the == or != operators instead of resourceids.Match.
AZR/AZR005_case_insensitive_segments_feature_flag
Package AZR005 defines an analyzer that reports assignments to the TreatUserSpecifiedSegmentsAsCaseInsensitive feature flag, which must not be configured.
Package AZR005 defines an analyzer that reports assignments to the TreatUserSpecifiedSegmentsAsCaseInsensitive feature flag, which must not be configured.
AZR/AZR006_stop_context_without_timeouts
Package AZR006 defines an analyzer that reports resources assigning ctx directly from the provider meta object instead of using a timeouts-wrapped StopContext.
Package AZR006 defines an analyzer that reports resources assigning ctx directly from the provider meta object instead of using a timeouts-wrapped StopContext.
AZR/AZR007_state_change_conf_custom_poller
Package AZR007 defines an analyzer that reports StateChangeConf usage, which should be replaced with a custom poller implementing the pollers.PollerType interface.
Package AZR007 defines an analyzer that reports StateChangeConf usage, which should be replaced with a custom poller implementing the pollers.PollerType interface.
AZR/AZR008_flatten_returns_nil_slice
Package AZR008 defines an analyzer that reports flatten* functions that return nil slices or maps.
Package AZR008 defines an analyzer that reports flatten* functions that return nil slices or maps.
AZR/AZR009_lifecycle_logging
Package AZR009 defines an analyzer that reports lifecycle narration logging — "preparing arguments for", "Creating %s", "Decoding state.." — inside a resource's Create, Read, Update, or Delete function, which the provider no longer does.
Package AZR009 defines an analyzer that reports lifecycle narration logging — "preparing arguments for", "Creating %s", "Decoding state.." — inside a resource's Create, Read, Update, or Delete function, which the provider no longer does.
AZR/AZR010_flatten_handles_nil_input
Package AZR010 defines an analyzer that reports flatten* calls whose pointer argument is nil-checked by the caller: the flatten function should handle nil input itself, so every call site can pass the field straight through.
Package AZR010 defines an analyzer that reports flatten* calls whose pointer argument is nil-checked by the caller: the flatten function should handle nil input itself, so every call site can pass the field straight through.
AZS
Package AZS collects the schema & typed SDK model checks.
Package AZS collects the schema & typed SDK model checks.
AZS/AZS001_typed_sdk_model_64bit_types
Package AZS001 defines an analyzer that reports tfschema-tagged typed SDK model fields using non-64-bit numeric types where the SDK's Encode/Decode requires int64/float64.
Package AZS001 defines an analyzer that reports tfschema-tagged typed SDK model fields using non-64-bit numeric types where the SDK's Encode/Decode requires int64/float64.
AZS/AZS002_schema_default_type_mismatch
Package AZS002 defines an analyzer that reports schema declarations whose Default value does not match the declared schema Type.
Package AZS002 defines an analyzer that reports schema declarations whose Default value does not match the declared schema Type.
AZS/AZS003_schema_allows_empty_block
Package AZS003 defines an analyzer that reports optional or required list blocks whose properties are all optional with no defaults, so an empty block (`foo {}`) is valid configuration that can crash expand functions or produce spurious diffs.
Package AZS003 defines an analyzer that reports optional or required list blocks whose properties are all optional with no defaults, so an empty block (`foo {}`) is valid configuration that can crash expand functions or produce spurious diffs.
AZS/AZS004_enum_validation_possible_values
Package AZS004 defines an analyzer that reports enum validations built from a hand-written []string that does not cover every possible value of the SDK enum being validated.
Package AZS004 defines an analyzer that reports enum validations built from a hand-written []string that does not cover every possible value of the SDK enum being validated.
AZS/AZS005_resource_missing_data_source
Package AZS005 defines an analyzer that reports registered resources that have no corresponding data source of the same name, across every registration flavour: untyped plugin SDK maps, typed sdk.Resource slices and framework wrapped resource slices.
Package AZS005 defines an analyzer that reports registered resources that have no corresponding data source of the same name, across every registration flavour: untyped plugin SDK maps, typed sdk.Resource slices and framework wrapped resource slices.
AZS/AZS006_data_source_missing_properties
Package AZS006 defines an analyzer that reports data sources whose same-named resource exposes schema properties the data source does not, across untyped plugin SDK, typed SDK and framework registration flavours.
Package AZS006 defines an analyzer that reports data sources whose same-named resource exposes schema properties the data source does not, across untyped plugin SDK, typed SDK and framework registration flavours.
AZS/AZS007_optional_computed_missing_comment
Package AZS007 defines an analyzer that reports schema declarations that have both Optional: true and Computed: true without a "// Note: O+C because ..." comment between the two fields, explaining why the field is Optional+Computed.
Package AZS007 defines an analyzer that reports schema declarations that have both Optional: true and Computed: true without a "// Note: O+C because ..." comment between the two fields, explaining why the field is Optional+Computed.
AZS/AZS008_registration_entries_sorted
Package AZS008 defines an analyzer that reports registration.go map and slice entries that are not sorted alphabetically.
Package AZS008 defines an analyzer that reports registration.go map and slice entries that are not sorted alphabetically.
AZS/AZS009_computed_only_field_input_attributes
Package AZS009 defines an analyzer that reports computed-only schema fields setting attributes that only apply to user input, and Optional/Required fields nested inside a computed-only block.
Package AZS009 defines an analyzer that reports computed-only schema fields setting attributes that only apply to user input, and Optional/Required fields nested inside a computed-only block.
AZT
Package AZT collects the acceptance testing checks.
Package AZT collects the acceptance testing checks.
AZT/AZT001_acceptance_test_external_package
Package AZT001 defines an analyzer that reports acceptance test files (for resources, data sources, actions and ephemeral resources) that do not use an external _test package.
Package AZT001 defines an analyzer that reports acceptance test files (for resources, data sources, actions and ephemeral resources) that do not use an external _test package.
AZT/AZT002_credentials_from_environment
Package AZT002 defines an analyzer that reports tests reading provider credentials from the environment instead of provisioning their own identity.
Package AZT002 defines an analyzer that reports tests reading provider credentials from the environment instead of provisioning their own identity.
AZV
Package AZV collects the validation checks.
Package AZV collects the validation checks.
AZV/AZV001_error_should_describe_expected_format
Package AZV001 defines an analyzer that reports unclear 'invalid format of' error messages that should describe the expected format instead.
Package AZV001 defines an analyzer that reports unclear 'invalid format of' error messages that should describe the expected format instead.
azignore
Package azignore implements '//azignore:AZX001 - reason' comment directives, letting individual checks be suppressed per line without disabling every azproviderlint check on that line the way '//nolint:azproviderlint' does.
Package azignore implements '//azignore:AZX001 - reason' comment directives, letting individual checks be suppressed per line without disabling every azproviderlint check on that line the way '//nolint:azproviderlint' does.
lib
astx
Package astx defines AST helper functions that are reused in multiple checks.
Package astx defines AST helper functions that are reused in multiple checks.
facts
Package facts is the plumbing shared by analyzers that attach a fact to every function and propagate it across packages: the fixpoint over a package's function declarations, the local-or-imported lookup, and the export.
Package facts is the plumbing shared by analyzers that attach a fact to every function and propagate it across packages: the fixpoint over a package's function declarations, the local-or-imported lookup, and the export.
lifecycle
Package lifecycle finds the functions that implement a resource's Create, Read, Update, and Delete steps, in both provider styles.
Package lifecycle finds the functions that implement a resource's Create, Read, Update, and Delete steps, in both provider styles.
nilguard
Package nilguard is the shared guard engine behind AZG008 and AZG009: it decides whether a pointer-typed variable or selector chain is provably non-nil at a given point in a function body.
Package nilguard is the shared guard engine behind AZG008 and AZG009: it decides whether a pointer-typed variable or selector chain is provably non-nil at a given point in a function body.
pointerpkg
Package pointerpkg locates the go-azure-helpers pointer package within a file so fixes can reference it, adding an import edit when the file does not import it yet.
Package pointerpkg locates the go-azure-helpers pointer package within a file so fixes can reference it, adding an import edit when the file does not import it yet.
requestbody
Package requestbody records which parameters of a function are sent as the body of an HTTP write (PUT, PATCH, POST), so callers can tell when a value they pass becomes a request payload.
Package requestbody records which parameters of a function are sent as the body of an HTTP write (PUT, PATCH, POST), so callers can tell when a value they pass becomes a request payload.
tf
Package tf defines helpers shared by checks that reason about terraform provider code: plugin SDK schema literals, service registration methods and data source files.
Package tf defines helpers shared by checks that reason about terraform provider code: plugin SDK schema literals, service registration methods and data source files.
Package plugin registers azproviderlint's analyzers as a golangci-lint module plugin.
Package plugin registers azproviderlint's analyzers as a golangci-lint module plugin.
Package version records the version and git commit the azproviderlint binary was built from.
Package version records the version and git commit the azproviderlint binary was built from.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL