Skip to content

Commit

Permalink
Merge pull request #298 from terraform-providers/release/1.0
Browse files Browse the repository at this point in the history
Prepare for v1.0 release
  • Loading branch information
manicminer committed Sep 3, 2020
2 parents 3892ca1 + 0ce07a1 commit b74f81a
Show file tree
Hide file tree
Showing 230 changed files with 12,328 additions and 9,129 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,6 @@ website/vendor

# goenv version file
.go-version

# built binary
terraform-provider-azuread
2 changes: 1 addition & 1 deletion .go-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.14.5
1.13.15
10 changes: 10 additions & 0 deletions .teamcity/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
default: tools

tools:
mvn -U dependency:sources

test: validate
mvn test -DtestPackage=tests

validate:
mvn teamcity-configs:generate
20 changes: 20 additions & 0 deletions .teamcity/components/build_azure.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import jetbrains.buildServer.configs.kotlin.v2019_2.ParametrizedWithType

class ClientConfiguration(var clientId: String,
var clientSecret: String,
val tenantId : String) {
}

class LocationConfiguration(var primary : String, var secondary : String, var ternary : String, var rotate : Boolean) {
}

fun ParametrizedWithType.ConfigureAzureSpecificTestParameters(environment: String, config: ClientConfiguration, locationsForEnv: LocationConfiguration) {
hiddenPasswordVariable("env.ARM_CLIENT_ID", config.clientId, "The AppID of the Application used for Testing")
hiddenPasswordVariable("env.ARM_CLIENT_SECRET", config.clientSecret, "The Client Secret of the Application used for Testing")
hiddenVariable("env.ARM_ENVIRONMENT", environment, "The Azure Environment in which the tests are running")
hiddenVariable("env.ARM_PROVIDER_DYNAMIC_TEST", "%b".format(locationsForEnv.rotate), "Should tests rotate between the supported regions?")
hiddenPasswordVariable("env.ARM_TENANT_ID", config.tenantId, "The ID of the Azure Tenant used for Testing")
hiddenVariable("env.ARM_TEST_LOCATION", locationsForEnv.primary, "The Primary region which should be used for testing")
hiddenVariable("env.ARM_TEST_LOCATION_ALT", locationsForEnv.secondary, "The Primary region which should be used for testing")
hiddenVariable("env.ARM_TEST_LOCATION_ALT2", locationsForEnv.ternary, "The Primary region which should be used for testing")
}
140 changes: 140 additions & 0 deletions .teamcity/components/build_components.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import jetbrains.buildServer.configs.kotlin.v2019_2.*
import jetbrains.buildServer.configs.kotlin.v2019_2.buildFeatures.GolangFeature
import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.ScriptBuildStep
import jetbrains.buildServer.configs.kotlin.v2019_2.triggers.schedule

// NOTE: in time this could be pulled out into a separate Kotlin package

// The native Go test runner (which TeamCity shells out to) will fail
// the entire test suite when a single test panics, which isn't ideal.
//
// Until that changes, we'll continue to use `teamcity-go-test` to run
// each test individually
const val useTeamCityGoTest = false

fun BuildFeatures.Golang() {
if (useTeamCityGoTest) {
feature(GolangFeature {
testFormat = "json"
})
}
}

fun BuildSteps.ConfigureGoEnv() {
step(ScriptBuildStep {
name = "Configure Go Version"
scriptContent = "goenv install -s \$(goenv local) && goenv rehash"
})
}

fun BuildSteps.DownloadTerraformBinary() {
// https://releases.hashicorp.com/terraform/0.12.28/terraform_0.12.28_linux_amd64.zip
var terraformUrl = "https://releases.hashicorp.com/terraform/%TERRAFORM_CORE_VERSION%/terraform_%TERRAFORM_CORE_VERSION%_linux_amd64.zip"
step(ScriptBuildStep {
name = "Download Terraform Core v%TERRAFORM_CORE_VERSION%.."
scriptContent = "mkdir -p tools && wget -O tf.zip %s && unzip tf.zip && mv terraform tools/".format(terraformUrl)
})
}

fun servicePath(packageName: String) : String {
return "./internal/services/%s".format(packageName)
}

fun BuildSteps.RunAcceptanceTests(packageName: String) {
var packagePath = servicePath(packageName)
var withTestsDirectoryPath = "##teamcity[setParameter name='SERVICE_PATH' value='%s/tests']".format(packagePath)

// some packages use a ./tests folder, others don't - conditionally append that if needed
step(ScriptBuildStep {
name = "Determine Working Directory for this Package"
scriptContent = "if [ -d \"%s/tests\" ]; then echo \"%s\"; fi".format(packagePath, withTestsDirectoryPath)
})

if (useTeamCityGoTest) {
step(ScriptBuildStep {
name = "Run Tests"
scriptContent = "go test -v \"%SERVICE_PATH%\" -timeout=\"%TIMEOUT%h\" -test.parallel=\"%PARALLELISM%\" -run=\"%TEST_PREFIX%\" -json"
})
} else {
step(ScriptBuildStep {
name = "Compile Test Binary"
scriptContent = "go test -c -o test-binary"
workingDir = "%SERVICE_PATH%"
})

step(ScriptBuildStep {
// ./test-binary -test.list=TestAccAzureRMResourceGroup_ | teamcity-go-test -test ./test-binary -timeout 1s
name = "Run via jen20/teamcity-go-test"
scriptContent = "./test-binary -test.list=\"%TEST_PREFIX%\" | teamcity-go-test -test ./test-binary -parallelism \"%PARALLELISM%\" -timeout \"%TIMEOUT%h\""
workingDir = "%SERVICE_PATH%"
})
}
}

fun BuildSteps.RunAcceptanceTestsForPullRequest(packageName: String) {
var servicePath = "%s/...".format(servicePath(packageName))
if (useTeamCityGoTest) {
step(ScriptBuildStep {
name = "Run Tests"
scriptContent = "go test -v \"$servicePath\" -timeout=\"%TIMEOUT%h\" -test.parallel=\"%PARALLELISM%\" -run=\"%TEST_PREFIX%\" -json"
})
} else {
// Building a binary with teamcity-go-test doesn't work for multiple packages, so fallback to this
step(ScriptBuildStep {
name = "Install tombuildsstuff/teamcity-go-test-json"
scriptContent = "wget https://github.com/tombuildsstuff/teamcity-go-test-json/releases/download/v0.2.0/teamcity-go-test-json_linux_amd64 && chmod +x teamcity-go-test-json_linux_amd64"
})

step(ScriptBuildStep {
name = "Run Tests"
scriptContent = "GOFLAGS=\"-mod=vendor\" ./teamcity-go-test-json_linux_amd64 -scope \"$servicePath\" -prefix \"%TEST_PREFIX%\" -count=1 -parallelism=%PARALLELISM% -timeout %TIMEOUT%"
})
}
}

fun ParametrizedWithType.TerraformAcceptanceTestParameters(parallelism : Int, prefix : String, timeout: String) {
text("PARALLELISM", "%d".format(parallelism))
text("TEST_PREFIX", prefix)
text("TIMEOUT", timeout)
}

fun ParametrizedWithType.ReadOnlySettings() {
hiddenVariable("teamcity.ui.settings.readOnly", "true", "Requires build configurations be edited via Kotlin")
}

fun ParametrizedWithType.TerraformAcceptanceTestsFlag() {
hiddenVariable("env.TF_ACC", "1", "Set to a value to run the Acceptance Tests")
}

fun ParametrizedWithType.TerraformCoreBinaryTesting() {
text("TERRAFORM_CORE_VERSION", defaultTerraformCoreVersion, "The version of Terraform Core which should be used for testing")
hiddenVariable("env.TF_ACC_TERRAFORM_PATH", "%system.teamcity.build.checkoutDir%/tools/terraform", "The path where the Terraform Binary is located")
}

fun ParametrizedWithType.TerraformShouldPanicForSchemaErrors() {
hiddenVariable("env.TF_SCHEMA_PANIC_ON_ERROR", "1", "Panic if unknown/unmatched fields are set into the state")
}

fun ParametrizedWithType.WorkingDirectory(packageName: String) {
text("SERVICE_PATH", servicePath(packageName), "", "The path at which to run - automatically updated", ParameterDisplay.HIDDEN)
}

fun ParametrizedWithType.hiddenVariable(name: String, value: String, description: String) {
text(name, value, "", description, ParameterDisplay.HIDDEN)
}

fun ParametrizedWithType.hiddenPasswordVariable(name: String, value: String, description: String) {
password(name, value, "", description, ParameterDisplay.HIDDEN)
}

fun Triggers.RunNightly(nightlyTestsEnabled: Boolean, startHour: Int) {
schedule{
enabled = nightlyTestsEnabled
branchFilter = "+:refs/heads/master"

schedulingPolicy = daily {
hour = startHour
timezone = "SERVER"
}
}
}
50 changes: 50 additions & 0 deletions .teamcity/components/build_config_pull_request.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import jetbrains.buildServer.configs.kotlin.v2019_2.*

class pullRequest(displayName: String, environment: String) {
val displayName = displayName
val environment = environment

fun buildConfiguration(providerName : String) : BuildType {
return BuildType {
// TC needs a consistent ID for dynamically generated packages
id(uniqueID(providerName))

name = displayName

vcs {
root(providerRepository)
cleanCheckout = true
}

steps {
var packageName = "\"%SERVICES%\""

ConfigureGoEnv()
DownloadTerraformBinary()
RunAcceptanceTestsForPullRequest(packageName)
}

failureConditions {
errorMessage = true
}

features {
Golang()
}

params {
TerraformAcceptanceTestParameters(defaultParallelism, "TestAcc", "12")
TerraformAcceptanceTestsFlag()
TerraformShouldPanicForSchemaErrors()
TerraformCoreBinaryTesting()
ReadOnlySettings()

text("SERVICES", "portal")
}
}
}

fun uniqueID(provider : String) : String {
return "%s_PR_%s".format(provider.toUpperCase(), environment.toUpperCase())
}
}
52 changes: 52 additions & 0 deletions .teamcity/components/build_config_service.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import jetbrains.buildServer.configs.kotlin.v2019_2.*

class serviceDetails(name: String, displayName: String, environment: String) {
val packageName = name
val displayName = displayName
val environment = environment

fun buildConfiguration(providerName : String, nightlyTestsEnabled: Boolean, startHour: Int, parallelism: Int) : BuildType {
return BuildType {
// TC needs a consistent ID for dynamically generated packages
id(uniqueID(providerName))

name = "%s - Acceptance Tests".format(displayName)

vcs {
root(providerRepository)
cleanCheckout = true
}

steps {
ConfigureGoEnv()
DownloadTerraformBinary()
RunAcceptanceTests(packageName)
}

failureConditions {
errorMessage = true
}

features {
Golang()
}

params {
TerraformAcceptanceTestParameters(parallelism, "TestAcc", "12")
TerraformAcceptanceTestsFlag()
TerraformCoreBinaryTesting()
TerraformShouldPanicForSchemaErrors()
ReadOnlySettings()
WorkingDirectory(packageName)
}

triggers {
RunNightly(nightlyTestsEnabled, startHour)
}
}
}

fun uniqueID(provider : String) : String {
return "%s_SERVICE_%s_%s".format(provider.toUpperCase(), environment.toUpperCase(), packageName.toUpperCase())
}
}
55 changes: 55 additions & 0 deletions .teamcity/components/project.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import jetbrains.buildServer.configs.kotlin.v2019_2.BuildType
import jetbrains.buildServer.configs.kotlin.v2019_2.Project

const val providerName = "azuread"

var services = mapOf(
"aadgraph" to "Azure Active Directory Graph"
)

fun AzureAD(environment: String, configuration : ClientConfiguration) : Project {
return Project{
vcsRoot(providerRepository)

var pullRequestBuildConfig = pullRequestBuildConfiguration(environment, configuration)
buildType(pullRequestBuildConfig)

var buildConfigs = buildConfigurationsForServices(services, providerName, environment, configuration)
buildConfigs.forEach { buildConfiguration ->
buildType(buildConfiguration)
}
}
}

fun buildConfigurationsForServices(services: Map<String, String>, providerName : String, environment: String, config : ClientConfiguration): List<BuildType> {
var list = ArrayList<BuildType>()
var locationsForEnv = locations.get(environment)!!

services.forEach { (serviceName, displayName) ->
// TODO: overriding locations
var testConfig = testConfiguration(defaultParallelism, defaultStartHour)
var runNightly = runNightly.getOrDefault(environment, false)

var service = serviceDetails(serviceName, displayName, environment)
var buildConfig = service.buildConfiguration(providerName, runNightly, testConfig.startHour, testConfig.parallelism)

buildConfig.params.ConfigureAzureSpecificTestParameters(environment, config, locationsForEnv)

list.add(buildConfig)
}

return list
}

fun pullRequestBuildConfiguration(environment: String, configuration: ClientConfiguration) : BuildType {
var locationsForEnv = locations.get(environment)!!
var pullRequest = pullRequest("! Run Pull Request", environment)
var buildConfiguration = pullRequest.buildConfiguration(providerName)
buildConfiguration.params.ConfigureAzureSpecificTestParameters(environment, configuration, locationsForEnv)
return buildConfiguration
}

class testConfiguration(parallelism: Int, startHour: Int) {
var parallelism = parallelism
var startHour = startHour
}
18 changes: 18 additions & 0 deletions .teamcity/components/settings.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// specifies the default hour (UTC) at which tests should be triggered, if enabled
var defaultStartHour = 0

// specifies the default level of parallelism per-service-package
var defaultParallelism = 20

// specifies the default version of Terraform Core which should be used for testing
var defaultTerraformCoreVersion = "0.12.28"

var locations = mapOf(
"public" to LocationConfiguration("westeurope", "eastus2", "francecentral", false),
"germany" to LocationConfiguration("germanynortheast", "germanycentral", "", false)
)

// specifies the list of Azure Environments where tests should be run nightly
var runNightly = mapOf(
"public" to true
)
11 changes: 11 additions & 0 deletions .teamcity/components/vcs_root.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import jetbrains.buildServer.configs.kotlin.v2019_2.vcs.GitVcsRoot

object providerRepository : GitVcsRoot({
name = "terraform-provider-azuread"
url = "https://github.com/terraform-providers/terraform-provider-azuread.git"
agentCleanPolicy = AgentCleanPolicy.ALWAYS
agentCleanFilesPolicy = AgentCleanFilesPolicy.ALL_UNTRACKED
branchSpec = "+:*"
branch = "refs/heads/master"
authMethod = anonymous()
})
Loading

0 comments on commit b74f81a

Please sign in to comment.