├── .github └── workflows │ ├── ci.yml │ └── release.yml ├── .gitignore ├── .goreleaser.yml ├── LICENSE ├── Makefile ├── README.md ├── client ├── client.go ├── github.go ├── project.go └── user.go ├── deploy ├── data_source_user.go ├── data_source_user_test.go ├── provider.go ├── provider_test.go ├── provider_utils.go ├── resource_custom_domain.go ├── resource_custom_domain_test.go ├── resource_custom_domain_validation.go ├── resource_project.go ├── resource_project_test.go └── testdata │ └── main.ts ├── dprint.json ├── go.mod ├── go.sum ├── main.go ├── tools ├── go.mod ├── go.sum └── tools.go └── website ├── allowed-subcategories.txt └── docs ├── d └── user.html.markdown └── r ├── custom_domain.html.markdown ├── custom_domain_validation.html.markdown └── project.html.markdown /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - main 10 | 11 | jobs: 12 | format: 13 | name: format & lint 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Set up Go 18 | uses: actions/setup-go@v2 19 | with: 20 | go-version: 1.16 21 | - name: Check format 22 | run: | 23 | gofmt -l . 24 | - name: Check lint 25 | uses: golangci/golangci-lint-action@v2 26 | with: 27 | version: latest 28 | - uses: dprint/check@v1.3 29 | # - name: Check docs 30 | # run: make docscheck 31 | test: 32 | name: Unit & Acceptance tests 33 | runs-on: ubuntu-latest 34 | steps: 35 | - uses: actions/checkout@v2 36 | - name: Set up Go 37 | uses: actions/setup-go@v2 38 | with: 39 | go-version: 1.16 40 | - name: Acceptance Tests 41 | run: make testacc 42 | env: 43 | DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }} -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | # This GitHub action can publish assets for release when a tag is created. 2 | # Currently its setup to run on any tag that matches the pattern "v*" (ie. v0.1.0). 3 | # 4 | # This uses an action (paultyng/ghaction-import-gpg) that assumes you set your 5 | # private key in the `GPG_PRIVATE_KEY` secret and passphrase in the `PASSPHRASE` 6 | # secret. If you would rather own your own GPG handling, please fork this action 7 | # or use an alternative one for key handling. 8 | # 9 | # You will need to pass the `--batch` flag to `gpg` in your signing step 10 | # in `goreleaser` to indicate this is being used in a non-interactive mode. 11 | # 12 | name: release 13 | on: 14 | push: 15 | tags: 16 | - "v*" 17 | jobs: 18 | goreleaser: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Checkout 22 | uses: actions/checkout@v2 23 | - name: Unshallow 24 | run: git fetch --prune --unshallow 25 | - name: Set up Go 26 | uses: actions/setup-go@v2 27 | with: 28 | go-version: 1.16 29 | - name: Import GPG key 30 | id: import_gpg 31 | uses: paultyng/ghaction-import-gpg@v2.1.0 32 | env: 33 | GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} 34 | PASSPHRASE: ${{ secrets.PASSPHRASE }} 35 | - name: Run GoReleaser 36 | uses: goreleaser/goreleaser-action@v2 37 | with: 38 | version: latest 39 | args: release --rm-dist 40 | env: 41 | GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} 42 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | bin/ 8 | 9 | # Test binary, built with `go test -c` 10 | *.test 11 | 12 | # Output of the go coverage tool, specifically when used with LiteIDE 13 | *.out 14 | 15 | # Dependency directories (remove the comment below to include it) 16 | # vendor/ 17 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | # Visit https://goreleaser.com for documentation on how to customize this 2 | # behavior. 3 | before: 4 | hooks: 5 | # this is just an example and not a requirement for provider building/publishing 6 | - go mod tidy 7 | builds: 8 | - env: 9 | # goreleaser does not work with CGO, it could also complicate 10 | # usage by users in CI/CD systems like Terraform Cloud where 11 | # they are unable to install libraries. 12 | - CGO_ENABLED=0 13 | mod_timestamp: "{{ .CommitTimestamp }}" 14 | flags: 15 | - -trimpath 16 | ldflags: 17 | - "-s -w -X main.version={{.Version}} -X main.commit={{.Commit}}" 18 | goos: 19 | - freebsd 20 | - windows 21 | - linux 22 | - darwin 23 | goarch: 24 | - amd64 25 | - "386" 26 | - arm 27 | - arm64 28 | ignore: 29 | - goos: darwin 30 | goarch: "386" 31 | binary: "{{ .ProjectName }}_v{{ .Version }}" 32 | archives: 33 | - format: zip 34 | name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}" 35 | checksum: 36 | name_template: "{{ .ProjectName }}_{{ .Version }}_SHA256SUMS" 37 | algorithm: sha256 38 | signs: 39 | - artifacts: checksum 40 | args: 41 | # if you are using this is a GitHub action or some other automated pipeline, you 42 | # need to pass the batch flag to indicate its not interactive. 43 | - "--batch" 44 | - "--local-user" 45 | - "{{ .Env.GPG_FINGERPRINT }}" # set this environment variable for your signing key 46 | - "--output" 47 | - "${signature}" 48 | - "--detach-sign" 49 | - "${artifact}" 50 | release: 51 | # If you want to manually examine the release before its live, uncomment this line: 52 | # draft: true 53 | changelog: 54 | skip: true -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Deno Land Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | HOSTNAME=github.com 2 | NAMESPACE=wperron 3 | NAME=deploy 4 | BINARY=terraform-provider-${NAME} 5 | VERSION=0.3.1 6 | OS_ARCH=linux_amd64 7 | 8 | default: install 9 | 10 | build: 11 | go build -o ${BINARY} 12 | 13 | install: build 14 | mkdir -p ~/.terraform.d/plugins/${HOSTNAME}/${NAMESPACE}/${NAME}/${VERSION}/${OS_ARCH} 15 | mv ${BINARY} ~/.terraform.d/plugins/${HOSTNAME}/${NAMESPACE}/${NAME}/${VERSION}/${OS_ARCH} 16 | 17 | release: 18 | GOOS=darwin GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_darwin_amd64 19 | GOOS=freebsd GOARCH=386 go build -o ./bin/${BINARY}_${VERSION}_freebsd_386 20 | GOOS=freebsd GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_freebsd_amd64 21 | GOOS=freebsd GOARCH=arm go build -o ./bin/${BINARY}_${VERSION}_freebsd_arm 22 | GOOS=linux GOARCH=386 go build -o ./bin/${BINARY}_${VERSION}_linux_386 23 | GOOS=linux GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_linux_amd64 24 | GOOS=linux GOARCH=arm go build -o ./bin/${BINARY}_${VERSION}_linux_arm 25 | GOOS=openbsd GOARCH=386 go build -o ./bin/${BINARY}_${VERSION}_openbsd_386 26 | GOOS=openbsd GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_openbsd_amd64 27 | GOOS=solaris GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_solaris_amd64 28 | GOOS=windows GOARCH=386 go build -o ./bin/${BINARY}_${VERSION}_windows_386 29 | GOOS=windows GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_windows_amd64 30 | 31 | fmt: 32 | gofmt -l . 33 | dprint fmt 34 | 35 | lint: tools 36 | golangci-lint run ./... 37 | 38 | testacc: 39 | TF_ACC=1 go test ./... -v -count=1 40 | 41 | docscheck: tools 42 | @tfproviderdocs check \ 43 | -allowed-resource-subcategories-file website/allowed-subcategories.txt \ 44 | -require-resource-subcategory 45 | 46 | tools: 47 | cd tools && go install github.com/bflad/tfproviderdocs 48 | cd tools && go install github.com/golangci/golangci-lint/cmd/golangci-lint 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # terraform-deploy-provider 2 | 3 | Terraform provider for Deno Deploy 4 | 5 | ## Installation 6 | 7 | You can download the latest release binary from the release page or build from 8 | source using `make install`. 9 | 10 | ## Prerequisites 11 | 12 | - [Go](https://golang.org) version 1.16 or above 13 | - [Terraform](https://terraform.io) version 0.14.5 or above 14 | - [Golangci-lint](https://golangci-lint.run/) 15 | - [Dprint](https://dprint.dev) 16 | -------------------------------------------------------------------------------- /client/client.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Deno Land Inc. All rights reserved. MIT License. 2 | package client 3 | 4 | import ( 5 | "encoding/json" 6 | "fmt" 7 | "io" 8 | "io/ioutil" 9 | "log" 10 | "net/http" 11 | "net/url" 12 | "path" 13 | ) 14 | 15 | var ( 16 | baseURL, _ = url.Parse("https://dash.deno.com") 17 | ) 18 | 19 | // Client is a simple wrapper around the std HTTP client used for the Deploy sdk. 20 | type Client struct { 21 | HTTPClient *http.Client 22 | Token string 23 | } 24 | 25 | // PageOptions defines the parameters used when requesting a paginated resource. 26 | type PageOptions struct { 27 | Page int 28 | Limit int 29 | } 30 | 31 | // PagingInfo is the structure returned by the API for paginated resources. 32 | type PagingInfo struct { 33 | Page int `json:"page"` 34 | Count int `json:"count"` 35 | Limit int `json:"limit"` 36 | TotalCount int `json:"totalCount"` 37 | TotalPages int `json:"totalPages"` 38 | } 39 | 40 | // New returns a pointer to a new instance of the Deploy sdk 41 | func New(token string) *Client { 42 | return &Client{ 43 | HTTPClient: http.DefaultClient, 44 | Token: token, 45 | } 46 | } 47 | 48 | func (c *Client) request(method, requestPath string, query url.Values, body io.Reader, responseStruct interface{}) error { 49 | r, err := c.newRequest(method, requestPath, query, body) 50 | if err != nil { 51 | return err 52 | } 53 | 54 | resp, err := c.HTTPClient.Do(r) 55 | if err != nil { 56 | return err 57 | } 58 | defer resp.Body.Close() 59 | 60 | bodyContents, err := ioutil.ReadAll(resp.Body) 61 | if err != nil { 62 | return err 63 | } 64 | 65 | if resp.StatusCode >= 400 { 66 | return fmt.Errorf("status: %d, body: %v", resp.StatusCode, string(bodyContents)) 67 | } 68 | 69 | if responseStruct == nil { 70 | return nil 71 | } 72 | 73 | err = json.Unmarshal(bodyContents, responseStruct) 74 | if err != nil { 75 | return err 76 | } 77 | 78 | return nil 79 | } 80 | 81 | func (c *Client) newRequest(method, requestPath string, query url.Values, body io.Reader) (*http.Request, error) { 82 | url := *baseURL 83 | url.Path = path.Join(url.Path, requestPath) 84 | url.RawQuery = query.Encode() 85 | req, err := http.NewRequest(method, url.String(), body) 86 | if err != nil { 87 | return req, err 88 | } 89 | 90 | if c.Token != "" { 91 | req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", c.Token)) 92 | } 93 | 94 | req.Header.Add("Content-Type", "application/json") 95 | log.Printf("[DEBUG] deploy sdk doing request %+v", req) 96 | return req, err 97 | } 98 | -------------------------------------------------------------------------------- /client/github.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Deno Land Inc. All rights reserved. MIT License. 2 | package client 3 | 4 | import ( 5 | "bytes" 6 | "encoding/json" 7 | ) 8 | 9 | // LinkProjectRequest is the expected request body schema for the LinkProject 10 | // function. 11 | type LinkProjectRequest struct { 12 | ProjectID string `json:"projectId"` 13 | Organization string `json:"organization"` 14 | Repo string `json:"repo"` 15 | Entrypoint string `json:"entrypoint"` 16 | } 17 | 18 | func (c *Client) LinkProject(req LinkProjectRequest) (Project, error) { 19 | bs, err := json.Marshal(req) 20 | if err != nil { 21 | return Project{}, nil 22 | } 23 | 24 | res := Project{} 25 | err = c.request("POST", "/api/github/link", nil, bytes.NewBuffer(bs), &res) 26 | if err != nil { 27 | return res, err 28 | } 29 | 30 | return res, nil 31 | } 32 | -------------------------------------------------------------------------------- /client/project.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Deno Land Inc. All rights reserved. MIT License. 2 | package client 3 | 4 | import ( 5 | "bytes" 6 | "encoding/json" 7 | "errors" 8 | "fmt" 9 | "log" 10 | "net/url" 11 | ) 12 | 13 | // A Project represents a Deploy project. 14 | // 15 | // Projects can be linked to a public GitHub repository or point directly to a 16 | // publicly accessible URL. The Project resource contains certain global 17 | // settings like the name of the project, domain names and environment variables. 18 | // Projects are made up of Deployments. Every time the source URL is updated or 19 | // a commit is pushed to the default branch on GitHub, a new Deployment is 20 | // created and the 'production' deployment is updated. 21 | // 22 | // The ProductionDeployment property is a pointer to the Deployment object that 23 | // represents the latest version of the project. When a project is first created 24 | // this value is nil and HasProductionDeployment is set to `false`. 25 | // 26 | // The Git property is only set if the project is linked to a GitHub repository, 27 | // otherwise it is nil. 28 | // 29 | // A Project also has a circular reference to a Deployment. The Deployment 30 | // property is only set when accessing the Project directly in the API, 31 | // otherwise it is omitted. 32 | type Project struct { 33 | ID string `json:"id"` 34 | Name string `json:"name"` 35 | Git *GitHubLink `json:"git,omitempty"` 36 | ProductionDeployment *Deployment `json:"productionDeployment,omitempty"` 37 | HasProductionDeployment bool `json:"hasProductionDeployment"` 38 | EnvVars EnvVars `json:"envVars"` 39 | UpdatedAt string `json:"updatedAt"` 40 | CreatedAt string `json:"createdAt"` 41 | } 42 | 43 | // EnvVars is a simple map used to created environment variables in a Project. 44 | type EnvVars []string 45 | 46 | // A GitHubLink is used in a Project to link it to a GitHub repository. it 47 | // contains a Repository struct and an entrypoint corresponding to the source 48 | // code file used as the entrypoint of the project. 49 | type GitHubLink struct { 50 | Repository Repository `json:"repository"` 51 | Entrypoint string `json:"entrypoint"` 52 | UpdatedAt string `json:"updatedAt"` 53 | CreatedAt string `json:"createdAt"` 54 | } 55 | 56 | // A Repository is a simple structure containing the information identifying the 57 | // GitHub repository. 58 | type Repository struct { 59 | ID int `json:"id"` 60 | Owner string `json:"owner"` 61 | Name string `json:"name"` 62 | } 63 | 64 | // A Deployment is an immutable version of a Project's source code. 65 | // 66 | // Each Deployment contains a URL to the source code's entrypoint, the auto 67 | // generated domain name that was created for the Deployment and a copy of the 68 | // environment variables of the project when the Deployment was created. 69 | // 70 | // If the project is linked to a GitHub repository, it will also contain a 71 | // CommitInfo containing the summary of the commit. 72 | // 73 | // A Deployment also has a circular reference to a Project. The Project property 74 | // is only set when accessing the Deployment directly in the API, otherwise it 75 | // is omitted. 76 | type Deployment struct { 77 | ID string `json:"id"` 78 | URL string `json:"url"` 79 | DomainMappings []DomainMapping `json:"domainMappings"` 80 | RelatedCommit *CommitInfo `json:"relatedCommit,omitempty"` 81 | Project *Project `json:"project"` 82 | ProjectID string `json:"projectId"` 83 | EnvVars EnvVars `json:"envVars"` 84 | UpdatedAt string `json:"updatedAt"` 85 | CreatedAt string `json:"createdAt"` 86 | } 87 | 88 | // A DomainMapping is a simple struct containing to immutable domain name of a 89 | // Deployment. 90 | type DomainMapping struct { 91 | Domain string `json:"domain"` 92 | UpdatedAt string `json:"updatedAt"` 93 | CreatedAt string `json:"createdAt"` 94 | } 95 | 96 | // A CommitInfo is used for Projects linked to a GitHub repository. It contains 97 | // the information about the commit that triggered a new Deployment for the 98 | // Project. 99 | type CommitInfo struct { 100 | Hash string `json:"hash"` 101 | Message string `json:"message"` 102 | AuthorName string `json:"authorName"` 103 | AuthorEmail string `json:"authorEmail"` 104 | AuthorGitHubUsername string `json:"authorGithubUsername,omitempty"` 105 | URL string `json:"url,omitempty"` 106 | } 107 | 108 | // A Domain is a custom domain name for a Project. 109 | type Domain struct { 110 | Domain string `json:"domain"` 111 | Token string `json:"token,omitempty"` 112 | IsValidated bool `json:"isValidated,omitempty"` 113 | Certificates []Certificate `json:"certificates,omitempty"` 114 | ProvisioningAttempts []ProvisioningAttempt `json:"provisioningAttempts,omitempty"` 115 | ProjectID string `json:"projectId,omitempty"` 116 | UpdatedAt string `json:"updatedAt,omitempty"` 117 | CreatedAt string `json:"createdAt,omitempty"` 118 | } 119 | 120 | // Possible values for the Certificates property of the Domain struct 121 | const ( 122 | TLSCipherRsa = "rsa" 123 | TLSCipherEc = "ec" 124 | TLSStrategyAutomatic = "automatic" 125 | TLSStrategyManual = "manual" 126 | ) 127 | 128 | type Certificate struct { 129 | Cipher string `json:"cipher"` 130 | ProvisioningStrategy string `json:"provisioningStrategy"` 131 | UpdatedAt string `json:"updatedAt"` 132 | CreatedAt string `json:"createdAt"` 133 | ExpiresAt string `json:"expiresAt"` 134 | } 135 | 136 | type ProvisioningAttempt struct { 137 | Domain string `json:"domain"` 138 | Cipher string `json:"cipher"` 139 | Error string `json:"error,omitempty"` 140 | UpdatedAt string `json:"updatedAt"` 141 | CreatedAt string `json:"createdAt"` 142 | CompletedAt string `json:"completedAt,omitempty"` 143 | } 144 | 145 | // ListProjects returns a slice of Projects owned by the current User. 146 | func (c *Client) ListProjects() ([]Project, error) { 147 | result := []Project{} 148 | err := c.request("GET", "/api/projects", nil, nil, &result) 149 | if err != nil { 150 | return result, err 151 | } 152 | 153 | return result, nil 154 | } 155 | 156 | // CreateProjectRequest is the expected request body schema for the 157 | // CreateProject function. 158 | type CreateProjectRequest struct { 159 | Name string `json:"name"` 160 | EnvVars NewEnvVars `json:"envVars"` 161 | } 162 | 163 | // NewEnvVars is the expected request body schema for the NewEnvVars function. 164 | type NewEnvVars map[string]string 165 | 166 | // CreateProject creates a new project with the given name. 167 | func (c *Client) CreateProject(name string, envVars NewEnvVars) (Project, error) { 168 | project := CreateProjectRequest{ 169 | Name: name, 170 | EnvVars: envVars, 171 | } 172 | 173 | bs, err := json.Marshal(project) 174 | if err != nil { 175 | return Project{}, err 176 | } 177 | 178 | res := Project{} 179 | err = c.request("POST", "/api/projects", nil, bytes.NewBuffer(bs), &res) 180 | if err != nil { 181 | return res, err 182 | } 183 | 184 | return res, nil 185 | } 186 | 187 | // UpdateProjectRequest is the expected request body schema for the 188 | // UpdateProject function. 189 | type UpdateProjectRequest struct { 190 | Name string `json:"name"` 191 | } 192 | 193 | // UpdateProject modifies an existing Project. 194 | func (c *Client) UpdateProject(projectID string, newName string) error { 195 | path := fmt.Sprintf("/api/projects/%s", projectID) 196 | project := UpdateProjectRequest{ 197 | Name: newName, 198 | } 199 | 200 | bs, err := json.Marshal(project) 201 | if err != nil { 202 | return err 203 | } 204 | 205 | return c.request("PATCH", path, nil, bytes.NewBuffer(bs), nil) 206 | } 207 | 208 | // DeleteProject deletes a Project and all of its associated Deployments. 209 | func (c *Client) DeleteProject(projectID string) error { 210 | path := fmt.Sprintf("/api/projects/%s", projectID) 211 | return c.request("DELETE", path, nil, nil, nil) 212 | } 213 | 214 | // GetProject returns the information about a given Project. 215 | func (c *Client) GetProject(projectID string) (Project, error) { 216 | path := fmt.Sprintf("/api/projects/%s", projectID) 217 | result := Project{} 218 | log.Printf("[DEBUG] GET %s", path) 219 | err := c.request("GET", path, nil, nil, &result) 220 | if err != nil { 221 | log.Printf("[DEBUG] Could not find project: %s", err) 222 | return result, err 223 | } 224 | 225 | bs, _ := json.Marshal(result) 226 | log.Printf("[DEBUG] GET Project response body: %s", string(bs)) 227 | 228 | return result, nil 229 | } 230 | 231 | // NewDeploymentRequest is the expected request body schema for the 232 | // NewProjectDeployment function. 233 | type NewDeploymentRequest struct { 234 | URL string `json:"url"` 235 | Production bool `json:"production,omitempty"` 236 | } 237 | 238 | // NewProjectDeployment creates a new Deployment for a Project. The URL param 239 | // is the URL of the source code used for the deployment. The URL needs to be 240 | // publicly available. 241 | // 242 | // Note that this function is not needed to create a new Deployment for a 243 | // Project linked to a GitHub repository. 244 | func (c *Client) NewProjectDeployment(projectID string, depl NewDeploymentRequest) (Deployment, error) { 245 | path := fmt.Sprintf("/api/projects/%s/deployments", projectID) 246 | 247 | bs, err := json.Marshal(depl) 248 | if err != nil { 249 | return Deployment{}, err 250 | } 251 | 252 | res := Deployment{} 253 | err = c.request("POST", path, nil, bytes.NewBuffer(bs), &res) 254 | if err != nil { 255 | return res, err 256 | } 257 | 258 | return res, nil 259 | } 260 | 261 | // ListDeployments returns a slice of Deployments owned by the current User for 262 | // a given Project. 263 | func (c *Client) ListDeployments(projectID string, pageOpts PageOptions) ([]Deployment, PagingInfo, error) { 264 | path := fmt.Sprintf("/api/projects/%s/deployments", projectID) 265 | // expected []Deployment at position 0 and PagingInfo at position 1 266 | result := []interface{}{} 267 | 268 | qs := url.Values{} 269 | if pageOpts.Page != 0 { 270 | qs.Set("page", fmt.Sprint(pageOpts.Page)) 271 | } 272 | if pageOpts.Limit != 0 { 273 | qs.Set("limit", fmt.Sprint(pageOpts.Limit)) 274 | } 275 | 276 | err := c.request("GET", path, qs, nil, &result) 277 | if err != nil { 278 | return []Deployment{}, PagingInfo{}, err 279 | } 280 | 281 | return result[0].([]Deployment), result[1].(PagingInfo), nil 282 | } 283 | 284 | // GetDeployment returns the information about a given Deployment. 285 | func (c *Client) GetDeployment(projectID string, deploymentID string) (Deployment, error) { 286 | path := fmt.Sprintf("/api/projects/%s/deployments/%s", projectID, deploymentID) 287 | result := Deployment{} 288 | err := c.request("GET", path, nil, nil, &result) 289 | if err != nil { 290 | return result, err 291 | } 292 | 293 | return result, nil 294 | } 295 | 296 | // GetLogs returns the log lines from a given Deployment 297 | func (c *Client) GetLogs(projectID string, deploymentID string) (interface{}, error) { 298 | return nil, errors.New("unimplemented") 299 | } 300 | 301 | // UpdateEnvVars overwrites the environment variables of a given Project. 302 | func (c *Client) UpdateEnvVars(projectID string, newVars NewEnvVars) error { 303 | path := fmt.Sprintf("/api/projects/%s/env", projectID) 304 | 305 | bs, err := json.Marshal(newVars) 306 | if err != nil { 307 | return err 308 | } 309 | 310 | return c.request("POST", path, nil, bytes.NewBuffer(bs), nil) 311 | } 312 | 313 | // Unlink removes the GitHub integration of a given project. 314 | // 315 | // This only affects future Deployments. Any active Deployment that was created 316 | // when the GitHub repository was linked will still be active. 317 | func (c *Client) Unlink(projectID string) error { 318 | path := fmt.Sprintf("/api/projects/%s/git", projectID) 319 | return c.request("DELETE", path, nil, nil, nil) 320 | } 321 | 322 | // ListDomains returns a list of all the custom domain names associated to the 323 | // Project. 324 | func (c *Client) ListDomains(projectID string) ([]Domain, error) { 325 | path := fmt.Sprintf("/api/projects/%s/domains", projectID) 326 | result := []Domain{} 327 | err := c.request("GET", path, nil, nil, &result) 328 | if err != nil { 329 | return result, err 330 | } 331 | 332 | return result, nil 333 | } 334 | 335 | // AddDomain adds a custom domain name to the project. This is typically 336 | // followed by the VerifyDomain function 337 | func (c *Client) AddDomain(projectID string, newDomain Domain) (Domain, error) { 338 | path := fmt.Sprintf("/api/projects/%s/domains", projectID) 339 | 340 | bs, err := json.Marshal(newDomain) 341 | if err != nil { 342 | return Domain{}, err 343 | } 344 | 345 | result := Domain{} 346 | err = c.request("POST", path, nil, bytes.NewBuffer(bs), &result) 347 | if err != nil { 348 | return result, err 349 | } 350 | 351 | return result, nil 352 | } 353 | 354 | // GetDomain returns the information about a given custom domain name. 355 | // 356 | // This is typically used to retrieve the information about the different 357 | // records that must be created by the user to properly verify the domain. 358 | func (c *Client) GetDomain(projectID, domainName string) (Domain, error) { 359 | path := fmt.Sprintf("/api/projects/%s/domains/%s", projectID, domainName) 360 | result := Domain{} 361 | err := c.request("GET", path, nil, nil, &result) 362 | if err != nil { 363 | return result, err 364 | } 365 | 366 | return result, nil 367 | } 368 | 369 | // DeleteDomain removes a custom domain name associated with a project. 370 | // 371 | // This action only removes the custom domain name resolution on the Deploy side. 372 | // The DNS records will still have to be removed on the user's registrar. 373 | func (c *Client) DeleteDomain(projectID, domainName string) error { 374 | path := fmt.Sprintf("/api/projects/%s/domains/%s", projectID, domainName) 375 | return c.request("DELETE", path, nil, nil, nil) 376 | } 377 | 378 | // VerifyDomain sends the signal to Deploy to verify the DNS records for custom 379 | // domain names. The DNS records must exist prior to starting the verification 380 | // process. Deploy will not create these for you. 381 | func (c *Client) VerifyDomain(projectID, domainName string) error { 382 | path := fmt.Sprintf("/api/projects/%s/domains/%s/verify", projectID, domainName) 383 | return c.request("POST", path, nil, nil, nil) 384 | } 385 | 386 | // ProvisionCertificateAutomatic automatically provisions a valid TLS 387 | // certificate for a custom domain name. 388 | func (c *Client) ProvisionCertificateAutomatic(projectID, domainName string) error { 389 | path := fmt.Sprintf("/api/projects/%s/domains/%s/certificates", projectID, domainName) 390 | bs, err := json.Marshal(map[string]string{"strategy": "automatic"}) 391 | if err != nil { 392 | return err 393 | } 394 | return c.request("POST", path, nil, bytes.NewBuffer(bs), nil) 395 | } 396 | 397 | // ProvisionCertificateManual adds a custom TLS certificate for a custom domain 398 | // name. 399 | func (c *Client) ProvisionCertificateManual(projectID, domainName string, certificateChain string, privateKey string) error { 400 | path := fmt.Sprintf("/api/projects/%s/domains/%s/certificates", projectID, domainName) 401 | bs, err := json.Marshal(map[string]string{"strategy": "manual", "certificateChain": certificateChain, "privateKey": privateKey}) 402 | if err != nil { 403 | return err 404 | } 405 | return c.request("POST", path, nil, bytes.NewBuffer(bs), nil) 406 | } 407 | -------------------------------------------------------------------------------- /client/user.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Deno Land Inc. All rights reserved. MIT License. 2 | package client 3 | 4 | import ( 5 | "time" 6 | ) 7 | 8 | // A User of the Deploy platform. 9 | type User struct { 10 | ID string `json:"id"` 11 | Login string `json:"login"` 12 | Name string `json:"name"` 13 | AvatarURL string `json:"avatarUrl"` 14 | GitHubID int `json:"githubId"` 15 | IsAdmin bool `json:"isAdmin"` 16 | IsBlocked bool `json:"isBlocked"` 17 | UpdatedAt time.Time `json:"updatedAt"` 18 | CreatedAt time.Time `json:"createdAt"` 19 | } 20 | 21 | // CurrentUser returns the currently signed in User, the owner of the Token used 22 | // by the client sdk. 23 | func (c *Client) CurrentUser() (User, error) { 24 | result := User{} 25 | err := c.request("GET", "/api/user", nil, nil, &result) 26 | if err != nil { 27 | return result, err 28 | } 29 | 30 | return result, nil 31 | } 32 | -------------------------------------------------------------------------------- /deploy/data_source_user.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Deno Land Inc. All rights reserved. MIT License. 2 | package deploy 3 | 4 | import ( 5 | "fmt" 6 | "log" 7 | 8 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 9 | "github.com/wperron/terraform-deploy-provider/client" 10 | ) 11 | 12 | func dataSourceUser() *schema.Resource { 13 | return &schema.Resource{ 14 | Read: dataSourceUserRead, 15 | Schema: map[string]*schema.Schema{ 16 | "id": { 17 | Type: schema.TypeString, 18 | Computed: true, 19 | }, 20 | "name": { 21 | Type: schema.TypeString, 22 | Computed: true, 23 | }, 24 | "github_id": { 25 | Type: schema.TypeString, 26 | Computed: true, 27 | Optional: true, 28 | }, 29 | }, 30 | } 31 | } 32 | 33 | func dataSourceUserRead(d *schema.ResourceData, m interface{}) error { 34 | c := m.(*client.Client) 35 | 36 | res, err := c.CurrentUser() 37 | 38 | if err != nil { 39 | return fmt.Errorf("error getting Current User: %w", err) 40 | } 41 | 42 | log.Printf("[DEBUG] Received Caller Identity: %s %s", res.ID, res.Name) 43 | 44 | d.SetId(res.ID) 45 | if err := d.Set("id", res.ID); err != nil { 46 | return err 47 | } 48 | if err := d.Set("name", res.Name); err != nil { 49 | return err 50 | } 51 | if err := d.Set("github_id", fmt.Sprint(res.GitHubID)); err != nil { 52 | return err 53 | } 54 | 55 | return nil 56 | } 57 | -------------------------------------------------------------------------------- /deploy/data_source_user_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Deno Land Inc. All rights reserved. MIT License. 2 | package deploy 3 | 4 | import ( 5 | "fmt" 6 | "testing" 7 | 8 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" 9 | "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" 10 | "github.com/wperron/terraform-deploy-provider/client" 11 | ) 12 | 13 | func TestAccUser_basic(t *testing.T) { 14 | resource.ParallelTest(t, resource.TestCase{ 15 | PreCheck: func() { testAccPreCheck(t) }, 16 | Providers: testAccProviders, 17 | Steps: []resource.TestStep{ 18 | { 19 | Config: testAccDeployUserConfig_basic, 20 | Check: resource.ComposeTestCheckFunc( 21 | testAccCheckDeployCurrentUser("data.deploy_user.current"), 22 | ), 23 | }, 24 | }, 25 | }) 26 | } 27 | 28 | func testAccCheckDeployCurrentUser(n string) resource.TestCheckFunc { 29 | return func(s *terraform.State) error { 30 | rs, ok := s.RootModule().Resources[n] 31 | if !ok { 32 | return fmt.Errorf("can't find current user: %s", n) 33 | } 34 | 35 | if rs.Primary.ID == "" { 36 | return fmt.Errorf("user ID resource ID not set.") 37 | } 38 | 39 | expected, err := testAccProvider.Meta().(*client.Client).CurrentUser() 40 | if err != nil { 41 | return fmt.Errorf("failed to get current user: %s", err) 42 | } 43 | if rs.Primary.Attributes["id"] != expected.ID { 44 | return fmt.Errorf("incorrect user ID: expected %q, got %q", expected.ID, rs.Primary.Attributes["id"]) 45 | } 46 | 47 | if rs.Primary.Attributes["name"] == "" { 48 | return fmt.Errorf("username expected to not be nil") 49 | } 50 | 51 | if rs.Primary.Attributes["github_id"] == "" { 52 | return fmt.Errorf("GitHub ID expected to not be nil") 53 | } 54 | 55 | return nil 56 | } 57 | } 58 | 59 | const testAccDeployUserConfig_basic = ` 60 | data "deploy_user" "current" {} 61 | ` 62 | -------------------------------------------------------------------------------- /deploy/provider.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Deno Land Inc. All rights reserved. MIT License. 2 | package deploy 3 | 4 | import ( 5 | "context" 6 | 7 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 8 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 9 | "github.com/wperron/terraform-deploy-provider/client" 10 | ) 11 | 12 | // Provider for Deno Deploy 13 | func Provider() *schema.Provider { 14 | return &schema.Provider{ 15 | Schema: map[string]*schema.Schema{ 16 | "api_token": { 17 | Type: schema.TypeString, 18 | Required: true, 19 | DefaultFunc: schema.EnvDefaultFunc("DEPLOY_TOKEN", nil), 20 | Description: "API Token used for accessing Deno Deploy", 21 | }, 22 | }, 23 | ResourcesMap: map[string]*schema.Resource{ 24 | "deploy_project": resourceProject(), 25 | "deploy_custom_domain": resourceCustomDomain(), 26 | "deploy_custom_domain_validation": resourceCustomDomainValidation(), 27 | }, 28 | DataSourcesMap: map[string]*schema.Resource{ 29 | "deploy_user": dataSourceUser(), 30 | }, 31 | ConfigureContextFunc: providerConfigure, 32 | } 33 | } 34 | 35 | func providerConfigure(ctx context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) { 36 | token := d.Get("api_token").(string) 37 | 38 | // Warning or errors can be collected in a slice type 39 | var diags diag.Diagnostics 40 | 41 | c := client.New(token) 42 | 43 | return c, diags 44 | } 45 | -------------------------------------------------------------------------------- /deploy/provider_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Deno Land Inc. All rights reserved. MIT License. 2 | package deploy 3 | 4 | import ( 5 | "fmt" 6 | "testing" 7 | 8 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" 9 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 10 | ) 11 | 12 | var testAccProviders map[string]*schema.Provider 13 | var testAccProvider *schema.Provider 14 | var providerConfig string 15 | 16 | func init() { 17 | testAccProvider = Provider() 18 | testAccProviders = map[string]*schema.Provider{ 19 | "deploy": testAccProvider, 20 | } 21 | 22 | providerConfig = fmt.Sprintf(` 23 | provider "deploy" { 24 | api_token = "%s" 25 | } 26 | `, testToken) 27 | } 28 | 29 | func TestProvider(t *testing.T) { 30 | if err := Provider().InternalValidate(); err != nil { 31 | t.Fatalf("err: %s", err) 32 | } 33 | } 34 | 35 | func TestProvider_impl(t *testing.T) { 36 | var _ *schema.Provider = Provider() 37 | } 38 | 39 | func TestAccProviderConfigure(t *testing.T) { 40 | resource.Test(t, resource.TestCase{ 41 | PreCheck: func() {}, 42 | Providers: testAccProviders, 43 | Steps: []resource.TestStep{ 44 | { 45 | Config: providerConfig, 46 | ExpectNonEmptyPlan: false, 47 | }, 48 | }, 49 | }) 50 | } 51 | -------------------------------------------------------------------------------- /deploy/provider_utils.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Deno Land Inc. All rights reserved. MIT License. 2 | package deploy 3 | 4 | import ( 5 | "os" 6 | "testing" 7 | ) 8 | 9 | var testToken string = os.Getenv("DEPLOY_TOKEN") 10 | 11 | func testAccPreCheck(t *testing.T) { 12 | if v := os.Getenv("DEPLOY_TOKEN"); v == "" { 13 | t.Fatal("DEPLOY_TOKEN must be set for acceptance tests") 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /deploy/resource_custom_domain.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Deno Land Inc. All rights reserved. MIT License. 2 | package deploy 3 | 4 | import ( 5 | "fmt" 6 | 7 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 8 | "github.com/wperron/terraform-deploy-provider/client" 9 | ) 10 | 11 | func resourceCustomDomain() *schema.Resource { 12 | return &schema.Resource{ 13 | Create: createCustomDomain, 14 | Read: readCustomDomain, 15 | Delete: deleteCustomDomain, 16 | // TODO(wperron) implement Importer 17 | Schema: map[string]*schema.Schema{ 18 | "project_id": { 19 | Type: schema.TypeString, 20 | Required: true, 21 | ForceNew: true, 22 | }, 23 | "domain_name": { 24 | Type: schema.TypeString, 25 | Required: true, 26 | ForceNew: true, 27 | }, 28 | "records": { 29 | Type: schema.TypeList, 30 | Computed: true, 31 | Elem: &schema.Resource{ 32 | Schema: map[string]*schema.Schema{ 33 | "domain_name": { 34 | Type: schema.TypeString, 35 | Computed: true, 36 | Elem: &schema.Schema{Type: schema.TypeString}, 37 | }, 38 | "type": { 39 | Type: schema.TypeString, 40 | Computed: true, 41 | Elem: &schema.Schema{Type: schema.TypeString}, 42 | }, 43 | "value": { 44 | Type: schema.TypeString, 45 | Computed: true, 46 | Elem: &schema.Schema{Type: schema.TypeString}, 47 | }, 48 | }, 49 | }, 50 | }, 51 | "is_validated": { 52 | Type: schema.TypeBool, 53 | Computed: true, 54 | }, 55 | }, 56 | } 57 | } 58 | 59 | func createCustomDomain(d *schema.ResourceData, meta interface{}) error { 60 | c := meta.(*client.Client) 61 | project := d.Get("project_id").(string) 62 | domain := d.Get("domain_name").(string) 63 | 64 | if _, err := c.AddDomain(project, client.Domain{ 65 | Domain: domain, 66 | }); err != nil { 67 | return err 68 | } 69 | 70 | d.SetId(domain) 71 | return readCustomDomain(d, meta) 72 | } 73 | 74 | func readCustomDomain(d *schema.ResourceData, meta interface{}) error { 75 | c := meta.(*client.Client) 76 | domain, err := c.GetDomain(d.Get("project_id").(string), d.Get("domain_name").(string)) 77 | if err != nil { 78 | return err 79 | } 80 | 81 | if err := d.Set("records", []map[string]interface{}{ 82 | { 83 | "domain_name": domain.Domain, 84 | "type": "A", 85 | "value": "34.120.54.55", 86 | }, 87 | { 88 | "domain_name": domain.Domain, 89 | "type": "AAAA", 90 | "value": "2600:1901:0:6d85::", 91 | }, 92 | { 93 | "domain_name": domain.Domain, 94 | "type": "TXT", 95 | "value": fmt.Sprintf("deno-com-validation=%s", domain.Token), 96 | }, 97 | }); err != nil { 98 | return err 99 | } 100 | 101 | if err := d.Set("is_validated", domain.IsValidated); err != nil { 102 | return err 103 | } 104 | return nil 105 | } 106 | 107 | func deleteCustomDomain(d *schema.ResourceData, meta interface{}) error { 108 | c := meta.(*client.Client) 109 | return c.DeleteDomain(d.Get("project_id").(string), d.Id()) 110 | } 111 | -------------------------------------------------------------------------------- /deploy/resource_custom_domain_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Deno Land Inc. All rights reserved. MIT License. 2 | package deploy 3 | 4 | import ( 5 | "fmt" 6 | "testing" 7 | 8 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" 9 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" 10 | "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" 11 | "github.com/wperron/terraform-deploy-provider/client" 12 | ) 13 | 14 | func TestAccCustomDomain_basic(t *testing.T) { 15 | randomID := acctest.RandStringFromCharSet(4, acctest.CharSetAlphaNum) 16 | 17 | config := fmt.Sprintf(testAccCustomDomainConfig_basic, randomID, randomID) 18 | randomDomain := fmt.Sprintf("foo-%s.example.org", randomID) 19 | 20 | var project client.Project 21 | var domain client.Domain 22 | resource.Test(t, resource.TestCase{ 23 | PreCheck: func() { testAccPreCheck(t) }, 24 | Providers: testAccProviders, 25 | CheckDestroy: testAccCustomDomainCheckDestroy(&project, &domain), 26 | Steps: []resource.TestStep{ 27 | { 28 | Config: config, 29 | Check: resource.ComposeTestCheckFunc( 30 | testAccCustomDomainCheckExists("deploy_custom_domain.test", &project, &domain), 31 | resource.TestCheckResourceAttrSet( 32 | "deploy_custom_domain.test", "project_id", 33 | ), 34 | resource.TestCheckResourceAttr( 35 | "deploy_custom_domain.test", "domain_name", randomDomain, 36 | ), 37 | resource.TestCheckResourceAttr( 38 | "deploy_custom_domain.test", "is_validated", "false", 39 | ), 40 | // TODO(wperron) figure out how to do this check properly 41 | // resource.TestCheckTypeSetElemNestedAttrs( 42 | // "deploy_custom_domain.test", "records.*", map[string]string{ 43 | // "domain_name": randomDomain, 44 | // "type": "*", 45 | // "value": "*", 46 | // }, 47 | // ), 48 | ), 49 | }, 50 | }, 51 | }) 52 | } 53 | 54 | func testAccCustomDomainCheckExists(rn string, p *client.Project, d *client.Domain) resource.TestCheckFunc { 55 | return func(s *terraform.State) error { 56 | rs, ok := s.RootModule().Resources[rn] 57 | if !ok { 58 | return fmt.Errorf("resource not found: %s", rn) 59 | } 60 | if rs.Primary.ID == "" { 61 | return fmt.Errorf("resource id not set") 62 | } 63 | domain := string(rs.Primary.ID) 64 | 65 | projectID, ok := rs.Primary.Attributes["project_id"] 66 | if !ok { 67 | return fmt.Errorf("property `project_id` is not set") 68 | } 69 | client := testAccProvider.Meta().(*client.Client) 70 | project, err := client.GetProject(projectID) 71 | if err != nil { 72 | return fmt.Errorf("failed to get project info: %s", err) 73 | } 74 | customDomain, err := client.GetDomain(project.ID, domain) 75 | if err != nil { 76 | return fmt.Errorf("error getting data source: %s", err) 77 | } 78 | if customDomain.Domain == "" { 79 | return fmt.Errorf("custom domain has no domain name") 80 | } 81 | *d = customDomain 82 | return nil 83 | } 84 | } 85 | 86 | func testAccCustomDomainCheckDestroy(p *client.Project, d *client.Domain) resource.TestCheckFunc { 87 | return func(s *terraform.State) error { 88 | client := testAccProvider.Meta().(*client.Client) 89 | domain, err := client.GetDomain(p.ID, d.Domain) 90 | if err == nil && domain.Domain != "" { 91 | return fmt.Errorf("project still exists") 92 | } 93 | return nil 94 | } 95 | } 96 | 97 | const testAccCustomDomainConfig_basic = ` 98 | resource "deploy_project" "test" { 99 | name = "terraform-test-%s" 100 | source_url = "https://dash.deno.com/examples/hello.js" 101 | } 102 | 103 | resource "deploy_custom_domain" "test" { 104 | project_id = deploy_project.test.id 105 | domain_name = "foo-%s.example.org" 106 | } 107 | ` 108 | -------------------------------------------------------------------------------- /deploy/resource_custom_domain_validation.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Deno Land Inc. All rights reserved. MIT License. 2 | package deploy 3 | 4 | import ( 5 | "errors" 6 | 7 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 8 | "github.com/wperron/terraform-deploy-provider/client" 9 | ) 10 | 11 | func resourceCustomDomainValidation() *schema.Resource { 12 | return &schema.Resource{ 13 | Create: createCustomDomainValidation, 14 | Read: readCustomDomainValidation, 15 | Delete: deleteCustomDomainValidation, 16 | Schema: map[string]*schema.Schema{ 17 | "project_id": { 18 | Type: schema.TypeString, 19 | ForceNew: true, 20 | Required: true, 21 | }, 22 | "custom_domain": { 23 | Type: schema.TypeString, 24 | ForceNew: true, 25 | Required: true, 26 | }, 27 | }, 28 | } 29 | } 30 | 31 | func createCustomDomainValidation(d *schema.ResourceData, meta interface{}) error { 32 | c := meta.(*client.Client) 33 | projectID := d.Get("project_id").(string) 34 | domainName := d.Get("custom_domain").(string) 35 | domain, err := c.GetDomain(projectID, domainName) 36 | if err != nil { 37 | return err 38 | } 39 | 40 | if err := c.VerifyDomain(projectID, domainName); err != nil { 41 | return err 42 | } 43 | 44 | if err := c.ProvisionCertificateAutomatic(projectID, domainName); err != nil { 45 | return err 46 | } 47 | 48 | d.SetId(domain.CreatedAt) 49 | return readCustomDomainValidation(d, meta) 50 | } 51 | 52 | func readCustomDomainValidation(d *schema.ResourceData, meta interface{}) error { 53 | c := meta.(*client.Client) 54 | projectID := d.Get("project_id").(string) 55 | domainName := d.Get("custom_domain").(string) 56 | domain, err := c.GetDomain(projectID, domainName) 57 | if err != nil { 58 | return err 59 | } 60 | 61 | if !domain.IsValidated || len(domain.Certificates) == 0 { 62 | return errors.New("domain is either not validated or does not have any certificates") 63 | } 64 | return nil 65 | } 66 | 67 | func deleteCustomDomainValidation(d *schema.ResourceData, meta interface{}) error { 68 | // since this is a logical resource, there's nothing to delete. 69 | return nil 70 | } 71 | -------------------------------------------------------------------------------- /deploy/resource_project.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Deno Land Inc. All rights reserved. MIT License. 2 | package deploy 3 | 4 | import ( 5 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 6 | "github.com/wperron/terraform-deploy-provider/client" 7 | ) 8 | 9 | func resourceProject() *schema.Resource { 10 | return &schema.Resource{ 11 | Create: createProject, 12 | Read: readProject, 13 | Update: updateProject, 14 | Delete: deleteProject, 15 | Exists: existsProject, 16 | // TODO(wperron) implement Importer 17 | Schema: map[string]*schema.Schema{ 18 | "project_id": { 19 | Type: schema.TypeString, 20 | Computed: true, 21 | }, 22 | "name": { 23 | Type: schema.TypeString, 24 | Required: true, 25 | }, 26 | "source_url": { 27 | Type: schema.TypeString, 28 | Optional: true, 29 | ConflictsWith: []string{"github_link"}, 30 | }, 31 | "github_link": { 32 | Type: schema.TypeList, 33 | MaxItems: 1, 34 | Optional: true, 35 | ConflictsWith: []string{"source_url"}, 36 | Elem: &schema.Resource{ 37 | Schema: map[string]*schema.Schema{ 38 | "organization": { 39 | Type: schema.TypeString, 40 | Required: true, 41 | Elem: &schema.Schema{Type: schema.TypeString}, 42 | }, 43 | "repo": { 44 | Type: schema.TypeString, 45 | Required: true, 46 | Elem: &schema.Schema{Type: schema.TypeString}, 47 | }, 48 | "entrypoint": { 49 | Type: schema.TypeString, 50 | Required: true, 51 | Elem: &schema.Schema{Type: schema.TypeString}, 52 | }, 53 | }, 54 | }, 55 | }, 56 | "production_deployment": { 57 | Type: schema.TypeList, 58 | Computed: true, 59 | Optional: true, 60 | MaxItems: 1, 61 | Elem: &schema.Resource{ 62 | Schema: map[string]*schema.Schema{ 63 | "id": { 64 | Type: schema.TypeString, 65 | Required: true, 66 | Elem: &schema.Schema{Type: schema.TypeString}, 67 | }, 68 | "url": { 69 | Type: schema.TypeString, 70 | Required: true, 71 | Elem: &schema.Schema{Type: schema.TypeString}, 72 | }, 73 | "domain_mappings": { 74 | Type: schema.TypeList, 75 | Required: true, 76 | Elem: &schema.Schema{ 77 | Type: schema.TypeMap, 78 | Elem: &schema.Schema{Type: schema.TypeString}, 79 | }, 80 | }, 81 | "related_commit": { 82 | Type: schema.TypeList, 83 | MaxItems: 1, 84 | Optional: true, 85 | Elem: &schema.Resource{ 86 | Schema: map[string]*schema.Schema{ 87 | "hash": { 88 | Type: schema.TypeString, 89 | Required: true, 90 | Elem: &schema.Schema{Type: schema.TypeString}, 91 | }, 92 | "message": { 93 | Type: schema.TypeString, 94 | Required: true, 95 | Elem: &schema.Schema{Type: schema.TypeString}, 96 | }, 97 | "author_name": { 98 | Type: schema.TypeString, 99 | Required: true, 100 | Elem: &schema.Schema{Type: schema.TypeString}, 101 | }, 102 | "author_email": { 103 | Type: schema.TypeString, 104 | Required: true, 105 | Elem: &schema.Schema{Type: schema.TypeString}, 106 | }, 107 | "author_github_username": { 108 | Type: schema.TypeString, 109 | Required: true, 110 | Elem: &schema.Schema{Type: schema.TypeString}, 111 | }, 112 | "url": { 113 | Type: schema.TypeString, 114 | Required: true, 115 | Elem: &schema.Schema{Type: schema.TypeString}, 116 | }, 117 | }, 118 | }, 119 | }, 120 | "env_var": { 121 | Type: schema.TypeList, 122 | Optional: true, 123 | Elem: &schema.Schema{Type: schema.TypeString}, 124 | }, 125 | "updated_at": { 126 | Type: schema.TypeString, 127 | Required: true, 128 | Elem: &schema.Schema{Type: schema.TypeString}, 129 | }, 130 | "created_at": { 131 | Type: schema.TypeString, 132 | Required: true, 133 | Elem: &schema.Schema{Type: schema.TypeString}, 134 | }, 135 | }, 136 | }, 137 | }, 138 | "has_production_deployment": { 139 | Type: schema.TypeBool, 140 | Computed: true, 141 | }, 142 | "env_var": { 143 | Type: schema.TypeList, 144 | Optional: true, 145 | Elem: &schema.Resource{ 146 | Schema: map[string]*schema.Schema{ 147 | "key": { 148 | Type: schema.TypeString, 149 | Required: true, 150 | Elem: &schema.Schema{Type: schema.TypeString}, 151 | }, 152 | "value": { 153 | Type: schema.TypeString, 154 | Required: true, 155 | Sensitive: true, 156 | Elem: &schema.Schema{Type: schema.TypeString}, 157 | }, 158 | }, 159 | }, 160 | }, 161 | }, 162 | } 163 | } 164 | 165 | func createProject(d *schema.ResourceData, meta interface{}) error { 166 | c := meta.(*client.Client) 167 | name := d.Get("name").(string) 168 | vars := make(client.NewEnvVars) 169 | tmp := d.Get("env_var").([]interface{}) 170 | for _, v := range tmp { 171 | keyval := v.(map[string]interface{}) 172 | vars[keyval["key"].(string)] = keyval["value"].(string) 173 | } 174 | 175 | project, err := c.CreateProject(name, vars) 176 | if err != nil { 177 | return err 178 | } 179 | 180 | if source, ok := d.GetOk("source_url"); ok { 181 | if _, err := c.NewProjectDeployment(project.ID, client.NewDeploymentRequest{ 182 | URL: source.(string), 183 | Production: true, 184 | }); err != nil { 185 | return err 186 | } 187 | } else if gh, ok := d.GetOk("github_link"); ok { 188 | ghLinkList := gh.([]interface{}) 189 | ghLink := ghLinkList[0].(map[string]interface{}) 190 | if _, err := c.LinkProject(client.LinkProjectRequest{ 191 | ProjectID: project.ID, 192 | Organization: ghLink["organization"].(string), 193 | Repo: ghLink["repo"].(string), 194 | Entrypoint: ghLink["entrypoint"].(string), 195 | }); err != nil { 196 | return err 197 | } 198 | } 199 | 200 | d.SetId(project.ID) 201 | return readProject(d, meta) 202 | } 203 | 204 | func readProject(d *schema.ResourceData, meta interface{}) error { 205 | c := meta.(*client.Client) 206 | project, err := c.GetProject(d.Id()) 207 | if err != nil { 208 | return err 209 | } 210 | 211 | if project.ProductionDeployment != nil { 212 | if err := d.Set("production_deployment", productionDeploymentToTerraformSchema(project.ProductionDeployment)); err != nil { 213 | return err 214 | } 215 | if source, ok := d.GetOk("source_url"); ok && source != project.ProductionDeployment.URL { 216 | if err := d.Set("source_url", project.ProductionDeployment.URL); err != nil { 217 | return err 218 | } 219 | } 220 | } 221 | if err := d.Set("has_production_deployment", project.HasProductionDeployment); err != nil { 222 | return err 223 | } 224 | 225 | if project.Git != nil { 226 | if err := d.Set("github_link", []map[string]interface{}{ 227 | { 228 | "organization": project.Git.Repository.Owner, 229 | "repo": project.Git.Repository.Name, 230 | "entrypoint": project.Git.Entrypoint, 231 | }, 232 | }); err != nil { 233 | return err 234 | } 235 | } 236 | return nil 237 | } 238 | 239 | func updateProject(d *schema.ResourceData, meta interface{}) error { 240 | c := meta.(*client.Client) 241 | if d.HasChange("name") { 242 | name := d.Get("name").(string) 243 | if err := c.UpdateProject(d.Id(), name); err != nil { 244 | return err 245 | } 246 | } 247 | 248 | if d.HasChange("env_var") { 249 | vars := make(client.NewEnvVars) 250 | tmp := d.Get("env_var").([]interface{}) 251 | for _, v := range tmp { 252 | keyval := v.(map[string]interface{}) 253 | vars[keyval["key"].(string)] = keyval["value"].(string) 254 | } 255 | 256 | if err := c.UpdateEnvVars(d.Id(), vars); err != nil { 257 | return err 258 | } 259 | } 260 | 261 | if d.HasChange("source_url") { 262 | if source, ok := d.GetOk("source_url"); ok { 263 | if _, err := c.NewProjectDeployment(d.Id(), client.NewDeploymentRequest{ 264 | URL: source.(string), 265 | Production: true, 266 | }); err != nil { 267 | return err 268 | } 269 | } 270 | } 271 | 272 | if d.HasChange("github_link") { 273 | if gh, ok := d.GetOk("github_link"); ok { 274 | ghLinkList := gh.([]interface{}) 275 | ghLink := ghLinkList[0].(map[string]interface{}) 276 | if _, err := c.LinkProject(client.LinkProjectRequest{ 277 | ProjectID: d.Id(), 278 | Organization: ghLink["organization"].(string), 279 | Repo: ghLink["repo"].(string), 280 | Entrypoint: ghLink["entrypoint"].(string), 281 | }); err != nil { 282 | return err 283 | } 284 | } else if o, n := d.GetChange("github_link"); len(o.([]interface{})) == 1 && len(n.([]interface{})) == 0 { 285 | // if the new value is empty but the old value is not, it means the 286 | // block was removed and the repo should be unlinked 287 | if err := c.Unlink(d.Id()); err != nil { 288 | return err 289 | } 290 | } 291 | } 292 | 293 | return readProject(d, meta) 294 | } 295 | 296 | func deleteProject(d *schema.ResourceData, meta interface{}) error { 297 | c := meta.(*client.Client) 298 | return c.DeleteProject(d.Id()) 299 | } 300 | 301 | func existsProject(d *schema.ResourceData, meta interface{}) (bool, error) { 302 | c := meta.(*client.Client) 303 | if _, err := c.GetProject(d.Id()); err != nil { 304 | return false, err 305 | } 306 | return true, nil 307 | } 308 | 309 | func productionDeploymentToTerraformSchema(depl *client.Deployment) []interface{} { 310 | if depl == nil { 311 | return nil 312 | } 313 | 314 | tfMap := map[string]interface{}{} 315 | tfMap["id"] = depl.ID 316 | tfMap["url"] = depl.URL 317 | domains := []interface{}{} 318 | for _, domain := range depl.DomainMappings { 319 | domains = append(domains, map[string]interface{}{ 320 | "domain": domain.Domain, 321 | "updated_at": domain.UpdatedAt, 322 | "created_at": domain.CreatedAt, 323 | }) 324 | } 325 | tfMap["domain_mappings"] = domains 326 | 327 | if depl.RelatedCommit != nil { 328 | tfMap["related_commit"] = []map[string]interface{}{ 329 | { 330 | "hash": depl.RelatedCommit.Hash, 331 | "message": depl.RelatedCommit.Message, 332 | "author_name": depl.RelatedCommit.AuthorName, 333 | "author_email": depl.RelatedCommit.AuthorEmail, 334 | "author_github_username": depl.RelatedCommit.AuthorGitHubUsername, 335 | "url": depl.RelatedCommit.URL, 336 | }, 337 | } 338 | } 339 | 340 | // vars := []map[string]interface{}{} 341 | // for k, v := range depl.EnvVars { 342 | // vars = append(vars, map[string]interface{}{ 343 | // "key": k, 344 | // "value": v, 345 | // }) 346 | // } 347 | tfMap["env_var"] = depl.EnvVars 348 | tfMap["updated_at"] = depl.UpdatedAt 349 | tfMap["created_at"] = depl.CreatedAt 350 | 351 | return []interface{}{tfMap} 352 | } 353 | -------------------------------------------------------------------------------- /deploy/resource_project_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Deno Land Inc. All rights reserved. MIT License. 2 | package deploy 3 | 4 | import ( 5 | "fmt" 6 | "testing" 7 | 8 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" 9 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" 10 | "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" 11 | "github.com/wperron/terraform-deploy-provider/client" 12 | ) 13 | 14 | func TestAccProject_basic(t *testing.T) { 15 | randomID := acctest.RandStringFromCharSet(4, acctest.CharSetAlphaNum) 16 | 17 | config := fmt.Sprintf(testAccProjectConfig_basic, randomID) 18 | updated := fmt.Sprintf(testAccProjectConfig_update, randomID) 19 | 20 | var project client.Project 21 | source := "https://dash.deno.com/examples/hello.js" 22 | resource.Test(t, resource.TestCase{ 23 | PreCheck: func() { testAccPreCheck(t) }, 24 | Providers: testAccProviders, 25 | CheckDestroy: testAccProjectCheckDestroy(&project), 26 | Steps: []resource.TestStep{ 27 | { 28 | Config: config, 29 | Check: resource.ComposeTestCheckFunc( 30 | testAccProjectCheckExists("deploy_project.test", &project), 31 | resource.TestCheckResourceAttr( 32 | "deploy_project.test", "name", fmt.Sprintf("terraform-test-%s", randomID), 33 | ), 34 | resource.TestCheckResourceAttr( 35 | "deploy_project.test", "has_production_deployment", "false", 36 | ), 37 | resource.TestCheckResourceAttrSet( 38 | "deploy_project.test", "id", 39 | ), 40 | ), 41 | }, 42 | { 43 | Config: updated, 44 | Check: resource.ComposeTestCheckFunc( 45 | testAccProjectCheckExists("deploy_project.test", &project), 46 | resource.TestCheckResourceAttr( 47 | "deploy_project.test", "name", fmt.Sprintf("terraform-test-%s", randomID), 48 | ), 49 | resource.TestCheckResourceAttr( 50 | "deploy_project.test", "has_production_deployment", "true", 51 | ), 52 | resource.TestCheckResourceAttr( 53 | "deploy_project.test", "source_url", "https://dash.deno.com/examples/hello.js", 54 | ), 55 | resource.TestCheckResourceAttrSet( 56 | "deploy_project.test", "id", 57 | ), 58 | testAccProjectDeployment(&project, testProductionDeployment{ 59 | SourceUrl: &source, 60 | EnvVars: make(client.NewEnvVars), 61 | }), 62 | ), 63 | }, 64 | }, 65 | }) 66 | } 67 | 68 | func TestAccProject_envVars(t *testing.T) { 69 | randomID := acctest.RandStringFromCharSet(4, acctest.CharSetAlphaNum) 70 | 71 | config := fmt.Sprintf(testAccProjectConfig_envVars, randomID) 72 | 73 | var project client.Project 74 | source := "https://dash.deno.com/examples/hello.js" 75 | resource.Test(t, resource.TestCase{ 76 | PreCheck: func() { testAccPreCheck(t) }, 77 | Providers: testAccProviders, 78 | CheckDestroy: testAccProjectCheckDestroy(&project), 79 | Steps: []resource.TestStep{ 80 | { 81 | Config: config, 82 | Check: resource.ComposeTestCheckFunc( 83 | testAccProjectCheckExists("deploy_project.test", &project), 84 | resource.TestCheckResourceAttr( 85 | "deploy_project.test", "name", fmt.Sprintf("terraform-test-%s", randomID), 86 | ), 87 | resource.TestCheckResourceAttr( 88 | "deploy_project.test", "has_production_deployment", "true", 89 | ), 90 | resource.TestCheckResourceAttrSet( 91 | "deploy_project.test", "id", 92 | ), 93 | testAccProjectDeployment(&project, testProductionDeployment{ 94 | SourceUrl: &source, 95 | EnvVars: client.NewEnvVars{ 96 | "foo": "bar", 97 | "fruit": "banana", 98 | }, 99 | }), 100 | ), 101 | }, 102 | }, 103 | }) 104 | } 105 | 106 | func TestAccProject_github(t *testing.T) { 107 | randomID := acctest.RandStringFromCharSet(4, acctest.CharSetAlphaNum) 108 | 109 | config := fmt.Sprintf(testAccProjectConfig_github, randomID) 110 | 111 | var project client.Project 112 | resource.Test(t, resource.TestCase{ 113 | PreCheck: func() { testAccPreCheck(t) }, 114 | Providers: testAccProviders, 115 | CheckDestroy: testAccProjectCheckDestroy(&project), 116 | Steps: []resource.TestStep{ 117 | { 118 | Config: config, 119 | Check: resource.ComposeTestCheckFunc( 120 | testAccProjectCheckExists("deploy_project.test", &project), 121 | resource.TestCheckResourceAttr( 122 | "deploy_project.test", "name", fmt.Sprintf("terraform-test-%s", randomID), 123 | ), 124 | resource.TestCheckResourceAttr( 125 | "deploy_project.test", "has_production_deployment", "true", 126 | ), 127 | resource.TestCheckResourceAttrSet( 128 | "deploy_project.test", "id", 129 | ), 130 | testAccProjectDeployment(&project, testProductionDeployment{ 131 | EnvVars: make(client.NewEnvVars), 132 | GitHub: &testGitHub{ 133 | Org: "wperron", 134 | Repo: "terraform-deploy-provider", 135 | Entrypoint: "/deploy/testdata/main.ts", 136 | }, 137 | }), 138 | ), 139 | }, 140 | }, 141 | }) 142 | } 143 | 144 | func TestAccProject_linkAndUnlink(t *testing.T) { 145 | randomID := acctest.RandStringFromCharSet(4, acctest.CharSetAlphaNum) 146 | 147 | config := fmt.Sprintf(testAccProjectConfig_update, randomID) 148 | linked := fmt.Sprintf(testAccProjectConfig_github, randomID) 149 | 150 | var project client.Project 151 | source := "https://dash.deno.com/examples/hello.js" 152 | resource.Test(t, resource.TestCase{ 153 | PreCheck: func() { testAccPreCheck(t) }, 154 | Providers: testAccProviders, 155 | CheckDestroy: testAccProjectCheckDestroy(&project), 156 | Steps: []resource.TestStep{ 157 | { 158 | Config: config, 159 | Check: resource.ComposeTestCheckFunc( 160 | testAccProjectCheckExists("deploy_project.test", &project), 161 | resource.TestCheckResourceAttr( 162 | "deploy_project.test", "name", fmt.Sprintf("terraform-test-%s", randomID), 163 | ), 164 | resource.TestCheckResourceAttr( 165 | "deploy_project.test", "has_production_deployment", "true", 166 | ), 167 | resource.TestCheckResourceAttrSet( 168 | "deploy_project.test", "id", 169 | ), 170 | testAccProjectDeployment(&project, testProductionDeployment{ 171 | SourceUrl: &source, 172 | EnvVars: make(client.NewEnvVars), 173 | }), 174 | ), 175 | }, 176 | { 177 | Config: linked, 178 | Check: resource.ComposeTestCheckFunc( 179 | testAccProjectCheckExists("deploy_project.test", &project), 180 | resource.TestCheckResourceAttr( 181 | "deploy_project.test", "name", fmt.Sprintf("terraform-test-%s", randomID), 182 | ), 183 | resource.TestCheckResourceAttr( 184 | "deploy_project.test", "has_production_deployment", "true", 185 | ), 186 | resource.TestCheckResourceAttrSet( 187 | "deploy_project.test", "id", 188 | ), 189 | testAccProjectDeployment(&project, testProductionDeployment{ 190 | EnvVars: make(client.NewEnvVars), 191 | GitHub: &testGitHub{ 192 | Org: "wperron", 193 | Repo: "terraform-deploy-provider", 194 | Entrypoint: "/deploy/testdata/main.ts", 195 | }, 196 | }), 197 | ), 198 | }, 199 | { 200 | Config: config, 201 | Check: resource.ComposeTestCheckFunc( 202 | testAccProjectCheckExists("deploy_project.test", &project), 203 | resource.TestCheckResourceAttr( 204 | "deploy_project.test", "name", fmt.Sprintf("terraform-test-%s", randomID), 205 | ), 206 | resource.TestCheckResourceAttr( 207 | "deploy_project.test", "has_production_deployment", "true", 208 | ), 209 | resource.TestCheckResourceAttrSet( 210 | "deploy_project.test", "id", 211 | ), 212 | testAccProjectDeployment(&project, testProductionDeployment{ 213 | SourceUrl: &source, 214 | EnvVars: make(client.NewEnvVars), 215 | GitHub: nil, 216 | }), 217 | ), 218 | }, 219 | }, 220 | }) 221 | } 222 | 223 | func testAccProjectCheckExists(rn string, p *client.Project) resource.TestCheckFunc { 224 | return func(s *terraform.State) error { 225 | rs, ok := s.RootModule().Resources[rn] 226 | if !ok { 227 | return fmt.Errorf("resource not found: %s", rn) 228 | } 229 | if rs.Primary.ID == "" { 230 | return fmt.Errorf("resource id not set") 231 | } 232 | id := string(rs.Primary.ID) 233 | client := testAccProvider.Meta().(*client.Client) 234 | project, err := client.GetProject(id) 235 | if err != nil { 236 | return fmt.Errorf("error getting data source: %s", err) 237 | } 238 | if project.ID == "" { 239 | return fmt.Errorf("project has no ID") 240 | } 241 | *p = project 242 | return nil 243 | } 244 | } 245 | 246 | func testAccProjectCheckDestroy(p *client.Project) resource.TestCheckFunc { 247 | return func(s *terraform.State) error { 248 | client := testAccProvider.Meta().(*client.Client) 249 | project, err := client.GetProject(p.ID) 250 | if err == nil && project.Name != "" { 251 | return fmt.Errorf("project still exists") 252 | } 253 | return nil 254 | } 255 | } 256 | 257 | type testProductionDeployment struct { 258 | SourceUrl *string 259 | EnvVars client.NewEnvVars 260 | GitHub *testGitHub 261 | } 262 | 263 | type testGitHub struct { 264 | Org string 265 | Repo string 266 | Entrypoint string 267 | } 268 | 269 | func testAccProjectDeployment(p *client.Project, expected testProductionDeployment) resource.TestCheckFunc { 270 | return func(s *terraform.State) error { 271 | if p == nil { 272 | return fmt.Errorf("cannot check production deployment: project does not exist") 273 | } 274 | if p.ProductionDeployment == nil { 275 | return fmt.Errorf("no production deployment found") 276 | } 277 | if !includes(p.ProductionDeployment.EnvVars, "DENO_DEPLOYMENT_ID") { 278 | return fmt.Errorf("production deployment doesn't have a `DENO_DEPLOYMENT_ID` environment variable") 279 | } 280 | if expected.SourceUrl != nil && *expected.SourceUrl != p.ProductionDeployment.URL { 281 | return fmt.Errorf("expected production deployment with a source url %s, found %s", *expected.SourceUrl, p.ProductionDeployment.URL) 282 | } 283 | if len(expected.EnvVars) > 0 { 284 | for k := range expected.EnvVars { 285 | if !includes(p.ProductionDeployment.EnvVars, k) { 286 | return fmt.Errorf("could not find the expected %s environment variable", k) 287 | } 288 | } 289 | } 290 | if expected.GitHub != nil { 291 | if p.Git == nil { 292 | return fmt.Errorf("expected github %s/%s%s to be linked, found none", expected.GitHub.Org, expected.GitHub.Repo, expected.GitHub.Entrypoint) 293 | } 294 | if p.ProductionDeployment.RelatedCommit == nil { 295 | return fmt.Errorf("expected production deployment to have a related commit, found none") 296 | } 297 | } 298 | return nil 299 | } 300 | } 301 | 302 | const testAccProjectConfig_basic = ` 303 | resource "deploy_project" "test" { 304 | name = "terraform-test-%s" 305 | } 306 | ` 307 | 308 | const testAccProjectConfig_update = ` 309 | resource "deploy_project" "test" { 310 | name = "terraform-test-%s" 311 | source_url = "https://dash.deno.com/examples/hello.js" 312 | } 313 | ` 314 | 315 | const testAccProjectConfig_envVars = ` 316 | resource "deploy_project" "test" { 317 | name = "terraform-test-%s" 318 | source_url = "https://dash.deno.com/examples/hello.js" 319 | 320 | env_var { 321 | key = "foo" 322 | value = "bar" 323 | } 324 | 325 | env_var { 326 | key = "fruit" 327 | value = "banana" 328 | } 329 | } 330 | ` 331 | 332 | const testAccProjectConfig_github = ` 333 | resource "deploy_project" "test" { 334 | name = "terraform-test-%s" 335 | github_link { 336 | organization = "wperron" 337 | repo = "terraform-deploy-provider" 338 | entrypoint = "/deploy/testdata/main.ts" 339 | } 340 | } 341 | ` 342 | 343 | func includes(l []string, s string) bool { 344 | for _, e := range l { 345 | if e == s { 346 | return true 347 | } 348 | } 349 | return false 350 | } 351 | -------------------------------------------------------------------------------- /deploy/testdata/main.ts: -------------------------------------------------------------------------------- 1 | addEventListener("fetch", (event) => { 2 | event.respondWith(new Response("OK")); 3 | }); -------------------------------------------------------------------------------- /dprint.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://dprint.dev/schemas/v0.json", 3 | "projectType": "openSource", 4 | "incremental": true, 5 | "markdown": { 6 | }, 7 | "includes": ["**/*.{md}"], 8 | "excludes": [ 9 | 10 | ], 11 | "plugins": [ 12 | "https://plugins.dprint.dev/markdown-0.7.0.wasm" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/wperron/terraform-deploy-provider 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/aws/aws-sdk-go v1.37.0 // indirect 7 | github.com/hashicorp/hcl/v2 v2.8.2 // indirect 8 | github.com/hashicorp/terraform-plugin-sdk/v2 v2.6.1 9 | github.com/mattn/go-colorable v0.1.8 // indirect 10 | golang.org/x/tools v0.0.0-20201028111035-eafbe7b904eb // indirect 11 | google.golang.org/api v0.34.0 // indirect 12 | ) 13 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= 4 | cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= 5 | cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= 6 | cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= 7 | cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= 8 | cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= 9 | cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= 10 | cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= 11 | cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= 12 | cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= 13 | cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= 14 | cloud.google.com/go v0.61.0/go.mod h1:XukKJg4Y7QsUu0Hxg3qQKUWR4VuWivmyMK2+rUyxAqw= 15 | cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= 16 | cloud.google.com/go v0.65.0 h1:Dg9iHVQfrhq82rUNu9ZxUDrJLaxFUe/HlCVaLyRruq8= 17 | cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= 18 | cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= 19 | cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= 20 | cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= 21 | cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= 22 | cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= 23 | cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= 24 | cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= 25 | cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= 26 | cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= 27 | cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= 28 | cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= 29 | cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= 30 | cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= 31 | cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= 32 | cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= 33 | cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= 34 | cloud.google.com/go/storage v1.10.0 h1:STgFzyU5/8miMl0//zKh2aQeTyeaUH3WN9bSUiJ09bA= 35 | cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= 36 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= 37 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 38 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 39 | github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= 40 | github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= 41 | github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= 42 | github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= 43 | github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= 44 | github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= 45 | github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= 46 | github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= 47 | github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= 48 | github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0= 49 | github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= 50 | github.com/andybalholm/crlf v0.0.0-20171020200849-670099aa064f/go.mod h1:k8feO4+kXDxro6ErPXBRTJ/ro2mf0SsFG8s7doP9kJE= 51 | github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= 52 | github.com/apparentlymart/go-cidr v1.0.1 h1:NmIwLZ/KdsjIUlhf+/Np40atNXm/+lZ5txfTJ/SpF+U= 53 | github.com/apparentlymart/go-cidr v1.0.1/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= 54 | github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= 55 | github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0 h1:MzVXffFUye+ZcSR6opIgz9Co7WcDx6ZcY+RjfFHoA0I= 56 | github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= 57 | github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0= 58 | github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= 59 | github.com/apparentlymart/go-textseg/v12 v12.0.0 h1:bNEQyAGak9tojivJNkoqWErVCQbjdL7GzRt3F8NvfJ0= 60 | github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= 61 | github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= 62 | github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= 63 | github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= 64 | github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= 65 | github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM= 66 | github.com/aws/aws-sdk-go v1.25.3/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= 67 | github.com/aws/aws-sdk-go v1.37.0 h1:GzFnhOIsrGyQ69s7VgqtrG2BG8v7X7vwB3Xpbd/DBBk= 68 | github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= 69 | github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= 70 | github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= 71 | github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= 72 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 73 | github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= 74 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 75 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= 76 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 77 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 78 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 79 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 80 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 81 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 82 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 83 | github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= 84 | github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= 85 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 86 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 87 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 88 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 89 | github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= 90 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= 91 | github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= 92 | github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= 93 | github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= 94 | github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= 95 | github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= 96 | github.com/go-git/go-billy/v5 v5.1.0 h1:4pl5BV4o7ZG/lterP4S6WzJ6xr49Ba5ET9ygheTYahk= 97 | github.com/go-git/go-billy/v5 v5.1.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= 98 | github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw= 99 | github.com/go-git/go-git/v5 v5.3.0 h1:8WKMtJR2j8RntEXR/uvTKagfEt4GYlwQ7mntE4+0GWc= 100 | github.com/go-git/go-git/v5 v5.3.0/go.mod h1:xdX4bWJ48aOrdhnl2XqHYstHbbp6+LFS4r4X+lNVprw= 101 | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= 102 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 103 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 104 | github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= 105 | github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= 106 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 107 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 108 | github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 109 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= 110 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 111 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 112 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 113 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= 114 | github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 115 | github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 116 | github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 117 | github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= 118 | github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 119 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 120 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 121 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 122 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 123 | github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 124 | github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= 125 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 126 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 127 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 128 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 129 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 130 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 131 | github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= 132 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 133 | github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 134 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 135 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 136 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 137 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 138 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 139 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 140 | github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 141 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 142 | github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 143 | github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 144 | github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 145 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 146 | github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= 147 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 148 | github.com/google/martian/v3 v3.0.0 h1:pMen7vLs8nvgEYhywH3KDWJIJTeEr2ULsVWHWYHQyBs= 149 | github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 150 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 151 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 152 | github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 153 | github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 154 | github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 155 | github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 156 | github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 157 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 158 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 159 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= 160 | github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= 161 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= 162 | github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= 163 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 164 | github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU= 165 | github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg= 166 | github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= 167 | github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= 168 | github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= 169 | github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI= 170 | github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs= 171 | github.com/hashicorp/go-getter v1.5.3 h1:NF5+zOlQegim+w/EUhSLh6QhXHmZMEeHLQzllkQ3ROU= 172 | github.com/hashicorp/go-getter v1.5.3/go.mod h1:BrrV/1clo8cCYu6mxvboYg+KutTiFnXjMEgDD8+i7ZI= 173 | github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= 174 | github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= 175 | github.com/hashicorp/go-hclog v0.15.0 h1:qMuK0wxsoW4D0ddCCYwPSTm4KQv1X1ke3WmPWZ0Mvsk= 176 | github.com/hashicorp/go-hclog v0.15.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= 177 | github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= 178 | github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= 179 | github.com/hashicorp/go-plugin v1.3.0/go.mod h1:F9eH4LrE/ZsRdbwhfjs9k9HoDUwAHnYtXdgmf1AVNs0= 180 | github.com/hashicorp/go-plugin v1.4.0 h1:b0O7rs5uiJ99Iu9HugEzsM67afboErkHUWddUSpUO3A= 181 | github.com/hashicorp/go-plugin v1.4.0/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ= 182 | github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= 183 | github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= 184 | github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 185 | github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= 186 | github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 187 | github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 188 | github.com/hashicorp/go-version v1.3.0 h1:McDWVJIU/y+u1BRV06dPaLfLCaT7fUTJLp5r04x7iNw= 189 | github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 190 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 191 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 192 | github.com/hashicorp/hcl/v2 v2.3.0/go.mod h1:d+FwDBbOLvpAM3Z6J7gPj/VoAGkNe/gm352ZhjJ/Zv8= 193 | github.com/hashicorp/hcl/v2 v2.8.2 h1:wmFle3D1vu0okesm8BTLVDyJ6/OL9DCLUwn0b2OptiY= 194 | github.com/hashicorp/hcl/v2 v2.8.2/go.mod h1:bQTN5mpo+jewjJgh8jr0JUguIi7qPHUF6yIfAEN3jqY= 195 | github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= 196 | github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= 197 | github.com/hashicorp/terraform-exec v0.13.3 h1:R6L2mNpDGSEqtLrSONN8Xth0xYwNrnEVzDz6LF/oJPk= 198 | github.com/hashicorp/terraform-exec v0.13.3/go.mod h1:SSg6lbUsVB3DmFyCPjBPklqf6EYGX0TlQ6QTxOlikDU= 199 | github.com/hashicorp/terraform-json v0.10.0 h1:9syPD/Y5t+3uFjG8AiWVPu1bklJD8QB8iTCaJASc8oQ= 200 | github.com/hashicorp/terraform-json v0.10.0/go.mod h1:3defM4kkMfttwiE7VakJDwCd4R+umhSQnvJwORXbprE= 201 | github.com/hashicorp/terraform-plugin-go v0.3.0 h1:AJqYzP52JFYl9NABRI7smXI1pNjgR5Q/y2WyVJ/BOZA= 202 | github.com/hashicorp/terraform-plugin-go v0.3.0/go.mod h1:dFHsQMaTLpON2gWhVWT96fvtlc/MF1vSy3OdMhWBzdM= 203 | github.com/hashicorp/terraform-plugin-sdk/v2 v2.6.1 h1:OZ+Q7irJBDhb71XzMSPGJvTIW101sOmbDg5i5qV1odY= 204 | github.com/hashicorp/terraform-plugin-sdk/v2 v2.6.1/go.mod h1:72j8cKfs9IirGhPMXJJWLTvRUK4zATtrCOvs2avDlo8= 205 | github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= 206 | github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ= 207 | github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= 208 | github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= 209 | github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 210 | github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= 211 | github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= 212 | github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= 213 | github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= 214 | github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= 215 | github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= 216 | github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= 217 | github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74= 218 | github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= 219 | github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= 220 | github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= 221 | github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= 222 | github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= 223 | github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= 224 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 225 | github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= 226 | github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= 227 | github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= 228 | github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= 229 | github.com/keybase/go-crypto v0.0.0-20161004153544-93f5b35093ba/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M= 230 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 231 | github.com/klauspost/compress v1.11.2 h1:MiK62aErc3gIiVEtyzKfeOHgW7atJb5g/KNX5m3c2nQ= 232 | github.com/klauspost/compress v1.11.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= 233 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 234 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 235 | github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= 236 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 237 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 238 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 239 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 240 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 241 | github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= 242 | github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= 243 | github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= 244 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 245 | github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= 246 | github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= 247 | github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 248 | github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 249 | github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 250 | github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 251 | github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= 252 | github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= 253 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 254 | github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 255 | github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4= 256 | github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= 257 | github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= 258 | github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 259 | github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= 260 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 261 | github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= 262 | github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= 263 | github.com/mitchellh/go-testing-interface v1.0.4 h1:ZU1VNC02qyufSZsjjs7+khruk2fKvbQ3TwRV/IBCeFA= 264 | github.com/mitchellh/go-testing-interface v1.0.4/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= 265 | github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= 266 | github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= 267 | github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= 268 | github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= 269 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 270 | github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= 271 | github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE= 272 | github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= 273 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= 274 | github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce h1:RPclfga2SEJmgMmz2k+Mg7cowZ8yv4Trqw9UsJby758= 275 | github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce/go.mod h1:uFMI8w+ref4v2r9jz+c9i1IfIttS/OkmLfrk1jne5hs= 276 | github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= 277 | github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= 278 | github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= 279 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 280 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 281 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 282 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 283 | github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= 284 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 285 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 286 | github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= 287 | github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= 288 | github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= 289 | github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= 290 | github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= 291 | github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 292 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 293 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 294 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 295 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 296 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 297 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 298 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 299 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 300 | github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ= 301 | github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= 302 | github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= 303 | github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= 304 | github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= 305 | github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= 306 | github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= 307 | github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= 308 | github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= 309 | github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 310 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 311 | github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 312 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 313 | github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= 314 | github.com/zclconf/go-cty v1.2.1/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= 315 | github.com/zclconf/go-cty v1.8.2 h1:u+xZfBKgpycDnTNjPhGiTEYZS5qS/Sb5MqSfm7vzcjg= 316 | github.com/zclconf/go-cty v1.8.2/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= 317 | github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= 318 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 319 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= 320 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 321 | go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 322 | go.opencensus.io v0.22.4 h1:LYy1Hy3MJdrCdMwwzxA/dRok4ejH+RwNGbuoD9fCjto= 323 | go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 324 | golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 325 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 326 | golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 327 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 328 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 329 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 330 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 331 | golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 332 | golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= 333 | golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= 334 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 335 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 336 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= 337 | golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= 338 | golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= 339 | golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 340 | golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 341 | golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 342 | golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= 343 | golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= 344 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 345 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 346 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 347 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 348 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 349 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 350 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 351 | golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 352 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 353 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= 354 | golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 355 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= 356 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 357 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= 358 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= 359 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 360 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= 361 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 362 | golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 363 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 364 | golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= 365 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 366 | golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 367 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 368 | golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 369 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 370 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 371 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 372 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 373 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 374 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 375 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 376 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 377 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 378 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 379 | golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 380 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 381 | golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 382 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 383 | golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 384 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 385 | golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 386 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 387 | golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 388 | golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 389 | golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 390 | golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 391 | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 392 | golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 393 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 394 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 395 | golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 396 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 397 | golang.org/x/net v0.0.0-20210326060303-6b1517762897 h1:KrsHThm5nFk34YtATK1LsThyGhGbGe1olrte/HInHvs= 398 | golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= 399 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 400 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 401 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 402 | golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 403 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 404 | golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 h1:ld7aEMNHoBnnDAX15v1T6z31v8HwR2A9FYOuAhWqkwc= 405 | golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 406 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 407 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 408 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 409 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 410 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 411 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 412 | golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 413 | golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 414 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 415 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 416 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 417 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 418 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 419 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 420 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 421 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 422 | golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 423 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 424 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 425 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 426 | golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 427 | golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 428 | golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 429 | golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 430 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 431 | golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 432 | golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 433 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 434 | golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 435 | golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 436 | golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 437 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 438 | golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 439 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 440 | golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 441 | golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 442 | golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 443 | golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 444 | golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 445 | golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 446 | golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 447 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 448 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 449 | golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 450 | golang.org/x/sys v0.0.0-20210324051608-47abb6519492 h1:Paq34FxTluEPvVyayQqMPgHm+vTOrIifmcYxFBx9TLg= 451 | golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 452 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= 453 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 454 | golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 455 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 456 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 457 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 458 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 459 | golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= 460 | golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 461 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 462 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 463 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 464 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 465 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 466 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 467 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 468 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 469 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 470 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 471 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 472 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 473 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 474 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 475 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 476 | golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 477 | golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 478 | golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 479 | golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 480 | golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 481 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 482 | golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 483 | golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 484 | golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 485 | golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 486 | golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 487 | golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 488 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 489 | golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 490 | golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 491 | golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 492 | golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 493 | golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 494 | golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= 495 | golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= 496 | golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= 497 | golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 498 | golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 499 | golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 500 | golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 501 | golang.org/x/tools v0.0.0-20200713011307-fd294ab11aed/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 502 | golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 503 | golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 504 | golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 505 | golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= 506 | golang.org/x/tools v0.0.0-20201028111035-eafbe7b904eb h1:KVWk3RW1AZlxWum4tYqegLgwJHb5oouozcGM8HfNQaw= 507 | golang.org/x/tools v0.0.0-20201028111035-eafbe7b904eb/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 508 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 509 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 510 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 511 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 512 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 513 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= 514 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= 515 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 516 | google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 517 | google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 518 | google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 519 | google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 520 | google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 521 | google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 522 | google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 523 | google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 524 | google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 525 | google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= 526 | google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= 527 | google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= 528 | google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= 529 | google.golang.org/api v0.34.0 h1:k40adF3uR+6x/+hO5Dh4ZFUqFp67vxvbpafFiJxl10A= 530 | google.golang.org/api v0.34.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= 531 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 532 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 533 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 534 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= 535 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 536 | google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= 537 | google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 538 | google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 539 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 540 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 541 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 542 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 543 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 544 | google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 545 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 546 | google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= 547 | google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 548 | google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 549 | google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 550 | google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 551 | google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 552 | google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 553 | google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= 554 | google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 555 | google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 556 | google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 557 | google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 558 | google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 559 | google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 560 | google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 561 | google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 562 | google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= 563 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 564 | google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= 565 | google.golang.org/genproto v0.0.0-20200711021454-869866162049/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 566 | google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 567 | google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 568 | google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 569 | google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d h1:92D1fum1bJLKSdr11OJ+54YeCMCGYIygTA7R/YZxH5M= 570 | google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 571 | google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= 572 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 573 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 574 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 575 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 576 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 577 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 578 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 579 | google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 580 | google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 581 | google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= 582 | google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 583 | google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 584 | google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 585 | google.golang.org/grpc v1.32.0 h1:zWTV+LMdc3kaiJMSTOFz2UgSBgx8RNQoTGiZu3fR9S0= 586 | google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 587 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 588 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 589 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 590 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 591 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 592 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 593 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 594 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 595 | google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= 596 | google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= 597 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 598 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 599 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 600 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 601 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 602 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 603 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 604 | gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= 605 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 606 | gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= 607 | gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= 608 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 609 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 610 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 611 | gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= 612 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 613 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 614 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 615 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 616 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 617 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 618 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 619 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 620 | honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 621 | honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 622 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= 623 | rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= 624 | rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= 625 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Deno Land Inc. All rights reserved. MIT License. 2 | package main 3 | 4 | import ( 5 | "github.com/hashicorp/terraform-plugin-sdk/v2/plugin" 6 | "github.com/wperron/terraform-deploy-provider/deploy" 7 | ) 8 | 9 | func main() { 10 | opts := &plugin.ServeOpts{ 11 | ProviderFunc: deploy.Provider, 12 | } 13 | 14 | plugin.Serve(opts) 15 | } 16 | -------------------------------------------------------------------------------- /tools/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/wperron/terraform-deploy-provider/tools 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/bflad/tfproviderdocs v0.9.1 7 | github.com/golangci/golangci-lint v1.39.0 8 | ) 9 | -------------------------------------------------------------------------------- /tools/tools.go: -------------------------------------------------------------------------------- 1 | // +build tools 2 | 3 | package main 4 | 5 | import ( 6 | _ "github.com/bflad/tfproviderdocs" 7 | _ "github.com/golangci/golangci-lint/cmd/golangci-lint" 8 | ) 9 | -------------------------------------------------------------------------------- /website/allowed-subcategories.txt: -------------------------------------------------------------------------------- 1 | 2 | Project -------------------------------------------------------------------------------- /website/docs/d/user.html.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | subcategory: "" 3 | layout: "deploy" 4 | page_title: "Deploy: User" 5 | description: |- 6 | Get information on the current user 7 | --- 8 | 9 | # Data Source: deploy_user 10 | 11 | This data source can be used to fetch information the owner of the token used 12 | by the provider's configuration. 13 | 14 | ## Example Usage 15 | 16 | ```terraform 17 | data "deploy_user" "current" {} 18 | 19 | output "user_id" { 20 | value = data.deploy_user.current.id 21 | } 22 | 23 | output "name" { 24 | value = data.deploy_user.current.name 25 | } 26 | 27 | output "github_id" { 28 | value = data.deploy_user.current.github_id 29 | } 30 | ``` 31 | 32 | ## Argument Reference 33 | 34 | There are no arguments available for this data source. 35 | 36 | ## Attributes Reference 37 | 38 | * `id` - The UUID of the user. 39 | * `name` - The GitHub username of the user. 40 | * `github_id` - The GitHub numeric ID of the user. -------------------------------------------------------------------------------- /website/docs/r/custom_domain.html.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | subcategory: "Project" 3 | layout: "deploy" 4 | page_title: "Deploy: custom domain" 5 | description: |- 6 | Assigns a custom domain name to a Deploy Project. 7 | --- 8 | 9 | # Resource: deploy_custom_domain 10 | 11 | Assigns a custom domain name to a Deploy Project. 12 | 13 | ## Example Usage 14 | 15 | ```terraform 16 | resource "deploy_project" "example" { 17 | name = "my-test-project" 18 | source_url = "https://dash.deno.com/examples/hello.js" 19 | } 20 | 21 | resource "deploy_custom_domain" "this" { 22 | project_id = deploy_project.this.id 23 | domain_name = "foo.example.org" 24 | } 25 | ``` 26 | 27 | ## Argument Reference 28 | 29 | The following arguments are required: 30 | 31 | * `project_id` - (Required) The project ID the domain name will be associated to. 32 | * `domain_name` - (Required) The fully-qualified domain name. 33 | 34 | ## Attributes Reference 35 | 36 | * `records` - A list of records that must be created and the values they should 37 | have for the validation process. 38 | * `is_validated` - Boolean value showing whether the domain name has been 39 | validated or not. -------------------------------------------------------------------------------- /website/docs/r/custom_domain_validation.html.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | subcategory: "Project" 3 | layout: "deploy" 4 | page_title: "Deploy: custom domain" 5 | description: |- 6 | Coordinates and waits for a custom domain to validated and provisioned with 7 | certificates. 8 | --- 9 | 10 | # Resource: deploy_custom_domain_validation 11 | 12 | This resource represents a successful validation of a custom domain name and the 13 | complete provisioning of TLS certificates for that domain. 14 | 15 | This would be used in concert with other resources such as [AWS's Route53][1], 16 | [Google DNS][2] or [CloudFlare][3] to manage the whole lifecycle of creating a 17 | new domain, adding it to Deno Deploy, creating the validation records and 18 | provisioning TLS certificates. 19 | 20 | * **WARNING:** This resource implements the validation workflow only. It does 21 | not represent a real-world resource in Deno Deploy. Changing or deleting this 22 | resource will not have any immediate effect. 23 | 24 | ## Example Usage 25 | 26 | ### DNS Validation using AWS Route53 27 | 28 | ```terraform 29 | resource "deploy_project" "this" { 30 | name = "my-test-project" 31 | source_url = "https://dash.deno.com/examples/hello.js" 32 | } 33 | 34 | resource "deploy_custom_domain" "this" { 35 | project_id = deploy_project.this.id 36 | domain_name = "foo.example.org" 37 | } 38 | 39 | data "aws_route53_zone" "this" { 40 | name = "example.org." 41 | } 42 | 43 | resource "aws_route53_record" "example" { 44 | for_each = { 45 | for domain in deploy_custom_domain.this.records : domain.type => { 46 | name = domain.domain_name 47 | value = domain.value 48 | } 49 | } 50 | 51 | allow_overwrite = true 52 | name = each.value.name 53 | records = [each.value.value] 54 | ttl = 60 55 | type = each.key 56 | zone_id = data.aws_route53_zone.this.zone_id 57 | } 58 | 59 | resource "deploy_custom_domain_validation" "this" { 60 | project_id = deploy_project.this.id 61 | custom_domain = deploy_custom_domain.this.domain_name 62 | 63 | # It's important to explicitely define the dependency on the DNS provider to 64 | # Terraform so that the resources get created in the correct order. 65 | depends_on = [aws_route53_record.example] 66 | } 67 | ``` 68 | 69 | ## Argument Reference 70 | 71 | The following arguments are required: 72 | 73 | * `project_id` - (Required) The project ID the domain name is linked to. 74 | * `custom_domain` - (Required) The custom domain name to validate. -------------------------------------------------------------------------------- /website/docs/r/project.html.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | subcategory: "Project" 3 | layout: "deploy" 4 | page_title: "Deploy: Project" 5 | description: |- 6 | Provides a Deno Deploy Project. 7 | --- 8 | 9 | # Resource: deploy_project 10 | 11 | Provides a Deno Deploy Project. 12 | 13 | ## Example Usage 14 | 15 | ### Basic Example 16 | 17 | ```terraform 18 | resource "deploy_project" "example" { 19 | name = "my-test-project" 20 | source_url = "https://dash.deno.com/examples/hello.js" 21 | } 22 | ``` 23 | 24 | ### Linking a GitHub Repo 25 | 26 | ```terraform 27 | resource "deploy_project" "example" { 28 | name = "my-test-project" 29 | github_link { 30 | organization = "username" 31 | repo = "my-repo" 32 | entrypoint = "/main.ts" 33 | } 34 | } 35 | ``` 36 | 37 | ### Environment Variables 38 | 39 | ```terraform 40 | resource "deploy_project" "example" { 41 | name = "my-test-project" 42 | source_url = "https://dash.deno.com/examples/hello.js" 43 | 44 | env_var { 45 | key = "foo" 46 | value = "bar" 47 | } 48 | 49 | env_var { 50 | key = "greeting" 51 | value = "Hello World!" 52 | } 53 | } 54 | ``` 55 | 56 | ## Argument Reference 57 | 58 | The following arguments are required: 59 | 60 | * `name` - (Required) Unique name for your project. 61 | 62 | The following arguments are optional: 63 | 64 | * `source_url` - (Optional) The URL where the entrypoint for the project is 65 | located. Conflicts with `github_link` 66 | * `github_link` - (Optional) Configuration block. Described below. Conflicts 67 | with `source_url` 68 | * `env_var` - (Optional) Configuration block. Described below. 69 | 70 | ### github_link 71 | 72 | GitHub link configuration that specifies the GitHub repository to link to the 73 | project as well as its entrypoint script. 74 | 75 | * `organization` - (Required) The name of the organization or user the 76 | repository belongs to. The current user must have admin access to the 77 | repository. 78 | * `repo` - (Required) The name of the repository. 79 | * `entrypoint` - (Required) Absolute path to the entrypoint of the project. Must 80 | start with a forward slash (`/`). 81 | 82 | ### env_var 83 | 84 | Environment variable to add to the project configuration. These are available 85 | within the script through [`Deno.env`][1] 86 | 87 | * `key` - (Required) The name of the environment variable 88 | * `value` - (Required) The value associated with the `key`. This is a sensitive 89 | value and won't show up in the logs. 90 | 91 | ## Attributes Reference 92 | 93 | In addition to all arguments above, the following attributes are exported: 94 | 95 | * `project_id` - The UUID of the project. 96 | * `production_deployment` - Detailed overview of the current production 97 | deployment of the project. 98 | * `has_production_deployment` - Boolean showing whether the project has a 99 | production deployment or not. 100 | 101 | [1]: https://doc.deno.land/builtin/stable#Deno.env --------------------------------------------------------------------------------