Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: christianbumann/terraform-provider-azuredevops
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: fhammerl/terraform-provider-azuredevops
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Able to merge. These branches can be automatically merged.

Commits on Oct 10, 2019

  1. Add a missing point at the end of a sentence (#85)

    christianbumann authored and Nicholas M. Iodice committed Oct 10, 2019
    Copy the full SHA
    8a7e457 View commit details
  2. Invoke acceptance tests during CI (#82)

    Nicholas M. Iodice authored and Stephen Henderson committed Oct 10, 2019
    Copy the full SHA
    b0aeb4e View commit details
  3. Adding nightly build; Removing full OS coverage from PR build; Update…

    … .azdo/main.tf for nightly build (#81)
    Nicholas M. Iodice authored and Stephen Henderson committed Oct 10, 2019
    Copy the full SHA
    d1f0e78 View commit details
  4. Document env vars in contributing docs; Update build badge to point t…

    …o proper pipeline (#87)
    
    * Adding documentation in contributing.md for env. vars
    
    * Updating build badge for nightly build on README.md
    Nicholas M. Iodice authored Oct 10, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    1a8ec7e View commit details
  5. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    cbc4cf7 View commit details
  6. Implement Update lifecycle operation for Service Endpoint Resource (#89)

    * Implemented Update operation
    KeithJRome authored Oct 10, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6507b9f View commit details
  7. Copy the full SHA
    ed69bc0 View commit details

Commits on Oct 14, 2019

  1. Add aspirational terraform template for MVP feature-set (#109)

    Nicholas M. Iodice authored Oct 14, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    5ba2591 View commit details

Commits on Oct 15, 2019

  1. Implement Project Update (#102)

    * Adding update feature
    
    * Adding ForceNew for non-update parameters
    
    * remove unnecessary debug line
    TsuyoshiUshio authored and Nicholas M. Iodice committed Oct 15, 2019
    Copy the full SHA
    7692708 View commit details
  2. Adding V1 Roadmap document (#111)

    * Adding V1 Roadmap document
    
    * Updated language to underscore that the document may change
    
    * Update docs/roadmap.md
    Nicholas M. Iodice authored Oct 15, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    96fabc1 View commit details

Commits on Oct 16, 2019

  1. This change migrates to a new version of the AzDO SDK that uses inter…

    …faces. (#117)
    
    * This change migrates to a new version of the SDK that uses interfaces.
    
    This change avoids the need to create new interfaces by hand whenver we
    need to test additional APIs in the provider. This includes the
    following:
     - Update documentation for generating mocks
     - Remove `mock_config.go` file that has all the generated mocks
     - Remove the hand-created interfaces from `config.go`
     - Update `./scripts/generate-mocks.sh` so that it discovers the azdo GO
       SDKs pulled into the project, and programatically generate mocks for
       those SDKs
    Nicholas M. Iodice authored Oct 16, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    c62a325 View commit details
  2. Define new resource for AzureDO Git repositories (#118)

    * Implemented resource schema and stubs
    * Define element type of list property in schema
    * Added git repo stanza to example tf deployment
    * Assign id so that APPLY will succeed even though no CRUD ops have been implemented yet
    * stubs for unit and acceptance tests
    * Clean roundtrip serialize/deserialize
    * removed stubs for irrelevant tests
    * examples were restructured
    KeithJRome authored Oct 16, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    18af944 View commit details
  3. Adding gitter badge (#119)

    Nicholas M. Iodice authored Oct 16, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    572cfdc View commit details
  4. Adding documentation for extending provider (#110)

    Nicholas M. Iodice authored Oct 16, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    80a44f8 View commit details
  5. This change migrates to the newly released terraform plugin SDK (#115)

    As per the HashiCorp recommendation
      https://www.terraform.io/docs/extend/plugin-sdk.html
    Nicholas M. Iodice authored Oct 16, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    ae0037b View commit details

Commits on Oct 21, 2019

  1. Introduce read, create, delete support for Azure Git Repos (#123)

    * Adding update feature
    
    * Adding ForceNew for non-update parameters
    
    * remove unnecessary debug line
    
    * Implement read functionality for repos
    
    * Adding delete feature
    
    * Implemented Create op
    
    * Add AzDO repo type to build def resource
    
    * Corrected aspirational template
    
    * Adding unit tests for delete; wiring up delete flow
    
    * Commented vars that aren't actually used yet
    
    * Remove default_branch for now
    
    * Build Def resource only supports github right now
    
    * Implement acceptance tests for azuredevops_azure_git_repository resource
    
    Co-authored-by: Keith Rome <keith.rome@gmail.com>
    Co-authored-by: Tsuyoshi Ushio <ushio@simplearchitect.com>
    
    * Finish acceptance tests. Validated a working create/read/delete flow
    
    Co-authored-by: Keith Rome <keith.rome@gmail.com>
    Co-authored-by: Tsuyoshi Ushio <ushio@simplearchitect.com>
    
    * Adding tests for flatten & expand; Removing unnecessary argument params
    
    * updated comment for expand function
    
    * Re-migrate to SDK
    
    * Removed extraneous comment from code file
    
    * Implement missing unit test
    
    * ENV Var for delaying execution after creating a new project
    
    * Adding documentation of config. values
    
    * Update azuredevops/resource_project.go
    
    Co-Authored-By: Nicholas M. Iodice <niiodice@microsoft.com>
    KeithJRome and Nicholas M. Iodice committed Oct 21, 2019
    Copy the full SHA
    21cc648 View commit details
  2. Introduce unit tests for the Service Endpoint resource (#132)

    * add CRUD and round-trip test code
    * removed un-needed commented code
    * removed WIP about secrets handling (belongs in another PR)
    * tests passing. ready for PR.
    Stephen Henderson authored Oct 21, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    d8fdb39 View commit details

Commits on Oct 22, 2019

  1. Update operation for AzDO-based Git Repository resource (#136)

    * Adding update feature for repo
    TsuyoshiUshio authored Oct 22, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    b75676a View commit details
  2. Enable TfsGit repos as sources for build definitions (#134)

    * Enable GitHub and TfsGit repos as sources for build definitions
    * Added unit test to verify that TfsGit is an accepted value for build definition repo type
    Nicholas M. Iodice authored Oct 22, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    09a546e View commit details
  3. Handle PAT/password secrets securely while also detecting changes to …

    …secrets between operations (#137)
    
    * adding ACC test
    * Clean-up docs, add Helper for secret flattening
    * Tune schema-def for secrets, more debug logging
    * Use flatten helper for secrets
    * remove dev-cycle cruft
    * typo
    * Insert bcrypt handling into secret mgmnt
    * keep secrets from appearing in `stdout/err`
    * remove useless debug ENVAR
    * centralize `_hash` key knowledge into one place
    * for the moment, ACC tests req a GitHub PAT
    * moar testing!
    Stephen Henderson authored Oct 22, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    ffdc0fb View commit details
  4. Var name lint fix for internal time outs (#139)

    * lint fix
    * test beta cache task
    * de-clash the vms, etc. cache less
    * string expansion safety
    Stephen Henderson authored Oct 22, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    af74b0f View commit details
  5. Implemented data source for azdo groups (#131)

    * Implemented data source for azdo groups
    
    * Uncommented group in aspirational TF
    Nicholas M. Iodice authored Oct 22, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    d79e8e9 View commit details

Commits on Oct 23, 2019

  1. Reference documentation (#145)

    Add reference documentation
    TsuyoshiUshio authored Oct 23, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e188c6d View commit details

Commits on Oct 24, 2019

  1. Undo 138 and restore the multi-platform CI/CD status (#144)

    * Revert #138, which caused issues in the nightly build due to caching logic introduced to the pipeline not being compatible with OSX
    Stephen Henderson authored and Nicholas M. Iodice committed Oct 24, 2019
    Copy the full SHA
    8fc1036 View commit details
  2. Add documentation for why AZDO_GITHUB_SERVICE_CONNECTION_PAT is (#148)

    needed, as well as when it needs to be defined.
    Nicholas M. Iodice authored Oct 24, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    47f2702 View commit details

Commits on Oct 25, 2019

  1. Azure git repo initialization (#152)

    * Initialization for Azure git repos
    * Acceptance test to ensure that new master branch is the default
    * Acceptance test for Uninitialized repo setting
    KeithJRome authored Oct 25, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    0be92a3 View commit details

Commits on Oct 28, 2019

  1. Add to on-boarding material to ease on-boarding pain (#149)

    * Add to on-boarding material to ease on-boarding pain
    Co-Authored-By: Dexter Williams <dexterwilliams04@gmail.com>
    Nicholas M. Iodice authored Oct 28, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    ab872c1 View commit details
  2. Add user entitlement resource (#154)

    merge!
    TsuyoshiUshio authored Oct 28, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    7344027 View commit details
  3. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    a524964 View commit details

Commits on Oct 29, 2019

  1. Passing GH token as secret to the acceptance tests (#159)

    Nicholas M. Iodice authored Oct 29, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    1b7b3a0 View commit details

Commits on Oct 30, 2019

  1. Implement group membership CRUD and unit/acceptance testing (#163)

    Implement group membership CRUD and unit/acceptance testing, along with documentation for client facing docs
    Nicholas M. Iodice authored Oct 30, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    0575967 View commit details

Commits on Oct 31, 2019

  1. Commenting acceptance tests that causes transient failures (#175)

    * Commenting acceptance tests that causes transient failures
    
    * removed unused imports
    Nicholas M. Iodice authored Oct 31, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    3e2a090 View commit details

Commits on Nov 1, 2019

  1. Add instructions for postman in the contributions guide. (#178)

    * Add instructions for postman and contributing back.
    
    * Add link to cli extension source.
    rguthriemsft authored and Nicholas M. Iodice committed Nov 1, 2019
    Copy the full SHA
    61b6175 View commit details
  2. Updating examples to work based on the latest implementation. (#176)

    Nicholas M. Iodice authored and rguthriemsft committed Nov 1, 2019
    Copy the full SHA
    50dc1d0 View commit details

Commits on Nov 2, 2019

  1. Reorg Validation and Suppressing Functions (#179)

    * Copied suppressing and validation functions from terraform-provider-azurerm
    
    * Replaced string suppress function in azuredevops\resource_project.go
    
    * Removed suppressing function and test from azuredevops\utils\tfhelper\tfhelper.go
    
    * Using NoEmptyStrings as validate function and comparing process names case insensitively in azuredevops\resource_project.go
    tmeckel authored and Nicholas M. Iodice committed Nov 2, 2019
    Copy the full SHA
    cc4b6e9 View commit details

Commits on Nov 4, 2019

  1. Implement Import AzDo project (#156)

    * add note in contribution guide
    
    * scripts : changes encoding for Linux
    implement the AzDo project Importer + tests + documentation
    Fix acceptance tests in TestAzureDevOpsProvider_SchemaIsValid method
    
    * apply gofmt
    
    * fix integration test
    
    * lintGo
    
    * add doc link for import acceptance testing
    
    * go lint
    mikaelkrief authored and Nicholas M. Iodice committed Nov 4, 2019
    Copy the full SHA
    4ab733f View commit details

Commits on Nov 6, 2019

  1. Added VSCode snippets for Terraform data source and resource (#180)

    * Added VSCode snippets for Terraform data source and resource
    
    * Added documenation for VSCode snippets
    
    * Corrected VSCode snippets based on review
    tmeckel authored and Nicholas M. Iodice committed Nov 6, 2019
    Copy the full SHA
    a843e0e View commit details
  2. Nate.docs.pataccess (#191)

    * doc updates
    
    * Updated docs for scoped PAT tokens
    NathanielRose authored Nov 6, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    4c5285c View commit details
  3. add help tip on format of list(string) (#190)

    also adds exclusion for .envrs files used by
    direnv tool - direnv.net.
    cicorias authored Nov 6, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    0123293 View commit details

Commits on Nov 7, 2019

  1. Simonpoeliises/165 refactor error messages (#193)

    * Enhanced error messages
    
    * Refactor user entitlement
    
    * Refactor service endpoint
    
    * Refactored group add, delete error messaging
    
    * Update project error messages
    
    * Fix tests
    
    * Fix unit tests
    EliiseS authored Nov 7, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    661ae67 View commit details
  2. Feature/dockerize (#192)

    Added docker for local development
    michaelperel authored Nov 7, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    93fb92c View commit details
  3. Eliises/171 add variable groups (#198)

    * Add build def
    
    * Flatten and expand variableGroups
    
    * Fix unit tests
    
    * Adding documentation for build_definition resource
    
    * adding link in index.md
    
    * Alphabetize params for docs
    EliiseS authored Nov 7, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    25d1ab6 View commit details
  4. Implements resource for AzDO Variable Group support (#195)

    * Add taskagent client to config.go.
    
    * Fix task agent client field name in aggregated client type.
    
    * added mock client for taskagent
    
    * Add variable group resource and example.
    
    * Register variable group in provider.
    
    * Change variable group resource to use TypeSet instead of TypeMap.
    
    * Added a SchemaSetFunc to determine hash for item key.
    
    * Move parse project ID and resource ID helper function to tfhelpers file (originally inside build definition).
    
    * Update example main.tf with variable group description.
    
    * Implement variable group resource create and read.
    
    * Implement variable group resource update and delete.
    
    * Added acceptance test for var groups
    
    * Add variable group mock data for unit testing and unit test for expand/flatten.
    
    * Fixed nil pointer response from SDK
    
    * Lint check fix
    
    * Added docs
    
    * Add issue for Variable Group allow_access feature inline.
    
    * Updated docs in response to comments
    
    * Resolving comments -- adding validation and removing unneeded comments
    
    
    Co-authored-by: Kevin Hartman <kevin@hart.mn>
    kevinhartman authored and awkwardindustries committed Nov 7, 2019

    Unverified

    This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
    Copy the full SHA
    fb2d779 View commit details

Commits on Nov 8, 2019

  1. Miperel/lint (#199)

    Added golint
    michaelperel authored Nov 8, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    bc6ba36 View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    eb3742d View commit details

Commits on Nov 14, 2019

  1. Provided better tooling for the development container (#206)

    * Provided better tooling for the development container
    
    * updated Dockerfile path in CI
    
    * updated -v flag to reflect Dockerfile val
    
    * analysis tools
    michaelperel authored and Nicholas M. Iodice committed Nov 14, 2019
    Copy the full SHA
    cf9837a View commit details

Commits on Nov 18, 2019

  1. Implementing Import for variable group (#204)

    * Implementing Import for variable group
    
    * Fix aggregatedClient to config.AggregatedClient
    
    * Fix Variable Group Acc tests for get the ID to import
    
    * add .idea to gitignore
    mikaelkrief authored and Nicholas M. Iodice committed Nov 18, 2019
    Copy the full SHA
    0724178 View commit details
  2. agent pool resource (#185)

    Add agent pool resource, unit tests, acceptance tests and documentation
    derhally authored and Nicholas M. Iodice committed Nov 18, 2019
    Copy the full SHA
    b87d2b2 View commit details

Commits on Nov 19, 2019

  1. Updated VSCode snippets according to new config struct members (#209)

    tmeckel authored and Nicholas M. Iodice committed Nov 19, 2019
    Copy the full SHA
    4fbc369 View commit details

Commits on Nov 20, 2019

  1. Build pipepine path (#207)

    Support build pipeline path
    exocom authored and Nicholas M. Iodice committed Nov 20, 2019
    Copy the full SHA
    4c6639d View commit details
Showing 2,508 changed files with 728,903 additions and 2,702 deletions.
28 changes: 28 additions & 0 deletions .azdo/azure-pipeline-nightly.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
schedules:
- cron: "0 0 * * *"
displayName: "Nightly Build"
branches:
include:
- 'master'

jobs:
- template: ./ci.yml
parameters:
maxParallel: 1 # any more and we get throttled by AzDO!

goVersions:
- value: '1.12.1'
ymlSafeName: '1_12_1'

- value: '1.12.10'
ymlSafeName: '1_12_10'

- value: '1.13.1'
ymlSafeName: '1_13_1'

vmImages:
- value: 'macOS-10.14'
ymlSafeName: 'macos_10_14'

- value: 'ubuntu-16.04'
ymlSafeName: ubuntu_16_04
9 changes: 0 additions & 9 deletions .azdo/azure-pipeline.yml
Original file line number Diff line number Diff line change
@@ -19,18 +19,9 @@ jobs:
- template: ./ci.yml
parameters:
goVersions:
- value: '1.12.1'
ymlSafeName: '1_12_1'

- value: '1.12.10'
ymlSafeName: '1_12_10'

- value: '1.13.1'
ymlSafeName: '1_13_1'

vmImages:
- value: 'macOS-10.14'
ymlSafeName: 'macos_10_14'

- value: 'ubuntu-16.04'
ymlSafeName: ubuntu_16_04
30 changes: 28 additions & 2 deletions .azdo/ci.yml
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
parameters:
goVersions: []
vmImages: []
maxParallel: 1

jobs:

@@ -13,6 +14,7 @@ jobs:

# Build on each combination of supported OS and Go version
strategy:
maxParallel: ${{ parameters.maxParallel }}
matrix:
${{ each goVersion in parameters.goVersions }}:
${{ each vmImage in parameters.vmImages }}:
@@ -32,12 +34,13 @@ jobs:
- bash: |
#!/usr/bin/env bash
cd "$BUILD_SOURCESDIRECTORY"
chmod +x ./scripts/*.sh
displayName: 'Set Scripts as Executable'
./scripts/fmt-check-go.sh
displayName: 'Run Format Check'
- bash: |
#!/usr/bin/env bash
cd "$BUILD_SOURCESDIRECTORY"
go get -u golang.org/x/lint/golint
./scripts/lint-check-go.sh
displayName: 'Run Lint Check'
@@ -46,3 +49,26 @@ jobs:
cd "$BUILD_SOURCESDIRECTORY"
./scripts/build.sh
displayName: 'Run Build Script'
- bash: |
#!/usr/bin/env bash
cd "$BUILD_SOURCESDIRECTORY"
./scripts/acctest.sh
displayName: 'Run Acceptance Tests'
env:
AZDO_ORG_SERVICE_URL: $(ACC_TEST_AZDO_ORG_URL)
AZDO_PERSONAL_ACCESS_TOKEN: $(ACC_TEST_AZDO_PAT)
AZDO_GITHUB_SERVICE_CONNECTION_PAT: $(ACC_TEST_GH_PAT)
AZDO_DOCKERHUB_SERVICE_CONNECTION_USERNAME: $(AZDO_DOCKERHUB_SERVICE_CONNECTION_USERNAME)
AZDO_DOCKERHUB_SERVICE_CONNECTION_EMAIL: $(AZDO_DOCKERHUB_SERVICE_CONNECTION_EMAIL)
AZDO_DOCKERHUB_SERVICE_CONNECTION_PASSWORD: $(AZDO_DOCKERHUB_SERVICE_CONNECTION_PASSWORD)
AZDO_BITBUCKET_SERVICE_CONNECTION_USERNAME: $(AZDO_BITBUCKET_SERVICE_CONNECTION_USERNAME)
AZDO_BITBUCKET_SERVICE_CONNECTION_PASSWORD: $(AZDO_BITBUCKET_SERVICE_CONNECTION_PASSWORD)
- bash: |
if [ -x "$(command -v docker)" ]; then
docker build -f .devcontainer/Dockerfile -t dev --build-arg GO_VERSION=${GO_VERSION} .
fi
env:
GO_VERSION: $(goVersion)
displayName: 'Run Build Script in Docker'
32 changes: 21 additions & 11 deletions .azdo/main.tf
Original file line number Diff line number Diff line change
@@ -11,24 +11,34 @@ resource "azuredevops_project" "project" {
work_item_template = "Agile"
}

resource "azuredevops_serviceendpoint" "github_serviceendpoint" {
project_id = azuredevops_project.project.id
service_endpoint_name = "GitHub Service Connection"
service_endpoint_type = "github"
service_endpoint_url = "http://github.com"
service_endpoint_owner = "library"
resource "azuredevops_serviceendpoint_github" "github_serviceendpoint" {
project_id = azuredevops_project.project.id
service_endpoint_name = "GitHub Service Connection"

auth_personal {
# personalAccessToken = "..." Or set with `AZDO_GITHUB_SERVICE_CONNECTION_PAT` env var
}
}

resource "azuredevops_serviceendpoint_dockerhub" "dockerhub_serviceendpoint" {
project_id = azuredevops_project.project.id
service_endpoint_name = "DockerHub Service Connection"

# docker_username = "..." - Or set with `AZDO_DOCKERHUB_SERVICE_CONNECTION_USERNAME` env var
# docker_email = "..." - Or set with `AZDO_DOCKERHUB_SERVICE_CONNECTION_EMAIL` env var
# docker_password = "..." - Or set with `AZDO_DOCKERHUB_SERVICE_CONNECTION_PASSWORD` env var
}

resource "azuredevops_build_definition" "build_definition" {
resource "azuredevops_build_definition" "nightly_build" {
project_id = azuredevops_project.project.id
agent_pool_name = "Hosted Ubuntu 1604"
name = "Provider CI Pipeline"
name = "Nightly Build"

repository {
repo_type = "GitHub"
repo_name = "microsoft/terraform-provider-azuredevops"
repo_id = "microsoft/terraform-provider-azuredevops"
branch_name = "master"
yml_path = ".azdo/azure-pipeline.yml"
service_connection_id = azuredevops_serviceendpoint.github_serviceendpoint.id
yml_path = ".azdo/azure-pipeline-nightly.yml"
service_connection_id = azuredevops_serviceendpoint_github.github_serviceendpoint.id
}
}
65 changes: 65 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
FROM golang:1.13-stretch

# Avoid warnings by switching to noninteractive
ENV DEBIAN_FRONTEND=noninteractive

ARG TERRAFORM_VERSION=0.12.24
ARG TFLINT_VERSION=0.15.3
ARG TERRAFORM_PROVIDER_AZUREDEVOPS_NAME=terraform-provider-azuredevops

RUN apt-get update \
&& apt-get -y install --no-install-recommends apt-utils 2>&1 \
# Verify git, process tools, lsb-release (common in install instructions for CLIs), unzip installed
&& apt-get -y install git procps lsb-release unzip \
# Install Editor
&& apt-get install vim -y \
# Install Terraform, tflint
&& mkdir -p /tmp/docker-downloads \
&& curl -sSL -o /tmp/docker-downloads/terraform.zip https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip \
&& unzip /tmp/docker-downloads/terraform.zip \
&& mv terraform /usr/local/bin \
&& curl -sSL -o /tmp/docker-downloads/tflint.zip https://github.com/wata727/tflint/releases/download/v${TFLINT_VERSION}/tflint_linux_amd64.zip \
&& unzip /tmp/docker-downloads/tflint.zip \
&& mv tflint /usr/local/bin \
&& cd ~ \
&& rm -rf /tmp/docker-downloads \
#
# Clean up
&& apt-get autoremove -y \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*

# Enable go modules
ENV GO111MODULE=on

# Install Go tools
RUN \
# --> Delve for debugging
go get github.com/go-delve/delve/cmd/dlv@v1.4.0 \
# --> Go language server
&& go get golang.org/x/tools/gopls@v0.3.4 \
# --> GolangCI-lint
&& curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sed 's/tar -/tar --no-same-owner -/g' | sh -s -- -b $(go env GOPATH)/bin \
# --> Go-outline for extracting a JSON representation of the declarations in a Go source file
&& go get -v github.com/ramya-rao-a/go-outline \
#
# Clean up
&& rm -rf /go/src/ && rm -rf /go/pkg

# Install AzDO terraform provider
ADD . ${TERRAFORM_PROVIDER_AZUREDEVOPS_NAME}
RUN (cd ${TERRAFORM_PROVIDER_AZUREDEVOPS_NAME} && make build) \
&& rm -rf ${TERRAFORM_PROVIDER_AZUREDEVOPS_NAME}

# Git command prompt
RUN git clone https://github.com/magicmonty/bash-git-prompt.git ~/.bash-git-prompt --depth=1 \
&& echo "if [ -f \"$HOME/.bash-git-prompt/gitprompt.sh\" ]; then GIT_PROMPT_ONLY_IN_REPO=1 && source $HOME/.bash-git-prompt/gitprompt.sh; fi" >> "/root/.bashrc"

# Add alias
RUN echo "alias tf=terraform" >> "/root/.bashrc"

# Switch back to dialog for any ad-hoc use of apt-get
ENV DEBIAN_FRONTEND=dialog

# Install goreleaser
RUN (cd /usr/local && curl -sfL https://install.goreleaser.com/github.com/goreleaser/goreleaser.sh | sh -s -- "v0.132.1")
56 changes: 56 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// For format details, see https://aka.ms/vscode-remote/devcontainer.json or the definition README at
// https://github.com/microsoft/vscode-dev-containers/tree/master/containers/docker-existing-dockerfile
{
"name": "Dev Dockerfile",
"dockerFile": "Dockerfile",
"context": "..",
// The optional 'runArgs' property can be used to specify additional runtime arguments.
"runArgs": [
// Enable go debugger
"--cap-add=SYS_PTRACE",
"--security-opt",
"seccomp=unconfined",
// Enable SSH for git
"-v",
"${env:HOME}${env:USERPROFILE}/.ssh:/root/.ssh-localhost:ro"
],
"postCreateCommand": "mkdir -p /root/.ssh && cp -r /root/.ssh-localhost/* /root/.ssh && chmod 700 /root/.ssh && chmod 600 /root/.ssh/*",
"settings": {
"files.eol": "\n",
"go.gopath": "/go",
"terminal.integrated.shell.linux": "/bin/bash",
"go.useLanguageServer": true,
"go.autocompleteUnimportedPackages": true,
"go.gotoSymbol.includeImports": true,
"go.gotoSymbol.includeGoroot": true,
"go.toolsEnvVars": {
"GO111MODULE": "on"
},
"go.lintFlags": [
"--fast"
],
"go.testFlags": [
"-v",
"-tags=all"
],
"go.testEnvVars": {
"TF_ACC": "1"
},
"go.testEnvFile": "${workspaceFolder}/.env",
"[go]": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true
}
},
"gopls": {
"usePlaceholders": true, // add parameter placeholders when completing a function
// Experimental settings
"completeUnimported": true, // autocomplete unimported packages
"deepCompletion": true // enable deep completion
},
},
"extensions": [
"ms-vscode.go"
]
}
4 changes: 4 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
go.mod text eol=lf
go.sum text eol=lf
*.sh text eol=lf
*.go text eol=lf
81 changes: 81 additions & 0 deletions .github/workflows/check-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
name: Build and Test Terraform provider AzDo
on: [pull_request]
jobs:

build:
name: Build
runs-on: ${{ matrix.os }}

strategy:
matrix:
os: [ubuntu-16.04]
go-version: [1.12.10]


steps:

- name: Set up Go
uses: actions/setup-go@v1
with:
go-version: ${{ matrix.go-version }}
id: go

- name: Check out code into the Go module directory
uses: actions/checkout@v1

- name: Get dependencies
run: |
go get -v -t -d ./...
if [ -f Gopkg.toml ]; then
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
dep ensure
fi
- name: Run Format Check
run: ./scripts/fmt-check-go.sh

- name: Run Lint Check
run: |
go get -u golang.org/x/lint/golint
./scripts/lint-check-go.sh
- name: Run Build Script
run: ./scripts/build.sh

- name: Run Acceptance Tests
run: ./scripts/acctest.sh
env:
AZDO_ORG_SERVICE_URL: ${{ secrets.AZDO_ORG_SERVICE_URL }}
AZDO_PERSONAL_ACCESS_TOKEN: ${{ secrets.AZDO_PERSONAL_ACCESS_TOKEN }}
AZDO_GITHUB_SERVICE_CONNECTION_PAT: ${{ secrets.GITHUB_TOKEN }}
AZDO_DOCKERHUB_SERVICE_CONNECTION_USERNAME: ${{ secrets.AZDO_DOCKERHUB_SERVICE_CONNECTION_USERNAME }}
AZDO_DOCKERHUB_SERVICE_CONNECTION_EMAIL: ${{ secrets.AZDO_DOCKERHUB_SERVICE_CONNECTION_EMAIL }}
AZDO_DOCKERHUB_SERVICE_CONNECTION_PASSWORD: ${{ secrets.AZDO_DOCKERHUB_SERVICE_CONNECTION_PASSWORD }}
AZDO_TEST_AAD_USER_EMAIL: ${{ secrets.AZDO_TEST_AAD_USER_EMAIL }}

- name: Run Build Script in Docker
run: docker build -f .devcontainer/Dockerfile -t dev --build-arg GO_VERSION=${GO_VERSION} .
env:
GO_VERSION: ${{ matrix.go-version }}

- name: Run Acceptance Tests in Docker
run: |
docker run \
--env AZDO_ORG_SERVICE_URL=${AZDO_ORG_SERVICE_URL} \
--env AZDO_PERSONAL_ACCESS_TOKEN=${AZDO_PERSONAL_ACCESS_TOKEN} \
--env AZDO_GITHUB_SERVICE_CONNECTION_PAT=${AZDO_GITHUB_SERVICE_CONNECTION_PAT} \
--env AZDO_TEST_AAD_USER_EMAIL=${AZDO_TEST_AAD_USER_EMAIL} \
--env AZDO_DOCKERHUB_SERVICE_CONNECTION_USERNAME=${AZDO_DOCKERHUB_SERVICE_CONNECTION_USERNAME} \
--env AZDO_DOCKERHUB_SERVICE_CONNECTION_EMAIL=${AZDO_DOCKERHUB_SERVICE_CONNECTION_EMAIL} \
--env AZDO_DOCKERHUB_SERVICE_CONNECTION_PASSWORD=${AZDO_DOCKERHUB_SERVICE_CONNECTION_PASSWORD} \
--workdir /workspaces/terraform-provider-azuredevops \
-v ${PWD}:/workspaces/terraform-provider-azuredevops \
dev ./scripts/acctest.sh
env:
AZDO_ORG_SERVICE_URL: ${{ secrets.AZDO_ORG_SERVICE_URL }}
AZDO_PERSONAL_ACCESS_TOKEN: ${{ secrets.AZDO_PERSONAL_ACCESS_TOKEN }}
AZDO_GITHUB_SERVICE_CONNECTION_PAT: ${{ secrets.GITHUB_TOKEN }}
AZDO_DOCKERHUB_SERVICE_CONNECTION_USERNAME: ${{ secrets.AZDO_DOCKERHUB_SERVICE_CONNECTION_USERNAME }}
AZDO_DOCKERHUB_SERVICE_CONNECTION_EMAIL: ${{ secrets.AZDO_DOCKERHUB_SERVICE_CONNECTION_EMAIL }}
AZDO_DOCKERHUB_SERVICE_CONNECTION_PASSWORD: ${{ secrets.AZDO_DOCKERHUB_SERVICE_CONNECTION_PASSWORD }}
AZDO_TEST_AAD_USER_EMAIL: ${{ secrets.AZDO_TEST_AAD_USER_EMAIL }}
11 changes: 10 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.env
.vscode/
#direnv files
.envrc
bin/

terraform-provider-azure-devops
@@ -15,3 +16,11 @@ crash.log

# .tfvars files
*.tfvars

# unwanted binary file
**/debug.test
dist


#GoLand Editor configuration
.idea
1 change: 1 addition & 0 deletions .go-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.14.2
37 changes: 37 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
run:
deadline: 10m10s
modules-download-mode: vendor

issues:
max-per-linter: 0
max-same-issues: 0

linters:
disable-all: true
enable:
- deadcode
- errcheck
- gofmt
- goimports
- gosimple
- govet
- ineffassign
- interfacer
- nakedret
- misspell
- staticcheck
- structcheck
- typecheck
- unused
- unconvert
- varcheck
- vet
- vetshadow
- whitespace

linters-settings:
errcheck:
ignore: github.com/hashicorp/terraform-plugin-sdk/helper/schema:ForceNew|Set,fmt:.*,io:Close
misspell:
ignore-words:
- hdinsight
28 changes: 28 additions & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# This is an example goreleaser.yaml file with some sane defaults.
builds:
- binary: "{{ .ProjectName }}_{{ .Tag }}"
env:
- CGO_ENABLED=0
goos:
- linux
- windows
- darwin
archives:
- name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}"
format_overrides:
- goos: windows
format: zip
checksum:
name_template: 'checksums.txt'
snapshot:
name_template: "terraform-provider-azuredevops"
changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
release:
github:
owner: microsoft
name: terraform-provider-azuredevops
194 changes: 194 additions & 0 deletions .vscode/terraform.code-snippets
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
{
// Place your terraform-provider-azuredevops workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
// Placeholders with the same ids are connected.
// Example:
// "Print to console": {
// "scope": "javascript,typescript",
// "prefix": "log",
// "body": [
// "console.log('$1');",
// "$2"
// ],
// "description": "Log output to console"
// }
"Resource Template": {
"scope": "go",
"prefix": "tf-azdo-rs",
"body": [
"package azuredevops",
"",
"import (",
" \"fmt\"",
"",
" \"github.com/hashicorp/terraform-plugin-sdk/helper/schema\"",
" \"github.com/hashicorp/terraform-plugin-sdk/helper/validation\"",
"",
" \"github.com/microsoft/azure-devops-go-api/azuredevops/core\"",
" \"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/config\"",
" \"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/converter\"",
" \"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/validate\"",
")",
"",
"func resource${1}() *schema.Resource {",
" return &schema.Resource{",
" Create: resource${1}Create,",
" Read: resource${1}Read,",
" Update: resource${1}Update,",
" Delete: resource${1}Delete,",
"",
" Schema: map[string]*schema.Schema{",
" // add properties here",
" },",
" }",
"}",
"",
"func resource${1}Create(d *schema.ResourceData, m interface{}) error {",
"",
" return resource${1}Read(d, m)",
"}",
"",
"func resource${1}Read(d *schema.ResourceData, m interface{}) error {",
" clients := m.(*config.AggregatedClient)",
"",
" return nil",
"}",
"",
"func resource${1}Update(d *schema.ResourceData, m interface{}) error {",
" return resource${1}Read(d, m)",
"}",
"",
"func resource${1}Delete(d *schema.ResourceData, m interface{}) error {",
" return nil",
"}",
""
],
"description": "Resource Template"
},
"Data Source Template": {
"scope": "go",
"prefix": "tf-azdo-ds",
"body": [
"package azuredevops",
"",
"import (",
" \"fmt\"",
"",
" \"github.com/hashicorp/terraform-plugin-sdk/helper/schema\"",
" \"github.com/hashicorp/terraform-plugin-sdk/helper/validation\"",
"",
" \"github.com/microsoft/azure-devops-go-api/azuredevops/core\"",
" \"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/config\"",
" \"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/converter\"",
" \"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/validate\"",
")",
"",
"func dataSource${1}() *schema.Resource {",
" return &schema.Resource{",
" Read: dataSource${1}Read,",
"",
" //https://godoc.org/github.com/hashicorp/terraform/helper/schema#Schema",
" Schema: map[string]*schema.Schema{",
" // add properties here",
" },",
"",
" }",
"}",
"",
"func dataSource${1}Read(d *schema.ResourceData, m interface{}) error {",
" clients := m.(*config.AggregatedClient)",
" ${1}s := make([]map[string]interface{}, 0)",
" ",
" // read data into map ${1}s",
"",
" d.SetId(\"${1}s\")",
" if err := d.Set(\"${1}s\", ${1}s); err != nil {",
" return fmt.Errorf(\"Error setting `${1}s`: %+v\", err)",
" }",
"",
" return nil",
"}",
""
],
"description": "Data Source Template"
},
"Test Template": {
"scope": "go",
"prefix": "tf-azdo-test",
"body": [
"// +build all",
"",
"package azuredevops",
"",
"// The tests in this file use the mock clients in mock_client.go to mock out",
"// the Azure DevOps client operations.",
"",
"import (",
" \"context\"",
" \"errors\"",
" \"fmt\"",
" \"testing\"",
"",
" \"github.com/microsoft/terraform-provider-azuredevops/azdosdkmocks\"",
" \"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/config\"",
" \"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/converter\"",
"",
" \"github.com/golang/mock/gomock\"",
" \"github.com/google/uuid\"",
" \"github.com/hashicorp/terraform-plugin-sdk/helper/acctest\"",
" \"github.com/hashicorp/terraform-plugin-sdk/helper/resource\"",
" \"github.com/hashicorp/terraform-plugin-sdk/helper/schema\"",
" \"github.com/hashicorp/terraform-plugin-sdk/terraform\"",
" \"github.com/microsoft/azure-devops-go-api/azuredevops/core\"",
" \"github.com/microsoft/azure-devops-go-api/azuredevops/operations\"",
" \"github.com/stretchr/testify/require\"",
")",
"",
"func init() {",
" /* add code for test setup here */",
"}",
"",
"/**",
" * Begin unit tests",
" */",
"",
"func Test${1:Resource}_${2:Function}_Test${3:Subject}(t *testing.T) {",
" ctrl := gomock.NewController(t)",
" defer ctrl.Finish()",
"",
" coreClient := azdosdkmocks.NewMockCoreClient(ctrl)",
" clients := &config.AggregatedClient{",
" CoreClient: coreClient,",
" Ctx: context.Background(),",
" }",
"",
" /* start writing test here */",
"}",
""
],
"description": "Test Template"
},
"Test Function Template": {
"scope": "go",
"prefix": "tf-azdo-test-func",
"body": [
"func Test${1:Resource}_${2:Function}_Test${3:Subject}(t *testing.T) {",
" ctrl := gomock.NewController(t)",
" defer ctrl.Finish()",
"",
" coreClient := azdosdkmocks.NewMockCoreClient(ctrl)",
" clients := &config.AggregatedClient{",
" CoreClient: coreClient,",
" Ctx: context.Background(),",
" }",
"",
" /* start writing test here */",
"}",
""
],
"description": "Test Function Template"
}
}
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
## 0.0.1 (Unreleased)

NOTES:
* The Azure DevOps provider can be used to configure Azure DevOps project in [Microsoft Azure](https://azure.microsoft.com/en-us/) using [Azure DevOps Service REST API](https://docs.microsoft.com/en-us/rest/api/azure/devops/?view=azure-devops-rest-5.1)

FEATURES:
* **New Resource** `azuredevops_build_definition`
* **New Resource** `azuredevops_project`
* **New Resource** `azuredevops_variable_group` [#21](https://github.com/microsoft/terraform-provider-azuredevops/issues/21)
* **New Resource** `azuredevops_serviceendpoint_github` [#3](https://github.com/microsoft/terraform-provider-azuredevops/issues/3)
* **New Resource** `azuredevops_serviceendpoint_dockerhub` [#3](https://github.com/microsoft/terraform-provider-azuredevops/issues/3)
* **New Resource** `azuredevops_serviceendpoint_azurerm` [#3](https://github.com/microsoft/terraform-provider-azuredevops/issues/3)
* **New Resource** `azuredevops_git_repository` [#94](https://github.com/microsoft/terraform-provider-azuredevops/issues/94) [#95](https://github.com/microsoft/terraform-provider-azuredevops/issues/95) [#96](https://github.com/microsoft/terraform-provider-azuredevops/issues/96) [#97](https://github.com/microsoft/terraform-provider-azuredevops/issues/97)
* **New Resource** `azuredevops_user_entitlement` [#125](https://github.com/microsoft/terraform-provider-azuredevops/issues/125)
* **New Resource** `azuredevops_group_membership` [#74](github.com/microsoft/terraform-provider-azuredevops/issues/74)
* **New Resource** `azuredevops_agent_pool` [#22](https://github.com/microsoft/terraform-provider-azuredevops/issues/22)
* **New Resource** `azuredevops_group` [#103](https://github.com/microsoft/terraform-provider-azuredevops/issues/103)
* **New Data Source** `azuredevops_group` [#126](https://github.com/microsoft/terraform-provider-azuredevops/issues/126)
* **New Data Source** `azuredevops_projects` [#17](https://github.com/microsoft/terraform-provider-azuredevops/issues/17)
80 changes: 80 additions & 0 deletions GNUmakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
TEST?=$$(go list ./... |grep -v 'vendor')
WEBSITE_REPO=github.com/hashicorp/terraform-website
PKG_NAME=azuredevops
TESTTIMEOUT=180m

.EXPORT_ALL_VARIABLES:
TF_SCHEMA_PANIC_ON_ERROR=1
GO111MODULE=on
GOFLAGS=-mod=vendor

default: build

tools:
@echo "==> installing required tooling..."
@sh "$(CURDIR)/scripts/gogetcookie.sh"
GO111MODULE=off go get -u github.com/golangci/golangci-lint/cmd/golangci-lint
GO111MODULE=off go get -u github.com/client9/misspell/cmd/misspell
GO111MODULE=off go get -u github.com/bflad/tfproviderlint/cmd/tfproviderlint
GO111MODULE=off go get -u github.com/bflad/tfproviderdocs
GO111MODULE=off go get -u github.com/katbyte/terrafmt

build: fmtcheck
go install

fmt:
@echo "==> Fixing source code with gofmt..."
@echo "# This logic should match the search logic in scripts/gofmtcheck.sh"
find . -name '*.go' | grep -v vendor | xargs gofmt -s -w

fmtcheck:
@sh -c "'$(CURDIR)/scripts/gofmtcheck.sh'"

lint:
@echo "==> Checking source code against linters..."
golangci-lint run ./...

test: fmtcheck
go test -tags "all" -i $(TEST) || exit 1
echo $(TEST) | \
xargs -t -n4 go test -tags "all" $(TESTARGS) -timeout=30s -parallel=4

testacc: fmtcheck
TF_ACC=1 go test -tags "all" $(TEST) -v $(TESTARGS) -timeout 120m

test-compile:
@if [ "$(TEST)" = "./..." ]; then \
echo "ERROR: Set TEST to a specific package. For example,"; \
echo " make test-compile TEST=./$(PKG_NAME)"; \
exit 1; \
fi
go test -c $(TEST) $(TESTARGS)

vet:
@echo "go vet ."
@go vet $$(go list ./... | grep -v vendor/) ; if [ $$? -eq 1 ]; then \
echo ""; \
echo "Vet found suspicious constructs. Please check the reported constructs"; \
echo "and fix them if necessary before submitting the code for review."; \
exit 1; \
fi

website:
ifeq (,$(wildcard $(GOPATH)/src/$(WEBSITE_REPO)))
echo "$(WEBSITE_REPO) not found in your GOPATH (necessary for layouts and assets), get-ting..."
git clone https://$(WEBSITE_REPO) $(GOPATH)/src/$(WEBSITE_REPO)
endif
@$(MAKE) -C $(GOPATH)/src/$(WEBSITE_REPO) website-provider PROVIDER_PATH=$(shell pwd) PROVIDER_NAME=$(PKG_NAME)

website-lint:
@echo "==> Checking website against linters..."
@misspell -error -source=text website/

website-test:
ifeq (,$(wildcard $(GOPATH)/src/$(WEBSITE_REPO)))
echo "$(WEBSITE_REPO) not found in your GOPATH (necessary for layouts and assets), get-ting..."
git clone https://$(WEBSITE_REPO) $(GOPATH)/src/$(WEBSITE_REPO)
endif
@$(MAKE) -C $(GOPATH)/src/$(WEBSITE_REPO) website-provider-test PROVIDER_PATH=$(shell pwd) PROVIDER_NAME=$(PKG_NAME)

.PHONY: build test testacc vet fmt fmtcheck lint tools test-compile website website-lint website-test
187 changes: 157 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,20 @@
# Terraform Provider for Azure DevOps
# Terraform Provider for Azure DevOps (Devops Resource Manager)

[![Build Status](https://dev.azure.com/terraform-azdo/terraform-provider-azuredevops/_apis/build/status/microsoft.terraform-provider-azuredevops?branchName=master)](https://dev.azure.com/terraform-azdo/terraform-provider-azuredevops/_build/latest?definitionId=3&branchName=master)
[![Gitter](https://badges.gitter.im/terraform-provider-azuredevops/community.svg)](https://gitter.im/terraform-provider-azuredevops/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Go Report Card](https://goreportcard.com/badge/github.com/microsoft/terraform-provider-azuredevops)](https://goreportcard.com/report/github.com/microsoft/terraform-provider-azuredevops)

The AzDO (Azure DevOps) Provider supports Terraform 0.11.x and later - but Terraform 0.12.x is recommended.
The AzureRM Provider supports Terraform 0.12.x and later.

* [Terraform Website](https://www.terraform.io)
* [AzDO Website](https://azure.microsoft.com/en-us/services/devops/)
* [AzDO Provider Usage Examples](./examples/)

## Important!
This repository is a work in progress and is not yet suitable for production workloads. Community contributions are welcome.
* [Azure DevOps Website](https://azure.microsoft.com/en-us/services/devops/)
* [Provider Documentation](./website/docs/index.html.markdown)
* [Resources Documentation](./website/docs/r/)
* [Data Sources Documentation](./website/docs/d/)
* [Usage Examples](./examples/)
* [Gitter Channel](https://gitter.im/terraform-provider-azuredevops/community)

## Usage Example

* Installing the provider
```bash
./scripts/build.sh # build & test provider code
./scripts/local-install.sh # install provider locally
```

* Using the provider
```hcl
# Make sure to set the following environment variables:
# AZDO_PERSONAL_ACCESS_TOKEN
@@ -30,28 +24,161 @@ provider "azuredevops" {
}
resource "azuredevops_project" "project" {
project_name = "Test Project"
description = "Test Project Description"
visibility = "private"
version_control = "Git"
work_item_template = "Agile"
project_name = "My Awesome Project"
description = "All of my awesomee things"
}
resource "azuredevops_git_repository" "repository" {
project_id = azuredevops_project.project.id
name = "My Awesome Repo"
initialization {
init_type = "Clean"
}
}
resource "azuredevops_build_definition" "build_definition" {
project_id = azuredevops_project.project.id
name = "Test Pipeline"
agent_pool_name = "Hosted Ubuntu 1604"
project_id = azuredevops_project.project.id
name = "My Awesome Build Pipeline"
path = "\\"
repository {
repo_type = "GitHub"
repo_name = "nmiodice/terraform-azure-devops-hack"
branch_name = "master"
yml_path = "azdo-api-samples/azure-pipeline.yml"
service_connection_id = "1a0e1da9-57a6-4470-8e96-160a622c4a17" # Note: Eventually this will come from a GitHub Service Connection resource...
repo_type = "TfsGit"
repo_id = azuredevops_git_repository.repository.id
branch_name = azuredevops_git_repository.repository.default_branch
yml_path = "azure-pipelines.yml"
}
}
```

# Contributing
## Developer Requirements

* [Terraform](https://www.terraform.io/downloads.html) version 0.12.x +
* [Go](https://golang.org/doc/install) version 1.13.x (to build the provider plugin)

If you're on Windows you'll also need:
* [Git for Windows](https://git-scm.com/download/win)

If you what to use the `makefile` build strategy on Windows it's required to install

* [Make for Windows](http://gnuwin32.sourceforge.net/packages/make.htm)

For *GNU32 Make*, make sure its bin path is added to PATH environment variable.*

For *Git Bash for Windows*, at the step of "Adjusting your PATH environment", please choose "Use Git and optional Unix tools from Windows Command Prompt".*

As [described below](#build-using-powerShell-scripts) we provide some PowerShell scripts to build the provider on Windows, without the requiremet to install any Unix based tools aside Go.

## Developing the Provider

If you wish to work on the provider, you'll first need [Go](http://www.golang.org) installed on your machine (version 1.13+ is **required**). You'll also need to correctly setup a [GOPATH](http://golang.org/doc/code.html#GOPATH), as well as adding `$GOPATH/bin` to your `$PATH`.

### Using the GOPATH model

First clone the repository to: `$GOPATH/src/github.com/terraform-providers/terraform-provider-azuredevops`

```sh
$ mkdir -p $GOPATH/src/github.com/terraform-providers && cd "$_"
$ git clone git@github.com:microsoft/terraform-provider-azuredevops.git
$ cd terraform-provider-azuredevops
```

Once you've cloned, run the `./scripts/build.sh` and `./scripts/local-install.sh`, as recommended [here](https://github.com/microsoft/terraform-provider-azuredevops/blob/master/docs/contributing.md#3-build--install-provider).
These commands will sideload the plugin for Terraform.

### Using a directory separate from GOPATH

The infrastructure supports building and testing the provider outside `GOPATH` in an arbitrary directory.
In this scenario all required packages of the provider during build will be managed via the `pkg` in `$GOPATH`. As with the [GOPATH Model](#using-the-gopath-model), you can redefine the `GOPATH` environment variable to prevent existing packages in the current `GOPATH` directory from being changed.

### Build using make

Once inside the provider directory, you can run `make tools` to install the dependent tooling required to compile the provider.

At this point you can compile the provider by running `make build`, which will build the provider and put the provider binary in the `$GOPATH/bin` directory.

```sh
$ make build
...
$ $GOPATH/bin/terraform-provider-azuredevops
...
```

You can also cross-compile if necessary:

```sh
GOOS=windows GOARCH=amd64 make build
```

In order to run the Unit Tests for the provider, you can run:

```sh
$ make test
```

The majority of tests in the provider are Acceptance Tests - which provisions real resources in Azure. It's possible to run the entire acceptance test suite by running `make testacc` - however it's likely you'll want to run a subset, which you can do using a prefix, by running:

```sh
make testacc SERVICE='resource' TESTARGS='-run=TestAccAzureRMResourceGroup' TESTTIMEOUT='60m'
```

### Build using PowerShell scripts

If you like to develop on Windows, we provide a set of PowerShell scripts to build and test the provider.
They don't offer the luxury of a Makefile environment but are quite sufficient to develop on Windows.

#### `scripts\build.ps1`

The `build.ps1`is used to build the provider. Aside this the script runs (if not skipped) the defined unit tests and is able to install the compiled provider locally.

| Parameter | Description |
|-------------|-------------------------------------------------------------------------------------------|
| -SkipTests | Skip running unit tests during build |
| -Install | Install the provider locally, after a successful build |
| -DebugBuild | Build the provider with extra debugging information |
| -GoMod | Control the `-mod` build parameter: Valid values: '' (Empty string), 'vendor', 'readonly' |

#### `scripts\unittest.ps1`

The script is used to execute unit tests. The script is also executed by `build.ps1` if the `-SkipTest` are not specified.

| Parameter | Description |
|-------------|-----------------------------------------------------------------------------------------------------------------------------------|
| -TestFilter | A GO regular expression which filters the test functions to be executed |
| -Tag | Tests in the provider project are organized with GO build tags. The parameter accepts a list of tag names which should be tested. |
| -GoMod | Control the `-mod` build parameter: Valid values: '' (Empty string), 'vendor', 'readonly' |

#### `scripts\acctest.ps1`

The script is used to execute unit tests.

| Parameter | Description |
|-------------|-----------------------------------------------------------------------------------------------------------------------------------|
| -TestFilter | A GO regular expression which filters the test functions to be executed |
| -Tag | Tests in the provider project are organized with GO build tags. The parameter accepts a list of tag names which should be tested. |
| -GoMod | Control the `-mod` build parameter: Valid values: '' (Empty string), 'vendor', 'readonly' |

#### `scripts\gofmtcheck.ps1`

To validate if all `.go` files adhere to the required formatting rules, execute `gofmtcheck.ps1`

| Parameter | Description |
|-----------|----------------------------------------------------------------------------------------------------------------|
| -Fix | Fix any formatting rule deviations automatically. If the parameter is not set, the script runs in report mode. |

#### `scripts\lint-check-go.ps1`

Like with `gofmtcheck.ps1` the script validate if all `.go` files adhere to the required formatting rules and if any style mistakes exist. In difference to `gofmtcheck.ps1` the script uses Golint instead of Gofmt.

## Environment variables for acceptance tests

The following Environment Variables must be set in your shell prior to running acceptance tests:

- `AZDO_ORG_SERVICE_URL`
- `AZDO_PERSONAL_ACCESS_TOKEN`
- `AZDO_DOCKERHUB_SERVICE_CONNECTION_EMAIL`
- `AZDO_DOCKERHUB_SERVICE_CONNECTION_PASSWORD`
- `AZDO_DOCKERHUB_SERVICE_CONNECTION_USERNAME`
- `AZDO_GITHUB_SERVICE_CONNECTION_PAT`
- `AZDO_TEST_AAD_USER_EMAIL`

Interested in contributing to the provider? Great, we need your help. Get started by reading the [contributing](./docs/contributing.md) document.
**Note:** Acceptance tests create real resources in Azure DevOps which often cost money to run.
80 changes: 80 additions & 0 deletions README.md.lengacy
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Terraform Provider for Azure DevOps

[![Gitter](https://badges.gitter.im/terraform-provider-azuredevops/community.svg)](https://gitter.im/terraform-provider-azuredevops/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Build Status](https://dev.azure.com/terraform-azdo/terraform-provider-azuredevops/_apis/build/status/Nightly%20Build?branchName=master)](https://dev.azure.com/terraform-azdo/terraform-provider-azuredevops/_build/latest?definitionId=27&branchName=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/microsoft/terraform-provider-azuredevops)](https://goreportcard.com/report/github.com/microsoft/terraform-provider-azuredevops)

The AzDO (Azure DevOps) Provider supports Terraform 0.11.x and later - but Terraform 0.12.x is recommended.

* [Terraform Website](https://www.terraform.io)
* [AzDO Website](https://azure.microsoft.com/en-us/services/devops/)
* [AzDO Provider Documentation](website/docs/index.html.markdown)
* [AzDO Provider Usage Examples](./examples/)

Checkout our [Project Roadmap](./docs/roadmap.md).

## Important!
This repository is a work in progress and is not yet suitable for production workloads. Community contributions are welcome.

## Looking for AzDO Provider Documentation?

![docs](docs/images/terraform-docs-website.png)

The documentation for things like resource specific usage examples, required parameters and default values can be found under the [/website](website) directory, which contains all of the [AzDO Provider Documentation](website/docs/index.html.markdown).

## Configuration Values

| Environment Variable | Description | Required? | Example |
| --- | --- | --- | --- |
| `AZDO_PERSONAL_ACCESS_TOKEN` | A personal access token that grants access to Azure DevOps APIs within the org specified by `AZDO_ORG_SERVICE_URL` | yes | `d7894a91db7610e39decbe09b2dfd449ed2ed5a` |
| `AZDO_ORG_SERVICE_URL` | URL of the Azure DevOps org in which resources will be provisioned/managed | yes | `https://dev.azure.com/contoso-org` |
| `AZDO_GITHUB_SERVICE_CONNECTION_PAT` | If running the acceptance tests, you will need this defined in order to validate the GitHub Service Connection resource | for acceptance tests only | `a9194a91d75643e39decbe09b2dfd558dd2abca` |
| `AZDO_PRJ_CREATE_DELAY` | Delay (in seconds) to insert after creation of projects. This was determined to be useful based on observed behavior of the AzDO APIs | no | `10` |

## Usage Example

* Installing the provider
```bash
./scripts/build.sh # build & test provider code
./scripts/local-install.sh # install provider locally
```

* Provision project, repository and build pipeline using the provider
```hcl
# Make sure to set the following environment variables:
# AZDO_PERSONAL_ACCESS_TOKEN
# AZDO_ORG_SERVICE_URL
provider "azuredevops" {
version = ">= 0.0.1"
}

resource "azuredevops_project" "project" {
project_name = "My Awesome Project"
description = "All of my awesomee things"
}

resource "azuredevops_git_repository" "repository" {
project_id = azuredevops_project.project.id
name = "My Awesome Repo"
initialization {
init_type = "Clean"
}
}

resource "azuredevops_build_definition" "build_definition" {
project_id = azuredevops_project.project.id
name = "My Awesome Build Pipeline"
path = "\\"

repository {
repo_type = "TfsGit"
repo_name = azuredevops_git_repository.repository.name
branch_name = azuredevops_git_repository.repository.default_branch
yml_path = "azure-pipelines.yml"
}
}
```

# Contributing

Interested in contributing to the provider? Great, we need your help. Get started by reading the [contributing](./docs/contributing.md) document.
50 changes: 50 additions & 0 deletions azdosdkmocks/accounts_sdk_mock.go
1,202 changes: 1,202 additions & 0 deletions azdosdkmocks/build_sdk_mock.go

Large diffs are not rendered by default.

422 changes: 422 additions & 0 deletions azdosdkmocks/core_sdk_mock.go

Large diffs are not rendered by default.

1,763 changes: 1,763 additions & 0 deletions azdosdkmocks/git_sdk_mock.go

Large diffs are not rendered by default.

389 changes: 389 additions & 0 deletions azdosdkmocks/graph_sdk_mock.go

Large diffs are not rendered by default.

498 changes: 498 additions & 0 deletions azdosdkmocks/identity_sdk_mock.go

Large diffs are not rendered by default.

257 changes: 257 additions & 0 deletions azdosdkmocks/memberentitlementmanagement_sdk_mock.go
50 changes: 50 additions & 0 deletions azdosdkmocks/operations_sdk_mock.go
214 changes: 214 additions & 0 deletions azdosdkmocks/policy_sdk_mock.go
50 changes: 50 additions & 0 deletions azdosdkmocks/profile_sdk_mock.go
184 changes: 184 additions & 0 deletions azdosdkmocks/serviceendpoint_sdk_mock.go
688 changes: 688 additions & 0 deletions azdosdkmocks/taskagent_sdk_mock.go

Large diffs are not rendered by default.

708 changes: 708 additions & 0 deletions azdosdkmocks/test_sdk_mock.go

Large diffs are not rendered by default.

217 changes: 0 additions & 217 deletions azuredevops/config.go

This file was deleted.

270 changes: 270 additions & 0 deletions azuredevops/crud/serviceendpoint/crud_service_endpoint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
package crudserviceendpoint

import (
"errors"
"fmt"
"strings"

"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/microsoft/azure-devops-go-api/azuredevops/serviceendpoint"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/config"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/converter"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/tfhelper"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/validate"
)

const errMsgTfConfigRead = "Error reading terraform configuration: %+v"

type flatFunc func(d *schema.ResourceData, serviceEndpoint *serviceendpoint.ServiceEndpoint, projectID *string)
type expandFunc func(d *schema.ResourceData) (*serviceendpoint.ServiceEndpoint, *string, error)
type importFunc func(clients *config.AggregatedClient, id string) (string, string, error)

//GenBaseServiceEndpointResource creates a Resource with the common parts
// that all Service Endpoints require.
func GenBaseServiceEndpointResource(f flatFunc, e expandFunc, i importFunc) *schema.Resource {
return &schema.Resource{
Create: genServiceEndpointCreateFunc(f, e),
Read: genServiceEndpointReadFunc(f),
Update: genServiceEndpointUpdateFunc(f, e),
Delete: genServiceEndpointDeleteFunc(e),
Importer: &schema.ResourceImporter{
State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
projectID, serviceEndpointID, err := i(meta.(*config.AggregatedClient), d.Id())
if err != nil {
return nil, fmt.Errorf("Error parsing the variable service endpoint ID from the Terraform resource data: %v", err)
}
d.Set("project_id", projectID)
d.SetId(serviceEndpointID)

return []*schema.ResourceData{d}, nil
},
},
Schema: genBaseSchema(),
}
}

func genBaseSchema() map[string]*schema.Schema {
return map[string]*schema.Schema{
"project_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"service_endpoint_name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validate.NoEmptyStrings,
ForceNew: true,
},
"description": {
Type: schema.TypeString,
Optional: true,
Default: "Managed by Terraform",
},
"authorization": {
Type: schema.TypeMap,
Optional: true,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
}
}

// DoBaseExpansion performs the expansion for the 'base' attributes that are defined in the schema, above
func DoBaseExpansion(d *schema.ResourceData) (*serviceendpoint.ServiceEndpoint, *string) {
// an "error" is OK here as it is expected in the case that the ID is not set in the resource data
var serviceEndpointID *uuid.UUID
parsedID, err := uuid.Parse(d.Id())
if err == nil {
serviceEndpointID = &parsedID
}
projectID := converter.String(d.Get("project_id").(string))
serviceEndpoint := &serviceendpoint.ServiceEndpoint{
Id: serviceEndpointID,
Name: converter.String(d.Get("service_endpoint_name").(string)),
Owner: converter.String("library"),
Description: converter.String(d.Get("description").(string)),
}

return serviceEndpoint, projectID
}

// DoBaseFlattening performs the flattening for the 'base' attributes that are defined in the schema, above
func DoBaseFlattening(d *schema.ResourceData, serviceEndpoint *serviceendpoint.ServiceEndpoint, projectID *string) {
d.SetId(serviceEndpoint.Id.String())
d.Set("service_endpoint_name", *serviceEndpoint.Name)
d.Set("project_id", projectID)
d.Set("description", *serviceEndpoint.Description)
d.Set("authorization", &map[string]interface{}{
"scheme": *serviceEndpoint.Authorization.Scheme,
})
}

// GetScheme allows you to get the nested scheme value
func GetScheme(d *schema.ResourceData) (string, error) {
authorization := d.Get("authorization").(*schema.Set)
if authorization == nil {
return "", errors.New("authorization not set")
}
authorizationList := authorization.List()
if len(authorizationList) != 1 {
return "", errors.New("authorization is invalid")
}
scheme := authorizationList[0].(map[string]interface{})["scheme"].(string)
return scheme, nil
}

// MakeProtectedSchema create protected schema
func MakeProtectedSchema(r *schema.Resource, keyName, envVarName, description string) {
r.Schema[keyName] = &schema.Schema{
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc(envVarName, nil),
Description: description,
Sensitive: true,
DiffSuppressFunc: tfhelper.DiffFuncSuppressSecretChanged,
}

secretHashKey, secretHashSchema := tfhelper.GenerateSecreteMemoSchema(keyName)
r.Schema[secretHashKey] = secretHashSchema
}

// MakeUnprotectedSchema create unprotected schema
func MakeUnprotectedSchema(r *schema.Resource, keyName, envVarName, description string) {
r.Schema[keyName] = &schema.Schema{
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc(envVarName, nil),
Description: description,
}
}

// Make the Azure DevOps API call to create the endpoint
func createServiceEndpoint(clients *config.AggregatedClient, endpoint *serviceendpoint.ServiceEndpoint, project *string) (*serviceendpoint.ServiceEndpoint, error) {
if strings.EqualFold(*endpoint.Type, "github") && strings.EqualFold(*endpoint.Authorization.Scheme, "InstallationToken") {
return nil, fmt.Errorf("Github Apps must be created on Github and then can be imported")
}
createdServiceEndpoint, err := clients.ServiceEndpointClient.CreateServiceEndpoint(
clients.Ctx,
serviceendpoint.CreateServiceEndpointArgs{
Endpoint: endpoint,
Project: project,
})

return createdServiceEndpoint, err
}

func deleteServiceEndpoint(clients *config.AggregatedClient, project *string, endPointID *uuid.UUID) error {
err := clients.ServiceEndpointClient.DeleteServiceEndpoint(
clients.Ctx,
serviceendpoint.DeleteServiceEndpointArgs{
Project: project,
EndpointId: endPointID,
})

return err
}

func updateServiceEndpoint(clients *config.AggregatedClient, endpoint *serviceendpoint.ServiceEndpoint, project *string) (*serviceendpoint.ServiceEndpoint, error) {
if strings.EqualFold(*endpoint.Type, "github") && strings.EqualFold(*endpoint.Authorization.Scheme, "InstallationToken") {
return nil, fmt.Errorf("Github Apps can not be updated must match imported values exactly")
}
updatedServiceEndpoint, err := clients.ServiceEndpointClient.UpdateServiceEndpoint(
clients.Ctx,
serviceendpoint.UpdateServiceEndpointArgs{
Endpoint: endpoint,
Project: project,
EndpointId: endpoint.Id,
})

return updatedServiceEndpoint, err
}

func genServiceEndpointCreateFunc(flatFunc flatFunc, expandFunc expandFunc) func(d *schema.ResourceData, m interface{}) error {
return func(d *schema.ResourceData, m interface{}) error {
clients := m.(*config.AggregatedClient)
serviceEndpoint, projectID, err := expandFunc(d)
if err != nil {
return fmt.Errorf(errMsgTfConfigRead, err)
}

createdServiceEndpoint, err := createServiceEndpoint(clients, serviceEndpoint, projectID)
if err != nil {
return fmt.Errorf("Error creating service endpoint in Azure DevOps: %+v", err)
}

flatFunc(d, createdServiceEndpoint, projectID)
return nil
}
}

func genServiceEndpointReadFunc(flatFunc flatFunc) func(d *schema.ResourceData, m interface{}) error {
return func(d *schema.ResourceData, m interface{}) error {
clients := m.(*config.AggregatedClient)

var serviceEndpointID *uuid.UUID
parsedServiceEndpointID, err := uuid.Parse(d.Id())
if err != nil {
return fmt.Errorf("Error parsing the service endpoint ID from the Terraform resource data: %v", err)
}
serviceEndpointID = &parsedServiceEndpointID
projectID := converter.String(d.Get("project_id").(string))

serviceEndpoint, err := clients.ServiceEndpointClient.GetServiceEndpointDetails(
clients.Ctx,
serviceendpoint.GetServiceEndpointDetailsArgs{
EndpointId: serviceEndpointID,
Project: projectID,
},
)
if err != nil {
if utils.ResponseWasNotFound(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error looking up service endpoint given ID (%v) and project ID (%v): %v", serviceEndpointID, projectID, err)
}

if serviceEndpoint.Id == nil {
// e.g. service endpoint has been deleted separately without TF
d.SetId("")
} else {
flatFunc(d, serviceEndpoint, projectID)
}
return nil
}
}

func genServiceEndpointUpdateFunc(flatFunc flatFunc, expandFunc expandFunc) schema.UpdateFunc {
return func(d *schema.ResourceData, m interface{}) error {
clients := m.(*config.AggregatedClient)
serviceEndpoint, projectID, err := expandFunc(d)
if err != nil {
return fmt.Errorf(errMsgTfConfigRead, err)
}

updatedServiceEndpoint, err := updateServiceEndpoint(clients, serviceEndpoint, projectID)
if err != nil {
return fmt.Errorf("Error updating service endpoint in Azure DevOps: %+v", err)
}

flatFunc(d, updatedServiceEndpoint, projectID)
return nil
}
}

func genServiceEndpointDeleteFunc(expandFunc expandFunc) schema.DeleteFunc {
return func(d *schema.ResourceData, m interface{}) error {
clients := m.(*config.AggregatedClient)
serviceEndpoint, projectID, err := expandFunc(d)
if err != nil {
return fmt.Errorf(errMsgTfConfigRead, err)
}

return deleteServiceEndpoint(clients, projectID, serviceEndpoint.Id)
}
}
32 changes: 32 additions & 0 deletions azuredevops/data_client_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package azuredevops

import (
"time"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/config"
)

const (
organizationURL = "organization_url"
)

func dataClientConfig() *schema.Resource {
return &schema.Resource{
Read: clientConfigRead,
Schema: map[string]*schema.Schema{
organizationURL: {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func clientConfigRead(d *schema.ResourceData, m interface{}) error {
// The ID is meaningless for this data source, so ID can act as a
// point in time snapshot
d.SetId(time.Now().UTC().String())
d.Set(organizationURL, m.(*config.AggregatedClient).OrganizationURL)
return nil
}
37 changes: 37 additions & 0 deletions azuredevops/data_client_config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// +build all core

package azuredevops

import (
"os"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/testhelper"
)

/**
* Begin acceptance tests
*/

// Verifies that the client config data source loads the configured AzDO org
func TestAccClientConfig_LoadsCorrectProperties(t *testing.T) {
tfNode := "data.azuredevops_client_config.c"
resource.Test(t, resource.TestCase{
PreCheck: func() { testhelper.TestAccPreCheck(t, nil) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: `data "azuredevops_client_config" "c" {}`,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet(tfNode, "id"),
resource.TestCheckResourceAttr(tfNode, "organization_url", os.Getenv("AZDO_ORG_SERVICE_URL")),
),
},
},
})
}

func init() {
InitProvider()
}
225 changes: 225 additions & 0 deletions azuredevops/data_git_repositories.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
package azuredevops

import (
"crypto/sha1"
"encoding/base64"
"fmt"
"log"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/microsoft/azure-devops-go-api/azuredevops/git"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/config"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/converter"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/suppress"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/validate"
)

func dataGitRepositories() *schema.Resource {
return &schema.Resource{
Read: dataSourceGitRepositoriesRead,
Schema: map[string]*schema.Schema{
"project_id": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validate.UUID,
DiffSuppressFunc: suppress.CaseDifference,
},
"name": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validate.NoEmptyStrings,
DiffSuppressFunc: suppress.CaseDifference,
},
"include_hidden": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"repositories": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Computed: true,
},
"id": {
Type: schema.TypeString,
Computed: true,
},
"url": {
Type: schema.TypeString,
Computed: true,
},
"ssh_url": {
Type: schema.TypeString,
Computed: true,
},
"web_url": {
Type: schema.TypeString,
Computed: true,
},
"remote_url": {
Type: schema.TypeString,
Computed: true,
},
"project_id": {
Type: schema.TypeString,
Computed: true,
},
"size": {
Type: schema.TypeInt,
Computed: true,
},
"default_branch": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
},
}
}

func dataSourceGitRepositoriesRead(d *schema.ResourceData, m interface{}) error {
clients := m.(*config.AggregatedClient)

projectRepos, err := getGitRepositoriesByNameAndProject(d, clients)
if err != nil {
if utils.ResponseWasNotFound(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error finding repositories. Error: %v", err)
}
log.Printf("[TRACE] plugin.terraform-provider-azuredevops: Read [%d] Git repositories", len(*projectRepos))

results, err := flattenGitRepositories(projectRepos)
if err != nil {
return fmt.Errorf("Error flattening projects. Error: %v", err)
}

repoNames, err := getAttributeValues(results, "name")
if err != nil {
return fmt.Errorf("Failed to get list of repository names: %v", err)
}
id, err := createGitRepositoryDataSourceID(d, &repoNames)
if err != nil {
return err
}
d.SetId(id)
err = d.Set("repositories", results)
if err != nil {
d.SetId("")
return err
}
return nil
}

func createGitRepositoryDataSourceID(d *schema.ResourceData, repoNames *[]string) (string, error) {
h := sha1.New()
var names []string
if nil == repoNames {
names = []string{}
} else {
names = *repoNames
}
if len(names) <= 0 {
names = append(names, "empty")
}
projectID := d.Get("project_id").(string)
if projectID != "" {
names = append([]string{projectID}, names...)
}
if _, err := h.Write([]byte(strings.Join(names, "-"))); err != nil {
return "", fmt.Errorf("Unable to compute hash for Git repository names: %v", err)
}
return "gitRepos#" + base64.URLEncoding.EncodeToString(h.Sum(nil)), nil
}

func flattenGitRepositories(repos *[]git.GitRepository) ([]interface{}, error) {
if repos == nil {
return []interface{}{}, nil
}

results := make([]interface{}, 0)

for _, element := range *repos {
output := make(map[string]interface{})
if element.Name != nil {
output["name"] = *element.Name
}

if element.Id != nil {
output["id"] = element.Id.String()
}

if element.Url != nil {
output["url"] = *element.Url
}

if element.RemoteUrl != nil {
output["remote_url"] = *element.RemoteUrl
}

if element.SshUrl != nil {
output["ssh_url"] = *element.SshUrl
}

if element.WebUrl != nil {
output["web_url"] = *element.WebUrl
}

if element.Project != nil && element.Project.Id != nil {
output["project_id"] = element.Project.Id.String()
}

if element.Size != nil {
output["size"] = *element.Size
}

if element.DefaultBranch != nil {
output["default_branch"] = *element.DefaultBranch
}

results = append(results, output)
}

return results, nil
}

func getGitRepositoriesByNameAndProject(d *schema.ResourceData, clients *config.AggregatedClient) (*[]git.GitRepository, error) {
var repos *[]git.GitRepository
var err error
name, projectID := d.Get("name").(string), d.Get("project_id").(string)
includeHidden := d.Get("include_hidden").(bool)

if name != "" && projectID != "" {
repo, err := gitRepositoryRead(clients, "", name, projectID)
if err != nil {
return nil, err
}
repos = &[]git.GitRepository{*repo}
} else {
repos, err = clients.GitReposClient.GetRepositories(clients.Ctx, git.GetRepositoriesArgs{
Project: converter.String(projectID),
IncludeHidden: converter.Bool(includeHidden),
})
if err != nil {
return nil, err
}
if name != "" {
for _, repo := range *repos {
if strings.EqualFold(*repo.Name, name) {
repos = &[]git.GitRepository{repo}
break
}
}
}
}
return repos, nil
}
334 changes: 334 additions & 0 deletions azuredevops/data_git_repositories_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,334 @@
// +build all core data_git_repositories

package azuredevops

import (
"context"
"errors"
"fmt"
"testing"

"github.com/golang/mock/gomock"
"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/microsoft/azure-devops-go-api/azuredevops/core"
"github.com/microsoft/azure-devops-go-api/azuredevops/git"
"github.com/microsoft/terraform-provider-azuredevops/azdosdkmocks"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/config"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/converter"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/testhelper"
"github.com/stretchr/testify/require"
)

func init() {
/* add code for test setup here */
}

var gitRepoListEmpty = []git.GitRepository{}

var azProjectRef = &core.TeamProjectReference{
Id: testhelper.CreateUUID(),
Name: converter.String("project-01"),
}

var gitRepoList = []git.GitRepository{
{
Links: nil,
DefaultBranch: nil,
Id: testhelper.CreateUUID(),
IsFork: converter.Bool(false),
Name: converter.String("repo-01"),
ParentRepository: nil,
Project: azProjectRef,
RemoteUrl: nil,
Size: nil,
SshUrl: nil,
Url: nil,
ValidRemoteUrls: nil,
WebUrl: nil,
},
{
Links: nil,
DefaultBranch: converter.String("master"),
Id: testhelper.CreateUUID(),
IsFork: converter.Bool(true),
Name: converter.String("repo-02"),
ParentRepository: &git.GitRepositoryRef{
Id: testhelper.CreateUUID(),
Name: converter.String("repo-parent-02"),
},
Project: azProjectRef,
RemoteUrl: nil,
Size: converter.UInt64(0),
SshUrl: nil,
Url: nil,
ValidRemoteUrls: nil,
WebUrl: nil,
},
{
Links: nil,
DefaultBranch: converter.String("dev"),
Id: testhelper.CreateUUID(),
IsFork: nil,
Name: converter.String("repo-03"),
ParentRepository: nil,
Project: &core.TeamProjectReference{
Id: testhelper.CreateUUID(),
Name: converter.String("project-02"),
},
RemoteUrl: nil,
Size: converter.UInt64(1234),
SshUrl: nil,
Url: nil,
ValidRemoteUrls: nil,
WebUrl: nil,
},
}

func TestGitRepositoriesDataSource_Read_TestHandleError(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

graphClient := azdosdkmocks.NewMockGraphClient(ctrl)
repoClient := azdosdkmocks.NewMockGitClient(ctrl)

clients := &config.AggregatedClient{
GitReposClient: repoClient,
GraphClient: graphClient,
Ctx: context.Background(),
}

expectedGetRepositoriesArgs := git.GetRepositoriesArgs{
IncludeHidden: converter.Bool(false),
}

repoClient.
EXPECT().
GetRepositories(clients.Ctx, expectedGetRepositoriesArgs).
Return(nil, errors.New("GetRepositories() Failed")).
Times(1)

resourceData := schema.TestResourceDataRaw(t, dataGitRepositories().Schema, nil)

err := dataSourceGitRepositoriesRead(resourceData, clients)
require.NotNil(t, err)
require.Zero(t, resourceData.Id())
repos := resourceData.Get("repositories").([]interface{})
require.NotNil(t, repos)
require.Zero(t, len(repos))
}

func TestGitRepositoriesDataSource_Read_TestHandleErrorWithSpecificRepository(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

graphClient := azdosdkmocks.NewMockGraphClient(ctrl)
repoClient := azdosdkmocks.NewMockGitClient(ctrl)

clients := &config.AggregatedClient{
GitReposClient: repoClient,
GraphClient: graphClient,
Ctx: context.Background(),
}

repo := gitRepoList[2]
expectedGetRepositoryArgs := git.GetRepositoryArgs{
RepositoryId: repo.Name,
Project: converter.String(repo.Project.Id.String()),
}
repoClient.
EXPECT().
GetRepository(clients.Ctx, expectedGetRepositoryArgs).
Return(nil, errors.New("GetRepository() Failed"))

resourceData := schema.TestResourceDataRaw(t, dataGitRepositories().Schema, nil)
resourceData.Set("name", *repo.Name)
resourceData.Set("project_id", repo.Project.Id.String())

err := dataSourceGitRepositoriesRead(resourceData, clients)
require.NotNil(t, err)
require.Zero(t, resourceData.Id())
repos := resourceData.Get("repositories").([]interface{})
require.NotNil(t, repos)
require.Zero(t, len(repos))
}

func TestGitRepositoriesDataSource_Read_NoRepositories(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

graphClient := azdosdkmocks.NewMockGraphClient(ctrl)
repoClient := azdosdkmocks.NewMockGitClient(ctrl)

clients := &config.AggregatedClient{
GitReposClient: repoClient,
GraphClient: graphClient,
Ctx: context.Background(),
}

expectedGetRepositoriesArgs := git.GetRepositoriesArgs{
IncludeHidden: converter.Bool(false),
}

repoClient.
EXPECT().
GetRepositories(clients.Ctx, expectedGetRepositoriesArgs).
Return(&[]git.GitRepository{}, nil).
Times(1)

resourceData := schema.TestResourceDataRaw(t, dataGitRepositories().Schema, nil)

err := dataSourceGitRepositoriesRead(resourceData, clients)
require.Nil(t, err)
repos := resourceData.Get("repositories").([]interface{})
require.NotNil(t, repos)
require.Zero(t, len(repos))
}

func TestGitRepositoriesDataSource_Read_AllRepositories(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

graphClient := azdosdkmocks.NewMockGraphClient(ctrl)
repoClient := azdosdkmocks.NewMockGitClient(ctrl)

clients := &config.AggregatedClient{
GitReposClient: repoClient,
GraphClient: graphClient,
Ctx: context.Background(),
}

expectedGetRepositoriesArgs := git.GetRepositoriesArgs{
IncludeHidden: converter.Bool(false),
}

repoClient.
EXPECT().
GetRepositories(clients.Ctx, expectedGetRepositoriesArgs).
Return(&gitRepoList, nil).
Times(1)

resourceData := schema.TestResourceDataRaw(t, dataGitRepositories().Schema, nil)

err := dataSourceGitRepositoriesRead(resourceData, clients)
require.Nil(t, err)
repos := resourceData.Get("repositories").([]interface{})
require.NotNil(t, repos)
require.Equal(t, len(repos), 3)
}

func TestGitRepositoriesDataSource_Read_AllRepositoriesByProject(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

graphClient := azdosdkmocks.NewMockGraphClient(ctrl)
repoClient := azdosdkmocks.NewMockGitClient(ctrl)

clients := &config.AggregatedClient{
GitReposClient: repoClient,
GraphClient: graphClient,
Ctx: context.Background(),
}

expectedGetRepositoriesArgs := git.GetRepositoriesArgs{
Project: converter.String(azProjectRef.Id.String()),
IncludeHidden: converter.Bool(false),
}

repoClient.
EXPECT().
GetRepositories(clients.Ctx, expectedGetRepositoriesArgs).
Return(&[]git.GitRepository{
gitRepoList[0],
gitRepoList[1],
}, nil).
Times(1)

resourceData := schema.TestResourceDataRaw(t, dataGitRepositories().Schema, nil)
resourceData.Set("project_id", azProjectRef.Id.String())

err := dataSourceGitRepositoriesRead(resourceData, clients)
require.Nil(t, err)
repos := resourceData.Get("repositories").([]interface{})
require.NotNil(t, repos)
require.Equal(t, len(repos), 2)
repoMap := make(map[string]interface{})
for _, item := range repos {
repoData := item.(map[string]interface{})
repoMap[repoData["name"].(string)] = repoData
}

for i := 0; i < 2; i++ {
require.Contains(t, repoMap, *gitRepoList[i].Name)
repo := repoMap[*gitRepoList[i].Name].(map[string]interface{})
require.Equal(t, gitRepoList[i].Project.Id.String(), repo["project_id"])
require.Equal(t, gitRepoList[i].Id.String(), repo["id"])
}
}

func TestGitRepositoriesDataSource_Read_SingleRepository(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

graphClient := azdosdkmocks.NewMockGraphClient(ctrl)
repoClient := azdosdkmocks.NewMockGitClient(ctrl)

clients := &config.AggregatedClient{
GitReposClient: repoClient,
GraphClient: graphClient,
Ctx: context.Background(),
}

repo := gitRepoList[1]
expectedGetRepositoryArgs := git.GetRepositoryArgs{
RepositoryId: repo.Name,
Project: converter.String(repo.Project.Id.String()),
}
repoClient.
EXPECT().
GetRepository(clients.Ctx, expectedGetRepositoryArgs).
Return(&repo, nil)

resourceData := schema.TestResourceDataRaw(t, dataGitRepositories().Schema, nil)
resourceData.Set("name", *repo.Name)
resourceData.Set("project_id", repo.Project.Id.String())

err := dataSourceGitRepositoriesRead(resourceData, clients)
require.Nil(t, err)
repos := resourceData.Get("repositories").([]interface{})
require.NotNil(t, repos)
require.Equal(t, len(repos), 1)
}

/**
* Begin acceptance tests
*/

// Verifies that the following sequence of events occurrs without error:
// (1) TF can create a project
// (2) A data source is added to the configuration, and that data source can find the created project
func TestAccAzureTfsGitRepositories_DataSource(t *testing.T) {
projectName := testhelper.TestAccResourcePrefix + acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
gitRepoName := testhelper.TestAccResourcePrefix + acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
tfConfigStep1 := testhelper.TestAccAzureGitRepoResource(projectName, gitRepoName, "Clean")
tfConfigStep2 := fmt.Sprintf("%s\n%s", tfConfigStep1, testhelper.TestAccProjectGitRepositories(projectName, gitRepoName))

tfNode := "data.azuredevops_git_repositories.repositories"
resource.Test(t, resource.TestCase{
PreCheck: func() { testhelper.TestAccPreCheck(t, nil) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: tfConfigStep1,
}, {
Config: tfConfigStep2,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(tfNode, "name", gitRepoName),
resource.TestCheckResourceAttr(tfNode, "repositories.0.name", gitRepoName),
resource.TestCheckResourceAttr(tfNode, "repositories.0.default_branch", "refs/heads/master"),
),
},
},
})
}
134 changes: 134 additions & 0 deletions azuredevops/data_group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package azuredevops

import (
"fmt"
"strings"

"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"github.com/microsoft/azure-devops-go-api/azuredevops/graph"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/config"
)

func dataGroup() *schema.Resource {
return &schema.Resource{
Read: dataSourceGroupRead,
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
ForceNew: true,
Required: true,
ValidateFunc: validation.NoZeroValues,
},
"project_id": {
Type: schema.TypeString,
ForceNew: true,
Required: true,
ValidateFunc: validation.NoZeroValues,
},
"descriptor": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

// Performs a lookup of a project group. This involves the following actions:
// (1) Identify AzDO graph descriptor for the project in which the group exists
// (2) Query for all AzDO groups that exist within the project. This leverages the AzDO graph descriptor for the project.
// This involves querying a paginated API, so multiple API calls may be needed for this step.
// (3) Select group that has the name identified by the schema
func dataSourceGroupRead(d *schema.ResourceData, m interface{}) error {
clients := m.(*config.AggregatedClient)
groupName, projectID := d.Get("name").(string), d.Get("project_id").(string)

projectDescriptor, err := getProjectDescriptor(clients, projectID)
if err != nil {
if utils.ResponseWasNotFound(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error finding descriptor for project with ID %s. Error: %v", projectID, err)
}

projectGroups, err := getGroupsForDescriptor(clients, projectDescriptor)
if err != nil {
return fmt.Errorf("Error finding groups for project with ID %s. Error: %v", projectID, err)
}

targetGroup := selectGroup(projectGroups, groupName)
if targetGroup == nil {
return fmt.Errorf("Could not find group with name %s in project with ID %s", groupName, projectID)
}

d.SetId(*targetGroup.Descriptor)
d.Set("descriptor", *targetGroup.Descriptor)
return nil
}

func getProjectDescriptor(clients *config.AggregatedClient, projectID string) (string, error) {
projectUUID, err := uuid.Parse(projectID)
if err != nil {
return "", err
}

descriptor, err := clients.GraphClient.GetDescriptor(clients.Ctx, graph.GetDescriptorArgs{StorageKey: &projectUUID})
if err != nil {
return "", err
}

return *descriptor.Value, nil
}

func getGroupsForDescriptor(clients *config.AggregatedClient, projectDescriptor string) (*[]graph.GraphGroup, error) {
var groups []graph.GraphGroup
var currentToken string

for hasMore := true; hasMore; {
newGroups, latestToken, err := getGroupsWithContinuationToken(clients, projectDescriptor, currentToken)
currentToken = latestToken
if err != nil {
return nil, err
}

groups = append(groups, *newGroups...)
hasMore = currentToken != ""
}

return &groups, nil
}

func getGroupsWithContinuationToken(clients *config.AggregatedClient, projectDescriptor string, continuationToken string) (*[]graph.GraphGroup, string, error) {
args := graph.ListGroupsArgs{ScopeDescriptor: &projectDescriptor}
if continuationToken != "" {
args.ContinuationToken = &continuationToken
}

response, err := clients.GraphClient.ListGroups(clients.Ctx, args)
if err != nil {
return nil, "", err
}

if response.ContinuationToken != nil && len(*response.ContinuationToken) > 1 {
return nil, "", fmt.Errorf("Expected at most 1 continuation token, but found %d", len(*response.ContinuationToken))
}

var newToken string
if response.ContinuationToken != nil && len(*response.ContinuationToken) > 0 {
newToken = (*response.ContinuationToken)[0]
}

return response.GraphGroups, newToken, nil
}

func selectGroup(groups *[]graph.GraphGroup, groupName string) *graph.GraphGroup {
for _, group := range *groups {
if strings.EqualFold(*group.DisplayName, groupName) {
return &group
}
}
return nil
}
180 changes: 180 additions & 0 deletions azuredevops/data_group_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
// +build all core data_group

package azuredevops

import (
"context"
"errors"
"testing"

"github.com/golang/mock/gomock"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/microsoft/azure-devops-go-api/azuredevops/graph"
"github.com/microsoft/terraform-provider-azuredevops/azdosdkmocks"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/config"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/converter"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/testhelper"
"github.com/stretchr/testify/require"
)

/**
* Begin unit tests
*/

// A helper type that is used in some of these tests to make initializing
// graph entities easier
type groupMeta struct {
name string
descriptor string
}

// verifies that the translation for project_id to project_descriptor has proper error handling
func TestGroupDataSource_DoesNotSwallowProjectDescriptorLookupError(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

projectID := uuid.New()
resourceData := createResourceData(t, projectID.String(), "group-name")

graphClient := azdosdkmocks.NewMockGraphClient(ctrl)
clients := &config.AggregatedClient{GraphClient: graphClient, Ctx: context.Background()}

expectedArgs := graph.GetDescriptorArgs{StorageKey: &projectID}
graphClient.
EXPECT().
GetDescriptor(clients.Ctx, expectedArgs).
Return(nil, errors.New("GetDescriptor() Failed"))

err := dataSourceGroupRead(resourceData, clients)
require.Contains(t, err.Error(), "GetDescriptor() Failed")
}

// verifies that the group lookup functionality has proper error handling
func TestGroupDataSource_DoesNotSwallowListGroupError(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

projectID := uuid.New()
resourceData := createResourceData(t, projectID.String(), "group-name")

graphClient := azdosdkmocks.NewMockGraphClient(ctrl)
clients := &config.AggregatedClient{GraphClient: graphClient, Ctx: context.Background()}

expectedProjectDescriptorLookupArgs := graph.GetDescriptorArgs{StorageKey: &projectID}
projectDescriptor := converter.String("descriptor")
projectDescriptorResponse := graph.GraphDescriptorResult{Value: projectDescriptor}
graphClient.
EXPECT().
GetDescriptor(clients.Ctx, expectedProjectDescriptorLookupArgs).
Return(&projectDescriptorResponse, nil)

expectedListGroupArgs := graph.ListGroupsArgs{ScopeDescriptor: projectDescriptor}
graphClient.
EXPECT().
ListGroups(clients.Ctx, expectedListGroupArgs).
Return(nil, errors.New("ListGroups() Failed"))

err := dataSourceGroupRead(resourceData, clients)
require.Contains(t, err.Error(), "ListGroups() Failed")
}

// verifies that the group lookup functionality will make multiple API calls using the continuation token
// returned from the `ListGroups` api, until the API no longer returns a token
func TestGroupDataSource_HandlesContinuationToken_And_SelectsCorrectGroup(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

projectID := uuid.New()
resourceData := createResourceData(t, projectID.String(), "name1")

graphClient := azdosdkmocks.NewMockGraphClient(ctrl)
clients := &config.AggregatedClient{GraphClient: graphClient, Ctx: context.Background()}

expectedProjectDescriptorLookupArgs := graph.GetDescriptorArgs{StorageKey: &projectID}
projectDescriptor := converter.String("descriptor")
projectDescriptorResponse := graph.GraphDescriptorResult{Value: projectDescriptor}
graphClient.
EXPECT().
GetDescriptor(clients.Ctx, expectedProjectDescriptorLookupArgs).
Return(&projectDescriptorResponse, nil)

firstListGroupCallArgs := graph.ListGroupsArgs{ScopeDescriptor: projectDescriptor}
continuationToken := "continuation-token"
firstListGroupCallResponse := createPaginatedResponse(continuationToken, groupMeta{name: "name1", descriptor: "descriptor1"})
firstCall := graphClient.
EXPECT().
ListGroups(clients.Ctx, firstListGroupCallArgs).
Return(firstListGroupCallResponse, nil)

secondListGroupCallArgs := graph.ListGroupsArgs{ScopeDescriptor: projectDescriptor, ContinuationToken: &continuationToken}
secondListGroupCallResponse := createPaginatedResponse("", groupMeta{name: "name2", descriptor: "descriptor2"})
secondCall := graphClient.
EXPECT().
ListGroups(clients.Ctx, secondListGroupCallArgs).
Return(secondListGroupCallResponse, nil)

gomock.InOrder(firstCall, secondCall)

err := dataSourceGroupRead(resourceData, clients)
require.Nil(t, err)
require.Equal(t, "descriptor1", resourceData.Id())
}

func createPaginatedResponse(continuationToken string, groups ...groupMeta) *graph.PagedGraphGroups {
continuationTokenList := []string{continuationToken}
return &graph.PagedGraphGroups{
ContinuationToken: &continuationTokenList,
GraphGroups: createGroupsWithDescriptors(groups...),
}
}

func createGroupsWithDescriptors(groups ...groupMeta) *[]graph.GraphGroup {
var graphs []graph.GraphGroup
for _, group := range groups {
graphs = append(graphs, graph.GraphGroup{Descriptor: &group.descriptor, DisplayName: &group.name})
}

return &graphs
}

func createResourceData(t *testing.T, projectID string, groupName string) *schema.ResourceData {
resourceData := schema.TestResourceDataRaw(t, dataGroup().Schema, nil)
resourceData.Set("project_id", projectID)
resourceData.Set("name", groupName)
return resourceData
}

/**
* Begin acceptance tests
*/

// Validates that a configuration containing a project group lookup is able to read the resource correctly.
// Because this is a data source, there are no resources to inspect in AzDO
func TestAccGroupDataSource_Read_HappyPath(t *testing.T) {
projectName := testhelper.TestAccResourcePrefix + acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
group := "Build Administrators"
tfBuildDefNode := "data.azuredevops_group.group"

resource.Test(t, resource.TestCase{
PreCheck: func() { testhelper.TestAccPreCheck(t, nil) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testhelper.TestAccGroupDataSource(projectName, group),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet(tfBuildDefNode, "name"),
resource.TestCheckResourceAttrSet(tfBuildDefNode, "project_id"),
resource.TestCheckResourceAttrSet(tfBuildDefNode, "id"),
resource.TestCheckResourceAttrSet(tfBuildDefNode, "descriptor"),
),
},
},
})
}

func init() {
InitProvider()
}
13 changes: 13 additions & 0 deletions azuredevops/data_project.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package azuredevops

import (
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)

func dataProject() *schema.Resource {
baseSchema := resourceProject()
return &schema.Resource{
Read: baseSchema.Read,
Schema: baseSchema.Schema,
}
}
52 changes: 52 additions & 0 deletions azuredevops/data_project_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// +build all core resource_project

package azuredevops

// The tests in this file use the mock clients in mock_client.go to mock out
// the Azure DevOps client operations.

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/testhelper"
)

/**
* Begin acceptance tests
*/

// Verifies that the following sequence of events occurrs without error:
// (1) TF can create a project
// (2) A data source is added to the configuration, and that data source can find the created project
func TestAccAzureDevOpsProject_DataSource(t *testing.T) {
projectName := testhelper.TestAccResourcePrefix + acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
tfConfigStep1 := testhelper.TestAccProjectResource(projectName)
tfConfigStep2 := fmt.Sprintf("%s\n%s", tfConfigStep1, testhelper.TestAccProjectDataSource(projectName))

tfNode := "data.azuredevops_project.project"
resource.Test(t, resource.TestCase{
PreCheck: func() { testhelper.TestAccPreCheck(t, nil) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: tfConfigStep1,
}, {
Config: tfConfigStep2,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet(tfNode, "process_template_id"),
resource.TestCheckResourceAttr(tfNode, "project_name", projectName),
resource.TestCheckResourceAttr(tfNode, "version_control", "Git"),
resource.TestCheckResourceAttr(tfNode, "visibility", "private"),
resource.TestCheckResourceAttr(tfNode, "work_item_template", "Agile"),
),
},
},
})
}

func init() {
InitProvider()
}
199 changes: 199 additions & 0 deletions azuredevops/data_projects.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
package azuredevops

import (
"crypto/sha1"
"encoding/base64"
"fmt"
"log"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/microsoft/azure-devops-go-api/azuredevops/core"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/config"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/suppress"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/validate"
)

func dataProjects() *schema.Resource {
return &schema.Resource{
Read: dataSourceProjectsRead,

Schema: map[string]*schema.Schema{
"project_name": {
Type: schema.TypeString,
ForceNew: true,
Optional: true,
ValidateFunc: validate.NoEmptyStrings,
DiffSuppressFunc: suppress.CaseDifference,
},
"state": {
Type: schema.TypeString,
ForceNew: true,
Optional: true,
Default: core.ProjectStateValues.All,
ValidateFunc: validation.StringInSlice([]string{
string(core.ProjectStateValues.Deleting),
string(core.ProjectStateValues.New),
string(core.ProjectStateValues.WellFormed),
string(core.ProjectStateValues.CreatePending),
string(core.ProjectStateValues.All),
string(core.ProjectStateValues.Unchanged),
string(core.ProjectStateValues.Deleted),
}, true),
},

"projects": {
Type: schema.TypeSet,
Computed: true,
Set: getProjectHash,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Computed: true,
},
"project_id": {
Type: schema.TypeString,
Computed: true,
},
"project_url": {
Type: schema.TypeString,
Computed: true,
},
"state": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
},
}
}

func getProjectHash(v interface{}) int {
return hashcode.String(v.(map[string]interface{})["project_id"].(string))
}

func dataSourceProjectsRead(d *schema.ResourceData, m interface{}) error {
clients := m.(*config.AggregatedClient)
state := d.Get("state").(string)
name := d.Get("project_name").(string)

projects, err := getProjectsForStateAndName(clients, state, name)
if err != nil {
return fmt.Errorf("Error finding projects with state %s. Error: %v", state, err)
}
log.Printf("[TRACE] plugin.terraform-provider-azuredevops: Read [%d] projects from current organization", len(projects))

results, err := flattenProjectReferences(&projects)
if err != nil {
return fmt.Errorf("Error flattening projects. Error: %v", err)
}

h := sha1.New()
projectNames, err := getAttributeValues(results, "name")
if err != nil {
return fmt.Errorf("Failed to get list of project names: %v", err)
}
if len(projectNames) <= 0 && name != "" {
projectNames = append(projectNames, name)
}
if _, err := h.Write([]byte(state + strings.Join(projectNames, "-"))); err != nil {
return fmt.Errorf("Unable to compute hash for project names: %v", err)
}
d.SetId("projects#" + base64.URLEncoding.EncodeToString(h.Sum(nil)))
err = d.Set("projects", results)
if err != nil {
return err
}
return nil
}

func getAttributeValues(items []interface{}, attributeName string) ([]string, error) {
var result []string
for _, element := range items {
result = append(result, element.(map[string]interface{})[attributeName].(string))
}
return result, nil
}

func flattenProjectReferences(input *[]core.TeamProjectReference) ([]interface{}, error) {
if input == nil {
return []interface{}{}, nil
}

results := make([]interface{}, 0)

for _, element := range *input {
output := make(map[string]interface{})
if element.Name != nil {
output["name"] = *element.Name
}

if element.Id != nil {
output["project_id"] = element.Id.String()
}

if element.Url != nil {
output["project_url"] = *element.Url
}

if element.State != nil {
output["state"] = string(*element.State)
}

results = append(results, output)
}

return results, nil
}

func getProjectsForStateAndName(clients *config.AggregatedClient, projectState string, projectName string) ([]core.TeamProjectReference, error) {
var projects []core.TeamProjectReference
var currentToken string

for hasMore := true; hasMore; {
newProjects, latestToken, err := getProjectsWithContinuationToken(clients, projectState, currentToken)
currentToken = latestToken
if err != nil {
return nil, err
}
log.Printf("[TRACE] plugin.terraform-provider-azuredevops: Received [%d] projects; Continuation token [%s]", len(newProjects), currentToken)

if projectName != "" {
log.Printf("[TRACE] plugin.terraform-provider-azuredevops: Searching for project name [%s]", projectName)
for _, project := range newProjects {
if strings.EqualFold(*project.Name, projectName) {
log.Printf("[TRACE] plugin.terraform-provider-azuredevops: Found project [%s] in current project list", projectName)
return []core.TeamProjectReference{project}, nil
}
}
} else {
projects = append(projects, newProjects...)
log.Printf("[TRACE] plugin.terraform-provider-azuredevops: Appended new projects to current project list (Length: %d)", len(projects))
}
hasMore = currentToken != ""
}

return projects, nil
}

func getProjectsWithContinuationToken(clients *config.AggregatedClient, projectState string, continuationToken string) ([]core.TeamProjectReference, string, error) {
state := core.ProjectState(projectState)
args := core.GetProjectsArgs{
StateFilter: &state,
}
if continuationToken != "" {
args.ContinuationToken = &continuationToken
}

response, err := clients.CoreClient.GetProjects(clients.Ctx, args)
if err != nil {
return nil, "", err
}

return response.Value, response.ContinuationToken, nil
}
362 changes: 362 additions & 0 deletions azuredevops/data_projects_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,362 @@
// +build all core data_projects

package azuredevops

// The tests in this file use the mock clients in mock_client.go to mock out
// the Azure DevOps client operations.

import (
"context"
"errors"
"testing"

"github.com/golang/mock/gomock"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/microsoft/azure-devops-go-api/azuredevops/core"
"github.com/microsoft/terraform-provider-azuredevops/azdosdkmocks"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/config"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/converter"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/testhelper"
"github.com/stretchr/testify/require"
)

func init() {
/* add code for test setup here */
}

var prjListEmpty = []core.TeamProjectReference{}

var prjListStateMixed = []core.TeamProjectReference{
{
Name: converter.String("vsteam-0177"),
Id: testhelper.CreateUUID(),
State: &core.ProjectStateValues.WellFormed,
Url: nil,
},
{
Name: converter.String("vsteam-0178"),
Id: testhelper.CreateUUID(),
State: &core.ProjectStateValues.Deleted,
Url: nil,
},
{
Name: converter.String("vsteam-0179"),
Id: testhelper.CreateUUID(),
State: &core.ProjectStateValues.New,
Url: nil,
},
}

var prjListStateWellFormed = []core.TeamProjectReference{
{
Name: converter.String("vsteam-0177"),
Id: testhelper.CreateUUID(),
State: &core.ProjectStateValues.WellFormed,
Url: nil,
},
{
Name: converter.String("vsteam-0178"),
Id: testhelper.CreateUUID(),
State: &core.ProjectStateValues.WellFormed,
Url: nil,
},
{
Name: converter.String("vsteam-0179"),
Id: testhelper.CreateUUID(),
State: &core.ProjectStateValues.WellFormed,
Url: nil,
},
}

var prjListStateWellFormed2 = []core.TeamProjectReference{
{
Name: converter.String("vsteam-0277"),
Id: testhelper.CreateUUID(),
State: &core.ProjectStateValues.WellFormed,
Url: nil,
},
{
Name: converter.String("vsteam-0278"),
Id: testhelper.CreateUUID(),
State: &core.ProjectStateValues.WellFormed,
Url: nil,
},
{
Name: converter.String("vsteam-0279"),
Id: testhelper.CreateUUID(),
State: &core.ProjectStateValues.WellFormed,
Url: nil,
},
}

var duplicatePrjID *uuid.UUID = testhelper.CreateUUID()
var prjListDoubleID = []core.TeamProjectReference{
{
Name: converter.String("vsteam-0177"),
Id: duplicatePrjID,
State: &core.ProjectStateValues.WellFormed,
Url: nil,
},
{
Name: converter.String("vsteam-0178"),
Id: testhelper.CreateUUID(),
State: &core.ProjectStateValues.WellFormed,
Url: nil,
},
{
Name: converter.String("vsteam-0179"),
Id: duplicatePrjID,
State: &core.ProjectStateValues.WellFormed,
Url: nil,
},
}

/**
* Begin unit tests
*/

func TestDataSourceProjects_Read_TestFindProjectByName(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

coreClient := azdosdkmocks.NewMockCoreClient(ctrl)
clients := &config.AggregatedClient{
CoreClient: coreClient,
Ctx: context.Background(),
}

expectedGetProjectsArgs := core.GetProjectsArgs{
StateFilter: &core.ProjectStateValues.WellFormed,
}

coreClient.
EXPECT().
GetProjects(clients.Ctx, expectedGetProjectsArgs).
Return(&core.GetProjectsResponseValue{
Value: prjListStateWellFormed,
ContinuationToken: "",
}, nil).
Times(1)

resourceData := schema.TestResourceDataRaw(t, dataProjects().Schema, nil)
resourceData.Set("project_name", "vsteam-0178")
resourceData.Set("state", "wellFormed")
err := dataSourceProjectsRead(resourceData, clients)
require.Nil(t, err)
require.Equal(t, "wellFormed", resourceData.Get("state").(string))
require.Equal(t, "vsteam-0178", resourceData.Get("project_name").(string))
projectSet := resourceData.Get("projects").(*schema.Set)
require.NotNil(t, projectSet)
require.Equal(t, 1, projectSet.Len())
projectReference := projectSet.List()[0].(map[string]interface{})
require.NotNil(t, projectReference)
require.Equal(t, "vsteam-0178", projectReference["name"])
require.Equal(t, prjListStateWellFormed[1].Id.String(), projectReference["project_id"])
require.Equal(t, "wellFormed", projectReference["state"])
}

func TestDataSourceProjects_Read_TestEmptyProjectList(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

coreClient := azdosdkmocks.NewMockCoreClient(ctrl)
clients := &config.AggregatedClient{
CoreClient: coreClient,
Ctx: context.Background(),
}

expectedGetProjectsArgs := core.GetProjectsArgs{
StateFilter: &core.ProjectStateValues.All,
}

coreClient.
EXPECT().
GetProjects(clients.Ctx, expectedGetProjectsArgs).
Return(&core.GetProjectsResponseValue{
Value: prjListEmpty,
ContinuationToken: "",
}, nil).
Times(1)

resourceData := schema.TestResourceDataRaw(t, dataProjects().Schema, nil)
err := dataSourceProjectsRead(resourceData, clients)
require.Nil(t, err)
require.Equal(t, "all", resourceData.Get("state").(string))
require.Equal(t, "", resourceData.Get("project_name").(string))
projectSet := resourceData.Get("projects").(*schema.Set)
require.NotNil(t, projectSet)
require.Equal(t, 0, projectSet.Len())
}

func TestDataSourceProjects_Read_TestFindAllProjects(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

coreClient := azdosdkmocks.NewMockCoreClient(ctrl)
clients := &config.AggregatedClient{
CoreClient: coreClient,
Ctx: context.Background(),
}

expectedGetProjectsArgs := core.GetProjectsArgs{
StateFilter: &core.ProjectStateValues.All,
}

coreClient.
EXPECT().
GetProjects(clients.Ctx, expectedGetProjectsArgs).
Return(&core.GetProjectsResponseValue{
Value: prjListStateWellFormed,
ContinuationToken: "",
}, nil).
Times(1)

resourceData := schema.TestResourceDataRaw(t, dataProjects().Schema, nil)
err := dataSourceProjectsRead(resourceData, clients)
require.Nil(t, err)
require.Equal(t, "all", resourceData.Get("state").(string))
require.Equal(t, "", resourceData.Get("project_name").(string))
projectSet := resourceData.Get("projects").(*schema.Set)
require.NotNil(t, projectSet)
require.Equal(t, 3, projectSet.Len())
}

func TestDataSourceProjects_Read_TestDuplicateProjectId(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

coreClient := azdosdkmocks.NewMockCoreClient(ctrl)
clients := &config.AggregatedClient{
CoreClient: coreClient,
Ctx: context.Background(),
}

expectedGetProjectsArgs := core.GetProjectsArgs{
StateFilter: &core.ProjectStateValues.All,
}

coreClient.
EXPECT().
GetProjects(clients.Ctx, expectedGetProjectsArgs).
Return(&core.GetProjectsResponseValue{
Value: prjListDoubleID,
ContinuationToken: "",
}, nil).
Times(1)

resourceData := schema.TestResourceDataRaw(t, dataProjects().Schema, nil)
err := dataSourceProjectsRead(resourceData, clients)
require.Nil(t, err)
require.Equal(t, "all", resourceData.Get("state").(string))
require.Equal(t, "", resourceData.Get("project_name").(string))
projectSet := resourceData.Get("projects").(*schema.Set)
require.NotNil(t, projectSet)
require.Equal(t, 2, projectSet.Len())
}

func TestDataSourceProjects_Read_TestFindProjectsWithState(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

coreClient := azdosdkmocks.NewMockCoreClient(ctrl)
clients := &config.AggregatedClient{
CoreClient: coreClient,
Ctx: context.Background(),
}

expectedGetProjectsArgs := core.GetProjectsArgs{
StateFilter: &core.ProjectStateValues.WellFormed,
}

coreClient.
EXPECT().
GetProjects(clients.Ctx, expectedGetProjectsArgs).
Return(&core.GetProjectsResponseValue{
Value: prjListStateWellFormed,
ContinuationToken: "",
}, nil).
Times(1)

resourceData := schema.TestResourceDataRaw(t, dataProjects().Schema, nil)
resourceData.Set("state", "wellFormed")
err := dataSourceProjectsRead(resourceData, clients)
require.Nil(t, err)
require.Equal(t, "wellFormed", resourceData.Get("state").(string))
require.Equal(t, "", resourceData.Get("project_name").(string))
projectSet := resourceData.Get("projects").(*schema.Set)
require.NotNil(t, projectSet)
require.Equal(t, 3, projectSet.Len())
}

func TestDataSourceProjects_Read_TestHandleError(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

coreClient := azdosdkmocks.NewMockCoreClient(ctrl)
clients := &config.AggregatedClient{
CoreClient: coreClient,
Ctx: context.Background(),
}

expectedGetProjectsArgs := core.GetProjectsArgs{
StateFilter: &core.ProjectStateValues.All,
}

coreClient.
EXPECT().
GetProjects(clients.Ctx, expectedGetProjectsArgs).
Return(nil, errors.New("GetProjects() Failed")).
Times(1)

resourceData := schema.TestResourceDataRaw(t, dataProjects().Schema, nil)
err := dataSourceProjectsRead(resourceData, clients)
require.Error(t, err)
require.Contains(t, err.Error(), "GetProjects() Failed")
}

func TestDataSourceProjects_Read_TestContinuationToken(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

coreClient := azdosdkmocks.NewMockCoreClient(ctrl)
clients := &config.AggregatedClient{
CoreClient: coreClient,
Ctx: context.Background(),
}

var calls []*gomock.Call
calls = append(calls, coreClient.
EXPECT().
GetProjects(clients.Ctx, core.GetProjectsArgs{
StateFilter: &core.ProjectStateValues.All,
}).
Return(&core.GetProjectsResponseValue{
Value: prjListStateWellFormed,
ContinuationToken: "2",
}, nil).
Times(1))

calls = append(calls, coreClient.
EXPECT().
GetProjects(clients.Ctx, core.GetProjectsArgs{
StateFilter: &core.ProjectStateValues.All,
ContinuationToken: converter.String("2"),
}).
Return(&core.GetProjectsResponseValue{
Value: prjListStateWellFormed2,
ContinuationToken: "",
}, nil).
Times(1))

gomock.InOrder(calls...)

resourceData := schema.TestResourceDataRaw(t, dataProjects().Schema, nil)
err := dataSourceProjectsRead(resourceData, clients)
require.Nil(t, err)
require.Equal(t, "all", resourceData.Get("state").(string))
require.Equal(t, "", resourceData.Get("project_name").(string))
projectSet := resourceData.Get("projects").(*schema.Set)
require.NotNil(t, projectSet)
require.Equal(t, 6, projectSet.Len())
}
216 changes: 216 additions & 0 deletions azuredevops/data_users.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
package azuredevops

import (
"crypto/sha1"
"encoding/base64"
"fmt"
"strings"

"github.com/ahmetb/go-linq"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/microsoft/azure-devops-go-api/azuredevops/graph"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/config"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/validate"
)

func dataUsers() *schema.Resource {
return &schema.Resource{
Read: dataUsersRead,

//https://godoc.org/github.com/hashicorp/terraform/helper/schema#Schema
Schema: map[string]*schema.Schema{
"principal_name": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validate.NoEmptyStrings,
ConflictsWith: []string{"origin", "origin_id"},
},
"subject_types": {
Type: schema.TypeSet,
Optional: true,
Set: schema.HashString,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"origin": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validate.NoEmptyStrings,
ConflictsWith: []string{"principal_name"},
},
"origin_id": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validate.NoEmptyStrings,
ConflictsWith: []string{"principal_name"},
},
"users": {
Type: schema.TypeSet,
Computed: true,
Set: getUserHash,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"descriptor": {
Type: schema.TypeString,
Computed: true,
},
"principal_name": {
Type: schema.TypeString,
Computed: true,
},
"origin": {
Type: schema.TypeString,
Computed: true,
},
"origin_id": {
Type: schema.TypeString,
Optional: true,
},
"display_name": {
Type: schema.TypeString,
Computed: true,
},
"mail_address": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
},
}
}

func dataUsersRead(d *schema.ResourceData, m interface{}) error {
clients := m.(*config.AggregatedClient)
users := make([]interface{}, 0)
subjectTypes := []string{}

linq.From(d.Get("subject_types").(*schema.Set).List()).
SelectT(func(x interface{}) string {
return x.(string)
}).
ToSlice(&subjectTypes)
principalName := d.Get("principal_name").(string)
origin := d.Get("origin").(string)
originID := d.Get("origin_id").(string)

var currentToken string
for hasMore := true; hasMore; {
newUsers, latestToken, err := getUsersWithContinuationToken(clients, &subjectTypes, currentToken)
currentToken = latestToken
hasMore = currentToken != ""
if err != nil {
return err
}

linq.From(newUsers).
WhereT(func(x interface{}) bool {
usr := x.(graph.GraphUser)
b := true
if principalName != "" {
b = usr.PrincipalName != nil && strings.EqualFold(*usr.PrincipalName, principalName)
}
if b && origin != "" {
b = usr.Origin != nil && strings.EqualFold(*usr.Origin, origin)
}
if b && originID != "" {
b = usr.OriginId != nil && strings.EqualFold(*usr.OriginId, originID)
}
return b
}).
ToSlice(&newUsers)
fusers, err := flattenUsers(&newUsers)
if err != nil {
return err
}
users = append(users, fusers...)
}

var descriptors []string
linq.From(users).
SelectT(
func(x interface{}) string {
item := x.(map[string]interface{})
return item["descriptor"].(string)
},
).
ToSlice(&descriptors)

h := sha1.New()
if _, err := h.Write([]byte(strings.Join(descriptors, "-"))); err != nil {
return fmt.Errorf("Unable to compute hash for user descriptors: %v", err)
}
d.SetId("users#" + base64.URLEncoding.EncodeToString(h.Sum(nil)))
if err := d.Set("users", users); err != nil {
return fmt.Errorf("Error setting `users`: %+v", err)
}

return nil
}

func getUserHash(v interface{}) int {
return hashcode.String(v.(map[string]interface{})["descriptor"].(string))
}

func flattenUsers(input *[]graph.GraphUser) ([]interface{}, error) {
if input == nil {
return []interface{}{}, nil
}
results := make([]interface{}, len(*input))
for i, element := range *input {
output, err := flattenUser(&element)
if err != nil {
return nil, err
}
results[i] = output
}
return results, nil
}

func flattenUser(user *graph.GraphUser) (map[string]interface{}, error) {
s := make(map[string]interface{})

if v := user.Descriptor; v != nil {
s["descriptor"] = *v
}
if v := user.PrincipalName; v != nil {
s["principal_name"] = *v
}
if v := user.Origin; v != nil {
s["origin"] = *v
}
if v := user.OriginId; v != nil {
s["origin_id"] = *v
}
if v := user.DisplayName; v != nil {
s["display_name"] = *v
}
if v := user.MailAddress; v != nil {
s["mail_address"] = *v
}

return s, nil
}

func getUsersWithContinuationToken(clients *config.AggregatedClient, subjectTypes *[]string, continuationToken string) ([]graph.GraphUser, string, error) {
args := graph.ListUsersArgs{
SubjectTypes: subjectTypes,
}
if continuationToken != "" {
args.ContinuationToken = &continuationToken
}
response, err := clients.GraphClient.ListUsers(clients.Ctx, args)
if err != nil {
return nil, "", fmt.Errorf("Error listing users: %q", err)
}

continuationToken = ""
if response.ContinuationToken != nil && (*response.ContinuationToken)[0] != "" {
continuationToken = (*response.ContinuationToken)[0]
}

return *response.GraphUsers, continuationToken, nil
}
425 changes: 425 additions & 0 deletions azuredevops/data_users_test.go

Large diffs are not rendered by default.

1,823 changes: 0 additions & 1,823 deletions azuredevops/mock_config.go

This file was deleted.

42 changes: 35 additions & 7 deletions azuredevops/provider.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,47 @@
package azuredevops

import (
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/config"
)

// Provider - The top level Azure DevOps Provider definition.
func Provider() *schema.Provider {
p := &schema.Provider{
ResourcesMap: map[string]*schema.Resource{
"azuredevops_build_definition": resourceBuildDefinition(),
"azuredevops_project": resourceProject(),
"azuredevops_serviceendpoint": resourceServiceEndpoint(),
"azuredevops_resource_authorization": resourceResourceAuthorization(),
"azuredevops_build_definition": resourceBuildDefinition(),
"azuredevops_project": resourceProject(),
"azuredevops_variable_group": resourceVariableGroup(),
"azuredevops_serviceendpoint_azurerm": resourceServiceEndpointAzureRM(),
"azuredevops_serviceendpoint_bitbucket": resourceServiceEndpointBitBucket(),
"azuredevops_serviceendpoint_dockerhub": resourceServiceEndpointDockerHub(),
"azuredevops_serviceendpoint_github": resourceServiceEndpointGitHub(),
"azuredevops_serviceendpoint_kubernetes": resourceServiceEndpointKubernetes(),
"azuredevops_git_repository": resourceGitRepository(),
"azuredevops_user_entitlement": resourceUserEntitlement(),
"azuredevops_group_membership": resourceGroupMembership(),
"azuredevops_agent_pool": resourceAzureAgentPool(),
"azuredevops_group": resourceGroup(),
},
DataSourcesMap: map[string]*schema.Resource{
"azuredevops_client_config": dataClientConfig(),
"azuredevops_group": dataGroup(),
"azuredevops_project": dataProject(),
"azuredevops_projects": dataProjects(),
"azuredevops_git_repositories": dataGitRepositories(),
"azuredevops_users": dataUsers(),
},
Schema: map[string]*schema.Schema{
"org_service_url": {
Type: schema.TypeString,
Required: true,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("AZDO_ORG_SERVICE_URL", nil),
Description: "The url of the Azure DevOps instance which should be used.",
},
"personal_access_token": {
Type: schema.TypeString,
Required: true,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("AZDO_PERSONAL_ACCESS_TOKEN", nil),
Description: "The personal access token which should be used.",
Sensitive: true,
@@ -36,7 +56,15 @@ func Provider() *schema.Provider {

func providerConfigure(p *schema.Provider) schema.ConfigureFunc {
return func(d *schema.ResourceData) (interface{}, error) {
client, err := getAzdoClient(d.Get("personal_access_token").(string), d.Get("org_service_url").(string))
terraformVersion := p.TerraformVersion
if terraformVersion == "" {
// Terraform 0.12 introduced this field to the protocol
// We can therefore assume that if it's missing it's 0.10 or 0.11
terraformVersion = "0.11+compatible"
}

client, err := config.GetAzdoClient(d.Get("personal_access_token").(string), d.Get("org_service_url").(string), terraformVersion)

return client, err
}
}
67 changes: 44 additions & 23 deletions azuredevops/provider_test.go
Original file line number Diff line number Diff line change
@@ -4,8 +4,8 @@ import (
"os"
"testing"

"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
"github.com/stretchr/testify/require"
)

@@ -15,9 +15,20 @@ var provider = Provider()

func TestAzureDevOpsProvider_HasChildResources(t *testing.T) {
expectedResources := []string{
"azuredevops_resource_authorization",
"azuredevops_build_definition",
"azuredevops_project",
"azuredevops_serviceendpoint",
"azuredevops_serviceendpoint_github",
"azuredevops_serviceendpoint_dockerhub",
"azuredevops_serviceendpoint_azurerm",
"azuredevops_serviceendpoint_bitbucket",
"azuredevops_serviceendpoint_kubernetes",
"azuredevops_variable_group",
"azuredevops_git_repository",
"azuredevops_user_entitlement",
"azuredevops_group_membership",
"azuredevops_group",
"azuredevops_agent_pool",
}

resources := provider.ResourcesMap
@@ -29,6 +40,25 @@ func TestAzureDevOpsProvider_HasChildResources(t *testing.T) {
}
}

func TestAzureDevOpsProvider_HasChildDataSources(t *testing.T) {
expectedDataSources := []string{
"azuredevops_client_config",
"azuredevops_group",
"azuredevops_project",
"azuredevops_projects",
"azuredevops_git_repositories",
"azuredevops_users",
}

dataSources := provider.DataSourcesMap
require.Equal(t, len(expectedDataSources), len(dataSources), "There are an unexpected number of registered data sources")

for _, resource := range expectedDataSources {
require.Contains(t, dataSources, resource, "An expected data source was not registered")
require.NotNil(t, dataSources[resource], "A data source cannot have a nil schema")
}
}

func TestAzureDevOpsProvider_SchemaIsValid(t *testing.T) {
type testParams struct {
name string
@@ -38,8 +68,8 @@ func TestAzureDevOpsProvider_SchemaIsValid(t *testing.T) {
}

tests := []testParams{
{"org_service_url", true, "AZDO_ORG_SERVICE_URL", false},
{"personal_access_token", true, "AZDO_PERSONAL_ACCESS_TOKEN", true},
{"org_service_url", false, "AZDO_ORG_SERVICE_URL", false},
{"personal_access_token", false, "AZDO_PERSONAL_ACCESS_TOKEN", true},
}

schema := provider.Schema
@@ -49,39 +79,30 @@ func TestAzureDevOpsProvider_SchemaIsValid(t *testing.T) {
require.Contains(t, schema, test.name, "An expected property was not found in the schema")
require.NotNil(t, schema[test.name], "A property in the schema cannot have a nil value")
require.Equal(t, test.sensitive, schema[test.name].Sensitive, "A property in the schema has an incorrect sensitivity value")
require.Equal(t, test.required, schema[test.name].Required, "A property in the schema has an incorrect required value")

if test.defaultEnvVar != "" {
expectedValue := "foo-env-var"
os.Setenv(test.defaultEnvVar, expectedValue)
expectedValue := os.Getenv(test.defaultEnvVar)

actualValue, err := schema[test.name].DefaultFunc()
if actualValue == nil {
actualValue = ""
}

require.Nil(t, err, "An error occurred when getting the default value from the environment")
require.Equal(t, expectedValue, actualValue, "The default value pulled from the environment has the wrong value")
}
}
}

// The configuration below can be used for every acceptance test in the project. For that reason,
// it will be defined once and will live in this file.

// pre-check to validate that the correct environment variables are set prior to running any acceptance test
func testAccPreCheck(t *testing.T) {
requiredEnvVars := []string{
"AZDO_ORG_SERVICE_URL",
"AZDO_PERSONAL_ACCESS_TOKEN",
}

for _, variable := range requiredEnvVars {
if os.Getenv(variable) == "" {
t.Fatalf("`%s` must be set for acceptance tests!", variable)
}
}
func init() {
InitProvider()
}

var testAccProviders map[string]terraform.ResourceProvider
var testAccProvider *schema.Provider

func init() {
func InitProvider() {
testAccProvider = provider
testAccProviders = map[string]terraform.ResourceProvider{
"azuredevops": testAccProvider,
168 changes: 168 additions & 0 deletions azuredevops/resource_agentpool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package azuredevops

import (
"fmt"
"strconv"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"github.com/microsoft/azure-devops-go-api/azuredevops/taskagent"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/config"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/converter"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/suppress"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/validate"
)

func resourceAzureAgentPool() *schema.Resource {
return &schema.Resource{
Create: resourceAzureAgentPoolCreate,
Read: resourceAzureAgentPoolRead,
Update: resourceAzureAgentPoolUpdate,
Delete: resourceAzureAgentPoolDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
ForceNew: false,
Required: true,
ValidateFunc: validate.NoEmptyStrings,
},
"pool_type": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Default: taskagent.TaskAgentPoolTypeValues.Automation,
DiffSuppressFunc: suppress.CaseDifference,
ValidateFunc: validation.StringInSlice([]string{
string(taskagent.TaskAgentPoolTypeValues.Automation),
string(taskagent.TaskAgentPoolTypeValues.Deployment),
}, false),
},
"auto_provision": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
},
}
}

func resourceAzureAgentPoolCreate(d *schema.ResourceData, m interface{}) error {
clients := m.(*config.AggregatedClient)
agentPool, err := expandAgentPool(d, true)
if err != nil {
return fmt.Errorf("Error converting terraform data model to AzDO agentPool reference: %+v", err)
}

createdAgentPool, err := createAzureAgentPool(clients, agentPool)
if err != nil {
return fmt.Errorf("Error creating agent pool in Azure DevOps: %+v", err)
}

flattenAzureAgentPool(d, createdAgentPool)

return resourceAzureAgentPoolRead(d, m)
}

func resourceAzureAgentPoolRead(d *schema.ResourceData, m interface{}) error {
poolID, err := strconv.Atoi(d.Id())
if err != nil {
return fmt.Errorf("Error getting agent pool Id: %+v", err)
}

clients := m.(*config.AggregatedClient)
agentPool, err := azureAgentPoolRead(clients, poolID)
if err != nil {
if utils.ResponseWasNotFound(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error looking up agent pool with ID %d. Error: %v", poolID, err)
}

flattenAzureAgentPool(d, agentPool)
return nil
}

func resourceAzureAgentPoolUpdate(d *schema.ResourceData, m interface{}) error {
clients := m.(*config.AggregatedClient)
agentPool, err := expandAgentPool(d, false)
if err != nil {
return fmt.Errorf("Error converting terraform data model to AzDO agent pool reference: %+v", err)
}

_, err = azureAgentPoolUpdate(clients, agentPool)
if err != nil {
return fmt.Errorf("Error updating agent pool in Azure DevOps: %+v", err)
}

return resourceAzureAgentPoolRead(d, m)
}

func resourceAzureAgentPoolDelete(d *schema.ResourceData, m interface{}) error {
poolID, err := strconv.Atoi(d.Id())
if err != nil {
return fmt.Errorf("Error getting agent pool Id: %+v", err)
}

clients := m.(*config.AggregatedClient)
return clients.TaskAgentClient.DeleteAgentPool(clients.Ctx, taskagent.DeleteAgentPoolArgs{
PoolId: &poolID,
})
}

func createAzureAgentPool(clients *config.AggregatedClient, agentPool *taskagent.TaskAgentPool) (*taskagent.TaskAgentPool, error) {
args := taskagent.AddAgentPoolArgs{
Pool: agentPool,
}

newTaskAgent, err := clients.TaskAgentClient.AddAgentPool(clients.Ctx, args)
return newTaskAgent, err
}

func azureAgentPoolRead(clients *config.AggregatedClient, poolID int) (*taskagent.TaskAgentPool, error) {
return clients.TaskAgentClient.GetAgentPool(clients.Ctx, taskagent.GetAgentPoolArgs{
PoolId: &poolID,
})
}

func azureAgentPoolUpdate(clients *config.AggregatedClient, agentPool *taskagent.TaskAgentPool) (*taskagent.TaskAgentPool, error) {
return clients.TaskAgentClient.UpdateAgentPool(
clients.Ctx,
taskagent.UpdateAgentPoolArgs{
PoolId: agentPool.Id,
Pool: &taskagent.TaskAgentPool{
Name: agentPool.Name,
PoolType: agentPool.PoolType,
AutoProvision: agentPool.AutoProvision,
},
})
}

func flattenAzureAgentPool(d *schema.ResourceData, agentPool *taskagent.TaskAgentPool) {
d.SetId(strconv.Itoa(*agentPool.Id))
d.Set("name", converter.ToString(agentPool.Name, ""))
d.Set("pool_type", *agentPool.PoolType)
d.Set("auto_provision", *agentPool.AutoProvision)
}

func expandAgentPool(d *schema.ResourceData, forCreate bool) (*taskagent.TaskAgentPool, error) {
poolID, err := strconv.Atoi(d.Id())
if !forCreate && err != nil {
return nil, fmt.Errorf("Error getting agent pool Id: %+v", err)
}

poolType := taskagent.TaskAgentPoolType(d.Get("pool_type").(string))

pool := &taskagent.TaskAgentPool{
Id: &poolID,
Name: converter.String(d.Get("name").(string)),
PoolType: &poolType,
AutoProvision: converter.Bool(d.Get("auto_provision").(bool)),
}

return pool, nil
}
284 changes: 284 additions & 0 deletions azuredevops/resource_agentpool_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
// +build all resource_agentpool

package azuredevops

// The tests in this file use the mock clients in mock_client.go to mock out
// the Azure DevOps client operations.

import (
"context"
"errors"
"fmt"
"math/rand"
"strconv"
"testing"

"github.com/golang/mock/gomock"
"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
"github.com/microsoft/azure-devops-go-api/azuredevops/taskagent"
"github.com/microsoft/terraform-provider-azuredevops/azdosdkmocks"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/config"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/converter"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/testhelper"
"github.com/stretchr/testify/require"
)

var testAgentPoolID = rand.Intn(100)

var testAgentPool = taskagent.TaskAgentPool{
Id: &testAgentPoolID,
Name: converter.String("Name"),
PoolType: &taskagent.TaskAgentPoolTypeValues.Automation,
AutoProvision: converter.Bool(false),
}

/**
* Begin unit tests
*/

// verifies that the flatten/expand round trip yields the same agent pool definition
func TestAzureDevOpsAgentPool_ExpandFlatten_Roundtrip(t *testing.T) {
resourceData := schema.TestResourceDataRaw(t, resourceAzureAgentPool().Schema, nil)
flattenAzureAgentPool(resourceData, &testAgentPool)

agentPoolAfterRoundTrip, err := expandAgentPool(resourceData, true)
require.Nil(t, err)
require.Equal(t, testAgentPool, *agentPoolAfterRoundTrip)
}

// verifies that the create operation is considered failed if the API call fails.
func TestAzureDevOpsAgentPool_CreateAgentPool_DoesNotSwallowErrorFromFailedAddAgentCall(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

taskAgentClient := azdosdkmocks.NewMockTaskagentClient(ctrl)
clients := &config.AggregatedClient{
TaskAgentClient: taskAgentClient,
Ctx: context.Background(),
}

expectedProjectCreateArgs := taskagent.AddAgentPoolArgs{
Pool: &testAgentPool,
}

taskAgentClient.
EXPECT().
AddAgentPool(clients.Ctx, expectedProjectCreateArgs).
Return(nil, errors.New("AddAgentPool() Failed")).
Times(1)

newTaskAgentPool, err := createAzureAgentPool(clients, &testAgentPool)
require.Nil(t, newTaskAgentPool)
require.Equal(t, "AddAgentPool() Failed", err.Error())
}

func TestAzureDevOpsAgentPool_DeleteAgentPool_ReturnsErrorIfIdReadFails(t *testing.T) {
client := &config.AggregatedClient{}

resourceData := schema.TestResourceDataRaw(t, resourceAzureAgentPool().Schema, nil)
flattenAzureAgentPool(resourceData, &testAgentPool)
resourceData.SetId("")

err := resourceAzureAgentPoolDelete(resourceData, client)
require.Equal(t, "Error getting agent pool Id: strconv.Atoi: parsing \"\": invalid syntax", err.Error())
}

func TestAzureDevOpsAgentPool_UpdateAgentPool_ReturnsErrorIfIdReadFails(t *testing.T) {
client := &config.AggregatedClient{}

resourceData := schema.TestResourceDataRaw(t, resourceAzureAgentPool().Schema, nil)
flattenAzureAgentPool(resourceData, &testAgentPool)
resourceData.SetId("")

err := resourceAzureAgentPoolUpdate(resourceData, client)
require.Equal(t, "Error converting terraform data model to AzDO agent pool reference: Error getting agent pool Id: strconv.Atoi: parsing \"\": invalid syntax", err.Error())
}

func TestAzureDevOpsAgentPool_UpdateAgentPool_UpdateAndRead(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

taskAgentClient := azdosdkmocks.NewMockTaskagentClient(ctrl)
clients := &config.AggregatedClient{
TaskAgentClient: taskAgentClient,
Ctx: context.Background(),
}

agentToUpdate := taskagent.TaskAgentPool{
Id: &testAgentPoolID,
Name: converter.String("Foo"),
PoolType: &taskagent.TaskAgentPoolTypeValues.Deployment,
AutoProvision: converter.Bool(true),
}

resourceData := schema.TestResourceDataRaw(t, resourceAzureAgentPool().Schema, nil)
flattenAzureAgentPool(resourceData, &agentToUpdate)

taskAgentClient.
EXPECT().
UpdateAgentPool(clients.Ctx, taskagent.UpdateAgentPoolArgs{
PoolId: &testAgentPoolID,
Pool: &taskagent.TaskAgentPool{
Name: agentToUpdate.Name,
PoolType: agentToUpdate.PoolType,
AutoProvision: agentToUpdate.AutoProvision,
},
}).
Return(&agentToUpdate, nil).
Times(1)

taskAgentClient.
EXPECT().
GetAgentPool(clients.Ctx, taskagent.GetAgentPoolArgs{
PoolId: &testAgentPoolID,
}).
Return(&agentToUpdate, nil).
Times(1)

err := resourceAzureAgentPoolUpdate(resourceData, clients)
require.Nil(t, err)

updatedTaskAgent, _ := expandAgentPool(resourceData, false)
require.Equal(t, agentToUpdate.Id, updatedTaskAgent.Id)
require.Equal(t, agentToUpdate.Name, updatedTaskAgent.Name)
require.Equal(t, agentToUpdate.PoolType, updatedTaskAgent.PoolType)
require.Equal(t, agentToUpdate.AutoProvision, updatedTaskAgent.AutoProvision)
}

// validates supported pool types are allowed by the schema
func TestAzureDevOpsAgentPoolDefinition_PoolTypeIsCorrect(t *testing.T) {
validPoolTypes := []string{
string(taskagent.TaskAgentPoolTypeValues.Automation),
string(taskagent.TaskAgentPoolTypeValues.Deployment),
}
poolTypeSchema := resourceAzureAgentPool().Schema["pool_type"]

for _, repoType := range validPoolTypes {
_, errors := poolTypeSchema.ValidateFunc(repoType, "")
require.Equal(t, 0, len(errors), "Agent pool type unexpectedly did not pass validation")
}
}

// validates invalid pool types are rejected by the schema
func TestAzureDevOpsAgentPoolDefinition_WhenPoolTypeIsNotCorrect_ReturnsError(t *testing.T) {
invalidPoolTypes := []string{"", "unknown"}
poolTypeSchema := resourceAzureAgentPool().Schema["pool_type"]

for _, poolType := range invalidPoolTypes {
_, errors := poolTypeSchema.ValidateFunc(poolType, "pool_type")
expectedError := fmt.Sprintf("expected pool_type to be one of [automation deployment], got %s", poolType)
require.Equal(t, 1, len(errors), "Agent pool type %v unexpectedly passed validation", poolType)
require.Equal(t, expectedError, errors[0].Error())
}
}

/**
* Begin acceptance tests
*/

// Verifies that the following sequence of events occurrs without error:
// (1) TF apply creates agent pool
// (2) TF state values are set
// (3) Agent pool can be queried by ID and has expected name
// (4) TF apply updates agent pool with new name
// (5) Agent pool can be queried by ID and has expected name
// (6) TF destroy deletes agent pool
// (7) Agent pool can no longer be queried by ID
func TestAccAzureDevOpsAgentPool_CreateAndUpdate(t *testing.T) {
poolNameFirst := testhelper.TestAccResourcePrefix + acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
poolNameSecond := testhelper.TestAccResourcePrefix + acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
tfNode := "azuredevops_agent_pool.pool"

resource.Test(t, resource.TestCase{
PreCheck: func() { testhelper.TestAccPreCheck(t, nil) },
Providers: testAccProviders,
CheckDestroy: testAccAgentPoolCheckDestroy,
Steps: []resource.TestStep{
{
Config: testhelper.TestAccAgentPoolResource(poolNameFirst),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(tfNode, "name", poolNameFirst),
resource.TestCheckResourceAttr(tfNode, "auto_provision", "false"),
resource.TestCheckResourceAttr(tfNode, "pool_type", "automation"),
testAccCheckAgentPoolResourceExists(poolNameFirst),
),
},
{
Config: testhelper.TestAccAgentPoolResource(poolNameSecond),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(tfNode, "name", poolNameSecond),
resource.TestCheckResourceAttr(tfNode, "auto_provision", "false"),
resource.TestCheckResourceAttr(tfNode, "pool_type", "automation"),
testAccCheckAgentPoolResourceExists(poolNameSecond),
),
},
{
// Resource Acceptance Testing https://www.terraform.io/docs/extend/resources/import.html#resource-acceptance-testing-implementation
ResourceName: tfNode,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

// Given the name of an AzDO project, this will return a function that will check whether
// or not the project (1) exists in the state and (2) exist in AzDO and (3) has the correct name
func testAccCheckAgentPoolResourceExists(expectedName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
resource, ok := s.RootModule().Resources["azuredevops_agent_pool.pool"]
if !ok {
return fmt.Errorf("Did not find a agent pool in the TF state")
}

clients := testAccProvider.Meta().(*config.AggregatedClient)
id, err := strconv.Atoi(resource.Primary.ID)
if err != nil {
return fmt.Errorf("Parse ID error, ID: %v !. Error= %v", resource.Primary.ID, err)
}

project, agentPoolErr := azureAgentPoolRead(clients, id)

if agentPoolErr != nil {
return fmt.Errorf("Agent Pool with ID=%d cannot be found!. Error=%v", id, err)
}

if *project.Name != expectedName {
return fmt.Errorf("Agent Pool with ID=%d has Name=%s, but expected Name=%s", id, *project.Name, expectedName)
}

return nil
}
}

// verifies that agent pool referenced in the state is destroyed. This will be invoked
// *after* terrafform destroys the resource but *before* the state is wiped clean.
func testAccAgentPoolCheckDestroy(s *terraform.State) error {
clients := testAccProvider.Meta().(*config.AggregatedClient)

// verify that every agent pool referenced in the state does not exist in AzDO
for _, resource := range s.RootModule().Resources {
if resource.Type != "azuredevops_agent_pool" {
continue
}

id, err := strconv.Atoi(resource.Primary.ID)
if err != nil {
return fmt.Errorf("Agent Pool ID=%d cannot be parsed!. Error=%v", id, err)
}

// indicates the agent pool still exists - this should fail the test
if _, err := azureAgentPoolRead(clients, id); err == nil {
return fmt.Errorf("Agent Pool ID %d should not exist", id)
}
}

return nil
}

func init() {
InitProvider()
}
664 changes: 618 additions & 46 deletions azuredevops/resource_build_definition.go

Large diffs are not rendered by default.

555 changes: 555 additions & 0 deletions azuredevops/resource_build_definition_test.go

Large diffs are not rendered by default.

412 changes: 412 additions & 0 deletions azuredevops/resource_git_repository.go

Large diffs are not rendered by default.

453 changes: 453 additions & 0 deletions azuredevops/resource_git_repository_test.go

Large diffs are not rendered by default.

389 changes: 389 additions & 0 deletions azuredevops/resource_group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,389 @@
package azuredevops

import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
"net/url"
"strings"

"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"github.com/microsoft/azure-devops-go-api/azuredevops"
"github.com/microsoft/azure-devops-go-api/azuredevops/graph"
"github.com/microsoft/azure-devops-go-api/azuredevops/webapi"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/config"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/converter"
)

func resourceGroup() *schema.Resource {
return &schema.Resource{
Create: resourceGroupCreate,
Read: resourceGroupRead,
Update: resourceGroupUpdate,
Delete: resourceGroupDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"scope": {
Type: schema.TypeString,
ValidateFunc: validation.NoZeroValues,
Optional: true,
ForceNew: true,
},

// ***
// One of
// origin_id => GraphGroupOriginIdCreationContext
// mail => GraphGroupMailAddressCreationContext
// display_name => GraphGroupVstsCreationContext
// must be specified
// ***

"origin_id": {
Type: schema.TypeString,
ValidateFunc: validation.NoZeroValues,
Optional: true,
Computed: true,
ForceNew: true,
ConflictsWith: []string{"mail", "display_name", "scope"},
},

"mail": {
Type: schema.TypeString,
ValidateFunc: validation.NoZeroValues,
Optional: true,
ForceNew: true,
Computed: true,
ConflictsWith: []string{"origin_id", "display_name", "scope"},
},

"display_name": {
Type: schema.TypeString,
ValidateFunc: validation.NoZeroValues,
Optional: true,
ForceNew: true,
Computed: true,
ConflictsWith: []string{"origin_id", "mail"},
},

"description": {
Type: schema.TypeString,
Optional: true,
},

"url": {
Type: schema.TypeString,
Computed: true,
},

"origin": {
Type: schema.TypeString,
Computed: true,
},

"subject_kind": {
Type: schema.TypeString,
Computed: true,
},

"domain": {
Type: schema.TypeString,
Computed: true,
},

"principal_name": {
Type: schema.TypeString,
Computed: true,
},

"descriptor": {
Type: schema.TypeString,
Computed: true,
},

"members": {
Type: schema.TypeSet,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validation.NoZeroValues,
},
Computed: true,
Optional: true,
ConfigMode: schema.SchemaConfigModeAttr,
Set: schema.HashString,
},
},
}
}

type azDOGraphCreateGroupArgs struct {
// (required) The subset of the full graph group used to uniquely find the graph subject in an external provider.
CreationContext interface{}
// (optional) A descriptor referencing the scope (collection, project) in which the group should be created.
// If omitted, will be created in the scope of the enclosing account or organization. Valid only for VSTS groups.
ScopeDescriptor *string
// (optional) A comma separated list of descriptors referencing groups you want the graph group to join
GroupDescriptors *[]string
}

func azDOGraphCreateGroup(ctx context.Context, client graph.Client, args azDOGraphCreateGroupArgs) (*graph.GraphGroup, error) {
if args.CreationContext == nil {
return nil, &azuredevops.ArgumentNilError{ArgumentName: "args.CreationContext"}
}
queryParams := url.Values{}
if args.ScopeDescriptor != nil {
queryParams.Add("scopeDescriptor", *args.ScopeDescriptor)
}
if args.GroupDescriptors != nil {
listAsString := strings.Join((*args.GroupDescriptors)[:], ",")
queryParams.Add("groupDescriptors", listAsString)
}

if _, ok := args.CreationContext.(*graph.GraphGroupMailAddressCreationContext); !ok {
if _, ok := args.CreationContext.(*graph.GraphGroupOriginIdCreationContext); !ok {
if _, ok := args.CreationContext.(*graph.GraphGroupVstsCreationContext); !ok {
return nil, fmt.Errorf("Unsupported group creation context")
}
}
}

body, marshalErr := json.Marshal(args.CreationContext)
if marshalErr != nil {
return nil, marshalErr
}
locationID, _ := uuid.Parse("ebbe6af8-0b91-4c13-8cf1-777c14858188")
if clientImpl, ok := client.(*graph.ClientImpl); ok {
resp, err := clientImpl.Client.Send(ctx, http.MethodPost, locationID, "5.1-preview.1", nil, queryParams, bytes.NewReader(body), "application/json", "application/json", nil)
if err != nil {
return nil, err
}
var responseValue graph.GraphGroup
err = clientImpl.Client.UnmarshalBody(resp, &responseValue)
return &responseValue, err
}

panic("Invalid Azure DevOps Graph client implementation")
}

func resourceGroupCreate(d *schema.ResourceData, m interface{}) error {
clients := m.(*config.AggregatedClient)

// using: POST https://vssps.dev.azure.com/{organization}/_apis/graph/groups?api-version=5.1-preview.1
cga := azDOGraphCreateGroupArgs{}
val, b := d.GetOk("scope")
if b {
uuid, _ := uuid.Parse(val.(string))
desc, err := clients.GraphClient.GetDescriptor(clients.Ctx, graph.GetDescriptorArgs{
StorageKey: &uuid,
})
if err != nil {
return err
}
cga.ScopeDescriptor = desc.Value
}
val, b = d.GetOk("origin_id")
if b {
if _, b = d.GetOk("mail"); b {
return fmt.Errorf("Unable to create group with invalid parameters: mail")
}
if _, b = d.GetOk("display_name"); b {
return fmt.Errorf("Unable to create group with invalid parameters: display_name")
}
cga.CreationContext = &graph.GraphGroupOriginIdCreationContext{
OriginId: converter.String(val.(string)),
}
} else {
val, b = d.GetOk("mail")
if b {
if _, b = d.GetOk("display_name"); b {
return fmt.Errorf("Unable to create group with invalid parameters: display_name")
}
cga.CreationContext = &graph.GraphGroupMailAddressCreationContext{
MailAddress: converter.String(val.(string)),
}
} else {
val, b = d.GetOk("display_name")
if b {
cga.CreationContext = &graph.GraphGroupVstsCreationContext{
DisplayName: converter.String(val.(string)),
Description: converter.String(d.Get("description").(string)),
}
} else {
return fmt.Errorf("INTERNAL ERROR: Unable to determine strategy to create group")
}
}
}
group, err := azDOGraphCreateGroup(clients.Ctx, clients.GraphClient, cga)
if err != nil {
return err
}
if group.Descriptor == nil {
return fmt.Errorf("DevOps REST API returned group object without descriptor")
}

stateMembers, exists := d.GetOk("members")
if exists {
members := expandGroupMembers(*group.Descriptor, stateMembers.(*schema.Set))
if err := addMembers(clients, members); err != nil {
return fmt.Errorf("Error adding group memberships during create: %+v", err)
}
}

d.SetId(*group.Descriptor)

return resourceGroupRead(d, m)
}

func resourceGroupRead(d *schema.ResourceData, m interface{}) error {
clients := m.(*config.AggregatedClient)

// using: GET https://vssps.dev.azure.com/{organization}/_apis/graph/groups/{groupDescriptor}?api-version=5.1-preview.1
// d.Get("descriptor").(string) => {groupDescriptor}
getGroupArgs := graph.GetGroupArgs{
GroupDescriptor: converter.String(d.Id()),
}
group, err := clients.GraphClient.GetGroup(clients.Ctx, getGroupArgs)
if err != nil {
if utils.ResponseWasNotFound(err) {
d.SetId("")
return nil
}
return err
}
if group.Descriptor == nil {
return fmt.Errorf("DevOps REST API returned group object without descriptor; group %s", d.Id())
}

members, err := groupReadMembers(*group.Descriptor, clients)
if err != nil {
return err
}
return flattenGroup(d, group, members)
}

func resourceGroupUpdate(d *schema.ResourceData, m interface{}) error {
clients := m.(*config.AggregatedClient)

// using: PATCH https://vssps.dev.azure.com/{organization}/_apis/graph/groups/{groupDescriptor}?api-version=5.1-preview.1
// d.Get("descriptor").(string) => {groupDescriptor}

if d.HasChange("description") {
description := d.Get("description")
uptGroupArgs := graph.UpdateGroupArgs{
GroupDescriptor: converter.String(d.Id()),
PatchDocument: &[]webapi.JsonPatchOperation{
{
Op: &webapi.OperationValues.Replace,
From: nil,
Path: converter.String("/description"),
Value: description.(string),
},
},
}

_, err := clients.GraphClient.UpdateGroup(clients.Ctx, uptGroupArgs)
if err != nil {
return err
}
}

if d.HasChange("members") {
group := d.Id()
oldData, newData := d.GetChange("members")
// members that need to be added will be missing from the old data, but present in the new data
membersToAdd := newData.(*schema.Set).Difference(oldData.(*schema.Set))
// members that need to be removed will be missing from the new data, but present in the old data
membersToRemove := oldData.(*schema.Set).Difference(newData.(*schema.Set))
if err := applyMembershipUpdate(m.(*config.AggregatedClient),
expandGroupMembers(group, membersToAdd),
expandGroupMembers(group, membersToRemove)); err != nil {
return err
}
}

return resourceGroupRead(d, m)
}

func resourceGroupDelete(d *schema.ResourceData, m interface{}) error {
clients := m.(*config.AggregatedClient)

// using: DELETE https://vssps.dev.azure.com/{organization}/_apis/graph/groups/{groupDescriptor}?api-version=5.1-preview.1
// d.Get("descriptor").(string) => {groupDescriptor}
delGroupArgs := graph.DeleteGroupArgs{
GroupDescriptor: converter.String(d.Id()),
}
err := clients.GraphClient.DeleteGroup(clients.Ctx, delGroupArgs)
if err != nil {
return err
}
d.SetId("")
return nil
}

func flattenGroup(d *schema.ResourceData, group *graph.GraphGroup, members *[]graph.GraphMembership) error {
if group.Descriptor != nil {
d.Set("descriptor", *group.Descriptor)
d.SetId(*group.Descriptor)
} else {
return fmt.Errorf("Group Object does not contain a descriptor")
}
if group.DisplayName != nil {
d.Set("display_name", *group.DisplayName)
}
if group.Url != nil {
d.Set("url", *group.Url)
}
if group.Origin != nil {
d.Set("origin", *group.Origin)
}
if group.OriginId != nil {
d.Set("origin_id", *group.OriginId)
}
if group.SubjectKind != nil {
d.Set("subject_kind", *group.SubjectKind)
}
if group.Domain != nil {
d.Set("domain", *group.Domain)
}
if group.MailAddress != nil {
d.Set("mail", *group.MailAddress)
}
if group.PrincipalName != nil {
d.Set("principal_name", *group.PrincipalName)
}
if group.Description != nil {
d.Set("description", *group.Description)
}
if members != nil {
dMembers := make([]string, len(*members))
for i, e := range *members {
dMembers[i] = *e.MemberDescriptor
}
d.Set("members", dMembers)
}
return nil
}

func groupReadMembers(groupDescriptor string, clients *config.AggregatedClient) (*[]graph.GraphMembership, error) {
actualMembers, err := clients.GraphClient.ListMemberships(clients.Ctx, graph.ListMembershipsArgs{
SubjectDescriptor: &groupDescriptor,
Direction: &graph.GraphTraversalDirectionValues.Down,
Depth: converter.Int(1),
})
if err != nil {
return nil, fmt.Errorf("Error reading group memberships during read: %+v", err)
}

members := make([]graph.GraphMembership, len(*actualMembers))
for i, membership := range *actualMembers {
members[i] = *buildMembership(groupDescriptor, *membership.MemberDescriptor)
}

return &members, nil
}
301 changes: 301 additions & 0 deletions azuredevops/resource_group_membership.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,301 @@
package azuredevops

import (
"fmt"
"math/rand"
"strings"
"time"

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"github.com/microsoft/azure-devops-go-api/azuredevops/graph"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/config"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/converter"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/suppress"
)

func resourceGroupMembership() *schema.Resource {
return &schema.Resource{
Create: resourceGroupMembershipCreate,
Read: resourceGroupMembershipRead,
Update: resourceGroupMembershipUpdate,
Delete: resourceGroupMembershipDelete,

Schema: map[string]*schema.Schema{
"group": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.NoZeroValues,
},
"mode": {
Type: schema.TypeString,
Optional: true,
Default: "add",
DiffSuppressFunc: suppress.CaseDifference,
ValidateFunc: validation.StringInSlice([]string{
"add", "overwrite",
}, true),
},
"members": {
Type: schema.TypeSet,
Required: true,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validation.NoZeroValues,
},
},
},
}
}

func resourceGroupMembershipCreate(d *schema.ResourceData, m interface{}) error {
clients := m.(*config.AggregatedClient)
group := d.Get("group").(string)
mode := d.Get("mode").(string)
membersToAdd := d.Get("members").(*schema.Set)
var membersToRemove *schema.Set = nil

if strings.EqualFold("overwrite", mode) {
actualMemberships, err := getGroupMemberships(clients, group)
if err != nil {
return fmt.Errorf("Error reading group memberships during read: %+v", err)
}
actualMembershipsSet, err := getGroupMembershipSet(actualMemberships)
if err != nil {
return fmt.Errorf("Error converting membership list to set: %+v", err)
}
membersToRemove = membersToAdd.Difference(actualMembershipsSet)
} else {
membersToRemove, _ = getGroupMembershipSet(nil)
}

err := applyMembershipUpdate(m.(*config.AggregatedClient),
expandGroupMembers(group, membersToAdd),
expandGroupMembers(group, membersToRemove))
if err != nil {
return fmt.Errorf("Error adding group memberships during create: %+v", err)
}

stateConf := &resource.StateChangeConf{
Pending: []string{"Waiting"},
Target: []string{"Synched"},
Refresh: func() (interface{}, string, error) {
clients := m.(*config.AggregatedClient)
state := "Waiting"
actualMemberships, err := getGroupMemberships(clients, group)
if err != nil {
return nil, "", fmt.Errorf("Error reading group memberships: %+v", err)
}
actualMembershipsSet, err := getGroupMembershipSet(actualMemberships)
if err != nil {
return nil, "", fmt.Errorf("Error converting membership list to set: %+v", err)
}
if (membersToAdd == nil || actualMembershipsSet.Intersection(membersToAdd).Len() <= 0) &&
(membersToRemove == nil || actualMembershipsSet.Intersection(membersToRemove).Len() <= 0) {
state = "Synched"
}

return state, state, nil
},
Timeout: 60 * time.Minute,
MinTimeout: 5 * time.Second,
Delay: 5 * time.Second,
ContinuousTargetOccurence: 3,
}
if _, err := stateConf.WaitForState(); err != nil {
return fmt.Errorf("Error waiting for DevOps synching memberships for group [%s]: %+v", group, err)
}

// The ID for this resource is meaningless so we can just assign a random ID
d.SetId(fmt.Sprintf("%d", rand.Int()))

return resourceGroupMembershipRead(d, m)
}

func resourceGroupMembershipUpdate(d *schema.ResourceData, m interface{}) error {
if !d.HasChange("members") {
return nil
}

group := d.Get("group").(string)
oldData, newData := d.GetChange("members")
// members that need to be added will be missing from the old data, but present in the new data
membersToAdd := newData.(*schema.Set).Difference(oldData.(*schema.Set))
// members that need to be removed will be missing from the new data, but present in the old data
membersToRemove := oldData.(*schema.Set).Difference(newData.(*schema.Set))

err := applyMembershipUpdate(m.(*config.AggregatedClient),
expandGroupMembers(group, membersToAdd),
expandGroupMembers(group, membersToRemove))
if err != nil {
return err
}

stateConf := &resource.StateChangeConf{
Pending: []string{"Waiting"},
Target: []string{"Synched"},
Refresh: func() (interface{}, string, error) {
clients := m.(*config.AggregatedClient)
state := "Waiting"
actualMemberships, err := getGroupMemberships(clients, group)
if err != nil {
return nil, "", fmt.Errorf("Error reading group memberships: %+v", err)
}
actualMembershipsSet, err := getGroupMembershipSet(actualMemberships)
if err != nil {
return nil, "", fmt.Errorf("Error converting membership list to set: %+v", err)
}
if actualMembershipsSet.Intersection(membersToAdd).Len() <= 0 &&
actualMembershipsSet.Intersection(membersToRemove).Len() <= 0 {
state = "Synched"
}

return state, state, nil
},
Timeout: 60 * time.Minute,
MinTimeout: 5 * time.Second,
Delay: 5 * time.Second,
ContinuousTargetOccurence: 3,
}
if _, err := stateConf.WaitForState(); err != nil {
return fmt.Errorf("Error waiting for DevOps synching memberships for group [%s]: %+v", group, err)
}

return resourceGroupMembershipRead(d, m)
}

func applyMembershipUpdate(clients *config.AggregatedClient, toAdd *[]graph.GraphMembership, toRemove *[]graph.GraphMembership) error {
if toRemove != nil && len(*toRemove) > 0 {
err := removeMembers(clients, toRemove)
if err != nil {
return fmt.Errorf("Error removing group memberships during update: %+v", err)
}
}

if toAdd != nil && len(*toAdd) > 0 {
err := addMembers(clients, toAdd)
if err != nil {
return fmt.Errorf("Error adding group memberships during update: %+v", err)
}
}
return nil
}

func resourceGroupMembershipDelete(d *schema.ResourceData, m interface{}) error {
clients := m.(*config.AggregatedClient)
memberships := expandGroupMembers(d.Get("group").(string), d.Get("members").(*schema.Set))

err := removeMembers(clients, memberships)
if err != nil {
return fmt.Errorf("Error removing group memberships during delete: %+v", err)
}

// this marks the resource as deleted
d.SetId("")
return nil
}

// Add members to a group using the AzDO REST API. If any error is encountered, the function immediately returns.
func addMembers(clients *config.AggregatedClient, memberships *[]graph.GraphMembership) error {
if memberships != nil {
for _, membership := range *memberships {
_, err := clients.GraphClient.AddMembership(clients.Ctx, graph.AddMembershipArgs{
SubjectDescriptor: membership.MemberDescriptor,
ContainerDescriptor: membership.ContainerDescriptor,
})

if err != nil {
return fmt.Errorf("Error adding member %s to group %s: %+v",
converter.ToString(membership.MemberDescriptor, "nil"),
converter.ToString(membership.ContainerDescriptor, "nil"),
err)
}
}
}
return nil
}

// Remove members from a group using the AzDO REST API. If any error is encountered, the function immediately returns.
func removeMembers(clients *config.AggregatedClient, memberships *[]graph.GraphMembership) error {
if memberships != nil {
for _, membership := range *memberships {
err := clients.GraphClient.RemoveMembership(clients.Ctx, graph.RemoveMembershipArgs{
SubjectDescriptor: membership.MemberDescriptor,
ContainerDescriptor: membership.ContainerDescriptor,
})

if err != nil {
return fmt.Errorf("Error removing member from group: %+v", err)
}
}
}
return nil
}

func expandGroupMembers(group string, memberSet *schema.Set) *[]graph.GraphMembership {
if memberSet == nil || memberSet.Len() <= 0 {
return &[]graph.GraphMembership{}
}
members := memberSet.List()
memberships := make([]graph.GraphMembership, len(members))

for i, member := range members {
memberships[i] = *buildMembership(group, member.(string))
}

return &memberships
}

func buildMembership(group string, member string) *graph.GraphMembership {
return &graph.GraphMembership{
ContainerDescriptor: &group,
MemberDescriptor: &member,
}
}

func resourceGroupMembershipRead(d *schema.ResourceData, m interface{}) error {
clients := m.(*config.AggregatedClient)
group := d.Get("group").(string)

actualMemberships, err := getGroupMemberships(clients, group)
if err != nil {
if utils.ResponseWasNotFound(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error reading group memberships during read: %+v", err)
}

mode := d.Get("mode").(string)
stateMembers := d.Get("members").(*schema.Set)
members := make([]string, 0)
for _, membership := range *actualMemberships {
if strings.EqualFold("overwrite", mode) || stateMembers.Contains(*membership.MemberDescriptor) {
members = append(members, *membership.MemberDescriptor)
}
}

d.Set("members", members)
return nil
}

func getGroupMemberships(clients *config.AggregatedClient, groupDescriptor string) (*[]graph.GraphMembership, error) {
return clients.GraphClient.ListMemberships(clients.Ctx, graph.ListMembershipsArgs{
SubjectDescriptor: &groupDescriptor,
Direction: &graph.GraphTraversalDirectionValues.Down,
Depth: converter.Int(1),
})
}

func getGroupMembershipSet(members *[]graph.GraphMembership) (*schema.Set, error) {
set := schema.NewSet(schema.HashString, nil)
if nil != members {
for _, member := range *members {
set.Add(*member.MemberDescriptor)
}
}
return set, nil
}
241 changes: 241 additions & 0 deletions azuredevops/resource_group_membership_test.go
427 changes: 427 additions & 0 deletions azuredevops/resource_group_test.go
219 changes: 157 additions & 62 deletions azuredevops/resource_project.go
167 changes: 91 additions & 76 deletions azuredevops/resource_project_test.go
168 changes: 168 additions & 0 deletions azuredevops/resource_resource_authorization.go
189 changes: 189 additions & 0 deletions azuredevops/resource_resource_authorization_test.go
147 changes: 0 additions & 147 deletions azuredevops/resource_serviceendpoint.go

This file was deleted.

144 changes: 144 additions & 0 deletions azuredevops/resource_serviceendpoint_azurerm.go
402 changes: 402 additions & 0 deletions azuredevops/resource_serviceendpoint_azurerm_test.go
37 changes: 37 additions & 0 deletions azuredevops/resource_serviceendpoint_bitbucket.go
245 changes: 245 additions & 0 deletions azuredevops/resource_serviceendpoint_bitbucket_test.go
63 changes: 63 additions & 0 deletions azuredevops/resource_serviceendpoint_dockerhub.go
269 changes: 269 additions & 0 deletions azuredevops/resource_serviceendpoint_dockerhub_test.go
166 changes: 166 additions & 0 deletions azuredevops/resource_serviceendpoint_github.go
271 changes: 271 additions & 0 deletions azuredevops/resource_serviceendpoint_github_test.go
307 changes: 307 additions & 0 deletions azuredevops/resource_serviceendpoint_kubernetes.go
652 changes: 652 additions & 0 deletions azuredevops/resource_serviceendpoint_kubernetes_test.go
387 changes: 387 additions & 0 deletions azuredevops/resource_user_entitlement.go
730 changes: 730 additions & 0 deletions azuredevops/resource_user_entitlement_test.go
387 changes: 387 additions & 0 deletions azuredevops/resource_variable_group.go
232 changes: 232 additions & 0 deletions azuredevops/resource_variable_group_test.go
22 changes: 22 additions & 0 deletions azuredevops/utils/HttpResponse.go
143 changes: 143 additions & 0 deletions azuredevops/utils/config/config.go
70 changes: 70 additions & 0 deletions azuredevops/utils/converter/converter.go
2 changes: 2 additions & 0 deletions azuredevops/utils/converter/converter_test.go
52 changes: 52 additions & 0 deletions azuredevops/utils/secretmemo/secretmemo.go
68 changes: 68 additions & 0 deletions azuredevops/utils/secretmemo/secretmemo_test.go
13 changes: 13 additions & 0 deletions azuredevops/utils/suppress/string.go
53 changes: 53 additions & 0 deletions azuredevops/utils/suppress/string_test.go
9 changes: 9 additions & 0 deletions azuredevops/utils/testhelper/dataGenerator.go
425 changes: 425 additions & 0 deletions azuredevops/utils/testhelper/hcl.go
27 changes: 27 additions & 0 deletions azuredevops/utils/testhelper/provider.go
155 changes: 149 additions & 6 deletions azuredevops/utils/tfhelper/tfhelper.go
27 changes: 0 additions & 27 deletions azuredevops/utils/tfhelper/tfhelper_test.go

This file was deleted.

34 changes: 34 additions & 0 deletions azuredevops/utils/validate/file_path.go
51 changes: 51 additions & 0 deletions azuredevops/utils/validate/file_path_test.go
20 changes: 20 additions & 0 deletions azuredevops/utils/validate/strings.go
101 changes: 101 additions & 0 deletions azuredevops/utils/validate/strings_test.go
42 changes: 42 additions & 0 deletions azuredevops/utils/validate/uuid.go
39 changes: 39 additions & 0 deletions azuredevops/utils/validate/uuid_test.go
388 changes: 359 additions & 29 deletions docs/contributing.md
16 changes: 14 additions & 2 deletions docs/debugging.md
Binary file added docs/images/prettyprintlogs.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions docs/roadmap.md
166 changes: 103 additions & 63 deletions docs/testing.md
3 changes: 3 additions & 0 deletions examples/.env.template
18 changes: 18 additions & 0 deletions examples/azdo-based-cicd/README.md
172 changes: 172 additions & 0 deletions examples/azdo-based-cicd/main.tf
4 changes: 4 additions & 0 deletions examples/azdo-based-cicd/variables.tf
11 changes: 11 additions & 0 deletions examples/github-based-cicd-simple/README.md
38 changes: 38 additions & 0 deletions examples/github-based-cicd-simple/main.tf
38 changes: 0 additions & 38 deletions examples/main.tf

This file was deleted.

13 changes: 10 additions & 3 deletions go.mod
159 changes: 113 additions & 46 deletions go.sum
4 changes: 2 additions & 2 deletions main.go
63 changes: 63 additions & 0 deletions scripts/acctest.ps1
2 changes: 1 addition & 1 deletion scripts/acctest.sh
87 changes: 87 additions & 0 deletions scripts/build.ps1
60 changes: 45 additions & 15 deletions scripts/build.sh
31 changes: 31 additions & 0 deletions scripts/changelog-links.sh
9 changes: 9 additions & 0 deletions scripts/commons.ps1
21 changes: 21 additions & 0 deletions scripts/fmt-check-go.sh
53 changes: 50 additions & 3 deletions scripts/generate-mocks.sh
40 changes: 40 additions & 0 deletions scripts/gofmtcheck.ps1
15 changes: 15 additions & 0 deletions scripts/gofmtcheck.sh
10 changes: 10 additions & 0 deletions scripts/gogetcookie.sh
34 changes: 34 additions & 0 deletions scripts/lint-check-go.ps1
15 changes: 5 additions & 10 deletions scripts/lint-check-go.sh
35 changes: 35 additions & 0 deletions scripts/local-install.ps1
3 changes: 1 addition & 2 deletions scripts/local-install.sh
46 changes: 46 additions & 0 deletions scripts/timeouts.sh
53 changes: 53 additions & 0 deletions scripts/unittest.ps1
2 changes: 1 addition & 1 deletion scripts/unittest.sh
202 changes: 202 additions & 0 deletions vendor/cloud.google.com/go/LICENSE
526 changes: 526 additions & 0 deletions vendor/cloud.google.com/go/compute/metadata/metadata.go
315 changes: 315 additions & 0 deletions vendor/cloud.google.com/go/iam/iam.go
54 changes: 54 additions & 0 deletions vendor/cloud.google.com/go/internal/annotate.go
108 changes: 108 additions & 0 deletions vendor/cloud.google.com/go/internal/optional/optional.go
54 changes: 54 additions & 0 deletions vendor/cloud.google.com/go/internal/retry.go
109 changes: 109 additions & 0 deletions vendor/cloud.google.com/go/internal/trace/trace.go
19 changes: 19 additions & 0 deletions vendor/cloud.google.com/go/internal/version/update_version.sh
71 changes: 71 additions & 0 deletions vendor/cloud.google.com/go/internal/version/version.go
32 changes: 32 additions & 0 deletions vendor/cloud.google.com/go/storage/README.md
335 changes: 335 additions & 0 deletions vendor/cloud.google.com/go/storage/acl.go
1,195 changes: 1,195 additions & 0 deletions vendor/cloud.google.com/go/storage/bucket.go
228 changes: 228 additions & 0 deletions vendor/cloud.google.com/go/storage/copy.go
176 changes: 176 additions & 0 deletions vendor/cloud.google.com/go/storage/doc.go
32 changes: 32 additions & 0 deletions vendor/cloud.google.com/go/storage/go110.go
330 changes: 330 additions & 0 deletions vendor/cloud.google.com/go/storage/hmac.go
130 changes: 130 additions & 0 deletions vendor/cloud.google.com/go/storage/iam.go
37 changes: 37 additions & 0 deletions vendor/cloud.google.com/go/storage/invoke.go
42 changes: 42 additions & 0 deletions vendor/cloud.google.com/go/storage/not_go110.go
188 changes: 188 additions & 0 deletions vendor/cloud.google.com/go/storage/notifications.go
403 changes: 403 additions & 0 deletions vendor/cloud.google.com/go/storage/reader.go
1,369 changes: 1,369 additions & 0 deletions vendor/cloud.google.com/go/storage/storage.go
30,067 changes: 30,067 additions & 0 deletions vendor/cloud.google.com/go/storage/storage.replay
260 changes: 260 additions & 0 deletions vendor/cloud.google.com/go/storage/writer.go
53 changes: 53 additions & 0 deletions vendor/github.com/agext/levenshtein/.gitignore
25 changes: 25 additions & 0 deletions vendor/github.com/agext/levenshtein/.travis.yml
36 changes: 36 additions & 0 deletions vendor/github.com/agext/levenshtein/DCO
201 changes: 201 additions & 0 deletions vendor/github.com/agext/levenshtein/LICENSE
1 change: 1 addition & 0 deletions vendor/github.com/agext/levenshtein/MAINTAINERS
5 changes: 5 additions & 0 deletions vendor/github.com/agext/levenshtein/NOTICE
38 changes: 38 additions & 0 deletions vendor/github.com/agext/levenshtein/README.md
1 change: 1 addition & 0 deletions vendor/github.com/agext/levenshtein/go.mod
290 changes: 290 additions & 0 deletions vendor/github.com/agext/levenshtein/levenshtein.go
152 changes: 152 additions & 0 deletions vendor/github.com/agext/levenshtein/params.go
10 changes: 10 additions & 0 deletions vendor/github.com/agext/levenshtein/test.sh
29 changes: 29 additions & 0 deletions vendor/github.com/ahmetb/go-linq/.gitignore
19 changes: 19 additions & 0 deletions vendor/github.com/ahmetb/go-linq/.travis.yml
201 changes: 201 additions & 0 deletions vendor/github.com/ahmetb/go-linq/LICENSE
222 changes: 222 additions & 0 deletions vendor/github.com/ahmetb/go-linq/README.md
158 changes: 158 additions & 0 deletions vendor/github.com/ahmetb/go-linq/aggregate.go
200 changes: 200 additions & 0 deletions vendor/github.com/ahmetb/go-linq/compare.go
74 changes: 74 additions & 0 deletions vendor/github.com/ahmetb/go-linq/concat.go
70 changes: 70 additions & 0 deletions vendor/github.com/ahmetb/go-linq/convert.go
98 changes: 98 additions & 0 deletions vendor/github.com/ahmetb/go-linq/distinct.go
6 changes: 6 additions & 0 deletions vendor/github.com/ahmetb/go-linq/doc.go
79 changes: 79 additions & 0 deletions vendor/github.com/ahmetb/go-linq/except.go
172 changes: 172 additions & 0 deletions vendor/github.com/ahmetb/go-linq/from.go
138 changes: 138 additions & 0 deletions vendor/github.com/ahmetb/go-linq/genericfunc.go
81 changes: 81 additions & 0 deletions vendor/github.com/ahmetb/go-linq/groupby.go
107 changes: 107 additions & 0 deletions vendor/github.com/ahmetb/go-linq/groupjoin.go
87 changes: 87 additions & 0 deletions vendor/github.com/ahmetb/go-linq/intersect.go
105 changes: 105 additions & 0 deletions vendor/github.com/ahmetb/go-linq/join.go
313 changes: 313 additions & 0 deletions vendor/github.com/ahmetb/go-linq/orderby.go
658 changes: 658 additions & 0 deletions vendor/github.com/ahmetb/go-linq/result.go
30 changes: 30 additions & 0 deletions vendor/github.com/ahmetb/go-linq/reverse.go
109 changes: 109 additions & 0 deletions vendor/github.com/ahmetb/go-linq/select.go
265 changes: 265 additions & 0 deletions vendor/github.com/ahmetb/go-linq/selectmany.go
134 changes: 134 additions & 0 deletions vendor/github.com/ahmetb/go-linq/skip.go
129 changes: 129 additions & 0 deletions vendor/github.com/ahmetb/go-linq/take.go
40 changes: 40 additions & 0 deletions vendor/github.com/ahmetb/go-linq/union.go
89 changes: 89 additions & 0 deletions vendor/github.com/ahmetb/go-linq/where.go
55 changes: 55 additions & 0 deletions vendor/github.com/ahmetb/go-linq/zip.go
19 changes: 19 additions & 0 deletions vendor/github.com/apparentlymart/go-cidr/LICENSE
218 changes: 218 additions & 0 deletions vendor/github.com/apparentlymart/go-cidr/cidr/cidr.go
37 changes: 37 additions & 0 deletions vendor/github.com/apparentlymart/go-cidr/cidr/wrangling.go
95 changes: 95 additions & 0 deletions vendor/github.com/apparentlymart/go-textseg/LICENSE
30 changes: 30 additions & 0 deletions vendor/github.com/apparentlymart/go-textseg/textseg/all_tokens.go
5,276 changes: 5,276 additions & 0 deletions vendor/github.com/apparentlymart/go-textseg/textseg/grapheme_clusters.go
1,583 changes: 1,583 additions & 0 deletions vendor/github.com/apparentlymart/go-textseg/textseg/grapheme_clusters_table.rl
5,700 changes: 5,700 additions & 0 deletions vendor/github.com/apparentlymart/go-textseg/textseg/tables.go
335 changes: 335 additions & 0 deletions vendor/github.com/apparentlymart/go-textseg/textseg/unicode2ragel.rb
19 changes: 19 additions & 0 deletions vendor/github.com/apparentlymart/go-textseg/textseg/utf8_seqs.go
22 changes: 22 additions & 0 deletions vendor/github.com/armon/go-radix/.gitignore
3 changes: 3 additions & 0 deletions vendor/github.com/armon/go-radix/.travis.yml
20 changes: 20 additions & 0 deletions vendor/github.com/armon/go-radix/LICENSE
38 changes: 38 additions & 0 deletions vendor/github.com/armon/go-radix/README.md
1 change: 1 addition & 0 deletions vendor/github.com/armon/go-radix/go.mod
540 changes: 540 additions & 0 deletions vendor/github.com/armon/go-radix/radix.go
202 changes: 202 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/LICENSE.txt
3 changes: 3 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/NOTICE.txt
164 changes: 164 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/awserr/error.go
221 changes: 221 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/awserr/types.go
108 changes: 108 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy.go
27 changes: 27 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/awsutil/equal.go
221 changes: 221 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go
113 changes: 113 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/awsutil/prettify.go
88 changes: 88 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/awsutil/string_value.go
96 changes: 96 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/client/client.go
177 changes: 177 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer.go
194 changes: 194 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/client/logger.go
28 changes: 28 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/client/no_op_retryer.go
536 changes: 536 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/config.go
37 changes: 37 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/context_1_5.go
11 changes: 11 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/context_1_9.go
56 changes: 56 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/context_background_1_5.go
20 changes: 20 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/context_background_1_7.go
24 changes: 24 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/context_sleep.go
918 changes: 918 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/convert_types.go
230 changes: 230 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go
37 changes: 37 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/corehandlers/user_agent.go
100 changes: 100 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider.go
299 changes: 299 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials.go
74 changes: 74 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider.go
12 changes: 12 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/credentials/example.ini
69 changes: 69 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/csm/doc.go
89 changes: 89 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/csm/enable.go
109 changes: 109 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/csm/metric.go
55 changes: 55 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/csm/metric_chan.go
26 changes: 26 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/csm/metric_exception.go
265 changes: 265 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/csm/reporter.go
207 changes: 207 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults.go
27 changes: 27 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/defaults/shared_config.go
56 changes: 56 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/doc.go
170 changes: 170 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go
152 changes: 152 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service.go
188 changes: 188 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/endpoints/decode.go
5,651 changes: 5,651 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go
141 changes: 141 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/endpoints/dep_service_ids.go
66 changes: 66 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/endpoints/doc.go
452 changes: 452 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/endpoints/endpoints.go
308 changes: 308 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model.go
351 changes: 351 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model_codegen.go
13 changes: 13 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/errors.go
12 changes: 12 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/jsonvalue.go
118 changes: 118 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/logger.go
322 changes: 322 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go
24 changes: 24 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/request/http_request.go
65 changes: 65 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader.go
670 changes: 670 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/request/request.go
39 changes: 39 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7.go
36 changes: 36 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8.go
14 changes: 14 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/request/request_context.go
264 changes: 264 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination.go
276 changes: 276 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go
286 changes: 286 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/request/validation.go
295 changes: 295 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/request/waiter.go
26 changes: 26 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/session/cabundle_transport.go
259 changes: 259 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/session/credentials.go
245 changes: 245 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/session/doc.go
277 changes: 277 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/session/env_config.go
660 changes: 660 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/session/session.go
491 changes: 491 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go
82 changes: 82 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/signer/v4/header_rules.go
7 changes: 7 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/signer/v4/options.go
24 changes: 24 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/signer/v4/uri_path.go
806 changes: 806 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/signer/v4/v4.go
207 changes: 207 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/types.go
12 changes: 12 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/url.go
29 changes: 29 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/url_1_7.go
8 changes: 8 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/aws/version.go
120 changes: 120 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/ast.go
11 changes: 11 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/comma_token.go
35 changes: 35 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/comment_token.go
29 changes: 29 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/doc.go
4 changes: 4 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/empty_token.go
24 changes: 24 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/expression.go
17 changes: 17 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/fuzz.go
51 changes: 51 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/ini.go
165 changes: 165 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/ini_lexer.go
349 changes: 349 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/ini_parser.go
324 changes: 324 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/literal_tokens.go
30 changes: 30 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/newline_token.go
152 changes: 152 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/number_helper.go
39 changes: 39 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/op_tokens.go
43 changes: 43 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/parse_error.go
60 changes: 60 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/parse_stack.go
41 changes: 41 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/sep_tokens.go
45 changes: 45 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/skipper.go
35 changes: 35 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/statement.go
284 changes: 284 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/value_util.go
166 changes: 166 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/visitor.go
25 changes: 25 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/walker.go
24 changes: 24 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/ini/ws_token.go
57 changes: 57 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/s3err/error.go
12 changes: 12 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/sdkio/byte.go
10 changes: 10 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/sdkio/io_go1.6.go
12 changes: 12 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/sdkio/io_go1.7.go
15 changes: 15 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/sdkmath/floor.go
56 changes: 56 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/sdkmath/floor_go1.9.go
29 changes: 29 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/sdkrand/locked_source.go
11 changes: 11 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/sdkrand/read.go
24 changes: 24 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/sdkrand/read_1_5.go
23 changes: 23 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/internal/sdkuri/path.go
144 changes: 144 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/private/protocol/eventstream/debug.go
68 changes: 68 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/private/protocol/host.go
54 changes: 54 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/private/protocol/host_prefix.go
75 changes: 75 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/private/protocol/idempotency.go
76 changes: 76 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/private/protocol/jsonvalue.go
81 changes: 81 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/private/protocol/payload.go
36 changes: 36 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/private/protocol/query/build.go
310 changes: 310 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/private/protocol/rest/build.go
45 changes: 45 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/private/protocol/rest/payload.go
237 changes: 237 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/private/protocol/rest/unmarshal.go
84 changes: 84 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/private/protocol/timestamp.go
21 changes: 21 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/private/protocol/unmarshal.go
306 changes: 306 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/build.go
24,952 changes: 24,952 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/service/s3/api.go
249 changes: 249 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/service/s3/body_hash.go
107 changes: 107 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/service/s3/bucket_location.go
75 changes: 75 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/service/s3/customizations.go
26 changes: 26 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/service/s3/doc.go
123 changes: 123 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/service/s3/doc_custom.go
48 changes: 48 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/service/s3/errors.go
155 changes: 155 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/service/s3/host_style_bucket.go
99 changes: 99 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/service/s3/service.go
84 changes: 84 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/service/s3/sse.go
40 changes: 40 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/service/s3/statusok_error.go
88 changes: 88 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/service/s3/unmarshal_error.go
214 changes: 214 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/service/s3/waiters.go
2,750 changes: 2,750 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/service/sts/api.go
11 changes: 11 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/service/sts/customizations.go
108 changes: 108 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/service/sts/doc.go
73 changes: 73 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/service/sts/errors.go
95 changes: 95 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/service/sts/service.go
96 changes: 96 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/service/sts/stsiface/interface.go
20 changes: 20 additions & 0 deletions vendor/github.com/bgentry/go-netrc/LICENSE
510 changes: 510 additions & 0 deletions vendor/github.com/bgentry/go-netrc/netrc/netrc.go
2 changes: 2 additions & 0 deletions vendor/github.com/bgentry/speakeasy/.gitignore
24 changes: 24 additions & 0 deletions vendor/github.com/bgentry/speakeasy/LICENSE
201 changes: 201 additions & 0 deletions vendor/github.com/bgentry/speakeasy/LICENSE_WINDOWS
30 changes: 30 additions & 0 deletions vendor/github.com/bgentry/speakeasy/Readme.md
49 changes: 49 additions & 0 deletions vendor/github.com/bgentry/speakeasy/speakeasy.go
93 changes: 93 additions & 0 deletions vendor/github.com/bgentry/speakeasy/speakeasy_unix.go
41 changes: 41 additions & 0 deletions vendor/github.com/bgentry/speakeasy/speakeasy_windows.go
15 changes: 15 additions & 0 deletions vendor/github.com/davecgh/go-spew/LICENSE
145 changes: 145 additions & 0 deletions vendor/github.com/davecgh/go-spew/spew/bypass.go
38 changes: 38 additions & 0 deletions vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
341 changes: 341 additions & 0 deletions vendor/github.com/davecgh/go-spew/spew/common.go
306 changes: 306 additions & 0 deletions vendor/github.com/davecgh/go-spew/spew/config.go
211 changes: 211 additions & 0 deletions vendor/github.com/davecgh/go-spew/spew/doc.go
509 changes: 509 additions & 0 deletions vendor/github.com/davecgh/go-spew/spew/dump.go
419 changes: 419 additions & 0 deletions vendor/github.com/davecgh/go-spew/spew/format.go
148 changes: 148 additions & 0 deletions vendor/github.com/davecgh/go-spew/spew/spew.go
5 changes: 5 additions & 0 deletions vendor/github.com/fatih/color/.travis.yml
27 changes: 27 additions & 0 deletions vendor/github.com/fatih/color/Gopkg.lock
30 changes: 30 additions & 0 deletions vendor/github.com/fatih/color/Gopkg.toml
20 changes: 20 additions & 0 deletions vendor/github.com/fatih/color/LICENSE.md
179 changes: 179 additions & 0 deletions vendor/github.com/fatih/color/README.md
603 changes: 603 additions & 0 deletions vendor/github.com/fatih/color/color.go
133 changes: 133 additions & 0 deletions vendor/github.com/fatih/color/doc.go
12 changes: 12 additions & 0 deletions vendor/github.com/golang/mock/AUTHORS
37 changes: 37 additions & 0 deletions vendor/github.com/golang/mock/CONTRIBUTORS
202 changes: 202 additions & 0 deletions vendor/github.com/golang/mock/LICENSE
427 changes: 427 additions & 0 deletions vendor/github.com/golang/mock/gomock/call.go
108 changes: 108 additions & 0 deletions vendor/github.com/golang/mock/gomock/callset.go
264 changes: 264 additions & 0 deletions vendor/github.com/golang/mock/gomock/controller.go
255 changes: 255 additions & 0 deletions vendor/github.com/golang/mock/gomock/matchers.go
3 changes: 3 additions & 0 deletions vendor/github.com/golang/protobuf/AUTHORS
3 changes: 3 additions & 0 deletions vendor/github.com/golang/protobuf/CONTRIBUTORS
28 changes: 28 additions & 0 deletions vendor/github.com/golang/protobuf/LICENSE
253 changes: 253 additions & 0 deletions vendor/github.com/golang/protobuf/proto/clone.go
427 changes: 427 additions & 0 deletions vendor/github.com/golang/protobuf/proto/decode.go
63 changes: 63 additions & 0 deletions vendor/github.com/golang/protobuf/proto/deprecated.go
350 changes: 350 additions & 0 deletions vendor/github.com/golang/protobuf/proto/discard.go
203 changes: 203 additions & 0 deletions vendor/github.com/golang/protobuf/proto/encode.go
301 changes: 301 additions & 0 deletions vendor/github.com/golang/protobuf/proto/equal.go
607 changes: 607 additions & 0 deletions vendor/github.com/golang/protobuf/proto/extensions.go
965 changes: 965 additions & 0 deletions vendor/github.com/golang/protobuf/proto/lib.go
181 changes: 181 additions & 0 deletions vendor/github.com/golang/protobuf/proto/message_set.go
360 changes: 360 additions & 0 deletions vendor/github.com/golang/protobuf/proto/pointer_reflect.go
313 changes: 313 additions & 0 deletions vendor/github.com/golang/protobuf/proto/pointer_unsafe.go
544 changes: 544 additions & 0 deletions vendor/github.com/golang/protobuf/proto/properties.go
2,776 changes: 2,776 additions & 0 deletions vendor/github.com/golang/protobuf/proto/table_marshal.go
654 changes: 654 additions & 0 deletions vendor/github.com/golang/protobuf/proto/table_merge.go
2,053 changes: 2,053 additions & 0 deletions vendor/github.com/golang/protobuf/proto/table_unmarshal.go
843 changes: 843 additions & 0 deletions vendor/github.com/golang/protobuf/proto/text.go
880 changes: 880 additions & 0 deletions vendor/github.com/golang/protobuf/proto/text_parser.go
2,887 changes: 2,887 additions & 0 deletions vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go
141 changes: 141 additions & 0 deletions vendor/github.com/golang/protobuf/ptypes/any.go
200 changes: 200 additions & 0 deletions vendor/github.com/golang/protobuf/ptypes/any/any.pb.go
154 changes: 154 additions & 0 deletions vendor/github.com/golang/protobuf/ptypes/any/any.proto
35 changes: 35 additions & 0 deletions vendor/github.com/golang/protobuf/ptypes/doc.go
102 changes: 102 additions & 0 deletions vendor/github.com/golang/protobuf/ptypes/duration.go
161 changes: 161 additions & 0 deletions vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go
117 changes: 117 additions & 0 deletions vendor/github.com/golang/protobuf/ptypes/duration/duration.proto
132 changes: 132 additions & 0 deletions vendor/github.com/golang/protobuf/ptypes/timestamp.go
179 changes: 179 additions & 0 deletions vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go
135 changes: 135 additions & 0 deletions vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto
27 changes: 27 additions & 0 deletions vendor/github.com/google/go-cmp/LICENSE
616 changes: 616 additions & 0 deletions vendor/github.com/google/go-cmp/cmp/compare.go
15 changes: 15 additions & 0 deletions vendor/github.com/google/go-cmp/cmp/export_panic.go
23 changes: 23 additions & 0 deletions vendor/github.com/google/go-cmp/cmp/export_unsafe.go
17 changes: 17 additions & 0 deletions vendor/github.com/google/go-cmp/cmp/internal/diff/debug_disable.go
122 changes: 122 additions & 0 deletions vendor/github.com/google/go-cmp/cmp/internal/diff/debug_enable.go
372 changes: 372 additions & 0 deletions vendor/github.com/google/go-cmp/cmp/internal/diff/diff.go
9 changes: 9 additions & 0 deletions vendor/github.com/google/go-cmp/cmp/internal/flags/flags.go
99 changes: 99 additions & 0 deletions vendor/github.com/google/go-cmp/cmp/internal/function/func.go
106 changes: 106 additions & 0 deletions vendor/github.com/google/go-cmp/cmp/internal/value/sort.go
48 changes: 48 additions & 0 deletions vendor/github.com/google/go-cmp/cmp/internal/value/zero.go
524 changes: 524 additions & 0 deletions vendor/github.com/google/go-cmp/cmp/options.go
308 changes: 308 additions & 0 deletions vendor/github.com/google/go-cmp/cmp/path.go
51 changes: 51 additions & 0 deletions vendor/github.com/google/go-cmp/cmp/report.go
296 changes: 296 additions & 0 deletions vendor/github.com/google/go-cmp/cmp/report_compare.go
278 changes: 278 additions & 0 deletions vendor/github.com/google/go-cmp/cmp/report_reflect.go
333 changes: 333 additions & 0 deletions vendor/github.com/google/go-cmp/cmp/report_slices.go
387 changes: 387 additions & 0 deletions vendor/github.com/google/go-cmp/cmp/report_text.go
121 changes: 121 additions & 0 deletions vendor/github.com/google/go-cmp/cmp/report_value.go
9 changes: 9 additions & 0 deletions vendor/github.com/google/uuid/.travis.yml
10 changes: 10 additions & 0 deletions vendor/github.com/google/uuid/CONTRIBUTING.md
9 changes: 9 additions & 0 deletions vendor/github.com/google/uuid/CONTRIBUTORS
27 changes: 27 additions & 0 deletions vendor/github.com/google/uuid/LICENSE
19 changes: 19 additions & 0 deletions vendor/github.com/google/uuid/README.md
80 changes: 80 additions & 0 deletions vendor/github.com/google/uuid/dce.go
12 changes: 12 additions & 0 deletions vendor/github.com/google/uuid/doc.go
1 change: 1 addition & 0 deletions vendor/github.com/google/uuid/go.mod
53 changes: 53 additions & 0 deletions vendor/github.com/google/uuid/hash.go
37 changes: 37 additions & 0 deletions vendor/github.com/google/uuid/marshal.go
90 changes: 90 additions & 0 deletions vendor/github.com/google/uuid/node.go
12 changes: 12 additions & 0 deletions vendor/github.com/google/uuid/node_js.go
33 changes: 33 additions & 0 deletions vendor/github.com/google/uuid/node_net.go
59 changes: 59 additions & 0 deletions vendor/github.com/google/uuid/sql.go
123 changes: 123 additions & 0 deletions vendor/github.com/google/uuid/time.go
43 changes: 43 additions & 0 deletions vendor/github.com/google/uuid/util.go
245 changes: 245 additions & 0 deletions vendor/github.com/google/uuid/uuid.go
44 changes: 44 additions & 0 deletions vendor/github.com/google/uuid/version1.go
38 changes: 38 additions & 0 deletions vendor/github.com/google/uuid/version4.go
27 changes: 27 additions & 0 deletions vendor/github.com/googleapis/gax-go/v2/LICENSE
161 changes: 161 additions & 0 deletions vendor/github.com/googleapis/gax-go/v2/call_option.go
39 changes: 39 additions & 0 deletions vendor/github.com/googleapis/gax-go/v2/gax.go
3 changes: 3 additions & 0 deletions vendor/github.com/googleapis/gax-go/v2/go.mod
25 changes: 25 additions & 0 deletions vendor/github.com/googleapis/gax-go/v2/go.sum
53 changes: 53 additions & 0 deletions vendor/github.com/googleapis/gax-go/v2/header.go
99 changes: 99 additions & 0 deletions vendor/github.com/googleapis/gax-go/v2/invoke.go
354 changes: 354 additions & 0 deletions vendor/github.com/hashicorp/errwrap/LICENSE
89 changes: 89 additions & 0 deletions vendor/github.com/hashicorp/errwrap/README.md
169 changes: 169 additions & 0 deletions vendor/github.com/hashicorp/errwrap/errwrap.go
1 change: 1 addition & 0 deletions vendor/github.com/hashicorp/errwrap/go.mod
363 changes: 363 additions & 0 deletions vendor/github.com/hashicorp/go-cleanhttp/LICENSE
30 changes: 30 additions & 0 deletions vendor/github.com/hashicorp/go-cleanhttp/README.md
57 changes: 57 additions & 0 deletions vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go
20 changes: 20 additions & 0 deletions vendor/github.com/hashicorp/go-cleanhttp/doc.go
1 change: 1 addition & 0 deletions vendor/github.com/hashicorp/go-cleanhttp/go.mod
48 changes: 48 additions & 0 deletions vendor/github.com/hashicorp/go-cleanhttp/handlers.go
354 changes: 354 additions & 0 deletions vendor/github.com/hashicorp/go-getter/LICENSE
362 changes: 362 additions & 0 deletions vendor/github.com/hashicorp/go-getter/README.md
16 changes: 16 additions & 0 deletions vendor/github.com/hashicorp/go-getter/appveyor.yml
314 changes: 314 additions & 0 deletions vendor/github.com/hashicorp/go-getter/checksum.go
298 changes: 298 additions & 0 deletions vendor/github.com/hashicorp/go-getter/client.go
24 changes: 24 additions & 0 deletions vendor/github.com/hashicorp/go-getter/client_mode.go
46 changes: 46 additions & 0 deletions vendor/github.com/hashicorp/go-getter/client_option.go
38 changes: 38 additions & 0 deletions vendor/github.com/hashicorp/go-getter/client_option_progress.go
14 changes: 14 additions & 0 deletions vendor/github.com/hashicorp/go-getter/common.go
78 changes: 78 additions & 0 deletions vendor/github.com/hashicorp/go-getter/copy_dir.go
58 changes: 58 additions & 0 deletions vendor/github.com/hashicorp/go-getter/decompress.go
45 changes: 45 additions & 0 deletions vendor/github.com/hashicorp/go-getter/decompress_bzip2.go
49 changes: 49 additions & 0 deletions vendor/github.com/hashicorp/go-getter/decompress_gzip.go
160 changes: 160 additions & 0 deletions vendor/github.com/hashicorp/go-getter/decompress_tar.go
33 changes: 33 additions & 0 deletions vendor/github.com/hashicorp/go-getter/decompress_tbz2.go
171 changes: 171 additions & 0 deletions vendor/github.com/hashicorp/go-getter/decompress_testing.go
39 changes: 39 additions & 0 deletions vendor/github.com/hashicorp/go-getter/decompress_tgz.go
39 changes: 39 additions & 0 deletions vendor/github.com/hashicorp/go-getter/decompress_txz.go
49 changes: 49 additions & 0 deletions vendor/github.com/hashicorp/go-getter/decompress_xz.go
101 changes: 101 additions & 0 deletions vendor/github.com/hashicorp/go-getter/decompress_zip.go
105 changes: 105 additions & 0 deletions vendor/github.com/hashicorp/go-getter/detect.go
66 changes: 66 additions & 0 deletions vendor/github.com/hashicorp/go-getter/detect_bitbucket.go
67 changes: 67 additions & 0 deletions vendor/github.com/hashicorp/go-getter/detect_file.go
43 changes: 43 additions & 0 deletions vendor/github.com/hashicorp/go-getter/detect_gcs.go
26 changes: 26 additions & 0 deletions vendor/github.com/hashicorp/go-getter/detect_git.go
47 changes: 47 additions & 0 deletions vendor/github.com/hashicorp/go-getter/detect_github.go
61 changes: 61 additions & 0 deletions vendor/github.com/hashicorp/go-getter/detect_s3.go
49 changes: 49 additions & 0 deletions vendor/github.com/hashicorp/go-getter/detect_ssh.go
65 changes: 65 additions & 0 deletions vendor/github.com/hashicorp/go-getter/folder_storage.go
152 changes: 152 additions & 0 deletions vendor/github.com/hashicorp/go-getter/get.go
20 changes: 20 additions & 0 deletions vendor/github.com/hashicorp/go-getter/get_base.go
36 changes: 36 additions & 0 deletions vendor/github.com/hashicorp/go-getter/get_file.go
29 changes: 29 additions & 0 deletions vendor/github.com/hashicorp/go-getter/get_file_copy.go
103 changes: 103 additions & 0 deletions vendor/github.com/hashicorp/go-getter/get_file_unix.go
136 changes: 136 additions & 0 deletions vendor/github.com/hashicorp/go-getter/get_file_windows.go
172 changes: 172 additions & 0 deletions vendor/github.com/hashicorp/go-getter/get_gcs.go
313 changes: 313 additions & 0 deletions vendor/github.com/hashicorp/go-getter/get_git.go
135 changes: 135 additions & 0 deletions vendor/github.com/hashicorp/go-getter/get_hg.go
328 changes: 328 additions & 0 deletions vendor/github.com/hashicorp/go-getter/get_http.go
54 changes: 54 additions & 0 deletions vendor/github.com/hashicorp/go-getter/get_mock.go
275 changes: 275 additions & 0 deletions vendor/github.com/hashicorp/go-getter/get_s3.go
23 changes: 23 additions & 0 deletions vendor/github.com/hashicorp/go-getter/go.mod
162 changes: 162 additions & 0 deletions vendor/github.com/hashicorp/go-getter/go.sum
14 changes: 14 additions & 0 deletions vendor/github.com/hashicorp/go-getter/helper/url/url.go
11 changes: 11 additions & 0 deletions vendor/github.com/hashicorp/go-getter/helper/url/url_unix.go
39 changes: 39 additions & 0 deletions vendor/github.com/hashicorp/go-getter/helper/url/url_windows.go
67 changes: 67 additions & 0 deletions vendor/github.com/hashicorp/go-getter/netrc.go
75 changes: 75 additions & 0 deletions vendor/github.com/hashicorp/go-getter/source.go
13 changes: 13 additions & 0 deletions vendor/github.com/hashicorp/go-getter/storage.go
1 change: 1 addition & 0 deletions vendor/github.com/hashicorp/go-hclog/.gitignore
21 changes: 21 additions & 0 deletions vendor/github.com/hashicorp/go-hclog/LICENSE
148 changes: 148 additions & 0 deletions vendor/github.com/hashicorp/go-hclog/README.md
38 changes: 38 additions & 0 deletions vendor/github.com/hashicorp/go-hclog/context.go
48 changes: 48 additions & 0 deletions vendor/github.com/hashicorp/go-hclog/global.go
7 changes: 7 additions & 0 deletions vendor/github.com/hashicorp/go-hclog/go.mod
6 changes: 6 additions & 0 deletions vendor/github.com/hashicorp/go-hclog/go.sum
527 changes: 527 additions & 0 deletions vendor/github.com/hashicorp/go-hclog/intlogger.go
176 changes: 176 additions & 0 deletions vendor/github.com/hashicorp/go-hclog/logger.go
52 changes: 52 additions & 0 deletions vendor/github.com/hashicorp/go-hclog/nulllogger.go
109 changes: 109 additions & 0 deletions vendor/github.com/hashicorp/go-hclog/stacktrace.go
83 changes: 83 additions & 0 deletions vendor/github.com/hashicorp/go-hclog/stdlog.go
74 changes: 74 additions & 0 deletions vendor/github.com/hashicorp/go-hclog/writer.go
12 changes: 12 additions & 0 deletions vendor/github.com/hashicorp/go-multierror/.travis.yml
353 changes: 353 additions & 0 deletions vendor/github.com/hashicorp/go-multierror/LICENSE
31 changes: 31 additions & 0 deletions vendor/github.com/hashicorp/go-multierror/Makefile
97 changes: 97 additions & 0 deletions vendor/github.com/hashicorp/go-multierror/README.md
41 changes: 41 additions & 0 deletions vendor/github.com/hashicorp/go-multierror/append.go
26 changes: 26 additions & 0 deletions vendor/github.com/hashicorp/go-multierror/flatten.go
27 changes: 27 additions & 0 deletions vendor/github.com/hashicorp/go-multierror/format.go
3 changes: 3 additions & 0 deletions vendor/github.com/hashicorp/go-multierror/go.mod
4 changes: 4 additions & 0 deletions vendor/github.com/hashicorp/go-multierror/go.sum
51 changes: 51 additions & 0 deletions vendor/github.com/hashicorp/go-multierror/multierror.go
37 changes: 37 additions & 0 deletions vendor/github.com/hashicorp/go-multierror/prefix.go
16 changes: 16 additions & 0 deletions vendor/github.com/hashicorp/go-multierror/sort.go
2 changes: 2 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/.gitignore
353 changes: 353 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/LICENSE
168 changes: 168 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/README.md
1,025 changes: 1,025 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/client.go
28 changes: 28 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/discover.go
24 changes: 24 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/error.go
17 changes: 17 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/go.mod
31 changes: 31 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/go.sum
457 changes: 457 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/grpc_broker.go
117 changes: 117 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/grpc_client.go
23 changes: 23 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/grpc_controller.go
142 changes: 142 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/grpc_server.go
3 changes: 3 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/internal/plugin/gen.go
73 changes: 73 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/log_entry.go
73 changes: 73 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/mtls.go
204 changes: 204 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/mux_broker.go
58 changes: 58 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/plugin.go
24 changes: 24 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/process.go
19 changes: 19 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/process_posix.go
29 changes: 29 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/process_windows.go
45 changes: 45 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/protocol.go
170 changes: 170 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/rpc_client.go
197 changes: 197 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/rpc_server.go
452 changes: 452 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/server.go
31 changes: 31 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/server_mux.go
18 changes: 18 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/stream.go
180 changes: 180 additions & 0 deletions vendor/github.com/hashicorp/go-plugin/testing.go
362 changes: 362 additions & 0 deletions vendor/github.com/hashicorp/go-safetemp/LICENSE
10 changes: 10 additions & 0 deletions vendor/github.com/hashicorp/go-safetemp/README.md
1 change: 1 addition & 0 deletions vendor/github.com/hashicorp/go-safetemp/go.mod
40 changes: 40 additions & 0 deletions vendor/github.com/hashicorp/go-safetemp/safetemp.go
12 changes: 12 additions & 0 deletions vendor/github.com/hashicorp/go-uuid/.travis.yml
363 changes: 363 additions & 0 deletions vendor/github.com/hashicorp/go-uuid/LICENSE
8 changes: 8 additions & 0 deletions vendor/github.com/hashicorp/go-uuid/README.md
1 change: 1 addition & 0 deletions vendor/github.com/hashicorp/go-uuid/go.mod
65 changes: 65 additions & 0 deletions vendor/github.com/hashicorp/go-uuid/uuid.go
13 changes: 13 additions & 0 deletions vendor/github.com/hashicorp/go-version/.travis.yml
354 changes: 354 additions & 0 deletions vendor/github.com/hashicorp/go-version/LICENSE
65 changes: 65 additions & 0 deletions vendor/github.com/hashicorp/go-version/README.md
204 changes: 204 additions & 0 deletions vendor/github.com/hashicorp/go-version/constraint.go
1 change: 1 addition & 0 deletions vendor/github.com/hashicorp/go-version/go.mod
380 changes: 380 additions & 0 deletions vendor/github.com/hashicorp/go-version/version.go
17 changes: 17 additions & 0 deletions vendor/github.com/hashicorp/go-version/version_collection.go
362 changes: 362 additions & 0 deletions vendor/github.com/hashicorp/golang-lru/LICENSE
161 changes: 161 additions & 0 deletions vendor/github.com/hashicorp/golang-lru/simplelru/lru.go
36 changes: 36 additions & 0 deletions vendor/github.com/hashicorp/golang-lru/simplelru/lru_interface.go
9 changes: 9 additions & 0 deletions vendor/github.com/hashicorp/hcl/.gitignore
12 changes: 12 additions & 0 deletions vendor/github.com/hashicorp/hcl/.travis.yml
354 changes: 354 additions & 0 deletions vendor/github.com/hashicorp/hcl/LICENSE
18 changes: 18 additions & 0 deletions vendor/github.com/hashicorp/hcl/Makefile
125 changes: 125 additions & 0 deletions vendor/github.com/hashicorp/hcl/README.md
19 changes: 19 additions & 0 deletions vendor/github.com/hashicorp/hcl/appveyor.yml
724 changes: 724 additions & 0 deletions vendor/github.com/hashicorp/hcl/decoder.go
11 changes: 11 additions & 0 deletions vendor/github.com/hashicorp/hcl/hcl.go
219 changes: 219 additions & 0 deletions vendor/github.com/hashicorp/hcl/hcl/ast/ast.go
52 changes: 52 additions & 0 deletions vendor/github.com/hashicorp/hcl/hcl/ast/walk.go
17 changes: 17 additions & 0 deletions vendor/github.com/hashicorp/hcl/hcl/parser/error.go
520 changes: 520 additions & 0 deletions vendor/github.com/hashicorp/hcl/hcl/parser/parser.go
651 changes: 651 additions & 0 deletions vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go
241 changes: 241 additions & 0 deletions vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go
46 changes: 46 additions & 0 deletions vendor/github.com/hashicorp/hcl/hcl/token/position.go
219 changes: 219 additions & 0 deletions vendor/github.com/hashicorp/hcl/hcl/token/token.go
117 changes: 117 additions & 0 deletions vendor/github.com/hashicorp/hcl/json/parser/flatten.go
313 changes: 313 additions & 0 deletions vendor/github.com/hashicorp/hcl/json/parser/parser.go
451 changes: 451 additions & 0 deletions vendor/github.com/hashicorp/hcl/json/scanner/scanner.go
46 changes: 46 additions & 0 deletions vendor/github.com/hashicorp/hcl/json/token/position.go
118 changes: 118 additions & 0 deletions vendor/github.com/hashicorp/hcl/json/token/token.go
38 changes: 38 additions & 0 deletions vendor/github.com/hashicorp/hcl/lex.go
39 changes: 39 additions & 0 deletions vendor/github.com/hashicorp/hcl/parse.go
56 changes: 56 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/CHANGELOG.md
353 changes: 353 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/LICENSE
205 changes: 205 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/README.md
13 changes: 13 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/appveyor.yml
143 changes: 143 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/diagnostic.go
311 changes: 311 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/diagnostic_text.go
24 changes: 24 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/didyoumean.go
34 changes: 34 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/doc.go
25 changes: 25 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/eval_context.go
46 changes: 46 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/expr_call.go
37 changes: 37 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/expr_list.go
44 changes: 44 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/expr_map.go
68 changes: 68 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/expr_unwrap.go
209 changes: 209 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/ext/customdecode/README.md
146 changes: 146 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/ext/customdecode/expression_type.go
184 changes: 184 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/ext/dynblock/README.md
262 changes: 262 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/ext/dynblock/expand_body.go
215 changes: 215 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/ext/dynblock/expand_spec.go
42 changes: 42 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/ext/dynblock/expr_wrap.go
66 changes: 66 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/ext/dynblock/iteration.go
47 changes: 47 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/ext/dynblock/public.go
50 changes: 50 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/ext/dynblock/schema.go
84 changes: 84 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/ext/dynblock/unknown_body.go
209 changes: 209 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/ext/dynblock/variables.go
135 changes: 135 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/ext/typeexpr/README.md
11 changes: 11 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/ext/typeexpr/doc.go
196 changes: 196 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/ext/typeexpr/get_type.go
129 changes: 129 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/ext/typeexpr/public.go
118 changes: 118 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/ext/typeexpr/type_type.go
21 changes: 21 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/go.mod
51 changes: 51 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/go.sum
322 changes: 322 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/gohcl/decode.go
53 changes: 53 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/gohcl/doc.go
191 changes: 191 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/gohcl/encode.go
174 changes: 174 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/gohcl/schema.go
16 changes: 16 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/gohcl/types.go
21 changes: 21 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hcldec/block_labels.go
36 changes: 36 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hcldec/decode.go
12 changes: 12 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hcldec/doc.go
23 changes: 23 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hcldec/gob.go
81 changes: 81 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hcldec/public.go
36 changes: 36 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hcldec/schema.go
1,591 changes: 1,591 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hcldec/spec.go
36 changes: 36 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hcldec/variables.go
4 changes: 4 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hcled/doc.go
34 changes: 34 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hcled/navigation.go
135 changes: 135 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclparse/parser.go
23 changes: 23 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/diagnostics.go
24 changes: 24 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/didyoumean.go
7 changes: 7 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/doc.go
1,491 changes: 1,491 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression.go
268 changes: 268 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression_ops.go
220 changes: 220 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression_template.go
76 changes: 76 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression_vars.go
20 changes: 20 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/file.go
9 changes: 9 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/generate.go
21 changes: 21 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/keywords.go
59 changes: 59 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/navigation.go
22 changes: 22 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/node.go
2,055 changes: 2,055 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/parser.go
799 changes: 799 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/parser_template.go
159 changes: 159 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/parser_traversal.go
212 changes: 212 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/peeker.go
171 changes: 171 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/public.go
301 changes: 301 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/scan_string_lit.go
105 changes: 105 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/scan_string_lit.rl
5,265 changes: 5,265 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/scan_tokens.go
395 changes: 395 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/scan_tokens.rl
941 changes: 941 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/spec.md
394 changes: 394 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/structure.go
118 changes: 118 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/structure_at_pos.go
320 changes: 320 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/token.go
131 changes: 131 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/token_type_string.go
335 changes: 335 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/unicode2ragel.rb
2,135 changes: 2,135 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/unicode_derived.rl
86 changes: 86 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/variables.go
41 changes: 41 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclsyntax/walk.go
121 changes: 121 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclwrite/ast.go
48 changes: 48 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclwrite/ast_attribute.go
118 changes: 118 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclwrite/ast_block.go
239 changes: 239 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclwrite/ast_body.go
224 changes: 224 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclwrite/ast_expression.go
11 changes: 11 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclwrite/doc.go
463 changes: 463 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclwrite/format.go
252 changes: 252 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclwrite/generate.go
23 changes: 23 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclwrite/native_node_sorter.go
260 changes: 260 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclwrite/node.go
599 changes: 599 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclwrite/parser.go
44 changes: 44 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclwrite/public.go
122 changes: 122 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/hclwrite/tokens.go
121 changes: 121 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/json/ast.go
33 changes: 33 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/json/didyoumean.go
12 changes: 12 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/json/doc.go
70 changes: 70 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/json/navigation.go
496 changes: 496 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/json/parser.go
25 changes: 25 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/json/peeker.go
94 changes: 94 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/json/public.go
297 changes: 297 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/json/scanner.go
405 changes: 405 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/json/spec.md
637 changes: 637 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/json/structure.go
29 changes: 29 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/json/tokentype_string.go
226 changes: 226 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/merged.go
288 changes: 288 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/ops.go
275 changes: 275 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/pos.go
152 changes: 152 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/pos_scanner.go
21 changes: 21 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/schema.go
691 changes: 691 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/spec.md
40 changes: 40 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/static_expr.go
151 changes: 151 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/structure.go
117 changes: 117 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/structure_at_pos.go
293 changes: 293 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/traversal.go
124 changes: 124 additions & 0 deletions vendor/github.com/hashicorp/hcl/v2/traversal_for_expr.go
22 changes: 22 additions & 0 deletions vendor/github.com/hashicorp/logutils/.gitignore
354 changes: 354 additions & 0 deletions vendor/github.com/hashicorp/logutils/LICENSE
36 changes: 36 additions & 0 deletions vendor/github.com/hashicorp/logutils/README.md
1 change: 1 addition & 0 deletions vendor/github.com/hashicorp/logutils/go.mod
81 changes: 81 additions & 0 deletions vendor/github.com/hashicorp/logutils/level.go
353 changes: 353 additions & 0 deletions vendor/github.com/hashicorp/terraform-config-inspect/LICENSE
130 changes: 130 additions & 0 deletions vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/load.go
3 changes: 3 additions & 0 deletions vendor/github.com/hashicorp/terraform-json/.gitignore
373 changes: 373 additions & 0 deletions vendor/github.com/hashicorp/terraform-json/LICENSE
20 changes: 20 additions & 0 deletions vendor/github.com/hashicorp/terraform-json/Makefile
33 changes: 33 additions & 0 deletions vendor/github.com/hashicorp/terraform-json/README.md
104 changes: 104 additions & 0 deletions vendor/github.com/hashicorp/terraform-json/action.go
184 changes: 184 additions & 0 deletions vendor/github.com/hashicorp/terraform-json/config.go
127 changes: 127 additions & 0 deletions vendor/github.com/hashicorp/terraform-json/expression.go
8 changes: 8 additions & 0 deletions vendor/github.com/hashicorp/terraform-json/go.mod
19 changes: 19 additions & 0 deletions vendor/github.com/hashicorp/terraform-json/go.sum
159 changes: 159 additions & 0 deletions vendor/github.com/hashicorp/terraform-json/plan.go
168 changes: 168 additions & 0 deletions vendor/github.com/hashicorp/terraform-json/schemas.go
141 changes: 141 additions & 0 deletions vendor/github.com/hashicorp/terraform-json/state.go
9 changes: 9 additions & 0 deletions vendor/github.com/hashicorp/terraform-json/tfjson.go
354 changes: 354 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/LICENSE
26 changes: 26 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/acctest/helper.go
1,406 changes: 1,406 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/helper/resource/testing.go
1,976 changes: 1,976 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/helper/schema/schema.go
246 changes: 246 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/helper/schema/set.go
301 changes: 301 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/internal/dag/dag.go
278 changes: 278 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/internal/dag/dot.go
391 changes: 391 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/internal/dag/graph.go
123 changes: 123 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/internal/dag/set.go
454 changes: 454 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/internal/dag/walk.go
473 changes: 473 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/internal/lang/eval.go
36 changes: 36 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/meta/meta.go
35 changes: 35 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/plugin/client.go
14 changes: 14 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/plugin/plugin.go
100 changes: 100 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/plugin/serve.go
882 changes: 882 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/terraform/context.go
1,441 changes: 1,441 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/terraform/diff.go
70 changes: 70 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/terraform/eval.go
838 changes: 838 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/terraform/evaluate.go
141 changes: 141 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/terraform/graph.go
145 changes: 145 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/terraform/hook.go
17 changes: 17 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/terraform/path.go
94 changes: 94 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/terraform/plan.go
510 changes: 510 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/terraform/resource.go
278 changes: 278 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/terraform/schemas.go
2,217 changes: 2,217 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/terraform/state.go
145 changes: 145 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/terraform/state_v1.go
75 changes: 75 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-sdk/terraform/util.go
353 changes: 353 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-test/LICENSE
4 changes: 4 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-test/README.md
60 changes: 60 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-test/config.go
7 changes: 7 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-test/doc.go
8 changes: 8 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-test/go.mod
170 changes: 170 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-test/go.sum
110 changes: 110 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-test/guard.go
285 changes: 285 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-test/helper.go
15 changes: 15 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-test/plugin.go
163 changes: 163 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-test/terraform.go
55 changes: 55 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-test/util.go
377 changes: 377 additions & 0 deletions vendor/github.com/hashicorp/terraform-plugin-test/working_dir.go
61 changes: 61 additions & 0 deletions vendor/github.com/hashicorp/terraform-svchost/auth/cache.go
118 changes: 118 additions & 0 deletions vendor/github.com/hashicorp/terraform-svchost/auth/credentials.go
48 changes: 48 additions & 0 deletions vendor/github.com/hashicorp/terraform-svchost/auth/from_map.go
Loading