azproviderlint

command module
v0.3.0 Latest Latest
Warning

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

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

README

azproviderlint

GitHub release build test lint govulncheck CodeQL Go Version License

A custom golangci-lint module plugin providing Azure provider-specific linting rules built on Go's analysis framework.

Installation

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

Then run directly (all rules run by default):

azproviderlint ./...

Each rule is also a flag, and setting any rule flag switches to running only the named rules; a category on its own (-AZG) runs every rule in that category:

azproviderlint -AZG001 ./...
azproviderlint -AZR001 -AZR003 ./...
azproviderlint -AZG ./...
azproviderlint -AZG -AZR001 ./...
As a golangci-lint Plugin

Add to your .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 custom binary:

golangci-lint custom

Then enable in .golangci.yml:

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

Individual rules can be enabled/disabled via plugin settings (an empty enable list means all rules):

linters:
  settings:
    custom:
      azproviderlint:
        type: module
        settings:
          disable: [AZR002]

To run just azproviderlint through the custom binary, skipping every other linter:

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

There is no CLI flag for a single rule — combine --enable-only with an enable: [AZG001] list in the plugin settings above, or use the standalone binary's per-rule flags.

Why the plugin over the standalone binary?

The plugin requires every consumer to build a custom golangci-lint binary (golangci-lint custom), but that one-time cost buys a lot on a codebase the size of a provider:

  • One package-load instead of two. On azurerm this is the dominant cost — loading and type-checking the provider codebase (with its enormous vendor tree) takes minutes, and every separate analysis binary pays it again from scratch. Folding checks into golangci-lint amortizes it, and golangci-lint's result cache makes warm local re-runs dramatically faster; a standalone multichecker reloads the world every single time.
  • Unified config and reporting. .golangci.yml path exclusions (generated files, /sdk/, third_party — already curated in the provider repo) apply to these checks for free; one output stream, one CI job, SARIF/annotations, and --new-from-rev — the killer feature for a codebase with 22+ pre-existing findings per service, since checks can be enforced on new code only instead of azignoring a decade of history.
  • //nolint works uniformly alongside //azignore (see Ignoring Reports).

The standalone binary remains the right tool for one-off or single-rule runs (azproviderlint -AZG001 ./...), editor integrations that expect a plain analysis-style vet tool, and quick iteration while developing new checks.

Rules

Rules are named AZ<category letter><number>, aligned with tfproviderlint's category letters (R, S, V, AT) where they overlap.

AZG — General Go Style / Readability
Rule Description
AZG000 //azignore directives must include a reason (//azignore:AZR001 - <reason>) documenting why the check does not apply — bare directives still suppress, but are themselves reported; disable this check to accept bare directives
AZG001 err := SomeFunc() or _, err := SomeFunc() followed by if err != nil should be combined into a single if init statement
AZG002 Error messages should describe the expected format instead of saying invalid format of ...
AZG003 pointer.To(sdk.SomeEnum(v)) explicit go-azure-sdk enum conversions must use the generic pointer.ToEnum[sdk.SomeEnum](v) helper instead
AZG004 y := <zero>; if x != nil { y = *x } zero-value initialization followed by a nil check and pointer dereference must use the generic pointer.From(x) helper instead
AZG005 x := <expr> immediately followed by y = x or return x, with no other use of x, should be inlined into the consuming statement
AZR — Resource Implementation
Rule Description
AZR001 SetId must not be passed a dereferenced pointer (d.SetId(*read.ID)) — use a generated Resource ID Formatter/Parser and d.SetId(id.ID())
AZR002 Resources must register separate Create and Update methods instead of a combined CreateUpdate method
AZR003 d.Get / metadata.ResourceData.Get must not be used inside a resource's Delete function, where it does not work as expected
AZR004 Resource IDs must not be compared with ==/!= — use resourceids.Match
AZR005 features.TreatUserSpecifiedSegmentsAsCaseInsensitive must not be set — the case-aware comparisons feature is not ready for use
AZR006 ctx must not be assigned directly from meta.(*clients.Client).StopContext — use timeouts.ForCreate/ForRead/ForUpdate/ForDelete so Custom Timeouts work
AZR007 StateChangeConf from github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry must not be used — prefer a custom poller implementing pollers.PollerType driven via pollers.NewPoller(...).PollUntilDone(ctx)
AZD — Data Sources
Rule Description
AZD001 Data sources must return an error when a resource cannot be found, not call d.SetId("")
AZD002 Data sources must return an error when a resource cannot be found, not call metadata.MarkAsGone
AZS — Schema & Typed SDK Models
Rule Description
AZS001 Typed SDK model fields (tagged tfschema) must use 64-bit numeric types — int64 not int/int16/int32, float64 not float32 — including slices, maps, pointers, named types, and aliases of them
AZS002 Schema Default values must match the declared Type — a bool default on a TypeInt schema only fails at plan time; named constants are resolved via the type checker
AZS003 Optional/required TypeList blocks whose properties are all optional with no defaults allow foo {}, which can crash expand functions or cause spurious diffs — constrain with AtLeastOneOf/ExactlyOneOf, a Required property, or a Default
AZS004 validation.StringInSlice with a hand-written list of SDK enum values must use the SDK's PossibleValuesFor<Enum>() helper instead — partial lists reject valid API values, and even complete lists go stale when the SDK adds new ones
AZS005 Registered resources must have a data source of the same name — checked across untyped plugin SDK maps, typed SDK slices and framework wrapped slices, including feature-flagged conditional registration
AZS006 Data sources must expose the properties of their same-named resource — compares recursively collected schema property names per registration flavour (untyped maps, typed Arguments()/Attributes(), framework Schema()) and reports resource properties absent from the data source
AZC — Clients & SDK Usage
Rule Description
AZC001 Azure SDK (track1 & kermit) clients must be created via NewFoosClientWithBaseURI with the resource manager endpoint explicitly specified, not NewFoosClient(o.SubscriptionId)
AZT — Acceptance Testing
Rule Description
AZT001 Acceptance test files (resource, data source, action, ephemeral — incl. list and generated variants) must use an external _test package to prevent circular dependencies
AZT002 Tests (_test.go files only) must not obtain credentials via os.Getenv("ARM_CLIENT_ID"/"ARM_CLIENT_SECRET"/"ARM_CLIENT_SECRET_ALT") — create an azurerm_user_assigned_identity with minimal permissions instead
AZN — Naming Conventions

No rules yet — reserved for property naming convention rules (e.g. percentage properties using a _percentage suffix rather than _in_percent).

AZV — Validation

No rules yet — reserved for missing/incorrect validation rules (e.g. string arguments without a ValidateFunc).

Ignoring Reports

When run via golangci-lint, all azproviderlint reports on a line can be ignored with a //nolint:azproviderlint comment at the end of the offending line or on the line immediately preceding it.

To ignore a specific check — leaving the others active, and working under any driver including the standalone binary — use a //azignore:<Rule> - <reason> comment in the same positions. Multiple rules can be listed separated by commas, and the reason is free text after the rule list — the - separator (/ also work) is optional:

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)

The reason is required: directives without one still suppress their target checks, but are themselves reported by AZG000 (disable that check to drop the requirement).

Documentation

The Go Gopher

There is no documentation for this package.

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_base_uri
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_error_should_describe_expected_format
Package AZG002 defines an analyzer that reports unclear 'invalid format of' error messages that should describe the expected format instead.
Package AZG002 defines an analyzer that reports unclear 'invalid format of' error messages that should describe the expected format instead.
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 immediately consumed by the next statement — `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 immediately consumed by the next statement — `x := <expr>` followed by `y = x` or `return x` where x has no other use — which should be inlined.
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
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.
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_missing_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.
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.
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.
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