Add Terratest Example for Compute Module (#66)

* Add Terratest Example for Compute Module

* Add Terratest Example for Compute Module

* style problem

* style problem

* style problem

* build test (#2)

* build test

* build test

* build test

* build test

* build test

* build test

* Add Terratest

* Add Terratest

* Add Terratest

* Update Files

* Hide Environment Variables

* Allow Pull Requests

* Update Files

* rake build

* Update .travis.yml

* Required Changes

* Required Changes

* Update README

* Add dep ensure

* Add dep init

* Update README

* Update Docker Image

* Use dep ensure in Dockerfile

* Dep Ensure in Rakefile

* Update README
This commit is contained in:
Zhenchen Xiao 2018-07-28 15:19:51 +08:00 коммит произвёл GitHub
Родитель 198fc3115e
Коммит 627c6c212a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
21 изменённых файлов: 419 добавлений и 151 удалений

5
.gitignore поставляемый
Просмотреть файл

@ -7,9 +7,12 @@ terraform.tfvars
*.tfstate
*.tfstate.backup
# Go vendor directory
vendor/
# Module directory
.terraform/
.test-data/
### https://raw.github.com/github/gitignore/abad92dac5a4306f72242dae3bca6e277bce3615/Global/Vim.gitignore

Просмотреть файл

@ -1,36 +0,0 @@
---
driver:
name: "terraform"
root_module_directory: "test/integration/fixtures"
parallelism: 1
variable_files:
- "test/integration/fixtures/testing.tfvars"
provisioner:
name: "terraform"
platforms:
-
name: "ubuntu"
transport:
name: "ssh"
ssh_key: ~/.ssh/id_rsa
verifier:
name: "terraform"
groups:
-
name: "remote"
controls:
- "operating_system"
hostnames: "test_target_public_dns"
port: 22
username: "azureuser"
-
name: "local"
controls:
- "state_file"
suites:
- name: "compute"

Просмотреть файл

@ -13,7 +13,7 @@ services:
- docker
env:
- TERRAFORM_VERSION=0.11.3 IMAGE_NAME=azure-compute-module
- TERRAFORM_VERSION=0.11.7 IMAGE_NAME=azure-compute-module
jobs:
include:

Просмотреть файл

@ -1,5 +1,5 @@
# Pull the base image with given version.
ARG BUILD_TERRAFORM_VERSION="0.11.1"
ARG BUILD_TERRAFORM_VERSION="0.11.7"
FROM microsoft/terraform-test:${BUILD_TERRAFORM_VERSION}
ARG MODULE_NAME="terraform-azurerm-compute"
@ -20,10 +20,18 @@ ENV ARM_TENANT_ID=${BUILD_ARM_TENANT_ID}
ENV ARM_TEST_LOCATION=${BUILD_ARM_TEST_LOCATION}
ENV ARM_TEST_LOCATION_ALT=${BUILD_ARM_TEST_LOCATION_ALT}
RUN mkdir /usr/src/${MODULE_NAME}
COPY . /usr/src/${MODULE_NAME}
# Set work directory and generate ssh key
RUN mkdir /go
RUN mkdir /go/bin
RUN mkdir /go/src
RUN mkdir /go/src/${MODULE_NAME}
COPY . /go/src/${MODULE_NAME}
WORKDIR /go/src/${MODULE_NAME}
RUN ssh-keygen -q -t rsa -b 4096 -f $HOME/.ssh/id_rsa
WORKDIR /usr/src/${MODULE_NAME}
# Install required go packages using dep ensure
ENV GOPATH /go
ENV PATH /usr/local/go/bin:$GOPATH/bin:$PATH
RUN /bin/bash -c "curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh"
RUN ["bundle", "install", "--gemfile", "./Gemfile"]

Просмотреть файл

@ -6,6 +6,4 @@ group :test do
git 'https://github.com/Azure/terramodtest.git' do
gem 'terramodtest', :tag => 'v0.2.0'
end
gem 'test-kitchen', '1.16.0'
gem 'kitchen-terraform', '3.0.0'
end

158
Gopkg.lock сгенерированный Normal file
Просмотреть файл

@ -0,0 +1,158 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
digest = "1:c3948295121c6b6f3db7c97733f1eb33f48f5d526a36e083434deb91d2e2cbeb"
name = "github.com/aws/aws-sdk-go"
packages = [
"aws",
"aws/awserr",
"aws/awsutil",
"aws/client",
"aws/client/metadata",
"aws/corehandlers",
"aws/credentials",
"aws/credentials/ec2rolecreds",
"aws/credentials/endpointcreds",
"aws/credentials/stscreds",
"aws/csm",
"aws/defaults",
"aws/ec2metadata",
"aws/endpoints",
"aws/request",
"aws/session",
"aws/signer/v4",
"internal/sdkio",
"internal/sdkrand",
"internal/sdkuri",
"internal/shareddefaults",
"private/protocol",
"private/protocol/ec2query",
"private/protocol/eventstream",
"private/protocol/eventstream/eventstreamapi",
"private/protocol/json/jsonutil",
"private/protocol/jsonrpc",
"private/protocol/query",
"private/protocol/query/queryutil",
"private/protocol/rest",
"private/protocol/restxml",
"private/protocol/xml/xmlutil",
"service/acm",
"service/autoscaling",
"service/cloudwatchlogs",
"service/ec2",
"service/iam",
"service/kms",
"service/s3",
"service/s3/s3iface",
"service/s3/s3manager",
"service/sns",
"service/sqs",
"service/sts",
]
pruneopts = "UT"
revision = "96313df4b1ba47ade3de7b2b90d69c02a81ddaa4"
version = "v1.14.33"
[[projects]]
digest = "1:e625e9cdf85de9b3cfd4324c4575d6dd23f9ac1e63f21f82c39d719d8698e79e"
name = "github.com/boombuler/barcode"
packages = [
".",
"qr",
"utils",
]
pruneopts = "UT"
revision = "3cfea5ab600ae37946be2b763b8ec2c1cf2d272d"
version = "v1.0.0"
[[projects]]
digest = "1:fe8a03a8222d5b913f256972933d26d24ad7c8286692a42943bc01633cc8fce3"
name = "github.com/go-ini/ini"
packages = ["."]
pruneopts = "UT"
revision = "358ee7663966325963d4e8b2e1fbd570c5195153"
version = "v1.38.1"
[[projects]]
digest = "1:8f8811f9be822914c3a25c6a071e93beb4c805d7b026cbf298bc577bc1cc945b"
name = "github.com/google/uuid"
packages = ["."]
pruneopts = "UT"
revision = "064e2069ce9c359c118179501254f67d7d37ba24"
version = "0.2"
[[projects]]
digest = "1:a2516c7b3e32d4545ea703e557d81755eff228623dcad3ce1039acc28d400544"
name = "github.com/gruntwork-io/terratest"
packages = [
"modules/aws",
"modules/collections",
"modules/files",
"modules/logger",
"modules/packer",
"modules/random",
"modules/retry",
"modules/shell",
"modules/ssh",
"modules/terraform",
"modules/test-structure",
]
pruneopts = "UT"
revision = "a3246fed2e3e40b345e13a745e435b36b17d0c16"
version = "v0.9.15"
[[projects]]
digest = "1:e22af8c7518e1eab6f2eab2b7d7558927f816262586cd6ed9f349c97a6c285c4"
name = "github.com/jmespath/go-jmespath"
packages = ["."]
pruneopts = "UT"
revision = "0b12d6b5"
[[projects]]
digest = "1:712648e44349f70516f646f06ab39fd48c311a3cade3ae1f951dc9488150a382"
name = "github.com/pquerna/otp"
packages = [
".",
"hotp",
"totp",
]
pruneopts = "UT"
revision = "b7b89250c468c06871d3837bee02e2d5c155ae19"
version = "v1.0.0"
[[projects]]
branch = "master"
digest = "1:6126c75359647f32c1437fead4933069915ead6a924cdf9f645a0e6e71262bff"
name = "golang.org/x/crypto"
packages = [
"curve25519",
"ed25519",
"ed25519/internal/edwards25519",
"internal/chacha20",
"internal/subtle",
"poly1305",
"ssh",
]
pruneopts = "UT"
revision = "c126467f60eb25f8f27e5a981f32a87e3965053f"
[[projects]]
branch = "master"
digest = "1:76ee51c3f468493aff39dbacc401e8831fbb765104cbf613b89bef01cf4bad70"
name = "golang.org/x/net"
packages = ["context"]
pruneopts = "UT"
revision = "3673e40ba22529d22c3fd7c93e97b0ce50fa7bdd"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
input-imports = [
"github.com/gruntwork-io/terratest/modules/retry",
"github.com/gruntwork-io/terratest/modules/ssh",
"github.com/gruntwork-io/terratest/modules/terraform",
"github.com/gruntwork-io/terratest/modules/test-structure",
]
solver-name = "gps-cdcl"
solver-version = 1

34
Gopkg.toml Normal file
Просмотреть файл

@ -0,0 +1,34 @@
# Gopkg.toml example
#
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
#
# [prune]
# non-go = false
# go-tests = true
# unused-packages = true
[[constraint]]
name = "github.com/gruntwork-io/terratest"
version = "0.9.15"
[prune]
go-tests = true
unused-packages = true

Просмотреть файл

@ -1,8 +1,8 @@
# terraform-azurerm-compute #
# terraform-azurerm-compute
[![Build Status](https://travis-ci.org/Azure/terraform-azurerm-compute.svg?branch=master)](https://travis-ci.org/Azure/terraform-azurerm-compute)
Deploys 1+ Virtual Machines to your provided VNet
=================================================
## Deploys 1+ Virtual Machines to your provided VNet
This Terraform module deploys Virtual Machines in Azure with the following characteristics:
@ -14,8 +14,7 @@ This Terraform module deploys Virtual Machines in Azure with the following chara
> Note: Terraform module registry is incorrect in the number of required parameters since it only deems required based on variables with non-existent values. The actual minimum required variables depends on the configuration and is specified below in the usage.
Simple Usage
-----
## Simple Usage
This contains the bare minimum options to be configured for the VM to be provisioned. The entire code block provisions a Windows and a Linux VM, but feel free to delete one or the other and corresponding outputs. The outputs are also not necessary to provision, but included to make it convenient to know the address to connect to the VMs after provisioning completes.
@ -58,8 +57,7 @@ Provisions an Ubuntu Server 16.04-LTS VM and a Windows 2016 Datacenter Server VM
}
```
Advanced Usage
-----
## Advanced Usage
The following example illustrates some of the configuration options available to deploy a virtual machine. Feel free to remove the Linux or Windows modules and corresponding outputs.
@ -81,7 +79,7 @@ More specifically this provisions:
- Two Public IP addresses (one for each VM)
- Opens up port 3389 for RDP access using the password as shown
```hcl
```hcl
module "linuxservers" {
source = "Azure/compute/azurerm"
resource_group_name = "terraform-advancedvms"
@ -149,10 +147,10 @@ More specifically this provisions:
```
Test
-----
## Test
### Configurations
- [Configure Terraform for Azure](https://docs.microsoft.com/en-us/azure/virtual-machines/linux/terraform-install-configure)
- [Generate and add SSH Key](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/) Save the key in ~/.ssh/id_rsa. This is not required for Windows deployments.
@ -161,9 +159,11 @@ We provide 2 ways to build, run, and test the module on a local development mach
### Native (Mac/Linux)
#### Prerequisites
- [Ruby **(~> 2.3)**](https://www.ruby-lang.org/en/downloads/)
- [Bundler **(~> 1.15)**](https://bundler.io/)
- [Terraform **(~> 0.11.0)**](https://www.terraform.io/downloads.html)
- [Terraform **(~> 0.11.7)**](https://www.terraform.io/downloads.html)
- [Golang **(~> 1.10.3)**](https://golang.org/dl/)
#### Quick Run
@ -174,7 +174,9 @@ $ curl -sSL https://raw.githubusercontent.com/Azure/terramodtest/master/tool/env
```
Then simply run it in local shell:
```sh
$ cd $GOPATH/src/{directory_name}/
$ bundle install
$ rake build
$ rake e2e
@ -208,11 +210,16 @@ This runs the end to end tests:
$ docker run --rm azure-compute /bin/bash -c "bundle install && rake e2e"
```
Authors
=======
This runs the full tests:
```sh
$ docker run --rm azure-compute /bin/bash -c "bundle install && rake full"
```
## Authors
Originally created by [David Tesar](http://github.com/dtzar)
License
=======
## License
[MIT](LICENSE)

Просмотреть файл

@ -6,13 +6,6 @@ require 'rspec/core/rake_task'
require 'bundler/setup'
require 'terramodtest'
namespace :presteps do
task :clean_up do
clean_up_kitchen
clean_up_terraform
end
end
namespace :static do
task :style do
style_tf
@ -26,21 +19,21 @@ namespace :static do
end
namespace :integration do
task :converge do
kitchen_converge
end
task :verify do
kitchen_verify
task :ensure do
success = system ("dep ensure")
if not success
raise "ERROR: Dep ensure failed!\n".red
end
end
task :test do
kitchen_test
end
task :destroy do
kitchen_destroy
success = system ("go test -v ./test/ -timeout 20m -args azureuser ~/.ssh/id_rsa")
if not success
raise "ERROR: Go test failed!\n".red
end
end
end
task :prereqs => [ 'presteps:clean_up' ]
task :prereqs => []
task :validate => [ 'static:style', 'static:lint' ]
@ -50,8 +43,8 @@ task :build => [ 'prereqs', 'validate' ]
task :unit => []
task :e2e => [ 'integration:test' ]
task :e2e => [ 'integration:ensure', 'integration:test' ]
task :default => [ 'build' ]
task :full => [ 'build', 'unit', 'e2e']
task :full => [ 'build', 'unit', 'e2e' ]

41
test/fixture/main.tf Normal file
Просмотреть файл

@ -0,0 +1,41 @@
provider "random" {
version = "~> 1.0"
}
resource "random_id" "ip_dns" {
byte_length = 8
}
module "ubuntuservers" {
source = "../../"
location = "${var.location}"
admin_username = "${var.admin_username}"
admin_password = "${var.admin_password}"
vm_os_simple = "${var.vm_os_simple_1}"
public_ip_dns = ["ubuntusimplevmips-${random_id.ip_dns.hex}"]
vnet_subnet_id = "${module.network.vnet_subnets[0]}"
ssh_key = "${var.ssh_key}"
resource_group_name = "${var.resource_group_name}-${random_id.ip_dns.hex}"
public_ip_address_allocation = "static"
}
module "debianservers" {
source = "../../"
location = "${var.location}"
vm_hostname = "mylinvm"
admin_username = "${var.admin_username}"
admin_password = "${var.admin_password}"
vm_os_simple = "${var.vm_os_simple_2}"
public_ip_dns = ["debiansimplevmips-${random_id.ip_dns.hex}"] // change to a unique name per datacenter region
vnet_subnet_id = "${module.network.vnet_subnets[0]}"
ssh_key = "${var.ssh_key}"
resource_group_name = "${var.resource_group_name}-${random_id.ip_dns.hex}"
public_ip_address_allocation = "static"
}
module "network" {
source = "Azure/network/azurerm"
version = "2.0.0"
location = "westus2"
resource_group_name = "${var.resource_group_name}-${random_id.ip_dns.hex}"
}

15
test/fixture/outputs.tf Normal file
Просмотреть файл

@ -0,0 +1,15 @@
output "ubuntu_vm_public_name" {
value = "${module.ubuntuservers.public_ip_dns_name}"
}
output "debian_vm_public_name" {
value = "${module.debianservers.public_ip_dns_name}"
}
output "ubuntu_ip_address" {
value = "${module.ubuntuservers.public_ip_address}"
}
output "debian_ip_address" {
value = "${module.debianservers.public_ip_address}"
}

Просмотреть файл

@ -0,0 +1,7 @@
location = "westus2"
ssh_key = "~/.ssh/id_rsa.pub"
resource_group_name = "terraform-compute"
vm_os_simple_1 = "UbuntuServer"
vm_os_simple_2 = "Debian"
admin_username = "azureuser"
admin_password = "P@ssw0rd12345!"

Просмотреть файл

@ -0,0 +1,7 @@
variable "location" {}
variable "ssh_key" {}
variable "resource_group_name" {}
variable "vm_os_simple_1" {}
variable "vm_os_simple_2" {}
variable "admin_username" {}
variable "admin_password" {}

Просмотреть файл

@ -1,10 +0,0 @@
# More info please refer to: https://www.inspec.io/docs/
# Define unique test case suite.
control 'operating_system' do
# Define how critical this control is.
impact 1.0
# The actual test case.
describe command('lsb_release -a') do
its('stdout') { should match (/Ubuntu/) }
end
end

Просмотреть файл

@ -1,18 +0,0 @@
# More info please refer to: https://www.inspec.io/docs/
# Get path to terraform state file from attribute of kitchen-terraform.
terraform_state = attribute "terraform_state", {}
# Define how critical this control is.
control "state_file" do
# Define how critical this control is.
impact 0.6
# The actual test case.
describe "the Terraform state file" do
# Get json object of terraform state file.
subject do json(terraform_state).terraform_version end
# Validate the terraform version number field.
it "is accessible" do is_expected.to match /\d+\.\d+\.\d+/ end
end
end

Просмотреть файл

@ -1,3 +0,0 @@
---
name: compute
version: 0.1.0

Просмотреть файл

@ -1,25 +0,0 @@
provider "random" {
version = "~> 1.0"
}
resource "random_id" "ip_dns" {
byte_length = 8
}
module "linuxservers" {
source = "../../../"
location = "${var.location}"
vm_os_simple = "${var.vm_os_simple}"
public_ip_address_allocation = "static"
public_ip_dns = ["linuxserver-${random_id.ip_dns.hex}"]
vnet_subnet_id = "${module.network.vnet_subnets[0]}"
ssh_key = "${var.ssh_key}"
resource_group_name = "${var.resource_group_name}"
}
module "network" {
version = "2.0.0"
source = "Azure/network/azurerm"
location = "${var.location}"
resource_group_name = "${var.resource_group_name}"
}

Просмотреть файл

@ -1,8 +0,0 @@
output "test_target_public_dns" {
value = "${module.linuxservers.public_ip_dns_name}"
}
output "terraform_state" {
description = "The path to the backend state file"
value = "${path.cwd}/terraform.tfstate.d/${terraform.workspace}/terraform.tfstate"
}

Просмотреть файл

@ -1,4 +0,0 @@
location = "West US 2"
ssh_key = "~/.ssh/id_rsa.pub"
resource_group_name = "azure_compute_e2e"
vm_os_simple = "UbuntuServer"

Просмотреть файл

@ -1,4 +0,0 @@
variable "location" {}
variable "ssh_key" {}
variable "resource_group_name" {}
variable "vm_os_simple" {}

Просмотреть файл

@ -0,0 +1,105 @@
package test
import (
"fmt"
"io/ioutil"
"os"
"strings"
"testing"
"time"
"github.com/gruntwork-io/terratest/modules/retry"
"github.com/gruntwork-io/terratest/modules/ssh"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/gruntwork-io/terratest/modules/test-structure"
)
func TestTerraformSshExample(t *testing.T) {
t.Parallel()
exampleFolder := "./fixture"
// At the end of the test, run `terraform destroy` to clean up any resources that were created
defer test_structure.RunTestStage(t, "teardown", func() {
terraformOptions := test_structure.LoadTerraformOptions(t, exampleFolder)
terraform.Destroy(t, terraformOptions)
})
// Deploy the example
test_structure.RunTestStage(t, "setup", func() {
terraformOptions := configureTerraformOptions(t, exampleFolder)
// Save the options so later test stages can use them
test_structure.SaveTerraformOptions(t, exampleFolder, terraformOptions)
// This will run `terraform init` and `terraform apply` and fail the test if there are any errors
terraform.InitAndApply(t, terraformOptions)
})
// Make sure we can SSH to virtual machines directly from the public Internet
test_structure.RunTestStage(t, "validate", func() {
terraformOptions := test_structure.LoadTerraformOptions(t, exampleFolder)
testSSHToPublicHost(t, terraformOptions, "ubuntu_ip_address")
testSSHToPublicHost(t, terraformOptions, "debian_ip_address")
})
}
func configureTerraformOptions(t *testing.T, exampleFolder string) *terraform.Options {
terraformOptions := &terraform.Options{
// The path to where our Terraform code is located
TerraformDir: exampleFolder,
// Variables to pass to our Terraform code using -var options
Vars: map[string]interface{}{},
}
return terraformOptions
}
func testSSHToPublicHost(t *testing.T, terraformOptions *terraform.Options, address string) {
// Run `terraform output` to get the value of an output variable
publicIP := terraform.Output(t, terraformOptions, address)
// Read private key from given file
buffer, err := ioutil.ReadFile(os.Args[len(os.Args)-1])
if err != nil {
t.Fatal(err)
}
keyPair := ssh.KeyPair{PrivateKey: string(buffer)}
// We're going to try to SSH to the virtual machine, using our local key pair and specific username
publicHost := ssh.Host{
Hostname: publicIP,
SshKeyPair: &keyPair,
SshUserName: os.Args[len(os.Args)-2],
}
// It can take a minute or so for the virtual machine to boot up, so retry a few times
maxRetries := 15
timeBetweenRetries := 5 * time.Second
description := fmt.Sprintf("SSH to public host %s", publicIP)
// Run a simple echo command on the server
expectedText := "Hello, World"
command := fmt.Sprintf("echo -n '%s'", expectedText)
// Verify that we can SSH to the virtual machine and run commands
retry.DoWithRetry(t, description, maxRetries, timeBetweenRetries, func() (string, error) {
// Run the command and get the output
actualText, err := ssh.CheckSshCommandE(t, publicHost, command)
if err != nil {
return "", err
}
// Check whether the output is correct
if strings.TrimSpace(actualText) != expectedText {
return "", fmt.Errorf("Expected SSH command to return '%s' but got '%s'", expectedText, actualText)
}
fmt.Println(actualText)
return "", nil
})
}