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

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

Open
hattan opened this issue Oct 14, 2020 · 4 comments
Open

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

hattan opened this issue Oct 14, 2020 · 4 comments

Comments

@hattan
Copy link
Contributor

hattan commented Oct 14, 2020

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.

  • tools/apispec-rule-gen/mappings could become tools/apispec-rule-gen/mappings-$PROVIDER_VERSION
  • Schema would reside in schema-$PROVIDER_VERSION
  • The tool will need to generate
    • docs-$PROVIDER_VERSION/rules
    • rules-$PROVIDER_VERSION/apispec
  • Manually created rules could live in rules-$PROVIDER_VERSION/

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.

  • git clone git@github.com:terraform-providers/terraform-provider-azurerm.git

  • git fetch && git fetch --tags

  • git checkout v2.27.0

    This can be read automatically from provider.tf via something like:

    providerVersion=$(cat provider.tf | grep version)
    providerVersion="v"$(echo "$providerVersion" | cut -d'"' -f 2)
  • grep -Ril "${resourceName}" . --include=*.go --exclude=*_test.go --exclude=*registration.go Find Go Source file for resource.

  • go list -json -f "{{.ImportPath}} {{.Imports}}" github.com/terraform-providers/terraform-provider-azurerm/$resourceFolder | jq -r '.Imports[] | select(. | contains("azure-sdk-for-go"))'
    popd

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
Copy link
Member

wata727 commented Oct 18, 2020

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
Copy link
Contributor Author

hattan commented Oct 19, 2020

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
Copy link
Member

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
Copy link
Contributor Author

hattan commented Nov 3, 2020

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants