terraform-linters / tflint-ruleset-azurerm

TFLint ruleset for terraform-provider-azurerm
Mozilla Public License 2.0
120 stars 25 forks source link

Proposal for supporting versions of the tflint-ruleset-azurerm #64

Open hattan opened 4 years ago

hattan commented 4 years ago

Hi @wata727 and @bendrucker ! Here is a proposal for adding support for versioning rules and allowing users to specify a rule version specific to the version for AzureRM terraform Provider.

Our team would be happy to help out with development and contribute to the project, I wanted to open the discussion and gather your thoughts.

Summary

This proposal is to add support for versioning and specifically pinning tflint rulesets to Terraform Provider versions and also API versions.

In the case of the TFlint ruleset for AzureRM, this would version the Terraform AzureRM provider against the version of the OpenApi Spec for the ARM Apis.

Currently a terraform resource is mapped to the ARM api version via a mapping file that is manually created.


Approach 1 - Applying version numbers to existing manual mapping structure.

As part of the CI/CD build, the version could be appended and attached to the final build artifact.


Approach 2 - Generating Mappings by inspection of AzureRM Source.

In this approach, rather than a manual static mapping. An automated process could clone the AzureRM repo and locate api information.

For example: Assuming we would like to find the ARM api for azurerm_analysis_services_server.

A basic implementation of this would be:

#!/usr/bin/env bash

declare version=""
declare resourceName=""
declare DEBUG_FLAG=false

while [[ "$#" -gt 0 ]]
do
  case $1 in
    -r | --resource)
      resourceName=$2
      ;;

    -d | --debug )             
      DEBUG_FLAG=true
      ;; 
  esac
  shift
done

providerVersion=$(cat provider.tf | grep version)
providerVersion="v"$(echo "$providerVersion" | cut -d'"' -f 2)
echo "Found Provider version: $providerVersion"

if [ ! -d ./terraform-provider-azurerm ]; then
  git clone git@github.com:terraform-providers/terraform-provider-azurerm.git
fi

pushd terraform-provider-azurerm
  git fetch && git fetch --tags
  git checkout $version

  resourceFile=$(grep -Ril "${resourceName}" . --include=*.go --exclude=*_test.go --exclude=*registration.go)
  resourceFolder="${resourceFile%/*}/"
  go list -json -f "{{.ImportPath}} {{.Imports}}" github.com/terraform-providers/terraform-provider-azurerm/$resourceFolder | jq -r '.Imports[]  | select(. | contains("azure-sdk-for-go"))'
 popd

Deployment of Rules.

We'd also like to propose a mechanism for easily loading up cloud specific rulesets. In the case of AzureRM, perfhaps adding a tflint command to load pluging rulesets.

 tflint -configure-plugin=azurerm

Which would then fetch the pluging from a blob storage account and configure it locally for the end user. As part of the CI/CD process for building the ruleset, the compiled binary could be pushed to the storage account.

Let me know your thoughts and we'd love to put together a quick spike to share with you when ready.

Thanks!

wata727 commented 4 years ago

Thank you for sharing your proposal. It's interesting.

provider versioning

Approach 2 is probably the most ideal for this way. However, it depends heavily on the implementation of the AzureRM provider, so its maintenance costs must be considered.

It's a good start with a bash script, but we may eventually need a script written in Go to do more (For example, we can use the go/parser package to get an AST)

Deployment of Rules

Yes, I strongly feel the need for this.

My current idea is to implement tflint --init as well as Terraform and download the plugins needed in the process. The required plugins can be obtained from the plugin definition written in .tflint.hcl.

hattan commented 4 years ago

Hi @wata727 - Thanks for the update, the AST sounds interesting and we'll take a look this week. With approach 2 we could also auto-generate the rules anytime AzureRM has a new release. This could be a workflow that runs and does the work.

In terms of downloading the plugins. Last week I was doing some work with terraform-bundle and it works great for grabbing the desired version of terraform and all the providers specified in a config file.

I think using a similar approach would work well.

bendrucker commented 4 years ago

I don't think source inspection is even necessary. Provider binaries can report their resources/schema. That's what powers the providers schema command.

Generating a TFLint plugin that supports a single version of a provider isn't too hard. Supporting multiple provider versions would be ideal, but a whole lot trickier. That implies not only packaging multiple versions of a rule, but also detecting the version of the provider in use. That probably involves some Terraform reverse engineering.

For now, making it easy for the latest plugin to correctly match the latest provider version seems like the accessible option that doesn't require significant new functionality in TFLint core.

hattan commented 4 years ago

Makes sense. We have an idea on how to support minimum and maximum versions for rules. I'll provide an update in the next day or so.