├── .gitignore ├── .travis.yml ├── Dockerfile ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── SECURITY.md └── build ├── file_utils.rb └── static_utils.rb /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | /.config 4 | /coverage/ 5 | /InstalledFiles 6 | /pkg/ 7 | /spec/reports/ 8 | /spec/examples.txt 9 | /test/tmp/ 10 | /test/version_tmp/ 11 | /tmp/ 12 | 13 | # Used by dotenv library to load environment variables. 14 | # .env 15 | 16 | ## Specific to RubyMotion: 17 | .dat* 18 | .repl_history 19 | *.bridgesupport 20 | build-iPhoneOS/ 21 | build-iPhoneSimulator/ 22 | 23 | ## Specific to RubyMotion (use of CocoaPods): 24 | # 25 | # We recommend against adding the Pods directory to your .gitignore. However 26 | # you should judge for yourself, the pros and cons are mentioned at: 27 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 28 | # 29 | # vendor/Pods/ 30 | 31 | ## Documentation cache and generated files: 32 | /.yardoc/ 33 | /_yardoc/ 34 | /doc/ 35 | /rdoc/ 36 | 37 | ## Environment normalization: 38 | /.bundle/ 39 | /vendor/bundle 40 | /lib/bundler/man/ 41 | 42 | # for a library or gem, you might want to ignore these files since the code is 43 | # intended to run in multiple environments; otherwise, check them in: 44 | # Gemfile.lock 45 | # .ruby-version 46 | # .ruby-gemset 47 | 48 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 49 | .rvmrc 50 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: true 2 | dist: trusty 3 | language: ruby 4 | rvm: 5 | - 2.3 6 | 7 | services: 8 | - docker 9 | 10 | jobs: 11 | include: 12 | - stage: build docker image 13 | if: type IN (pull_request) 14 | install: true 15 | script: 16 | - docker build -t microsoft/terraform-test:$TERRAFORM_VERSION . --build-arg tfver=$TERRAFORM_VERSION --build-arg gover=$GOLANG_VERSION 17 | - stage: push docker image 18 | if: (branch = master) AND (type IN (push, api, cron)) 19 | install: true 20 | script: 21 | - docker build -t microsoft/terraform-test:$TERRAFORM_VERSION -t microsoft/terraform-test:latest . --build-arg tfver=$TERRAFORM_VERSION --build-arg gover=$GOLANG_VERSION 22 | - docker login -u="$DOCKER_USER" -p="$DOCKER_PASSWORD" 23 | - docker push microsoft/terraform-test:$TERRAFORM_VERSION 24 | - docker push microsoft/terraform-test:latest 25 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ruby:2.7.1 2 | ARG tfver 3 | ARG gover 4 | ENV TERRAFORM_VERSION=$tfver 5 | ENV GOLANG_VERSION=$gover 6 | 7 | COPY ["Gemfile", "Rakefile", "/tf-test/"] 8 | COPY build/ /tf-test/build/ 9 | RUN apt-get update && gem update --system && apt-get install unzip \ 10 | && curl -Os https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip \ 11 | && curl -Os https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_SHA256SUMS \ 12 | && curl https://keybase.io/hashicorp/pgp_keys.asc | gpg --import \ 13 | && curl -Os https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_SHA256SUMS.sig \ 14 | && gpg --verify terraform_${TERRAFORM_VERSION}_SHA256SUMS.sig terraform_${TERRAFORM_VERSION}_SHA256SUMS \ 15 | && shasum -a 256 -c terraform_${TERRAFORM_VERSION}_SHA256SUMS 2>&1 | grep "${TERRAFORM_VERSION}_linux_amd64.zip:\sOK" \ 16 | && unzip terraform_${TERRAFORM_VERSION}_linux_amd64.zip -d /usr/local/bin 17 | 18 | RUN apt-get autoremove -y imagemagick 19 | 20 | WORKDIR /tf-test/ 21 | RUN gem install rake --version =13.0.1 \ 22 | && gem install colorize --version =0.8.1 \ 23 | && gem install rspec --version =3.9.0 24 | WORKDIR /tf-test/module 25 | 26 | RUN curl -Os https://storage.googleapis.com/golang/go${GOLANG_VERSION}.linux-amd64.tar.gz >/dev/null 2>&1 \ 27 | && tar -zxvf go${GOLANG_VERSION}.linux-amd64.tar.gz -C /usr/local/ >/dev/null 28 | ENV PATH /usr/local/go/bin:$PATH 29 | ENV GOPATH $HOME/go 30 | 31 | RUN go get github.com/katbyte/terrafmt -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | ruby "~> 2.3.0" 2 | 3 | source 'https://rubygems.org/' 4 | 5 | gem 'rake', '~>12.3.0' 6 | 7 | group :test do 8 | gem 'colorize', '~>0.8.0' 9 | gem 'kitchen-terraform', '~>3.0.0' 10 | gem 'rspec', '~>3.7.0' 11 | gem 'test-kitchen', '~>1.16.0' 12 | end 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | This Docker image (see [Dockerfile](https://github.com/Azure/terraform-test/blob/master/Dockerfile)) is for testing [Azure Terraform modules](https://registry.terraform.io/browse?provider=azurerm). 4 | 5 | [![Build Status](https://travis-ci.org/Azure/terraform-test.svg?branch=master)](https://travis-ci.org/Azure/terraform-test) 6 | 7 | # Terraform 0.13 8 | 9 | This image now supports terraform 0.13 alongside 012 and 0.11. 10 | 11 | # Usage 12 | 13 | This image can be used for terraform lint or end to end tests against Azure. 14 | 15 | ## Lint Tests 16 | 17 | These tests ensure consistency in formatting for the terraform module code. 18 | 19 | Setup the environment variable which specifies the root path of the module code on the local machine. 20 | 21 | ```shell 22 | export MODULE_PATH=/user/me/source/Azure/terraform-azurerm-modulename 23 | ``` 24 | 25 | Now run the lint tests: 26 | 27 | ```shell 28 | docker run -v $MODULE_PATH:/tf-test/module --rm microsoft/terraform-test rake -f ../Rakefile build 29 | ``` 30 | 31 | ## End to End Tests 32 | 33 | These tests will execute a `terraform apply` to deploy the azure module as defined in the `/test/integration` directory and then `terraform destroy` to delete them. 34 | 35 | ### Pre-requisites 36 | 37 | Azure Setup 38 | The container uses Azure SPN Keys to access Azure. The following environment variables need to be set on the local machine running the container image. 39 | 40 | ``` 41 | ARM_SUBSCRIPTION_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 42 | ARM_CLIENT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 43 | ARM_CLIENT_SECRET=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 44 | ARM_TENANT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 45 | ARM_TEST_LOCATION=westus 46 | ARM_TEST_LOCATION_ALT=westus 47 | ``` 48 | 49 | Log Setup 50 | The logs generated by the test will be stored in the `/tf-test/.kitchen` directory in the container. Mount this directory to the location of your choice so you can keep the logs once the test have completed. 51 | 52 | Secret Setup 53 | Some test may require SSH keys or other secrets to be passed to the container. For SSH keys, mount the directory where they are located as `/root/.ssh` in the container. If you are reusing your keys, the above command should be: 54 | 55 | ### Running the Tests 56 | 57 | Setup the environment variable which specifies the root path of the module code on the local machine. 58 | 59 | ```shell 60 | export MODULE_PATH=/user/me/source/Azure/terraform-azurerm-modulename 61 | ``` 62 | 63 | Now run the tests using this docker command: 64 | 65 | ```shell 66 | docker run -v ~/.ssh:/root/.ssh/ -v $MODULE_PATH/logs:/tf-test/module/.kitchen -v $MODULE_PATH:/tf-test/module -e ARM_CLIENT_ID -e ARM_TENANT_ID -e ARM_SUBSCRIPTION_ID -e ARM_CLIENT_SECRET -e ARM_TEST_LOCATION -e ARM_TEST_LOCATION_ALT --rm microsoft/terraform-test rake -f ../Rakefile e2e 67 | ``` 68 | 69 | This may take a number of minutes depending on the size of the module and there will be no output to the terminal until the tests complete. To see progress, look at the files being generated and updated under the local `$MODULE_PATH/logs` directory. 70 | 71 | # Contributing 72 | 73 | This project welcomes contributions and suggestions. Most contributions require you to agree to a 74 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us 75 | the rights to use your contribution. For details, visit https://cla.microsoft.com. 76 | 77 | When you submit a pull request, a CLA-bot will automatically determine whether you need to provide 78 | a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions 79 | provided by the bot. You will only need to do this once across all repos using our CLA. 80 | 81 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 82 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or 83 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 84 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'colorize' 2 | require 'rspec/core/rake_task' 3 | 4 | require_relative 'build/file_utils' 5 | require_relative 'build/static_utils' 6 | 7 | namespace :presteps do 8 | task :clean_up do 9 | clean_up_kitchen 10 | clean_up_terraform 11 | end 12 | end 13 | 14 | namespace :static do 15 | task :style do 16 | style_tf 17 | end 18 | task :lint do 19 | lint_tf 20 | end 21 | task :format do 22 | format_tf 23 | end 24 | end 25 | 26 | namespace :integration do 27 | task :converge do 28 | exit_code = system( "kitchen converge" ) 29 | if exit_code != true 30 | raise "ERROR: Test kitchen converge failed! #{exit_code}\n" 31 | end 32 | end 33 | task :verify do 34 | exit_code = system( "kitchen verify" ) 35 | if exit_code != true 36 | raise "ERROR: Test kitchen verify failed! #{exit_code}\n" 37 | end 38 | end 39 | task :test do 40 | exit_code = system( "kitchen test" ) 41 | if exit_code != true 42 | raise "ERROR: Test kitchen test failed! #{exit_code}\n" 43 | end 44 | end 45 | task :destroy do 46 | exit_code = system( "kitchen destroy" ) 47 | if exit_code != true 48 | raise "ERROR: Test kitchen destroy failed! #{exit_code}\n" 49 | end 50 | end 51 | end 52 | 53 | task :prereqs => [ 'presteps:clean_up' ] 54 | 55 | task :validate => [ 'static:style', 'static:lint' ] 56 | 57 | task :format => [ 'static:format' ] 58 | 59 | task :build => [ 'prereqs', 'validate' ] 60 | 61 | task :unit => [] 62 | 63 | task :e2e => [ 'integration:test' ] 64 | 65 | task :default => [ 'build' ] 66 | 67 | task :full => [ 'build', 'unit', 'e2e'] 68 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /build/file_utils.rb: -------------------------------------------------------------------------------- 1 | require 'fileutils' 2 | 3 | def clean_up_kitchen 4 | if File.exists? '.kitchen' 5 | print "INFO: Cleaning up the .kitchen folder...\n" 6 | FileUtils.rm_rf('.kitchen') 7 | end 8 | end 9 | 10 | def clean_up_terraform 11 | if File.exists? '.terraform' 12 | print "INFO: Cleaning up the .terraform folder...\n" 13 | FileUtils.rm_rf('.terraform') 14 | end 15 | end -------------------------------------------------------------------------------- /build/static_utils.rb: -------------------------------------------------------------------------------- 1 | require 'colorize' 2 | require 'fileutils' 3 | 4 | def lint_tf 5 | # Do the linting on current working folder. 6 | print "INFO: Linting Terraform configurations...\n".yellow 7 | 8 | if ENV['TERRAFORM_VERSION'].start_with?("0.12") 9 | success = system ("terraform init") 10 | if not success 11 | raise "ERROR: terraform init failed!\n".red 12 | end 13 | message = `terraform validate ./ >/dev/null` 14 | elsif ENV['TERRAFORM_VERSION'].start_with?("0.11") 15 | message = `terraform validate -check-variables=false 2>&1` 16 | end 17 | 18 | # Check the linting message. 19 | if not message.empty? 20 | raise "ERROR: Linting Terraform configurations failed!\n#{message}\n".red 21 | else 22 | print "INFO: Done!\n".green 23 | end 24 | end 25 | 26 | def style_tf 27 | # Do the style checking on current working folder. 28 | print "INFO: Styling Terraform configurations...\n".yellow 29 | if ENV['TERRAFORM_VERSION'].start_with?("0.12") 30 | message = `terraform fmt -check 2>&1` 31 | elsif ENV['TERRAFORM_VERSION'].start_with?("0.11") 32 | message = `terraform fmt -check=true 2>&1` 33 | end 34 | 35 | # Check the styling message. 36 | if not message.empty? 37 | raise "ERROR: Styling Terraform configurations failed!\n#{message}\n".red 38 | else 39 | print "INFO: Done!\n".green 40 | end 41 | end 42 | 43 | def format_tf 44 | # Apply the canonical format and style on current working folder. 45 | print "INFO: Formatting Terraform configurations...\n".yellow 46 | if ENV['TERRAFORM_VERSION'].start_with?("0.12") 47 | message = `terraform fmt -diff 2>&1` 48 | elsif ENV['TERRAFORM_VERSION'].start_with?("0.11") 49 | message = `terraform fmt -diff=true 2>&1` 50 | end 51 | 52 | # Check the styling message. 53 | if not message.empty? 54 | raise "ERROR: Formatting Terraform configurations failed!\n#{message}\n".red 55 | else 56 | print "INFO: Done!\n".green 57 | end 58 | end --------------------------------------------------------------------------------