├── .editorconfig ├── .github ├── CODEOWNERS ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── release.yaml ├── .gitignore ├── .goreleaser.yaml ├── LICENSE ├── Makefile ├── README.md ├── docs ├── data-sources │ ├── paper_folder.md │ ├── paper_sharing_policy.md │ ├── space_usage.md │ └── user_current.md ├── index.md └── resources │ ├── file.md │ ├── file_members.md │ ├── folder.md │ ├── folder_members.md │ ├── paper_doc.md │ ├── paper_doc_users.md │ └── paper_sharing_policy.md ├── dropbox ├── config.go ├── data_source_dropbox_paper_folder.go ├── data_source_dropbox_paper_folder_test.go ├── data_source_dropbox_paper_sharing_policy.go ├── data_source_dropbox_paper_sharing_policy_test.go ├── data_source_dropbox_space_usage.go ├── data_source_dropbox_space_usage_test.go ├── data_source_dropbox_user_current.go ├── data_source_dropbox_user_current_test.go ├── provider.go ├── provider_test.go ├── resource_dropbox_file.go ├── resource_dropbox_file_members.go ├── resource_dropbox_file_test.go ├── resource_dropbox_folder.go ├── resource_dropbox_folder_members.go ├── resource_dropbox_folder_members_test.go ├── resource_dropbox_folder_test.go ├── resource_dropbox_paper_doc.go ├── resource_dropbox_paper_doc_test.go ├── resource_dropbox_paper_doc_users.go ├── resource_dropbox_paper_doc_users_test.go ├── resource_dropbox_paper_sharing_policy.go ├── resource_dropbox_paper_sharing_policy_test.go ├── validators.go └── validators_test.go ├── go.mod ├── go.sum ├── main.go └── tools └── tools.go /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 4 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @callensm 2 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 1. Go to '...' 13 | 2. Click on '....' 14 | 3. Scroll down to '....' 15 | 4. See error 16 | 17 | **Expected behavior** 18 | A clear and concise description of what you expected to happen. 19 | 20 | **Screenshots** 21 | If applicable, add screenshots to help explain your problem. 22 | 23 | **Desktop (please complete the following information):** 24 | - OS: [e.g. iOS] 25 | - Browser [e.g. chrome, safari] 26 | - Version [e.g. 22] 27 | 28 | **Smartphone (please complete the following information):** 29 | - Device: [e.g. iPhone6] 30 | - OS: [e.g. iOS8.1] 31 | - Browser [e.g. stock browser, safari] 32 | - Version [e.g. 22] 33 | 34 | **Additional context** 35 | Add any other context about the problem here. 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: release 2 | on: 3 | push: 4 | tags: 5 | - "v*" 6 | jobs: 7 | goreleaser: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout 11 | uses: actions/checkout@v2.3.4 12 | - run: git fetch --prune --unshallow 13 | - name: Setup Go 14 | uses: actions/setup-go@v2.1.4 15 | with: 16 | go-version: 1.16 17 | - name: Import GPG Key 18 | id: import_gpg 19 | uses: hashicorp/ghaction-import-gpg@v2.1.0 20 | env: 21 | GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} 22 | PASSPHRASE: ${{ secrets.PASSPHRASE }} 23 | - name: GoReleaser 24 | uses: goreleaser/goreleaser-action@v2.7.0 25 | with: 26 | version: latest 27 | args: release --rm-dist 28 | env: 29 | GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} 30 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .env 3 | 4 | bin/ 5 | vendor/ 6 | -------------------------------------------------------------------------------- /.goreleaser.yaml: -------------------------------------------------------------------------------- 1 | before: 2 | hooks: 3 | - go mod tidy 4 | builds: 5 | - env: 6 | - CGO_ENABLED=0 7 | mod_timestamp: '{{ .CommitTimestamp }}' 8 | flags: 9 | - -trimpath 10 | ldflags: 11 | - '-s -w -X main.version={{ .Version }} -X main.commit={{ .Commit }}' 12 | goos: 13 | - freebsd 14 | - windows 15 | - linux 16 | - darwin 17 | goarch: 18 | - amd64 19 | - '386' 20 | - arm 21 | - arm64 22 | ignore: 23 | - goos: darwin 24 | goarch: '386' 25 | binary: '{{ .ProjectName }}_v{{ .Version }}' 26 | archives: 27 | - format: zip 28 | name_template: '{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}' 29 | checksum: 30 | name_template: '{{ .ProjectName }}_{{ .Version }}_SHA256SUMS' 31 | algorithm: sha256 32 | signs: 33 | - artifacts: checksum 34 | args: 35 | - '--batch' 36 | - '--local-user' 37 | - '{{ .Env.GPG_FINGERPRINT }}' 38 | - '--output' 39 | - '${signature}' 40 | - '--detach-sign' 41 | - '${artifact}' 42 | changelog: 43 | skip: true 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Matthew Callens 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 | clean: 2 | rm -rf vendor/ 3 | 4 | test: vendor 5 | go test -v ./... 6 | 7 | vendor: clean 8 | go mod tidy && go mod vendor 9 | 10 | .PHONY: clean test vendor 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Terraform Dropbox Provider 2 | 3 | This Terraform provider was modeled off of the [unofficial Dropbox Golang SDK](https://github.com/dropbox/dropbox-sdk-go-unofficial). Follow the usage documentation from that repository to setup your Dropbox application and generate an access token prior to using this provider. 4 | 5 | ### Provider Usage 6 | 7 | ```hcl 8 | provider "dropbox" { 9 | access_token = "${var.token}" 10 | } 11 | ``` 12 | 13 | **access_token** is the generated auth token from Dropbox when you create an application through their developer console. It can be manually placed in the provider configuration as shown above, or if not provided, it will automatically attempt to retrieve the token value from the `DROPBOX_TOKEN` environment variable. 14 | -------------------------------------------------------------------------------- /docs/data-sources/paper_folder.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "dropbox_paper_folder Data Source - terraform-provider-dropbox" 4 | subcategory: "" 5 | description: |- 6 | 7 | --- 8 | 9 | # dropbox_paper_folder (Data Source) 10 | 11 | 12 | 13 | 14 | 15 | 16 | ## Schema 17 | 18 | ### Required 19 | 20 | - **doc_id** (String) 21 | 22 | ### Optional 23 | 24 | - **id** (String) The ID of this resource. 25 | 26 | ### Read-Only 27 | 28 | - **folders** (List of Object) List of folders that contain the document reference (see [below for nested schema](#nestedatt--folders)) 29 | 30 | 31 | ### Nested Schema for `folders` 32 | 33 | Read-Only: 34 | 35 | - **id** (String) 36 | - **name** (String) 37 | 38 | 39 | -------------------------------------------------------------------------------- /docs/data-sources/paper_sharing_policy.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "dropbox_paper_sharing_policy Data Source - terraform-provider-dropbox" 4 | subcategory: "" 5 | description: |- 6 | 7 | --- 8 | 9 | # dropbox_paper_sharing_policy (Data Source) 10 | 11 | 12 | 13 | 14 | 15 | 16 | ## Schema 17 | 18 | ### Required 19 | 20 | - **doc_id** (String) 21 | 22 | ### Optional 23 | 24 | - **id** (String) The ID of this resource. 25 | - **public_policy** (String) 26 | - **team_policy** (String) 27 | 28 | 29 | -------------------------------------------------------------------------------- /docs/data-sources/space_usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "dropbox_space_usage Data Source - terraform-provider-dropbox" 4 | subcategory: "" 5 | description: |- 6 | 7 | --- 8 | 9 | # dropbox_space_usage (Data Source) 10 | 11 | 12 | 13 | 14 | 15 | 16 | ## Schema 17 | 18 | ### Optional 19 | 20 | - **id** (String) The ID of this resource. 21 | 22 | ### Read-Only 23 | 24 | - **allocated** (Number) 25 | - **is_team_allocation** (Boolean) 26 | - **used** (Number) 27 | 28 | 29 | -------------------------------------------------------------------------------- /docs/data-sources/user_current.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "dropbox_user_current Data Source - terraform-provider-dropbox" 4 | subcategory: "" 5 | description: |- 6 | 7 | --- 8 | 9 | # dropbox_user_current (Data Source) 10 | 11 | 12 | 13 | 14 | 15 | 16 | ## Schema 17 | 18 | ### Optional 19 | 20 | - **id** (String) The ID of this resource. 21 | 22 | ### Read-Only 23 | 24 | - **account_id** (String) 25 | - **account_type** (String) 26 | - **display_name** (String) 27 | - **email** (String) 28 | 29 | 30 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "dropbox Provider" 4 | subcategory: "" 5 | description: |- 6 | 7 | --- 8 | 9 | # dropbox Provider 10 | 11 | 12 | 13 | 14 | 15 | 16 | ## Schema 17 | 18 | ### Optional 19 | 20 | - **access_token** (String, Sensitive) Dropbox API access token generated from console 21 | -------------------------------------------------------------------------------- /docs/resources/file.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "dropbox_file Resource - terraform-provider-dropbox" 4 | subcategory: "" 5 | description: |- 6 | 7 | --- 8 | 9 | # dropbox_file (Resource) 10 | 11 | 12 | 13 | 14 | 15 | 16 | ## Schema 17 | 18 | ### Required 19 | 20 | - **content** (String) 21 | - **path** (String) 22 | 23 | ### Optional 24 | 25 | - **auto_rename** (Boolean) 26 | - **id** (String) The ID of this resource. 27 | - **mode** (String) Valid formats modes: add, overwrite, and update 28 | - **mute** (Boolean) 29 | 30 | ### Read-Only 31 | 32 | - **hash** (String) A generated hash of the uploaded content 33 | - **size** (Number) The size of the uploaded data in bytes 34 | 35 | 36 | -------------------------------------------------------------------------------- /docs/resources/file_members.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "dropbox_file_members Resource - terraform-provider-dropbox" 4 | subcategory: "" 5 | description: |- 6 | 7 | --- 8 | 9 | # dropbox_file_members (Resource) 10 | 11 | 12 | 13 | 14 | 15 | 16 | ## Schema 17 | 18 | ### Required 19 | 20 | - **file_id** (String) 21 | - **members** (Set of String) 22 | 23 | ### Optional 24 | 25 | - **access_level** (String) 26 | - **id** (String) The ID of this resource. 27 | - **message** (String) 28 | - **quiet** (Boolean) 29 | 30 | 31 | -------------------------------------------------------------------------------- /docs/resources/folder.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "dropbox_folder Resource - terraform-provider-dropbox" 4 | subcategory: "" 5 | description: |- 6 | 7 | --- 8 | 9 | # dropbox_folder (Resource) 10 | 11 | 12 | 13 | 14 | 15 | 16 | ## Schema 17 | 18 | ### Required 19 | 20 | - **path** (String) 21 | 22 | ### Optional 23 | 24 | - **auto_rename** (Boolean) 25 | - **id** (String) The ID of this resource. 26 | - **property_group_templates** (List of String) List of template IDs corresponding to the associated folder property groups 27 | 28 | ### Read-Only 29 | 30 | - **folder_id** (String) 31 | - **name** (String) 32 | 33 | 34 | -------------------------------------------------------------------------------- /docs/resources/folder_members.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "dropbox_folder_members Resource - terraform-provider-dropbox" 4 | subcategory: "" 5 | description: |- 6 | 7 | --- 8 | 9 | # dropbox_folder_members (Resource) 10 | 11 | 12 | 13 | 14 | 15 | 16 | ## Schema 17 | 18 | ### Required 19 | 20 | - **folder_id** (String) 21 | - **members** (Block List, Min: 1) (see [below for nested schema](#nestedblock--members)) 22 | 23 | ### Optional 24 | 25 | - **id** (String) The ID of this resource. 26 | - **message** (String) 27 | - **quiet** (Boolean) 28 | 29 | 30 | ### Nested Schema for `members` 31 | 32 | Required: 33 | 34 | - **identity** (String) 35 | 36 | Optional: 37 | 38 | - **access_level** (String) 39 | 40 | 41 | -------------------------------------------------------------------------------- /docs/resources/paper_doc.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "dropbox_paper_doc Resource - terraform-provider-dropbox" 4 | subcategory: "" 5 | description: |- 6 | 7 | --- 8 | 9 | # dropbox_paper_doc (Resource) 10 | 11 | 12 | 13 | 14 | 15 | 16 | ## Schema 17 | 18 | ### Required 19 | 20 | - **content** (String) 21 | - **import_format** (String) Valid formats include: html, markdown, plain_text, other 22 | 23 | ### Optional 24 | 25 | - **id** (String) The ID of this resource. 26 | - **parent_folder** (String) Unique identifier for the folder used as the destination 27 | 28 | ### Read-Only 29 | 30 | - **doc_id** (String) 31 | - **revision** (Number) 32 | - **title** (String) 33 | 34 | 35 | -------------------------------------------------------------------------------- /docs/resources/paper_doc_users.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "dropbox_paper_doc_users Resource - terraform-provider-dropbox" 4 | subcategory: "" 5 | description: |- 6 | 7 | --- 8 | 9 | # dropbox_paper_doc_users (Resource) 10 | 11 | 12 | 13 | 14 | 15 | 16 | ## Schema 17 | 18 | ### Required 19 | 20 | - **doc_id** (String) 21 | - **members** (Block List, Min: 1) (see [below for nested schema](#nestedblock--members)) 22 | 23 | ### Optional 24 | 25 | - **id** (String) The ID of this resource. 26 | - **message** (String) 27 | - **quiet** (Boolean) 28 | 29 | ### Read-Only 30 | 31 | - **shared_users** (List of String) Computed list of emails of those users invited and actively sharing the document 32 | 33 | 34 | ### Nested Schema for `members` 35 | 36 | Required: 37 | 38 | - **identity** (String) 39 | 40 | Optional: 41 | 42 | - **permissions** (String) Value must be either `edit` or `view_and_comment` 43 | 44 | 45 | -------------------------------------------------------------------------------- /docs/resources/paper_sharing_policy.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "dropbox_paper_sharing_policy Resource - terraform-provider-dropbox" 4 | subcategory: "" 5 | description: |- 6 | 7 | --- 8 | 9 | # dropbox_paper_sharing_policy (Resource) 10 | 11 | 12 | 13 | 14 | 15 | 16 | ## Schema 17 | 18 | ### Required 19 | 20 | - **doc_id** (String) 21 | 22 | ### Optional 23 | 24 | - **id** (String) The ID of this resource. 25 | - **public_policy** (String) 26 | - **team_policy** (String) 27 | 28 | 29 | -------------------------------------------------------------------------------- /dropbox/config.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | db "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox" 5 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 6 | ) 7 | 8 | // ProviderConfig is passed in as meta data to all data 9 | // source and resource management functions, containing 10 | // the configuration struct for the Dropbox API 11 | type ProviderConfig struct { 12 | DropboxConfig *db.Config 13 | } 14 | 15 | func providerConfig(d *schema.ResourceData) (interface{}, error) { 16 | cfg := &ProviderConfig{ 17 | DropboxConfig: &db.Config{Token: d.Get("access_token").(string)}, 18 | } 19 | 20 | return cfg, nil 21 | } 22 | -------------------------------------------------------------------------------- /dropbox/data_source_dropbox_paper_folder.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox/paper" 7 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 8 | ) 9 | 10 | func dataSourceDropboxPaperFolder() *schema.Resource { 11 | return &schema.Resource{ 12 | Read: dataSourceDropboxPaperFolderRead, 13 | 14 | Schema: map[string]*schema.Schema{ 15 | "doc_id": { 16 | Type: schema.TypeString, 17 | Required: true, 18 | }, 19 | "folders": { 20 | Type: schema.TypeList, 21 | Computed: true, 22 | Description: "List of folders that contain the document reference", 23 | Elem: &schema.Resource{ 24 | Schema: map[string]*schema.Schema{ 25 | "id": { 26 | Type: schema.TypeString, 27 | Computed: true, 28 | }, 29 | "name": { 30 | Type: schema.TypeString, 31 | Computed: true, 32 | }, 33 | }, 34 | }, 35 | }, 36 | }, 37 | } 38 | } 39 | 40 | func dataSourceDropboxPaperFolderRead(d *schema.ResourceData, meta interface{}) error { 41 | config := meta.(*ProviderConfig).DropboxConfig 42 | client := paper.New(*config) 43 | 44 | opts := paper.NewRefPaperDoc(d.Get("doc_id").(string)) 45 | info, err := client.DocsGetFolderInfo(opts) 46 | if err != nil { 47 | return fmt.Errorf("Paper Folder Data Failure: %s", err) 48 | } 49 | 50 | outputFolders := flattenPaperFolders(info.Folders) 51 | d.SetId(fmt.Sprintf("folder_ds:%s", d.Get("doc_id").(string))) 52 | d.Set("folders", outputFolders) 53 | 54 | return nil 55 | } 56 | 57 | func flattenPaperFolders(folders []*paper.Folder) []map[string]interface{} { 58 | outputFolders := make([]map[string]interface{}, 0, len(folders)) 59 | for _, f := range folders { 60 | newFolder := make(map[string]interface{}) 61 | newFolder["id"] = f.Id 62 | newFolder["name"] = f.Name 63 | outputFolders = append(outputFolders, newFolder) 64 | } 65 | return outputFolders 66 | } 67 | -------------------------------------------------------------------------------- /dropbox/data_source_dropbox_paper_folder_test.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "testing" 7 | 8 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" 9 | "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" 10 | ) 11 | 12 | func TestAccDropboxPaperFolder(t *testing.T) { 13 | resource.Test(t, resource.TestCase{ 14 | PreCheck: func() { testAccPreCheck(t) }, 15 | Providers: testAccProviders, 16 | Steps: []resource.TestStep{ 17 | { 18 | Config: testAccDropboxPaperFolderDataConfig, 19 | Check: resource.ComposeTestCheckFunc( 20 | testAccPaperFolderExists("data.dropbox_paper_folder.foo"), 21 | ), 22 | }, 23 | }, 24 | }) 25 | } 26 | 27 | func testAccPaperFolderExists(name string) resource.TestCheckFunc { 28 | return func(s *terraform.State) error { 29 | rs, ok := s.RootModule().Resources[name] 30 | if !ok { 31 | return fmt.Errorf("Paper Folder Failure: %s not found", name) 32 | } 33 | 34 | if rs.Primary.ID == "" { 35 | return fmt.Errorf("Paper Folder Failure: ID is not set") 36 | } 37 | 38 | if num, _ := strconv.Atoi(rs.Primary.Attributes["folders.#"]); num < 1 { 39 | return fmt.Errorf("Paper Folder Failure: Should find at least 1 folder but instead found %d", num) 40 | } 41 | 42 | return nil 43 | } 44 | } 45 | 46 | const testAccDropboxPaperFolderDataConfig = ` 47 | data "dropbox_paper_folder" "foo" { 48 | doc_id = "jXl1jhXj78S7NLyloBMCB" 49 | } 50 | ` 51 | -------------------------------------------------------------------------------- /dropbox/data_source_dropbox_paper_sharing_policy.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox/paper" 7 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 8 | ) 9 | 10 | func dataSourceDropboxPaperSharingPolicy() *schema.Resource { 11 | return &schema.Resource{ 12 | Read: dataSourceDropboxPaperSharingPolicyRead, 13 | 14 | Schema: map[string]*schema.Schema{ 15 | "doc_id": { 16 | Type: schema.TypeString, 17 | Required: true, 18 | }, 19 | "public_policy": { 20 | Type: schema.TypeString, 21 | Optional: true, 22 | Computed: true, 23 | }, 24 | "team_policy": { 25 | Type: schema.TypeString, 26 | Optional: true, 27 | Computed: true, 28 | }, 29 | }, 30 | } 31 | } 32 | 33 | func dataSourceDropboxPaperSharingPolicyRead(d *schema.ResourceData, meta interface{}) error { 34 | config := meta.(*ProviderConfig).DropboxConfig 35 | client := paper.New(*config) 36 | 37 | opts := paper.NewRefPaperDoc(d.Get("doc_id").(string)) 38 | policy, err := client.DocsSharingPolicyGet(opts) 39 | if err != nil { 40 | return fmt.Errorf("Sharing Policy Data Failure: %s", err) 41 | } 42 | 43 | d.SetId(fmt.Sprintf("policy_ds:%s", d.Get("doc_id").(string))) 44 | 45 | if public := policy.PublicSharingPolicy; public != nil { 46 | d.Set("public_policy", public.Tag) 47 | } 48 | 49 | if team := policy.TeamSharingPolicy; team != nil { 50 | d.Set("team_policy", team.Tag) 51 | } 52 | 53 | return nil 54 | } 55 | -------------------------------------------------------------------------------- /dropbox/data_source_dropbox_paper_sharing_policy_test.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" 8 | "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" 9 | ) 10 | 11 | func TestAccDropboxPaperSharingPolicy(t *testing.T) { 12 | resource.Test(t, resource.TestCase{ 13 | PreCheck: func() { testAccPreCheck(t) }, 14 | Providers: testAccProviders, 15 | Steps: []resource.TestStep{ 16 | { 17 | Config: testAccDropboxPaperSharingPolicyDataConfig, 18 | Check: resource.ComposeAggregateTestCheckFunc( 19 | testAccPaperSharingPolicyExists("data.dropbox_paper_sharing_policy.foo"), 20 | ), 21 | }, 22 | }, 23 | }) 24 | } 25 | 26 | func testAccPaperSharingPolicyExists(name string) resource.TestCheckFunc { 27 | return func(s *terraform.State) error { 28 | rs, ok := s.RootModule().Resources[name] 29 | if !ok { 30 | return fmt.Errorf("Paper Sharing Policy Failure: %s not found", name) 31 | } 32 | 33 | if rs.Primary.ID == "" { 34 | return fmt.Errorf("Paper Sharing Policy Failure: ID is not set") 35 | } 36 | 37 | if rs.Primary.Attributes["public_policy"] == "" && rs.Primary.Attributes["team_policy"] == "" { 38 | return fmt.Errorf("Paper Sharing Policy Failure: Both policy types were unset") 39 | } 40 | 41 | return nil 42 | } 43 | } 44 | 45 | const testAccDropboxPaperSharingPolicyDataConfig = ` 46 | data "dropbox_paper_sharing_policy" "foo" { 47 | doc_id = "jXl1jhXj78S7NLyloBMCB" 48 | } 49 | ` 50 | -------------------------------------------------------------------------------- /dropbox/data_source_dropbox_space_usage.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox/users" 7 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 8 | ) 9 | 10 | func dataSourceDropboxSpaceUsage() *schema.Resource { 11 | return &schema.Resource{ 12 | Read: dataSourceDropboxSpaceUsageRead, 13 | 14 | Schema: map[string]*schema.Schema{ 15 | "used": { 16 | Type: schema.TypeInt, 17 | Computed: true, 18 | }, 19 | "allocated": { 20 | Type: schema.TypeInt, 21 | Computed: true, 22 | }, 23 | "is_team_allocation": { 24 | Type: schema.TypeBool, 25 | Computed: true, 26 | }, 27 | }, 28 | } 29 | } 30 | 31 | func dataSourceDropboxSpaceUsageRead(d *schema.ResourceData, meta interface{}) error { 32 | config := meta.(*ProviderConfig).DropboxConfig 33 | client := users.New(*config) 34 | 35 | usage, err := client.GetSpaceUsage() 36 | if err != nil { 37 | return err 38 | } 39 | 40 | used := usage.Used 41 | isTeam := false 42 | 43 | var allocated uint64 44 | if tag := usage.Allocation.Tag; tag == "individual" { 45 | allocated = usage.Allocation.Individual.Allocated 46 | } else { 47 | isTeam = true 48 | used = usage.Allocation.Team.Used 49 | allocated = usage.Allocation.Team.Allocated 50 | } 51 | 52 | d.SetId(fmt.Sprintf("%d:%d", used, allocated)) 53 | d.Set("used", usage.Used) 54 | d.Set("allocated", allocated) 55 | d.Set("is_team_allocation", isTeam) 56 | return nil 57 | } 58 | -------------------------------------------------------------------------------- /dropbox/data_source_dropbox_space_usage_test.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "testing" 7 | 8 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" 9 | "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" 10 | ) 11 | 12 | func TestAccDropboxSpaceUsage(t *testing.T) { 13 | resource.Test(t, resource.TestCase{ 14 | PreCheck: func() { testAccPreCheck(t) }, 15 | Providers: testAccProviders, 16 | Steps: []resource.TestStep{ 17 | { 18 | Config: testAccDropboxSpaceUsageDataConfig, 19 | Check: resource.ComposeTestCheckFunc( 20 | testAccValidUsage("data.dropbox_space_usage.usage"), 21 | ), 22 | }, 23 | }, 24 | }) 25 | } 26 | 27 | func testAccValidUsage(name string) resource.TestCheckFunc { 28 | return func(s *terraform.State) error { 29 | rs, ok := s.RootModule().Resources[name] 30 | if !ok { 31 | return fmt.Errorf("Space Usage Failure: %s not found", name) 32 | } 33 | 34 | if rs.Primary.ID == "" { 35 | return fmt.Errorf("Space Usage Failure: ID is not set") 36 | } 37 | 38 | if v, _ := strconv.Atoi(rs.Primary.Attributes["used"]); v == 0 { 39 | return fmt.Errorf("Space Usage Failure: 0B or invalid usage amount") 40 | } 41 | 42 | fmt.Printf("Current Usage: %v\n", rs.Primary.Attributes["used"]) 43 | return nil 44 | } 45 | } 46 | 47 | const testAccDropboxSpaceUsageDataConfig = ` 48 | data "dropbox_space_usage" "usage" {} 49 | ` 50 | -------------------------------------------------------------------------------- /dropbox/data_source_dropbox_user_current.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox/users" 5 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 6 | ) 7 | 8 | func dataSourceDropboxUserCurrent() *schema.Resource { 9 | return &schema.Resource{ 10 | Read: dataSourceDropboxUserCurrentRead, 11 | 12 | Schema: map[string]*schema.Schema{ 13 | "account_id": { 14 | Type: schema.TypeString, 15 | Computed: true, 16 | }, 17 | "account_type": { 18 | Type: schema.TypeString, 19 | Computed: true, 20 | }, 21 | "display_name": { 22 | Type: schema.TypeString, 23 | Computed: true, 24 | }, 25 | "email": { 26 | Type: schema.TypeString, 27 | Computed: true, 28 | }, 29 | }, 30 | } 31 | } 32 | 33 | func dataSourceDropboxUserCurrentRead(d *schema.ResourceData, meta interface{}) error { 34 | config := meta.(*ProviderConfig).DropboxConfig 35 | client := users.New(*config) 36 | 37 | account, err := client.GetCurrentAccount() 38 | if err != nil { 39 | return err 40 | } 41 | 42 | d.SetId(account.AccountId) 43 | d.Set("account_id", account.AccountId) 44 | d.Set("account_type", account.AccountType.Tag) 45 | d.Set("display_name", account.Name.DisplayName) 46 | d.Set("email", account.Email) 47 | return nil 48 | } 49 | -------------------------------------------------------------------------------- /dropbox/data_source_dropbox_user_current_test.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" 8 | "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" 9 | ) 10 | 11 | func TestAccDropboxUserCurrent(t *testing.T) { 12 | resource.Test(t, resource.TestCase{ 13 | PreCheck: func() { testAccPreCheck(t) }, 14 | Providers: testAccProviders, 15 | Steps: []resource.TestStep{ 16 | { 17 | Config: testAccDropboxUserCurrentDataConfig, 18 | Check: resource.ComposeTestCheckFunc( 19 | testAccUserCurrentExists("data.dropbox_user_current.user"), 20 | ), 21 | }, 22 | }, 23 | }) 24 | } 25 | 26 | func TestAccDropboxUserCurrent_type(t *testing.T) { 27 | resource.Test(t, resource.TestCase{ 28 | PreCheck: func() { testAccPreCheck(t) }, 29 | Providers: testAccProviders, 30 | Steps: []resource.TestStep{ 31 | { 32 | Config: testAccDropboxUserCurrentDataConfig, 33 | Check: resource.ComposeTestCheckFunc( 34 | resource.TestCheckResourceAttr("data.dropbox_user_current.user", "account_type", "basic"), 35 | ), 36 | }, 37 | }, 38 | }) 39 | } 40 | 41 | func testAccUserCurrentExists(name string) resource.TestCheckFunc { 42 | return func(s *terraform.State) error { 43 | rs, ok := s.RootModule().Resources[name] 44 | if !ok { 45 | return fmt.Errorf("User Current Failure: %s not found", name) 46 | } 47 | 48 | if rs.Primary.ID == "" { 49 | return fmt.Errorf("User Current Failure: ID is not set") 50 | } 51 | 52 | for attr, val := range rs.Primary.Attributes { 53 | if val == "" { 54 | return fmt.Errorf("User Current Failure: Attribute %s was not found", attr) 55 | } 56 | } 57 | 58 | fmt.Printf("User: %+v\n", rs.Primary.Attributes) 59 | return nil 60 | } 61 | } 62 | 63 | const testAccDropboxUserCurrentDataConfig = ` 64 | data "dropbox_user_current" "user" {} 65 | ` 66 | -------------------------------------------------------------------------------- /dropbox/provider.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 5 | ) 6 | 7 | // Provider for the Dropbox API in Terraform 8 | // returns a terraform.ResourceProvider 9 | func Provider() *schema.Provider { 10 | return &schema.Provider{ 11 | Schema: map[string]*schema.Schema{ 12 | "access_token": { 13 | Type: schema.TypeString, 14 | Required: true, 15 | Sensitive: true, 16 | DefaultFunc: schema.EnvDefaultFunc("DROPBOX_TOKEN", ""), 17 | Description: "Dropbox API access token generated from console", 18 | }, 19 | }, 20 | 21 | ResourcesMap: map[string]*schema.Resource{ 22 | "dropbox_file": resourceDropboxFile(), 23 | "dropbox_file_members": resourceDropboxFileMembers(), 24 | "dropbox_folder": resourceDropboxFolder(), 25 | "dropbox_folder_members": resourceDropboxFolderMembers(), 26 | "dropbox_paper_doc": resourceDropboxPaperDoc(), 27 | "dropbox_paper_doc_users": resourceDropboxPaperDocUsers(), 28 | "dropbox_paper_sharing_policy": resourceDropboxPaperSharingPolicy(), 29 | }, 30 | 31 | DataSourcesMap: map[string]*schema.Resource{ 32 | "dropbox_user_current": dataSourceDropboxUserCurrent(), 33 | "dropbox_space_usage": dataSourceDropboxSpaceUsage(), 34 | "dropbox_paper_folder": dataSourceDropboxPaperFolder(), 35 | "dropbox_paper_sharing_policy": dataSourceDropboxPaperSharingPolicy(), 36 | }, 37 | 38 | ConfigureFunc: providerConfig, 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /dropbox/provider_test.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "log" 5 | "os" 6 | "testing" 7 | 8 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 9 | "github.com/joho/godotenv" 10 | ) 11 | 12 | var testAccProviders map[string]*schema.Provider 13 | var testAccProvider *schema.Provider 14 | 15 | func init() { 16 | godotenv.Load() 17 | 18 | token := os.Getenv("ACCESS_TOKEN") 19 | if err := os.Setenv("DROPBOX_TOKEN", token); err != nil { 20 | log.Fatalf("Initialization failure: Failed to set the DROPBOX_TOKEN env. %s", err) 21 | } 22 | 23 | log.Printf("DROPBOX_TOKEN successfully set to: %s", token) 24 | 25 | testAccProvider = Provider() 26 | testAccProviders = map[string]*schema.Provider{ 27 | "dropbox": testAccProvider, 28 | } 29 | } 30 | 31 | func TestProvider(t *testing.T) { 32 | if err := Provider().InternalValidate(); err != nil { 33 | t.Fatalf("Provider test failure: %s", err) 34 | } 35 | } 36 | 37 | func testAccPreCheck(t *testing.T) { 38 | if v := os.Getenv("DROPBOX_TOKEN"); v == "" { 39 | t.Fatal("Precheck Failure: Environment variable DROPBOX_TOKEN is not set.") 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /dropbox/resource_dropbox_file.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | db "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox" 8 | "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox/files" 9 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 10 | ) 11 | 12 | func resourceDropboxFile() *schema.Resource { 13 | return &schema.Resource{ 14 | Create: resourceDropboxFileCreate, 15 | Read: resourceDropboxFileRead, 16 | Update: resourceDropboxFileUpdate, 17 | Delete: resourceDropboxFileDelete, 18 | 19 | Schema: map[string]*schema.Schema{ 20 | "content": { 21 | Type: schema.TypeString, 22 | Required: true, 23 | ForceNew: true, 24 | StateFunc: convertContentToB64(), 25 | }, 26 | "path": { 27 | Type: schema.TypeString, 28 | Required: true, 29 | ValidateFunc: validateWithRegExp(uploadPathPattern), 30 | }, 31 | "mode": { 32 | Type: schema.TypeString, 33 | Optional: true, 34 | Default: "add", 35 | Description: "Valid formats modes: add, overwrite, and update", 36 | ValidateFunc: validateFileWriteMode(), 37 | }, 38 | "auto_rename": { 39 | Type: schema.TypeBool, 40 | Optional: true, 41 | Default: false, 42 | }, 43 | "mute": { 44 | Type: schema.TypeBool, 45 | Optional: true, 46 | Default: false, 47 | }, 48 | "hash": { 49 | Type: schema.TypeString, 50 | Computed: true, 51 | Description: "A generated hash of the uploaded content", 52 | }, 53 | "size": { 54 | Type: schema.TypeInt, 55 | Computed: true, 56 | Description: "The size of the uploaded data in bytes", 57 | }, 58 | }, 59 | } 60 | } 61 | 62 | func resourceDropboxFileCreate(d *schema.ResourceData, meta interface{}) error { 63 | config := meta.(*ProviderConfig).DropboxConfig 64 | client := files.New(*config) 65 | 66 | content := d.Get("content").(string) 67 | reader := strings.NewReader(content) 68 | 69 | opts := &files.CommitInfo{ 70 | Path: d.Get("path").(string), 71 | Mode: &files.WriteMode{Tagged: db.Tagged{Tag: d.Get("mode").(string)}}, 72 | Autorename: d.Get("auto_rename").(bool), 73 | Mute: d.Get("mute").(bool), 74 | } 75 | 76 | metadata, err := client.Upload(opts, reader) 77 | if err != nil { 78 | return fmt.Errorf("File Creation Failure: %s", err) 79 | } 80 | 81 | d.SetId(metadata.Id) 82 | return resourceDropboxFileRead(d, meta) 83 | } 84 | 85 | func resourceDropboxFileRead(d *schema.ResourceData, meta interface{}) error { 86 | config := meta.(*ProviderConfig).DropboxConfig 87 | client := files.New(*config) 88 | 89 | opts := files.NewDownloadArg(d.Get("path").(string)) 90 | res, _, err := client.Download(opts) 91 | if err != nil { 92 | return fmt.Errorf("File Read Failure: %s", err) 93 | } 94 | 95 | d.Set("hash", res.ContentHash) 96 | d.Set("size", res.Size) 97 | return nil 98 | } 99 | 100 | func resourceDropboxFileUpdate(d *schema.ResourceData, meta interface{}) error { 101 | config := meta.(*ProviderConfig).DropboxConfig 102 | client := files.New(*config) 103 | 104 | optsRead := files.NewGetMetadataArg(d.Id()) 105 | res, err := client.GetMetadata(optsRead) 106 | if err != nil { 107 | return fmt.Errorf("File Update Failure: %s", err) 108 | } 109 | oldPath := res.(*files.FileMetadata).PathDisplay 110 | 111 | d.Partial(true) 112 | if d.HasChange("path") { 113 | newPath := files.NewRelocationPath(oldPath, d.Get("path").(string)) 114 | 115 | optsMove := &files.RelocationArg{ 116 | RelocationPath: *newPath, 117 | } 118 | _, err := client.MoveV2(optsMove) 119 | if err != nil { 120 | return fmt.Errorf("File Update Failure: %s", err) 121 | } 122 | } 123 | d.Partial(false) 124 | 125 | return nil 126 | } 127 | 128 | func resourceDropboxFileDelete(d *schema.ResourceData, meta interface{}) error { 129 | config := meta.(*ProviderConfig).DropboxConfig 130 | client := files.New(*config) 131 | 132 | opts := &files.DeleteArg{Path: d.Get("path").(string)} 133 | _, err := client.DeleteV2(opts) 134 | if err != nil { 135 | return fmt.Errorf("File Deletion Failure: %s", err) 136 | } 137 | 138 | return nil 139 | } 140 | -------------------------------------------------------------------------------- /dropbox/resource_dropbox_file_members.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "fmt" 5 | "regexp" 6 | 7 | db "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox" 8 | "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox/sharing" 9 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 10 | ) 11 | 12 | func resourceDropboxFileMembers() *schema.Resource { 13 | return &schema.Resource{ 14 | Create: resourceDropboxFileMembersCreate, 15 | Read: resourceDropboxFileMembersRead, 16 | Update: resourceDropboxFileMembersUpdate, 17 | Delete: resourceDropboxFileMembersDelete, 18 | 19 | Schema: map[string]*schema.Schema{ 20 | "file_id": { 21 | Type: schema.TypeString, 22 | Required: true, 23 | ForceNew: true, 24 | ValidateFunc: validateWithRegExp(fileIDPattern), 25 | }, 26 | "members": { 27 | Type: schema.TypeSet, 28 | Required: true, 29 | MinItems: 1, 30 | Elem: &schema.Schema{Type: schema.TypeString}, 31 | Set: schema.HashString, 32 | }, 33 | "message": { 34 | Type: schema.TypeString, 35 | Optional: true, 36 | }, 37 | "quiet": { 38 | Type: schema.TypeBool, 39 | Optional: true, 40 | Default: false, 41 | }, 42 | "access_level": { 43 | Type: schema.TypeString, 44 | Optional: true, 45 | Default: "viewer", 46 | ValidateFunc: validateAccessLevel(), 47 | }, 48 | }, 49 | } 50 | } 51 | 52 | func resourceDropboxFileMembersCreate(d *schema.ResourceData, meta interface{}) error { 53 | config := meta.(*ProviderConfig).DropboxConfig 54 | client := sharing.New(*config) 55 | 56 | opts := &sharing.AddFileMemberArgs{ 57 | File: d.Get("file_id").(string), 58 | Members: createListOfMemberSelectors(d.Get("members").([]string)), 59 | Quiet: d.Get("quiet").(bool), 60 | AccessLevel: &sharing.AccessLevel{Tagged: db.Tagged{Tag: d.Get("access_level").(string)}}, 61 | } 62 | 63 | if msg, ok := d.GetOk("message"); ok { 64 | opts.CustomMessage = msg.(string) 65 | } 66 | 67 | res, err := client.AddFileMember(opts) 68 | if err != nil { 69 | return fmt.Errorf("File Member Creation Failure: %s", err) 70 | } 71 | 72 | for _, r := range res { 73 | if r.Result.MemberError != nil { 74 | return fmt.Errorf("File Member Creation Failure: %+v", r.Result.MemberError) 75 | } 76 | } 77 | 78 | d.SetId(fmt.Sprintf("%s:%d", d.Get("file_id").(string), len(opts.Members))) 79 | return nil 80 | } 81 | 82 | func resourceDropboxFileMembersRead(d *schema.ResourceData, meta interface{}) error { 83 | config := meta.(*ProviderConfig).DropboxConfig 84 | client := sharing.New(*config) 85 | 86 | opts := sharing.NewListFileMembersArg(d.Get("file_id").(string)) 87 | fileMembers, err := client.ListFileMembers(opts) 88 | if err != nil { 89 | return fmt.Errorf("File Member Read Failure: %s", err) 90 | } 91 | 92 | var members []string 93 | for _, m := range fileMembers.Users { 94 | if email := m.User.Email; email != "" { 95 | members = append(members, email) 96 | } else { 97 | members = append(members, m.User.AccountId) 98 | } 99 | } 100 | 101 | d.Set("members", members) 102 | return nil 103 | } 104 | 105 | func resourceDropboxFileMembersUpdate(d *schema.ResourceData, meta interface{}) error { 106 | d.Partial(true) 107 | if d.HasChange("memebrs") { 108 | return resourceDropboxFileMembersCreate(d, meta) 109 | } 110 | d.Partial(false) 111 | 112 | return nil 113 | } 114 | 115 | func resourceDropboxFileMembersDelete(d *schema.ResourceData, meta interface{}) error { 116 | config := meta.(*ProviderConfig).DropboxConfig 117 | client := sharing.New(*config) 118 | 119 | opts := &sharing.RemoveFileMemberArg{ 120 | File: d.Get("file_id").(string), 121 | } 122 | 123 | for _, member := range createListOfMemberSelectors(d.Get("members").([]string)) { 124 | opts.Member = member 125 | res, err := client.RemoveFileMember2(opts) 126 | if err != nil { 127 | return fmt.Errorf("File Member Deletion Failure: %s", err) 128 | } 129 | if res.MemberError != nil { 130 | return fmt.Errorf("File Member Deletion Failure: %+v", res.MemberError) 131 | } 132 | } 133 | 134 | return nil 135 | } 136 | 137 | func createListOfMemberSelectors(members []string) []*sharing.MemberSelector { 138 | selectors := make([]*sharing.MemberSelector, len(members)) 139 | emailRx := regexp.MustCompile(emailPattern) 140 | 141 | for _, m := range members { 142 | var s *sharing.MemberSelector 143 | if emailRx.MatchString(m) { 144 | s.Tag = "email" 145 | s.Email = m 146 | } else { 147 | s.Tag = "dropbox_id" 148 | s.DropboxId = m 149 | } 150 | selectors = append(selectors, s) 151 | } 152 | return selectors 153 | } 154 | -------------------------------------------------------------------------------- /dropbox/resource_dropbox_file_test.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox/files" 8 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" 9 | "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" 10 | ) 11 | 12 | func TestAccDropboxFile_basic(t *testing.T) { 13 | resource.Test(t, resource.TestCase{ 14 | PreCheck: func() { testAccPreCheck(t) }, 15 | Providers: testAccProviders, 16 | Steps: []resource.TestStep{ 17 | { 18 | Config: testAccDropboxFileConfig, 19 | Check: resource.ComposeTestCheckFunc( 20 | testAccFileCreated("dropbox_file.foo"), 21 | ), 22 | }, 23 | }, 24 | }) 25 | } 26 | 27 | func TestAccDropboxFile_folder(t *testing.T) { 28 | resource.Test(t, resource.TestCase{ 29 | PreCheck: func() { testAccPreCheck(t) }, 30 | Providers: testAccProviders, 31 | Steps: []resource.TestStep{ 32 | { 33 | Config: testAccDropboxFileFolderConfig, 34 | Check: resource.ComposeTestCheckFunc( 35 | testAccFileCreated("dropbox_file.bar"), 36 | ), 37 | }, 38 | }, 39 | }) 40 | } 41 | 42 | func testAccFileCreated(name string) resource.TestCheckFunc { 43 | return func(s *terraform.State) error { 44 | rs, ok := s.RootModule().Resources[name] 45 | if !ok { 46 | return fmt.Errorf("File Failure: %s not found", name) 47 | } 48 | 49 | if rs.Primary.ID == "" { 50 | return fmt.Errorf("File Failure: ID is not set") 51 | } 52 | 53 | config := testAccProvider.Meta().(*ProviderConfig).DropboxConfig 54 | client := files.New(*config) 55 | path := rs.Primary.Attributes["path"] 56 | 57 | opts := files.NewGetMetadataArg(path) 58 | result, err := client.GetMetadata(opts) 59 | if err != nil { 60 | return fmt.Errorf("File Failure: %s", err) 61 | } 62 | 63 | if result.(*files.FileMetadata).ContentHash != rs.Primary.Attributes["hash"] { 64 | return fmt.Errorf("File Failure: Content hashes for created and found don't match") 65 | } 66 | 67 | return nil 68 | } 69 | } 70 | 71 | const testAccDropboxFileConfig = ` 72 | resource "dropbox_file" "foo" { 73 | content = "${file("../Makefile")}" 74 | path = "/Makefile" 75 | mute = true 76 | } 77 | ` 78 | 79 | const testAccDropboxFileFolderConfig = ` 80 | resource "dropbox_folder" "dest" { 81 | path = "/test" 82 | auto_rename = false 83 | } 84 | 85 | resource "dropbox_file" "bar" { 86 | content = "${file("../Makefile")}" 87 | path = "/test/Makefile" 88 | mode = "add" 89 | mute = true 90 | } 91 | ` 92 | -------------------------------------------------------------------------------- /dropbox/resource_dropbox_folder.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox/file_properties" 5 | "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox/files" 6 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 7 | ) 8 | 9 | func resourceDropboxFolder() *schema.Resource { 10 | return &schema.Resource{ 11 | Create: resourceDropboxFolderCreate, 12 | Read: resourceDropboxFolderRead, 13 | Delete: resourceDropboxFolderDelete, 14 | 15 | Schema: map[string]*schema.Schema{ 16 | "path": { 17 | Type: schema.TypeString, 18 | Required: true, 19 | ForceNew: true, 20 | ValidateFunc: validateWithRegExp(folderPathPattern), 21 | }, 22 | "auto_rename": { 23 | Type: schema.TypeBool, 24 | Optional: true, 25 | Default: false, 26 | ForceNew: true, 27 | }, 28 | "folder_id": { 29 | Type: schema.TypeString, 30 | Computed: true, 31 | }, 32 | "name": { 33 | Type: schema.TypeString, 34 | Computed: true, 35 | }, 36 | "property_group_templates": { 37 | Type: schema.TypeList, 38 | Optional: true, 39 | Computed: true, 40 | Description: "List of template IDs corresponding to the associated folder property groups", 41 | Elem: &schema.Schema{Type: schema.TypeString}, 42 | }, 43 | }, 44 | } 45 | } 46 | 47 | func resourceDropboxFolderCreate(d *schema.ResourceData, meta interface{}) error { 48 | config := meta.(*ProviderConfig).DropboxConfig 49 | client := files.New(*config) 50 | 51 | opts := &files.CreateFolderArg{ 52 | Path: d.Get("path").(string), 53 | Autorename: d.Get("auto_rename").(bool), 54 | } 55 | folder, err := client.CreateFolderV2(opts) 56 | if err != nil { 57 | return err 58 | } 59 | 60 | data := folder.Metadata 61 | d.SetId(data.Id) 62 | 63 | if data.PropertyGroups != nil { 64 | d.Set("property_group_templates", flattenPropertyGroupIds(data.PropertyGroups)) 65 | } 66 | 67 | return resourceDropboxFolderRead(d, meta) 68 | } 69 | 70 | func resourceDropboxFolderRead(d *schema.ResourceData, meta interface{}) error { 71 | config := meta.(*ProviderConfig).DropboxConfig 72 | client := files.New(*config) 73 | 74 | path := d.Get("path").(string) 75 | opts := files.NewGetMetadataArg(path) 76 | folder, err := client.GetMetadata(opts) 77 | if err != nil { 78 | return err 79 | } 80 | 81 | if folder.(*files.FolderMetadata).PathDisplay != "" { 82 | d.Set("path", folder.(*files.FolderMetadata).PathDisplay) 83 | } else { 84 | d.Set("path", path) 85 | } 86 | d.Set("folder_id", folder.(*files.FolderMetadata).Id) 87 | d.Set("name", folder.(*files.FolderMetadata).Name) 88 | return nil 89 | } 90 | 91 | func resourceDropboxFolderDelete(d *schema.ResourceData, meta interface{}) error { 92 | config := meta.(*ProviderConfig).DropboxConfig 93 | client := files.New(*config) 94 | 95 | opts := &files.DeleteArg{Path: d.Get("path").(string)} 96 | _, err := client.DeleteV2(opts) 97 | if err != nil { 98 | return err 99 | } 100 | 101 | return nil 102 | } 103 | 104 | func flattenPropertyGroupIds(groups []*file_properties.PropertyGroup) []string { 105 | groupIds := make([]string, 0, len(groups)) 106 | for _, g := range groups { 107 | groupIds = append(groupIds, g.TemplateId) 108 | } 109 | return groupIds 110 | } 111 | -------------------------------------------------------------------------------- /dropbox/resource_dropbox_folder_members.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "fmt" 5 | "regexp" 6 | 7 | db "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox" 8 | "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox/sharing" 9 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 10 | ) 11 | 12 | func resourceDropboxFolderMembers() *schema.Resource { 13 | return &schema.Resource{ 14 | Create: resourceDropboxFolderMembersCreate, 15 | Read: resourceDropboxFolderMembersRead, 16 | Update: resourceDropboxFolderMembersUpdate, 17 | Delete: resourceDropboxFolderMembersDelete, 18 | 19 | Schema: map[string]*schema.Schema{ 20 | "folder_id": { 21 | Type: schema.TypeString, 22 | Required: true, 23 | ForceNew: true, 24 | ValidateFunc: validateWithRegExp(folderIDPattern), 25 | }, 26 | "members": { 27 | Type: schema.TypeList, 28 | Required: true, 29 | ForceNew: true, 30 | Elem: &schema.Resource{ 31 | Schema: map[string]*schema.Schema{ 32 | "identity": { 33 | Type: schema.TypeString, 34 | Required: true, 35 | }, 36 | "access_level": { 37 | Type: schema.TypeString, 38 | Optional: true, 39 | Default: "viewer", 40 | ValidateFunc: validateAccessLevel(), 41 | }, 42 | }, 43 | }, 44 | }, 45 | "message": { 46 | Type: schema.TypeString, 47 | Optional: true, 48 | }, 49 | "quiet": { 50 | Type: schema.TypeBool, 51 | Optional: true, 52 | Default: false, 53 | }, 54 | }, 55 | } 56 | } 57 | 58 | func resourceDropboxFolderMembersCreate(d *schema.ResourceData, meta interface{}) error { 59 | config := meta.(*ProviderConfig).DropboxConfig 60 | client := sharing.New(*config) 61 | 62 | opts := &sharing.AddFolderMemberArg{ 63 | SharedFolderId: d.Get("folder_id").(string), 64 | Members: createListOfFolderMembers(d.Get("members").([]map[string]interface{})), 65 | Quiet: d.Get("quiet").(bool), 66 | } 67 | 68 | if msg, ok := d.GetOk("message"); ok { 69 | opts.CustomMessage = msg.(string) 70 | } 71 | 72 | err := client.AddFolderMember(opts) 73 | if err != nil { 74 | return fmt.Errorf("Folder Member Creation Failure: %s", err) 75 | } 76 | 77 | d.SetId(fmt.Sprintf("%s:%d", d.Get("folder_id").(string), len(opts.Members))) 78 | return nil 79 | } 80 | 81 | func resourceDropboxFolderMembersRead(d *schema.ResourceData, meta interface{}) error { 82 | config := meta.(*ProviderConfig).DropboxConfig 83 | client := sharing.New(*config) 84 | 85 | opts := &sharing.ListFolderMembersArgs{ 86 | ListFolderMembersCursorArg: *sharing.NewListFolderMembersCursorArg(), 87 | SharedFolderId: d.Get("folder_id").(string), 88 | } 89 | members, err := client.ListFolderMembers(opts) 90 | if err != nil { 91 | return fmt.Errorf("Folder Member Read Failure: %s", err) 92 | } 93 | 94 | d.Set("members", createListOfTerraformMembers(members.Users)) 95 | return nil 96 | } 97 | 98 | func resourceDropboxFolderMembersUpdate(d *schema.ResourceData, meta interface{}) error { 99 | return resourceDropboxFolderMembersCreate(d, meta) 100 | } 101 | 102 | func resourceDropboxFolderMembersDelete(d *schema.ResourceData, meta interface{}) error { 103 | config := meta.(*ProviderConfig).DropboxConfig 104 | client := sharing.New(*config) 105 | 106 | opts := &sharing.RemoveFolderMemberArg{ 107 | SharedFolderId: d.Get("folder_id").(string), 108 | LeaveACopy: false, 109 | } 110 | err := removeFolderShareMembers(opts, &client, d.Get("members").([]map[string]string)) 111 | if err != nil { 112 | return fmt.Errorf("Folder Member Deletion Failure: %s", err) 113 | } 114 | 115 | return nil 116 | } 117 | 118 | func createListOfTerraformMembers(m []*sharing.UserMembershipInfo) []map[string]string { 119 | output := make([]map[string]string, len(m)) 120 | for _, i := range m { 121 | member := map[string]string{ 122 | "access_level": i.AccessType.Tag, 123 | } 124 | 125 | if i.User.Email != "" { 126 | member["identity"] = i.User.Email 127 | } else if i.User.AccountId != "" { 128 | member["identity"] = i.User.AccountId 129 | } 130 | 131 | output = append(output, member) 132 | } 133 | return output 134 | } 135 | 136 | func createListOfFolderMembers(m []map[string]interface{}) []*sharing.AddMember { 137 | members := make([]*sharing.AddMember, 0, len(m)) 138 | emailRx := regexp.MustCompile(emailPattern) 139 | 140 | for _, i := range m { 141 | var selector sharing.MemberSelector 142 | identity := i["identity"].(string) 143 | 144 | if emailRx.MatchString(identity) { 145 | selector.Tag = "email" 146 | selector.Email = identity 147 | } else { 148 | selector.Tag = "dropbox_id" 149 | selector.DropboxId = identity 150 | } 151 | 152 | mem := &sharing.AddMember{ 153 | AccessLevel: &sharing.AccessLevel{Tagged: db.Tagged{Tag: i["access_level"].(string)}}, 154 | Member: &selector, 155 | } 156 | 157 | members = append(members, mem) 158 | } 159 | return members 160 | } 161 | 162 | func removeFolderShareMembers(arg *sharing.RemoveFolderMemberArg, client *sharing.Client, members []map[string]string) error { 163 | emailRx := regexp.MustCompile(emailPattern) 164 | for _, mem := range members { 165 | if emailRx.MatchString(mem["identity"]) { 166 | arg.Member = &sharing.MemberSelector{ 167 | Tagged: db.Tagged{Tag: "email"}, 168 | Email: mem["identity"], 169 | } 170 | } else { 171 | arg.Member = &sharing.MemberSelector{ 172 | Tagged: db.Tagged{Tag: "dropbox_id"}, 173 | DropboxId: mem["identity"], 174 | } 175 | } 176 | _, err := (*client).RemoveFolderMember(arg) 177 | if err != nil { 178 | return err 179 | } 180 | } 181 | return nil 182 | } 183 | -------------------------------------------------------------------------------- /dropbox/resource_dropbox_folder_members_test.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox/sharing" 8 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" 9 | "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" 10 | ) 11 | 12 | func TestAccDropboxFolderMember(t *testing.T) { 13 | resource.Test(t, resource.TestCase{ 14 | PreCheck: func() { testAccPreCheck(t) }, 15 | Providers: testAccProviders, 16 | Steps: []resource.TestStep{ 17 | { 18 | Config: testAccDropboxFolderMemberConfig, 19 | Check: resource.ComposeTestCheckFunc( 20 | testAccFolderMembersSet("dropbox_folder_members.foo"), 21 | ), 22 | }, 23 | }, 24 | }) 25 | } 26 | 27 | func testAccFolderMembersSet(name string) resource.TestCheckFunc { 28 | return func(s *terraform.State) error { 29 | rs, ok := s.RootModule().Resources[name] 30 | if !ok { 31 | return fmt.Errorf("Folder Member Failure: %s not found", name) 32 | } 33 | 34 | if rs.Primary.ID == "" { 35 | return fmt.Errorf("Folder Member Failure: ID is not set") 36 | } 37 | 38 | config := testAccProvider.Meta().(*ProviderConfig).DropboxConfig 39 | client := sharing.New(*config) 40 | memberCount := len(rs.Primary.Attributes["members"]) 41 | 42 | results, err := client.ListFolderMembers(&sharing.ListFolderMembersArgs{ 43 | ListFolderMembersCursorArg: *sharing.NewListFolderMembersCursorArg(), 44 | SharedFolderId: rs.Primary.Attributes["folder_id"], 45 | }) 46 | 47 | if err != nil { 48 | return fmt.Errorf("Folder Member Failure: Issue listing folders %s", err) 49 | } 50 | 51 | if len(results.Users) != memberCount { 52 | return fmt.Errorf("Folder Member Failure: Retrieve member count doesn't match argued count") 53 | } 54 | 55 | return nil 56 | } 57 | } 58 | 59 | const testAccDropboxFolderMemberConfig = ` 60 | resource "dropbox_folder" "src" { 61 | path = "/terraform-member-test" 62 | auto_rename = false 63 | } 64 | 65 | resource "dropbox_folder_members" "foo" { 66 | folder_id = "${dropbox_folder.src.folder_id}" 67 | quiet = true 68 | members = [ 69 | { 70 | identity = "test@example.com" 71 | access_level = "viewer" 72 | }, 73 | { 74 | identity = "agqorghqovn34" 75 | } 76 | ] 77 | } 78 | ` 79 | -------------------------------------------------------------------------------- /dropbox/resource_dropbox_folder_test.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox/files" 8 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" 9 | "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" 10 | ) 11 | 12 | func TestAccDropboxFolder_basic(t *testing.T) { 13 | resource.Test(t, resource.TestCase{ 14 | PreCheck: func() { testAccPreCheck(t) }, 15 | Providers: testAccProviders, 16 | Steps: []resource.TestStep{ 17 | { 18 | Config: testAccDropboxFolderConfig, 19 | Check: resource.ComposeTestCheckFunc( 20 | testAccFolderCreated("dropbox_folder.foo"), 21 | ), 22 | }, 23 | }, 24 | }) 25 | } 26 | 27 | func TestAccDropboxFolder_nested(t *testing.T) { 28 | resource.Test(t, resource.TestCase{ 29 | PreCheck: func() { testAccPreCheck(t) }, 30 | Providers: testAccProviders, 31 | Steps: []resource.TestStep{ 32 | { 33 | Config: testAccDropboxFolderNestedConfig, 34 | Check: resource.ComposeTestCheckFunc( 35 | testAccFolderCreated("dropbox_folder.test_B"), 36 | ), 37 | }, 38 | }, 39 | }) 40 | } 41 | 42 | func testAccFolderCreated(name string) resource.TestCheckFunc { 43 | return func(s *terraform.State) error { 44 | rs, ok := s.RootModule().Resources[name] 45 | if !ok { 46 | return fmt.Errorf("Folder Failure: %s not found", name) 47 | } 48 | 49 | if rs.Primary.ID == "" { 50 | return fmt.Errorf("Folder Failure: ID is not set") 51 | } 52 | 53 | config := testAccProvider.Meta().(*ProviderConfig).DropboxConfig 54 | client := files.New(*config) 55 | path := rs.Primary.Attributes["path"] 56 | 57 | opts := &files.ListFolderArg{ 58 | Path: path, 59 | Recursive: true, 60 | } 61 | results, err := client.ListFolder(opts) 62 | if err != nil { 63 | return fmt.Errorf("Folder Failure: Issue listing folders %s", err) 64 | } 65 | 66 | for _, e := range results.Entries { 67 | if e.(*files.FolderMetadata).PathDisplay == path { 68 | return nil 69 | } 70 | } 71 | 72 | return fmt.Errorf("Folder Failure: No folder system was found that matched %s", path) 73 | } 74 | } 75 | 76 | const testAccDropboxFolderConfig = ` 77 | resource "dropbox_folder" "foo" { 78 | path = "/terraform-created" 79 | auto_rename = false 80 | } 81 | ` 82 | 83 | const testAccDropboxFolderNestedConfig = ` 84 | resource "dropbox_folder" "test_A" { 85 | path = "/terraform-test-A" 86 | } 87 | 88 | resource "dropbox_folder" "test_B" { 89 | path = "${dropbox_folder.test_A.path}/test-B" 90 | } 91 | ` 92 | -------------------------------------------------------------------------------- /dropbox/resource_dropbox_paper_doc.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "encoding/base64" 5 | "fmt" 6 | "strings" 7 | 8 | db "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox" 9 | "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox/paper" 10 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 11 | ) 12 | 13 | func resourceDropboxPaperDoc() *schema.Resource { 14 | return &schema.Resource{ 15 | Create: resourceDropboxPaperDocCreate, 16 | Read: resourceDropboxPaperDocRead, 17 | Update: resourceDropboxPaperDocUpdate, 18 | Delete: resourceDropboxPaperDocDelete, 19 | 20 | Schema: map[string]*schema.Schema{ 21 | "content": { 22 | Type: schema.TypeString, 23 | Required: true, 24 | StateFunc: convertContentToB64(), 25 | }, 26 | "parent_folder": { 27 | Type: schema.TypeString, 28 | Optional: true, 29 | ForceNew: true, 30 | Default: "", 31 | Description: "Unique identifier for the folder used as the destination", 32 | }, 33 | "import_format": { 34 | Type: schema.TypeString, 35 | Required: true, 36 | Description: "Valid formats include: html, markdown, plain_text, other", 37 | ValidateFunc: validateDocImportFormat(), 38 | }, 39 | "doc_id": { 40 | Type: schema.TypeString, 41 | Computed: true, 42 | }, 43 | "revision": { 44 | Type: schema.TypeInt, 45 | Computed: true, 46 | }, 47 | "title": { 48 | Type: schema.TypeString, 49 | Computed: true, 50 | }, 51 | }, 52 | } 53 | } 54 | 55 | func resourceDropboxPaperDocCreate(d *schema.ResourceData, meta interface{}) error { 56 | config := meta.(*ProviderConfig).DropboxConfig 57 | client := paper.New(*config) 58 | 59 | content := d.Get("content").(string) 60 | reader := strings.NewReader(content) 61 | 62 | opts := &paper.PaperDocCreateArgs{ 63 | ImportFormat: &paper.ImportFormat{Tagged: db.Tagged{Tag: d.Get("import_format").(string)}}, 64 | ParentFolderId: d.Get("parent_folder").(string), 65 | } 66 | 67 | results, err := client.DocsCreate(opts, reader) 68 | if err != nil { 69 | return fmt.Errorf("Doc Creation Failure: %s", err) 70 | } 71 | 72 | d.SetId(results.DocId) 73 | d.Set("doc_id", results.DocId) 74 | d.Set("title", results.Title) 75 | d.Set("revision", results.Revision) 76 | return nil 77 | } 78 | 79 | func resourceDropboxPaperDocRead(d *schema.ResourceData, meta interface{}) error { 80 | config := meta.(*ProviderConfig).DropboxConfig 81 | client := paper.New(*config) 82 | 83 | var tag paper.ExportFormat 84 | switch format := d.Get("import_format").(string); format { 85 | case "html": 86 | tag.Tag = paper.ExportFormatHtml 87 | case "markdown": 88 | tag.Tag = paper.ExportFormatMarkdown 89 | case "plain_text": 90 | case "other": 91 | tag.Tag = paper.ExportFormatOther 92 | default: 93 | return fmt.Errorf("Invalid import format given for paper document creation: %s", format) 94 | } 95 | 96 | opts := &paper.PaperDocExport{ 97 | RefPaperDoc: *paper.NewRefPaperDoc(d.Id()), 98 | ExportFormat: &tag, 99 | } 100 | export, _, err := client.DocsDownload(opts) 101 | if err != nil { 102 | return fmt.Errorf("Doc Read Failure: %s", err) 103 | } 104 | 105 | d.Set("doc_id", d.Id()) 106 | d.Set("title", export.Title) 107 | d.Set("revision", export.Revision) 108 | return nil 109 | } 110 | 111 | func resourceDropboxPaperDocUpdate(d *schema.ResourceData, meta interface{}) error { 112 | config := meta.(*ProviderConfig).DropboxConfig 113 | client := paper.New(*config) 114 | pid := d.Id() 115 | 116 | content := d.Get("content").(string) 117 | reader := strings.NewReader(content) 118 | 119 | d.Partial(true) 120 | if d.HasChange("content") || d.HasChange("import_format") { 121 | updateOpts := &paper.PaperDocUpdateArgs{ 122 | RefPaperDoc: *paper.NewRefPaperDoc(pid), 123 | DocUpdatePolicy: &paper.PaperDocUpdatePolicy{Tagged: db.Tagged{Tag: "overwrite_all"}}, 124 | Revision: d.Get("revision").(int64), 125 | ImportFormat: &paper.ImportFormat{Tagged: db.Tagged{Tag: d.Get("import_format").(string)}}, 126 | } 127 | 128 | res, err := client.DocsUpdate(updateOpts, reader) 129 | if err != nil { 130 | return fmt.Errorf("Doc Update Failure: %s", err) 131 | } 132 | 133 | d.Set("revision", res.Revision) 134 | } 135 | d.Partial(false) 136 | 137 | return nil 138 | } 139 | 140 | func resourceDropboxPaperDocDelete(d *schema.ResourceData, meta interface{}) error { 141 | config := meta.(*ProviderConfig).DropboxConfig 142 | client := paper.New(*config) 143 | 144 | opts := paper.NewRefPaperDoc(d.Id()) 145 | err := client.DocsArchive(opts) 146 | return err 147 | } 148 | 149 | func convertContentToB64() schema.SchemaStateFunc { 150 | return func(data interface{}) string { 151 | content := data.(string) 152 | return base64.StdEncoding.EncodeToString([]byte(content)) 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /dropbox/resource_dropbox_paper_doc_test.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | db "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox" 8 | "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox/paper" 9 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" 10 | "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" 11 | ) 12 | 13 | func TestAccDropboxPaperDoc_basic(t *testing.T) { 14 | resource.Test(t, resource.TestCase{ 15 | PreCheck: func() { testAccPreCheck(t) }, 16 | Providers: testAccProviders, 17 | Steps: []resource.TestStep{ 18 | { 19 | Config: testAccDropboxPaperDocConfig, 20 | Check: resource.ComposeTestCheckFunc( 21 | testAccPaperDocCreated("dropbox_paper_doc.doc"), 22 | ), 23 | }, 24 | }, 25 | }) 26 | } 27 | 28 | func TestAccDropboxPaperDoc_foldered(t *testing.T) { 29 | resource.Test(t, resource.TestCase{ 30 | PreCheck: func() { testAccPreCheck(t) }, 31 | Providers: testAccProviders, 32 | Steps: []resource.TestStep{ 33 | { 34 | Config: testAccDropboxPaperDocFolderConfig, 35 | Check: resource.ComposeTestCheckFunc( 36 | testAccPaperDocCreated("dropbox_paper_doc.foldered_doc"), 37 | ), 38 | }, 39 | }, 40 | }) 41 | } 42 | 43 | func testAccPaperDocCreated(name string) resource.TestCheckFunc { 44 | return func(s *terraform.State) error { 45 | rs, ok := s.RootModule().Resources[name] 46 | if !ok { 47 | return fmt.Errorf("Paper Doc Failure: %s not found", name) 48 | } 49 | 50 | if rs.Primary.ID == "" { 51 | return fmt.Errorf("Paper Doc Failure: ID is not set") 52 | } 53 | 54 | config := testAccProvider.Meta().(*ProviderConfig).DropboxConfig 55 | client := paper.New(*config) 56 | 57 | opts := &paper.ListPaperDocsArgs{ 58 | Limit: 1000, 59 | FilterBy: &paper.ListPaperDocsFilterBy{Tagged: db.Tagged{Tag: "docs_created"}}, 60 | SortBy: &paper.ListPaperDocsSortBy{Tagged: db.Tagged{Tag: "created"}}, 61 | SortOrder: &paper.ListPaperDocsSortOrder{Tagged: db.Tagged{Tag: "descending"}}, 62 | } 63 | results, err := client.DocsList(opts) 64 | if err != nil { 65 | return fmt.Errorf("Paper Doc Failure: %s", err) 66 | } 67 | 68 | for _, id := range results.DocIds { 69 | if id == rs.Primary.Attributes["doc_id"] { 70 | return nil 71 | } 72 | } 73 | 74 | return fmt.Errorf("Paper Doc Failure: Document with ID %s was not found in fetched list", rs.Primary.Attributes["doc_id"]) 75 | } 76 | } 77 | 78 | const testAccDropboxPaperDocConfig = ` 79 | resource "dropbox_paper_doc" "doc" { 80 | content_file = "${file("../token.txt")}" 81 | import_format = "plain_text" 82 | } 83 | ` 84 | 85 | const testAccDropboxPaperDocFolderConfig = ` 86 | resource "dropbox_paper_doc" "foldered_doc" { 87 | content_file = "${file("../token.txt")}" 88 | parent_folder = "e.1gg8YzoPEhbTkrhvQwJ2zz3QnCdRv14CYjZI6kJODQUKnl1Usxt7" 89 | import_format = "plain_text" 90 | } 91 | ` 92 | -------------------------------------------------------------------------------- /dropbox/resource_dropbox_paper_doc_users.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "fmt" 5 | "regexp" 6 | 7 | db "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox" 8 | "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox/paper" 9 | "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox/sharing" 10 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 11 | ) 12 | 13 | func resourceDropboxPaperDocUsers() *schema.Resource { 14 | return &schema.Resource{ 15 | Create: resourceDropboxPaperDocUserCreate, 16 | Read: resourceDropboxPaperDocUserRead, 17 | Update: resourceDropboxPaperDocUserUpdate, 18 | Delete: resourceDropboxPaperDocUserDelete, 19 | 20 | Schema: map[string]*schema.Schema{ 21 | "doc_id": { 22 | Type: schema.TypeString, 23 | Required: true, 24 | ForceNew: true, 25 | }, 26 | "members": { 27 | Type: schema.TypeList, 28 | Required: true, 29 | Elem: &schema.Resource{ 30 | Schema: map[string]*schema.Schema{ 31 | "identity": { 32 | Type: schema.TypeString, 33 | Required: true, 34 | }, 35 | "permissions": { 36 | Type: schema.TypeString, 37 | Optional: true, 38 | Default: "view_and_comment", 39 | Description: "Value must be either `edit` or `view_and_comment`", 40 | ValidateFunc: validateDocUserPermissionsType(), 41 | }, 42 | }, 43 | }, 44 | }, 45 | "message": { 46 | Type: schema.TypeString, 47 | Optional: true, 48 | }, 49 | "quiet": { 50 | Type: schema.TypeBool, 51 | Optional: true, 52 | Default: false, 53 | }, 54 | "shared_users": { 55 | Type: schema.TypeList, 56 | Computed: true, 57 | Description: "Computed list of emails of those users invited and actively sharing the document", 58 | Elem: &schema.Schema{Type: schema.TypeString}, 59 | }, 60 | }, 61 | } 62 | } 63 | 64 | func resourceDropboxPaperDocUserCreate(d *schema.ResourceData, meta interface{}) error { 65 | config := meta.(*ProviderConfig).DropboxConfig 66 | client := paper.New(*config) 67 | 68 | opts := &paper.AddPaperDocUser{ 69 | RefPaperDoc: *paper.NewRefPaperDoc(d.Get("doc_id").(string)), 70 | Members: createListOfAddMembers(d.Get("members").([]map[string]interface{})), 71 | Quiet: d.Get("quiet").(bool), 72 | } 73 | 74 | if msg, ok := d.GetOk("message"); ok { 75 | opts.CustomMessage = msg.(string) 76 | } 77 | 78 | statuses, err := client.DocsUsersAdd(opts) 79 | if err != nil { 80 | return fmt.Errorf("Doc Users Failure: %s", err) 81 | } 82 | 83 | for _, s := range statuses { 84 | tag := s.Result.Tag 85 | if tag != "success" && tag != "user_is_owner" && tag != "permission_already_granted" { 86 | var id string 87 | if s.Member.Email != "" { 88 | id = s.Member.Email 89 | } else { 90 | id = s.Member.DropboxId 91 | } 92 | return fmt.Errorf("Doc Users Failure: User %s returned status %s", id, tag) 93 | } 94 | } 95 | 96 | d.SetId(fmt.Sprintf("%s:%d", d.Get("doc_id").(string), len(opts.Members))) 97 | return resourceDropboxPaperDocUserRead(d, meta) 98 | } 99 | 100 | func resourceDropboxPaperDocUserRead(d *schema.ResourceData, meta interface{}) error { 101 | config := meta.(*ProviderConfig).DropboxConfig 102 | client := paper.New(*config) 103 | 104 | opts := paper.NewListUsersOnPaperDocArgs(d.Get("doc_id").(string)) 105 | response, err := client.DocsUsersList(opts) 106 | if err != nil { 107 | return fmt.Errorf("Doc Users Failure: %s", err) 108 | } 109 | 110 | invitees, shared := response.Invitees, response.Users 111 | emails := make([]string, 0, len(invitees)+len(shared)) 112 | for _, s := range shared { 113 | emails = append(emails, s.User.Email) 114 | } 115 | for _, i := range invitees { 116 | emails = append(emails, i.Invitee.Email) 117 | } 118 | 119 | d.Set("shared_users", emails) 120 | 121 | return nil 122 | } 123 | 124 | func resourceDropboxPaperDocUserUpdate(d *schema.ResourceData, meta interface{}) error { 125 | d.Partial(true) 126 | if d.HasChange("members") { 127 | return resourceDropboxPaperDocUserCreate(d, meta) 128 | } 129 | d.Partial(false) 130 | 131 | return nil 132 | } 133 | 134 | func resourceDropboxPaperDocUserDelete(d *schema.ResourceData, meta interface{}) error { 135 | config := meta.(*ProviderConfig).DropboxConfig 136 | client := paper.New(*config) 137 | 138 | opts := &paper.RemovePaperDocUser{ 139 | RefPaperDoc: *paper.NewRefPaperDoc(d.Get("doc_id").(string)), 140 | } 141 | 142 | membersList := d.Get("members").([]map[string]interface{}) 143 | ids := make([]string, len(membersList)) 144 | for i, m := range membersList { 145 | ids[i] = m["identity"].(string) 146 | } 147 | 148 | for _, member := range createListOfMemberSelectors(ids) { 149 | opts.Member = member 150 | err := client.DocsUsersRemove(opts) 151 | if err != nil { 152 | return fmt.Errorf("Doc Users Failure: %s", err) 153 | } 154 | } 155 | 156 | return nil 157 | } 158 | 159 | func createListOfAddMembers(m []map[string]interface{}) []*paper.AddMember { 160 | members := make([]*paper.AddMember, 0, len(m)) 161 | emailRx := regexp.MustCompile(emailPattern) 162 | 163 | for _, i := range m { 164 | var selector sharing.MemberSelector 165 | identity := i["identity"].(string) 166 | 167 | if emailRx.MatchString(identity) { 168 | selector.Tag = "email" 169 | selector.Email = identity 170 | } else { 171 | selector.Tag = "dropbox_id" 172 | selector.DropboxId = identity 173 | } 174 | 175 | mem := &paper.AddMember{ 176 | PermissionLevel: &paper.PaperDocPermissionLevel{Tagged: db.Tagged{Tag: i["permissions"].(string)}}, 177 | Member: &selector, 178 | } 179 | 180 | members = append(members, mem) 181 | } 182 | return members 183 | } 184 | -------------------------------------------------------------------------------- /dropbox/resource_dropbox_paper_doc_users_test.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" 7 | ) 8 | 9 | func TestAccDropboxPaperDocUsers(t *testing.T) { 10 | resource.Test(t, resource.TestCase{ 11 | PreCheck: func() { testAccPreCheck(t) }, 12 | Providers: testAccProviders, 13 | Steps: []resource.TestStep{ 14 | { 15 | Config: testAccDropboxPaperUsersConfig, 16 | Check: resource.ComposeTestCheckFunc(), 17 | }, 18 | }, 19 | }) 20 | } 21 | 22 | const testAccDropboxPaperUsersConfig = ` 23 | resource "dropbox_paper_doc_users" "foo" { 24 | doc_id = "oeWK68vUIXUnDe3r5H5wo" 25 | quiet = false 26 | members = [ 27 | { 28 | identity = "callensmatt@gmail.com" 29 | permissions = "edit" 30 | } 31 | ] 32 | } 33 | ` 34 | -------------------------------------------------------------------------------- /dropbox/resource_dropbox_paper_sharing_policy.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "fmt" 5 | 6 | db "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox" 7 | "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox/paper" 8 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 9 | ) 10 | 11 | func resourceDropboxPaperSharingPolicy() *schema.Resource { 12 | return &schema.Resource{ 13 | Create: resourceDropboxPaperSharingPolicyCreate, 14 | Read: resourceDropboxPaperSharingPolicyRead, 15 | Update: resourceDropboxPaperSharingPolicyUpdate, 16 | Delete: resourceDropboxPaperSharingPolicyDelete, 17 | 18 | Schema: map[string]*schema.Schema{ 19 | "doc_id": { 20 | Type: schema.TypeString, 21 | Required: true, 22 | }, 23 | "public_policy": { 24 | Type: schema.TypeString, 25 | Optional: true, 26 | ValidateFunc: validateDocPolicyType("public"), 27 | }, 28 | "team_policy": { 29 | Type: schema.TypeString, 30 | Optional: true, 31 | ValidateFunc: validateDocPolicyType("team"), 32 | }, 33 | }, 34 | } 35 | } 36 | 37 | func resourceDropboxPaperSharingPolicyCreate(d *schema.ResourceData, meta interface{}) error { 38 | config := meta.(*ProviderConfig).DropboxConfig 39 | client := paper.New(*config) 40 | 41 | opts := &paper.PaperDocSharingPolicy{ 42 | RefPaperDoc: *paper.NewRefPaperDoc(d.Get("doc_id").(string)), 43 | SharingPolicy: &paper.SharingPolicy{ 44 | PublicSharingPolicy: &paper.SharingPublicPolicyType{Tagged: db.Tagged{Tag: d.Get("public_policy").(string)}}, 45 | TeamSharingPolicy: &paper.SharingTeamPolicyType{Tagged: db.Tagged{Tag: d.Get("team_policy").(string)}}, 46 | }, 47 | } 48 | 49 | err := client.DocsSharingPolicySet(opts) 50 | if err != nil { 51 | return fmt.Errorf("Sharing Policy Creation Failure: %s", err) 52 | } 53 | 54 | d.SetId(fmt.Sprintf("pset:%s", d.Get("doc_id").(string))) 55 | return nil 56 | } 57 | 58 | func resourceDropboxPaperSharingPolicyRead(d *schema.ResourceData, meta interface{}) error { 59 | config := meta.(*ProviderConfig).DropboxConfig 60 | client := paper.New(*config) 61 | 62 | opts := paper.NewRefPaperDoc(d.Get("doc_id").(string)) 63 | policy, err := client.DocsSharingPolicyGet(opts) 64 | if err != nil { 65 | return fmt.Errorf("Sharing Policy Read Failure: %s", err) 66 | } 67 | 68 | d.Set("public_policy", policy.PublicSharingPolicy.Tag) 69 | d.Set("team_policy", policy.TeamSharingPolicy.Tag) 70 | return nil 71 | } 72 | 73 | func resourceDropboxPaperSharingPolicyUpdate(d *schema.ResourceData, meta interface{}) error { 74 | config := meta.(*ProviderConfig).DropboxConfig 75 | client := paper.New(*config) 76 | 77 | d.Partial(true) 78 | if d.HasChange("doc_id") || d.HasChange("public_policy") || d.HasChange("team_policy") { 79 | opts := &paper.PaperDocSharingPolicy{ 80 | RefPaperDoc: *paper.NewRefPaperDoc(d.Get("doc_id").(string)), 81 | SharingPolicy: &paper.SharingPolicy{ 82 | PublicSharingPolicy: &paper.SharingPublicPolicyType{Tagged: db.Tagged{Tag: d.Get("public_policy").(string)}}, 83 | TeamSharingPolicy: &paper.SharingTeamPolicyType{Tagged: db.Tagged{Tag: d.Get("team_policy").(string)}}, 84 | }, 85 | } 86 | 87 | err := client.DocsSharingPolicySet(opts) 88 | if err != nil { 89 | return fmt.Errorf("Sharing Policy Update Failure: %s", err) 90 | } 91 | } 92 | d.Partial(false) 93 | 94 | return nil 95 | } 96 | 97 | func resourceDropboxPaperSharingPolicyDelete(d *schema.ResourceData, meta interface{}) error { 98 | config := meta.(*ProviderConfig).DropboxConfig 99 | client := paper.New(*config) 100 | 101 | opts := &paper.PaperDocSharingPolicy{ 102 | RefPaperDoc: *paper.NewRefPaperDoc(d.Get("doc_id").(string)), 103 | SharingPolicy: &paper.SharingPolicy{ 104 | PublicSharingPolicy: &paper.SharingPublicPolicyType{Tagged: db.Tagged{Tag: "invite_only"}}, 105 | TeamSharingPolicy: &paper.SharingTeamPolicyType{Tagged: db.Tagged{Tag: "invite_only"}}, 106 | }, 107 | } 108 | 109 | err := client.DocsSharingPolicySet(opts) 110 | if err != nil { 111 | return fmt.Errorf("Sharing Policy Deletion Failure: %s", err) 112 | } 113 | 114 | return nil 115 | } 116 | -------------------------------------------------------------------------------- /dropbox/resource_dropbox_paper_sharing_policy_test.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox/paper" 8 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" 9 | "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" 10 | ) 11 | 12 | func TestAccDropboxResPaperSharingPolicy(t *testing.T) { 13 | resource.Test(t, resource.TestCase{ 14 | PreCheck: func() { testAccPreCheck(t) }, 15 | Providers: testAccProviders, 16 | Steps: []resource.TestStep{ 17 | { 18 | Config: testAccDropboxResPaperSharingConfig, 19 | Check: resource.ComposeTestCheckFunc( 20 | testAccPaperSharingCreated("dropbox_paper_sharing_policy.foo"), 21 | ), 22 | }, 23 | }, 24 | }) 25 | } 26 | 27 | func testAccPaperSharingCreated(name string) resource.TestCheckFunc { 28 | return func(s *terraform.State) error { 29 | rs, ok := s.RootModule().Resources[name] 30 | if !ok { 31 | return fmt.Errorf("Paper Sharing Policy Failure: %s not found", name) 32 | } 33 | 34 | if rs.Primary.ID == "" { 35 | return fmt.Errorf("Paper Sharing Policy Failure: ID is not set") 36 | } 37 | 38 | client := paper.New(*testAccProvider.Meta().(*ProviderConfig).DropboxConfig) 39 | 40 | pid := rs.Primary.Attributes["doc_id"] 41 | policies, err := client.DocsSharingPolicyGet(paper.NewRefPaperDoc(pid)) 42 | if err != nil { 43 | return fmt.Errorf("Paper Sharing Policy Failure: %s", err) 44 | } 45 | 46 | if policies.PublicSharingPolicy.Tag == "disabled" && policies.TeamSharingPolicy.Tag == "invite_only" { 47 | return nil 48 | } 49 | 50 | return fmt.Errorf("Paper Sharing Policy Failure: Retrieved policies didn't match the resource input") 51 | } 52 | } 53 | 54 | const testAccDropboxResPaperSharingConfig = ` 55 | resource "dropbox_paper_doc" "doc" { 56 | content_file = "${file("../token.txt")}" 57 | import_format = "plain_text" 58 | } 59 | 60 | resource "dropbox_paper_sharing_policy" "foo" { 61 | doc_id = "${dropbox_paper_doc.doc.id}" 62 | public_policy = "disabled" 63 | team_policy = "invite_only" 64 | } 65 | ` 66 | -------------------------------------------------------------------------------- /dropbox/validators.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import ( 4 | "fmt" 5 | "regexp" 6 | 7 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 8 | ) 9 | 10 | const fileIDPattern = "((/|id:).*|nspath:[0-9]+:.*)|ns:[0-9]+(/.*)?" 11 | 12 | const folderIDPattern = "[-_0-9a-zA-Z:]+" 13 | 14 | const emailPattern = "^['&A-Za-z0-9._%+-]+@[A-Za-z0-9-][A-Za-z0-9.-]*.[A-Za-z]{2,15}$" 15 | 16 | const folderPathPattern = "(/(.|[\r\n])*)|(ns:[0-9]+(/.*)?)" 17 | 18 | const uploadPathPattern = "(/(.|[\r\n])*)|(ns:[0-9]+(/.*)?)|(id:.*)" 19 | 20 | func validateWithRegExp(pattern string) schema.SchemaValidateFunc { 21 | return func(v interface{}, k string) (ws []string, errors []error) { 22 | value := v.(string) 23 | ok, err := regexp.MatchString(pattern, value) 24 | if err != nil { 25 | errors = append(errors, fmt.Errorf("RegExp Validation Failure: %s", err)) 26 | } 27 | if !ok { 28 | errors = append(errors, fmt.Errorf("RegExp Validation Failure: %s does not match the pattern %s", value, pattern)) 29 | } 30 | return 31 | } 32 | } 33 | 34 | func validateDocImportFormat() schema.SchemaValidateFunc { 35 | return func(v interface{}, k string) (ws []string, errors []error) { 36 | format := v.(string) 37 | validFormats := []string{"html", "markdown", "plain_text", "other"} 38 | 39 | for _, f := range validFormats { 40 | if f == format { 41 | return 42 | } 43 | } 44 | 45 | errors = append(errors, fmt.Errorf("Import Format Validation Failure: %s is not a valid import format", format)) 46 | return 47 | } 48 | } 49 | 50 | func validateDocUserPermissionsType() schema.SchemaValidateFunc { 51 | return func(v interface{}, k string) (ws []string, errors []error) { 52 | level := v.(string) 53 | 54 | if level == "" { 55 | ws = append(ws, fmt.Sprintf("User Permission Validation Warning: No permission level value was given, resorting to default.")) 56 | return 57 | } 58 | 59 | if level == "edit" || level == "view_and_comment" { 60 | return 61 | } 62 | 63 | errors = append(errors, fmt.Errorf("User Permission Validation Error: %s is not a valid permission level for a Paper doc", level)) 64 | return 65 | } 66 | } 67 | 68 | func validateDocPolicyType(env string) schema.SchemaValidateFunc { 69 | return func(v interface{}, k string) (ws []string, errors []error) { 70 | policy := v.(string) 71 | approved := []string{"people_with_link_can_edit", "people_with_link_can_view_and_comment", "invite_only"} 72 | approvedPublic := append(approved, "disabled") 73 | 74 | if env == "public" { 75 | for _, p := range approvedPublic { 76 | if policy == p { 77 | return 78 | } 79 | } 80 | errors = append(errors, fmt.Errorf("Share Policy Validation Failure: %s is not an approved public policy", policy)) 81 | } else { 82 | for _, p := range approved { 83 | if policy == p { 84 | return 85 | } 86 | } 87 | errors = append(errors, fmt.Errorf("Share Policy Validation Failure: %s is not an approved team policy", policy)) 88 | } 89 | return 90 | } 91 | } 92 | 93 | func validateFileWriteMode() schema.SchemaValidateFunc { 94 | return func(v interface{}, k string) (ws []string, errors []error) { 95 | mode := v.(string) 96 | valid := []string{"add", "overwrite", "update"} 97 | 98 | for _, v := range valid { 99 | if mode == v { 100 | return 101 | } 102 | } 103 | 104 | errors = append(errors, fmt.Errorf("Write Mode Validation Failure: %s is not a valid write mode", mode)) 105 | return 106 | } 107 | } 108 | 109 | func validateAccessLevel() schema.SchemaValidateFunc { 110 | return func(v interface{}, k string) (ws []string, errors []error) { 111 | level := v.(string) 112 | valid := []string{"owner", "editor", "viewer", "viewer_no_comment"} 113 | 114 | for _, v := range valid { 115 | if level == v { 116 | return 117 | } 118 | } 119 | 120 | errors = append(errors, fmt.Errorf("Access Level Validation Failure: %s is not a valid file access level", level)) 121 | return 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /dropbox/validators_test.go: -------------------------------------------------------------------------------- 1 | package dropbox 2 | 3 | import "testing" 4 | 5 | func TestValidateRegExp(t *testing.T) { 6 | validIDs := map[string]string{ 7 | "id:3kmLmQFnf1AAAAAAAAAAAw": fileIDPattern, 8 | } 9 | 10 | for key, val := range validIDs { 11 | _, errors := validateWithRegExp(val)(key, "test") 12 | if len(errors) != 0 { 13 | t.Fatalf("RegExp Validator Failure: %s produced an output with errors", key) 14 | } 15 | } 16 | } 17 | 18 | func TestDocImportFormats(t *testing.T) { 19 | validFormats := []string{"html", "markdown", "plain_text", "other"} 20 | 21 | for _, format := range validFormats { 22 | _, errors := validateDocImportFormat()(format, "test") 23 | if len(errors) != 0 { 24 | t.Fatalf("Import Format Validator Failure: %s produced an output with errors", format) 25 | } 26 | } 27 | } 28 | 29 | func TestPermissionTypes(t *testing.T) { 30 | validTypes := []string{"edit", "view_and_comment"} 31 | 32 | for _, perm := range validTypes { 33 | _, errors := validateDocUserPermissionsType()(perm, "test") 34 | if len(errors) != 0 { 35 | t.Fatalf("Permission Type Validator Failure: %s produced an output with errors", perm) 36 | } 37 | } 38 | } 39 | 40 | func TestDocPolicyType(t *testing.T) { 41 | validPolicies := []string{"people_with_link_can_edit", "people_with_link_can_view_and_comment", "invite_only"} 42 | 43 | for _, policy := range validPolicies { 44 | _, errors := validateDocPolicyType("team")(policy, "test") 45 | if len(errors) != 0 { 46 | t.Fatalf("Doc Policy Validator Failure: %s produced an output with errors", policy) 47 | } 48 | } 49 | 50 | _, errors := validateDocPolicyType("team")("disabled", "test") 51 | if len(errors) == 0 { 52 | t.Fatalf("Doc Policy Validator Failure: there was no error for passing `disabled` to `team` policy type") 53 | } 54 | } 55 | 56 | func TestFileWriteMode(t *testing.T) { 57 | validModes := []string{"add", "overwrite", "update"} 58 | 59 | for _, mode := range validModes { 60 | _, errors := validateFileWriteMode()(mode, "test") 61 | if len(errors) != 0 { 62 | t.Fatalf("File Write Mode Validator Failure: %s produced an output with errors", mode) 63 | } 64 | } 65 | } 66 | 67 | func TestAccessLevels(t *testing.T) { 68 | validLevels := []string{"owner", "editor", "viewer", "viewer_no_comment"} 69 | 70 | for _, level := range validLevels { 71 | _, errors := validateAccessLevel()(level, "test") 72 | if len(errors) != 0 { 73 | t.Fatalf("Access Level Validator Failure: %s produced an output with errors", level) 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/callensm/terraform-provider-dropbox 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/dropbox/dropbox-sdk-go-unofficial/v6 v6.0.2 7 | github.com/hashicorp/terraform-plugin-docs v0.4.0 8 | github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.0 9 | github.com/joho/godotenv v1.3.0 10 | ) 11 | -------------------------------------------------------------------------------- /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 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= 40 | github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= 41 | github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= 42 | github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= 43 | github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= 44 | github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= 45 | github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= 46 | github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= 47 | github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= 48 | github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ= 49 | github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= 50 | github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= 51 | github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= 52 | github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= 53 | github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= 54 | github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= 55 | github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= 56 | github.com/andybalholm/crlf v0.0.0-20171020200849-670099aa064f/go.mod h1:k8feO4+kXDxro6ErPXBRTJ/ro2mf0SsFG8s7doP9kJE= 57 | github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= 58 | github.com/apparentlymart/go-cidr v1.0.1/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= 59 | github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= 60 | github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0 h1:MzVXffFUye+ZcSR6opIgz9Co7WcDx6ZcY+RjfFHoA0I= 61 | github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= 62 | github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0= 63 | github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= 64 | github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= 65 | github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= 66 | github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= 67 | github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to= 68 | github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= 69 | github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= 70 | github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM= 71 | github.com/aws/aws-sdk-go v1.25.3 h1:uM16hIw9BotjZKMZlX05SN2EFtaWfi/NonPKIARiBLQ= 72 | github.com/aws/aws-sdk-go v1.25.3/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= 73 | github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= 74 | github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= 75 | github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= 76 | github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= 77 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 78 | github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= 79 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 80 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= 81 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 82 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 83 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 84 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 85 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 86 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 87 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 88 | github.com/dropbox/dropbox-sdk-go-unofficial/v6 v6.0.2 h1:g7J3J9ppMgiMtV3OnjTWh0XPksfn5pzPtl4MWSpeWbc= 89 | github.com/dropbox/dropbox-sdk-go-unofficial/v6 v6.0.2/go.mod h1:rSS3kM9XMzSQ6pw91Qgd6yB5jdt70N4OdtrAf74As5M= 90 | github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= 91 | github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= 92 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 93 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 94 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 95 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 96 | github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= 97 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= 98 | github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= 99 | github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= 100 | github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= 101 | github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= 102 | github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= 103 | github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= 104 | github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34= 105 | github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= 106 | github.com/go-git/go-git-fixtures/v4 v4.0.1/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw= 107 | github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0= 108 | github.com/go-git/go-git/v5 v5.1.0/go.mod h1:ZKfuPUoY1ZqIG4QG9BDBh3G4gLM5zvPuSJAozQrZuyM= 109 | github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4= 110 | github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= 111 | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= 112 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 113 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 114 | github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= 115 | github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= 116 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 117 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 118 | github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 119 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= 120 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 121 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 122 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 123 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= 124 | github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 125 | github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 126 | github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 127 | github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= 128 | github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 129 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 130 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 131 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 132 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 133 | github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 134 | github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= 135 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 136 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 137 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 138 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 139 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 140 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 141 | github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= 142 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 143 | github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 144 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 145 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 146 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 147 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 148 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 149 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 150 | github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 151 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 152 | github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 153 | github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 154 | github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= 155 | github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 156 | github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= 157 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 158 | github.com/google/martian/v3 v3.0.0 h1:pMen7vLs8nvgEYhywH3KDWJIJTeEr2ULsVWHWYHQyBs= 159 | github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 160 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 161 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 162 | github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 163 | github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 164 | github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 165 | github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 166 | github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 167 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 168 | github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= 169 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 170 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= 171 | github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= 172 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= 173 | github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= 174 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 175 | github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU= 176 | github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg= 177 | github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= 178 | github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= 179 | github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= 180 | github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI= 181 | github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs= 182 | github.com/hashicorp/go-getter v1.4.0/go.mod h1:7qxyCd8rBfcShwsvxgIguu4KbS3l8bUCwg2Umn7RjeY= 183 | github.com/hashicorp/go-getter v1.5.3 h1:NF5+zOlQegim+w/EUhSLh6QhXHmZMEeHLQzllkQ3ROU= 184 | github.com/hashicorp/go-getter v1.5.3/go.mod h1:BrrV/1clo8cCYu6mxvboYg+KutTiFnXjMEgDD8+i7ZI= 185 | github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= 186 | github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= 187 | github.com/hashicorp/go-hclog v0.15.0 h1:qMuK0wxsoW4D0ddCCYwPSTm4KQv1X1ke3WmPWZ0Mvsk= 188 | github.com/hashicorp/go-hclog v0.15.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= 189 | github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= 190 | github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= 191 | github.com/hashicorp/go-plugin v1.3.0/go.mod h1:F9eH4LrE/ZsRdbwhfjs9k9HoDUwAHnYtXdgmf1AVNs0= 192 | github.com/hashicorp/go-plugin v1.4.1 h1:6UltRQlLN9iZO513VveELp5xyaFxVD2+1OVylE+2E+w= 193 | github.com/hashicorp/go-plugin v1.4.1/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ= 194 | github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= 195 | github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= 196 | github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 197 | github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= 198 | github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 199 | github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 200 | github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 201 | github.com/hashicorp/go-version v1.3.0 h1:McDWVJIU/y+u1BRV06dPaLfLCaT7fUTJLp5r04x7iNw= 202 | github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 203 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 204 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 205 | github.com/hashicorp/hcl/v2 v2.3.0 h1:iRly8YaMwTBAKhn1Ybk7VSdzbnopghktCD031P8ggUE= 206 | github.com/hashicorp/hcl/v2 v2.3.0/go.mod h1:d+FwDBbOLvpAM3Z6J7gPj/VoAGkNe/gm352ZhjJ/Zv8= 207 | github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= 208 | github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= 209 | github.com/hashicorp/terraform-exec v0.12.0/go.mod h1:SGhto91bVRlgXQWcJ5znSz+29UZIa8kpBbkGwQ+g9E8= 210 | github.com/hashicorp/terraform-exec v0.14.0 h1:UQoUcxKTZZXhyyK68Cwn4mApT4mnFPmEXPiqaHL9r+w= 211 | github.com/hashicorp/terraform-exec v0.14.0/go.mod h1:qrAASDq28KZiMPDnQ02sFS9udcqEkRly002EA2izXTA= 212 | github.com/hashicorp/terraform-json v0.8.0/go.mod h1:3defM4kkMfttwiE7VakJDwCd4R+umhSQnvJwORXbprE= 213 | github.com/hashicorp/terraform-json v0.12.0 h1:8czPgEEWWPROStjkWPUnTQDXmpmZPlkQAwYYLETaTvw= 214 | github.com/hashicorp/terraform-json v0.12.0/go.mod h1:pmbq9o4EuL43db5+0ogX10Yofv1nozM+wskr/bGFJpI= 215 | github.com/hashicorp/terraform-plugin-docs v0.4.0 h1:xJIXsMzBFwBvC1zcjoNz743GL2tNEfYFFU9+Hjp4Uek= 216 | github.com/hashicorp/terraform-plugin-docs v0.4.0/go.mod h1:fKj/V3t45tiXpSlUms/0G4OrBayyWpbUJ4WtLjBkINU= 217 | github.com/hashicorp/terraform-plugin-go v0.3.0 h1:AJqYzP52JFYl9NABRI7smXI1pNjgR5Q/y2WyVJ/BOZA= 218 | github.com/hashicorp/terraform-plugin-go v0.3.0/go.mod h1:dFHsQMaTLpON2gWhVWT96fvtlc/MF1vSy3OdMhWBzdM= 219 | github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.0 h1:SuI59MqNjYDrL7EfqHX9V6P/24isgqYx/FdglwVs9bg= 220 | github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.0/go.mod h1:grseeRo9g3yNkYW09iFlV8LG78jTa1ssBgouogQg/RU= 221 | github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= 222 | github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ= 223 | github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= 224 | github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= 225 | github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= 226 | github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 227 | github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= 228 | github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= 229 | github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= 230 | github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= 231 | github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= 232 | github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= 233 | github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 234 | github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= 235 | github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= 236 | github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74= 237 | github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= 238 | github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= 239 | github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= 240 | github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= 241 | github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= 242 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 243 | github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= 244 | github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= 245 | github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= 246 | github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= 247 | github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= 248 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 249 | github.com/klauspost/compress v1.11.2 h1:MiK62aErc3gIiVEtyzKfeOHgW7atJb5g/KNX5m3c2nQ= 250 | github.com/klauspost/compress v1.11.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= 251 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 252 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 253 | github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= 254 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 255 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 256 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 257 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 258 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 259 | github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= 260 | github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= 261 | github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= 262 | github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= 263 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 264 | github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= 265 | github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= 266 | github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 267 | github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 268 | github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 269 | github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 270 | github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= 271 | github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= 272 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 273 | github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 274 | github.com/mitchellh/cli v1.1.1/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= 275 | github.com/mitchellh/cli v1.1.2 h1:PvH+lL2B7IQ101xQL63Of8yFS2y+aDlsFcsqNc+u/Kw= 276 | github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4= 277 | github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= 278 | github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= 279 | github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= 280 | github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 281 | github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= 282 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 283 | github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= 284 | github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= 285 | github.com/mitchellh/go-testing-interface v1.0.4 h1:ZU1VNC02qyufSZsjjs7+khruk2fKvbQ3TwRV/IBCeFA= 286 | github.com/mitchellh/go-testing-interface v1.0.4/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= 287 | github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= 288 | github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= 289 | github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= 290 | github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= 291 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 292 | github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= 293 | github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= 294 | github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= 295 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= 296 | github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce h1:RPclfga2SEJmgMmz2k+Mg7cowZ8yv4Trqw9UsJby758= 297 | github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce/go.mod h1:uFMI8w+ref4v2r9jz+c9i1IfIttS/OkmLfrk1jne5hs= 298 | github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= 299 | github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= 300 | github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= 301 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 302 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 303 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 304 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 305 | github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w= 306 | github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= 307 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 308 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 309 | github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= 310 | github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= 311 | github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4= 312 | github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= 313 | github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= 314 | github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= 315 | github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= 316 | github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= 317 | github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 318 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 319 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 320 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 321 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 322 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 323 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 324 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 325 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 326 | github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= 327 | github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ= 328 | github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= 329 | github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= 330 | github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= 331 | github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= 332 | github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= 333 | github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= 334 | github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= 335 | github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= 336 | github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= 337 | github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 338 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 339 | github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 340 | github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= 341 | github.com/zclconf/go-cty v1.2.1/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= 342 | github.com/zclconf/go-cty v1.7.1/go.mod h1:VDR4+I79ubFBGm1uJac1226K5yANQFHeauxPBoP54+o= 343 | github.com/zclconf/go-cty v1.8.4 h1:pwhhz5P+Fjxse7S7UriBrMu6AUJSZM5pKqGem1PjGAs= 344 | github.com/zclconf/go-cty v1.8.4/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= 345 | github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= 346 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 347 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= 348 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 349 | go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 350 | go.opencensus.io v0.22.4 h1:LYy1Hy3MJdrCdMwwzxA/dRok4ejH+RwNGbuoD9fCjto= 351 | go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 352 | golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 353 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 354 | golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 355 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 356 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 357 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 358 | golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 359 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 360 | golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 361 | golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= 362 | golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg= 363 | golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= 364 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 365 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 366 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= 367 | golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= 368 | golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= 369 | golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 370 | golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 371 | golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 372 | golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= 373 | golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= 374 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 375 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 376 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 377 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 378 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 379 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 380 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 381 | golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 382 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 383 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= 384 | golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 385 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= 386 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 387 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= 388 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= 389 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 390 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= 391 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 392 | golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 393 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 394 | golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= 395 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 396 | golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 397 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 398 | golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 399 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 400 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 401 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 402 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 403 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 404 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 405 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 406 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 407 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 408 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 409 | golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 410 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 411 | golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 412 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 413 | golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 414 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 415 | golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 416 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 417 | golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 418 | golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 419 | golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 420 | golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 421 | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 422 | golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 423 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 424 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 425 | golang.org/x/net v0.0.0-20210326060303-6b1517762897 h1:KrsHThm5nFk34YtATK1LsThyGhGbGe1olrte/HInHvs= 426 | golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= 427 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 428 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 429 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 430 | golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 431 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 432 | golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5 h1:Lm4OryKCca1vehdsWogr9N4t7NfZxLbJoc/H0w4K4S4= 433 | golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 434 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 435 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 436 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 437 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 438 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 439 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 440 | golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 441 | golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 442 | golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 443 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 444 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 445 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 446 | golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 447 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 448 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 449 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 450 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 451 | golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 452 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 453 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 454 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 455 | golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 456 | golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 457 | golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 458 | golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 459 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 460 | golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 461 | golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 462 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 463 | golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 464 | golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 465 | golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 466 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 467 | golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 468 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 469 | golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 470 | golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 471 | golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 472 | golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 473 | golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 474 | golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 475 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 476 | golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 477 | golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 478 | golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79 h1:RX8C8PRZc2hTIod4ds8ij+/4RQX3AqhYj3uOHmyaz4E= 479 | golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 480 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 481 | golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 482 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 483 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 484 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 485 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 486 | golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= 487 | golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 488 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 489 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 490 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 491 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 492 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 493 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 494 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 495 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 496 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 497 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 498 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 499 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 500 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 501 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 502 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 503 | golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 504 | golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 505 | golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 506 | golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 507 | golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 508 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 509 | golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 510 | golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 511 | golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 512 | golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 513 | golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 514 | golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 515 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 516 | golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 517 | golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 518 | golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 519 | golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 520 | golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 521 | golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= 522 | golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= 523 | golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= 524 | golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 525 | golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 526 | golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 527 | golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 528 | golang.org/x/tools v0.0.0-20200713011307-fd294ab11aed/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 529 | golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 530 | golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 531 | golang.org/x/tools v0.0.0-20200825202427-b303f430e36d h1:W07d4xkoAUSNOkOzdzXCdFGxT7o2rW4q8M34tB2i//k= 532 | golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 533 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 534 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 535 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 536 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 537 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 538 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= 539 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= 540 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 541 | google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 542 | google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 543 | google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 544 | google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 545 | google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 546 | google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 547 | google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 548 | google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 549 | google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 550 | google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= 551 | google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= 552 | google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= 553 | google.golang.org/api v0.30.0 h1:yfrXXP61wVuLb0vBcG6qaOoIoqYEzOQS8jum51jkv2w= 554 | google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= 555 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 556 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 557 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 558 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= 559 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 560 | google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= 561 | google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 562 | google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 563 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 564 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 565 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 566 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 567 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 568 | google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 569 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 570 | google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= 571 | google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 572 | google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 573 | google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 574 | google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 575 | google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 576 | google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 577 | google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= 578 | google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 579 | google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 580 | google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 581 | google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 582 | google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 583 | google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 584 | google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 585 | google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 586 | google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= 587 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 588 | google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= 589 | google.golang.org/genproto v0.0.0-20200711021454-869866162049/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 590 | google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 591 | google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 592 | google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 h1:PDIOdWxZ8eRizhKa1AAvY53xsvLB1cWorMjslvY3VA8= 593 | google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 594 | google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= 595 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 596 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 597 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 598 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 599 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 600 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 601 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 602 | google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 603 | google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 604 | google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= 605 | google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 606 | google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 607 | google.golang.org/grpc v1.32.0 h1:zWTV+LMdc3kaiJMSTOFz2UgSBgx8RNQoTGiZu3fR9S0= 608 | google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 609 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 610 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 611 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 612 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 613 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 614 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 615 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 616 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 617 | google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= 618 | google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= 619 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 620 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 621 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 622 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 623 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 624 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 625 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 626 | gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= 627 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 628 | gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= 629 | gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= 630 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 631 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 632 | gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= 633 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 634 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 635 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 636 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 637 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 638 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 639 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 640 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 641 | honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 642 | honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 643 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= 644 | rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= 645 | rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= 646 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/hashicorp/terraform-plugin-sdk/v2/plugin" 5 | 6 | "github.com/callensm/terraform-provider-dropbox/dropbox" 7 | ) 8 | 9 | var ( 10 | commit string 11 | version string 12 | ) 13 | 14 | //go:generate go run github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs 15 | 16 | func main() { 17 | plugin.Serve(&plugin.ServeOpts{ 18 | ProviderFunc: dropbox.Provider, 19 | }) 20 | } 21 | -------------------------------------------------------------------------------- /tools/tools.go: -------------------------------------------------------------------------------- 1 | // +build tools 2 | 3 | package tools 4 | 5 | import ( 6 | _ "github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs" 7 | ) 8 | --------------------------------------------------------------------------------