├── .github
└── workflows
│ ├── golangci.yml
│ └── release.yml
├── .gitignore
├── .golangci.yml
├── .goreleaser.yml
├── .idea
├── .gitignore
├── misc.xml
├── modules.xml
├── terraform-provider-mongodb.iml
└── vcs.xml
├── LICENSE
├── Makefile
├── README.md
├── docker
├── conf
│ └── config.js
├── docker-compose-socks.yml
├── docker-compose-ssl.yaml
├── docker-compose.yml
└── docker-mongo-ssl
│ ├── Dockerfile
│ ├── mongod.conf
│ ├── scripts
│ ├── run.sh
│ └── setup_user.sh
│ └── ssl
│ ├── ca.pem
│ └── kaginari.pem
├── docs
├── index.md
└── resources
│ ├── database_role.md
│ └── database_user.md
├── examples
├── Makefile
├── documentDB
│ ├── Makefile
│ ├── main.tf
│ └── variables.tf
└── main.tf
├── go.mod
├── go.sum
├── main.go
├── mmo.md
└── mongodb
├── config.go
├── helpers.go
├── provider.go
├── resource_db_role.go
└── resource_db_user.go
/.github/workflows/golangci.yml:
--------------------------------------------------------------------------------
1 | name: golangci
2 | on:
3 | push:
4 | tags:
5 | - v*
6 | branches:
7 | - master
8 | pull_request:
9 |
10 | jobs:
11 | go_lint:
12 | name: golangci-lint
13 | runs-on: ubuntu-latest
14 | steps:
15 | - uses: actions/checkout@v2
16 | - name: Run golangci-lint
17 | uses: golangci/golangci-lint-action@v2
18 | with:
19 | version: v1.30
20 | skip-go-installation: true
21 |
22 | go_test:
23 | name: golang test
24 | runs-on: ubuntu-latest
25 | steps:
26 | - uses: actions/checkout@v2
27 | - name: Download Go modules
28 | run: go mod download
29 | - name: Run Test
30 | run: go test ./...
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
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
12 | - name: Unshallow
13 | run: git fetch --prune --unshallow
14 | - name: Set up Go
15 | uses: actions/setup-go@v2
16 | with:
17 | go-version: 1.17
18 | - name: Import GPG key
19 | id: import_gpg
20 | uses: paultyng/ghaction-import-gpg@v2.1.0
21 | env:
22 | GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
23 | PASSPHRASE: ${{ secrets.PASSPHRASE }}
24 | - name: Run GoReleaser
25 | uses: goreleaser/goreleaser-action@v2
26 | with:
27 | version: latest
28 | args: release --rm-dist
29 | env:
30 | GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }}
31 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
32 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/*.tfstate
2 | **/*.tfstate.backup
3 | **/*.idea
4 | **/.terraform
5 | **/*.locl.hcl
6 | **/testgo/**
7 | **/.terraform.lock.hcl
8 |
--------------------------------------------------------------------------------
/.golangci.yml:
--------------------------------------------------------------------------------
1 | run:
2 | deadline: 10m
3 |
4 | issues:
5 | max-per-linter: 0
6 | max-same-issues: 0
7 |
8 | linters:
9 | disable-all: true
10 | enable:
11 | - deadcode
12 | - errcheck
13 | - ineffassign
14 | - interfacer
15 | - nakedret
16 | - misspell
17 | - typecheck
18 | - unused
19 | - unconvert
20 | - unparam
21 | - varcheck
22 | - vet
23 | - vetshadow
24 |
25 | linters-settings:
26 | errcheck:
27 | ignore: github.com/hashicorp/terraform-plugin-sdk/helper/schema:ForceNew|Set,fmt:.*,io:Close
28 | misspell:
29 | ignore-words:
30 | - hdinsight
31 | - exportfs
--------------------------------------------------------------------------------
/.goreleaser.yml:
--------------------------------------------------------------------------------
1 | # Visit https://goreleaser.com for documentation on how to customize this
2 | # behavior.
3 | before:
4 | hooks:
5 | # this is just an example and not a requirement for provider building/publishing
6 | - go mod tidy
7 | builds:
8 | - env:
9 | # goreleaser does not work with CGO, it could also complicate
10 | # usage by users in CI/CD systems like Terraform Cloud where
11 | # they are unable to install libraries.
12 | - CGO_ENABLED=0
13 | mod_timestamp: '{{ .CommitTimestamp }}'
14 | flags:
15 | - -trimpath
16 | ldflags:
17 | - '-s -w -X main.version={{.Version}} -X main.commit={{.Commit}}'
18 | goos:
19 | - freebsd
20 | - windows
21 | - linux
22 | - darwin
23 | goarch:
24 | - amd64
25 | - '386'
26 | - arm
27 | - arm64
28 | ignore:
29 | - goos: darwin
30 | goarch: '386'
31 | binary: '{{ .ProjectName }}_{{ .Version }}'
32 | archives:
33 | - format: zip
34 | name_template: '{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}'
35 | checksum:
36 | name_template: '{{ .ProjectName }}_{{ .Version }}_SHA256SUMS'
37 | algorithm: sha256
38 | signs:
39 | - artifacts: checksum
40 | args:
41 | # if you are using this is a GitHub action or some other automated pipeline, you
42 | # need to pass the batch flag to indicate its not interactive .
43 | - "--batch"
44 | - "--local-user"
45 | - "{{ .Env.GPG_FINGERPRINT }}" # set this environment variable for your signing key
46 | - "--output"
47 | - "${signature}"
48 | - "--detach-sign"
49 | - "${artifact}"
50 | release:
51 | # If you want to manually examine the release before its live, uncomment this line:
52 | # draft: true
53 | changelog:
54 | skip: true
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /../../../../../../../../../:\Users\monta\go\src\github.com\Kaginari\terraform-provider-mongodb\.idea/dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/terraform-provider-mongodb.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Kaginari
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 | ifndef VERBOSE
2 | MAKEFLAGS += --no-print-directory
3 | endif
4 |
5 | default: install
6 |
7 | .PHONY: install lint unit
8 |
9 | OS_ARCH=linux_amd64
10 | #
11 | # Set correct OS_ARCH on Mac
12 | UNAME := $(shell uname -s)
13 | ifeq ($(UNAME),Darwin)
14 | HW := $(shell uname -m)
15 | ifeq ($(HW),arm64)
16 | ARCH=$(HW)
17 | else
18 | ARCH=amd64
19 | endif
20 | OS_ARCH=darwin_$(ARCH)
21 | endif
22 |
23 | HOSTNAME=registry.terraform.io
24 | NAMESPACE=Kaginari
25 | NAME=mongodb
26 | VERSION=9.9.9
27 | ## on linux base os
28 | TERRAFORM_PLUGINS_DIRECTORY=~/.terraform.d/plugins/${HOSTNAME}/${NAMESPACE}/${NAME}/${VERSION}/${OS_ARCH}
29 |
30 |
31 | install:
32 | mkdir -p ${TERRAFORM_PLUGINS_DIRECTORY}
33 | go build -o ${TERRAFORM_PLUGINS_DIRECTORY}/terraform-provider-${NAME}
34 | cd examples && rm -rf .terraform
35 | cd examples && make init
36 | re-install:
37 | rm -f ${TERRAFORM_PLUGINS_DIRECTORY}/terraform-provider-${NAME}
38 | go build -o ${TERRAFORM_PLUGINS_DIRECTORY}/terraform-provider-${NAME}
39 | cd examples && rm -rf .terraform
40 | cd examples && make init
41 | lint:
42 | golangci-lint run
43 |
44 |
45 | documentdb-test:
46 | rm -f ${TERRAFORM_PLUGINS_DIRECTORY}/terraform-provider-${NAME}
47 | go build -o ${TERRAFORM_PLUGINS_DIRECTORY}/terraform-provider-${NAME}
48 | cd examples && rm -rf .terraform
49 | cd examples/documentDB && rm -rf .terraform && make init
50 |
51 | documentdb-test-apply:
52 | rm -f ${TERRAFORM_PLUGINS_DIRECTORY}/terraform-provider-${NAME}
53 | go build -o ${TERRAFORM_PLUGINS_DIRECTORY}/terraform-provider-${NAME}
54 | cd examples && rm -rf .terraform
55 | cd examples/documentDB && rm -rf .terraform && make init && make apply
56 |
57 | documentdb-test-apply:
58 | rm -f ${TERRAFORM_PLUGINS_DIRECTORY}/terraform-provider-${NAME}
59 | go build -o ${TERRAFORM_PLUGINS_DIRECTORY}/terraform-provider-${NAME}
60 | cd examples && rm -rf .terraform
61 | cd examples/documentDB && rm -rf .terraform && make init && make destroy
62 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Terraform Provider Mongodb
2 | 
3 | 
4 | 
5 | 
6 | 
7 |
8 |
9 | This repository is a Terraform Mongodb for [Terraform](https://www.terraform.io).
10 |
11 | ### Requirements
12 |
13 | - [Terraform](https://www.terraform.io/downloads.html) >= 0.13
14 | - [Go](https://golang.org/doc/install) >= 1.17
15 |
16 | ### Installation
17 |
18 | 1. Clone the repository
19 | 1. Enter the repository directory
20 | 1. Build the provider using the `make install` command:
21 |
22 | ````bash
23 | git clone https://github.com/Kaginari/terraform-provider-mongodb
24 | cd terraform-provider-mongodb
25 | make install
26 | ````
27 |
28 | ### To test locally
29 |
30 | **1.1: create mongo image with ssl**
31 |
32 |
33 | ````bash
34 | cd docker/docker-mongo-ssl
35 | docker build -t mongo-local .
36 | ````
37 | **1.2: create ssl for localhost**
38 |
39 |
40 | *follow the instruction in this link*
41 |
42 | https://ritesh-yadav.github.io/tech/getting-valid-ssl-certificate-for-localhost-from-letsencrypt/
43 |
44 |
45 | ````bash
46 | nano /etc/hosts
47 | 127.0.0.1 kaginar.herokuapp.com ### add this line
48 | ````
49 |
50 |
51 | **1.3: start the docker-compose**
52 | ````bash
53 | cd docker
54 | docker-compose up -d
55 | ````
56 | **1.4 : create admin user in mongo**
57 |
58 | ````bash
59 | $ docker exec -it mongo -c mongo
60 | > use admin
61 | > db.createUser({ user: "root" , pwd: "root", roles: ["userAdminAnyDatabase", "dbAdminAnyDatabase", "readWriteAnyDatabase"]})
62 | ````
63 | **2: Build the provider**
64 |
65 | follow the [Installation](#Installation)
66 |
67 | **3: Use the provider**
68 |
69 | ````bash
70 | cd mongodb
71 | make apply
72 | ````
73 |
--------------------------------------------------------------------------------
/docker/conf/config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | mongodb: {
3 | ssl: true,
4 | sslValidate: false,
5 | }
6 | };
--------------------------------------------------------------------------------
/docker/docker-compose-socks.yml:
--------------------------------------------------------------------------------
1 | version: '3.1'
2 |
3 | networks:
4 | network:
5 | driver: bridge
6 |
7 | services:
8 | mongo:
9 | container_name: mongo
10 | image: mongo:3.6
11 | restart: always
12 | environment:
13 | - MONGODB_USER:root
14 | - MONGODB_PASS:root
15 | - MONGODB_DATABASE=admin
16 | volumes:
17 | - mongo_data:/data/db
18 | ports:
19 | - 27017:27017
20 | networks:
21 | - network
22 | mongo-express:
23 | image: mongo-express
24 | container_name: mongo-express
25 | ports:
26 | - 8081:8081
27 | environment:
28 | ME_CONFIG_BASICAUTH_USERNAME: root
29 | ME_CONFIG_BASICAUTH_PASSWORD: root
30 | ME_CONFIG_MONGODB_SERVER: mongo
31 | ME_CONFIG_MONGODB_PORT: 27017
32 | ME_CONFIG_MONGODB_ADMINUSERNAME: root
33 | ME_CONFIG_MONGODB_ADMINPASSWORD: root
34 | links:
35 | - mongo:mongo
36 | networks:
37 | - network
38 | depends_on:
39 | - mongo
40 | socks5:
41 | image: serjs/go-socks5-proxy
42 | container_name: socks
43 | ports:
44 | - 1080:1080
45 | networks:
46 | - network
47 | depends_on:
48 | - mongo
49 | volumes:
50 | mongo_data: {}
--------------------------------------------------------------------------------
/docker/docker-compose-ssl.yaml:
--------------------------------------------------------------------------------
1 | version: '3.1'
2 |
3 | networks:
4 | network:
5 | driver: bridge
6 | ipam:
7 | config:
8 | - subnet: 172.30.0.0/24
9 | gateway: 172.30.0.1
10 | services:
11 | mongo:
12 | container_name: mongo
13 | image: mongo-local
14 | restart: always
15 | volumes:
16 | - mongo_data:/data/db
17 | - config_db:/data/configdb
18 | ports:
19 | - 27017:27017
20 | networks:
21 | network:
22 | ipv4_address: 172.30.0.2
23 | mongo-express:
24 | image: mongo-express
25 | container_name: mongo-express
26 | restart: always
27 | ports:
28 | - 8081:8081
29 | environment:
30 | ME_CONFIG_BASICAUTH_USERNAME: admin
31 | ME_CONFIG_BASICAUTH_PASSWORD: admin
32 | ME_CONFIG_MONGODB_SERVER: kaginari.herokuapp.com
33 | ME_CONFIG_MONGODB_PORT: 27017
34 | ME_CONFIG_MONGODB_ADMINUSERNAME: root
35 | ME_CONFIG_MONGODB_ADMINPASSWORD: root
36 | network_mode: host
37 | volumes:
38 | - "./conf/config.js:/node_modules/mongo-express/config.js:ro"
39 | depends_on:
40 | - mongo
41 | volumes:
42 | mongo_data: {}
43 | config_db: {}
44 |
--------------------------------------------------------------------------------
/docker/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.1'
2 |
3 | networks:
4 | network:
5 | driver: bridge
6 |
7 | services:
8 | mongo:
9 | container_name: mongo
10 | image: mongo:3.6
11 | restart: always
12 | environment:
13 | - MONGODB_USER:root
14 | - MONGODB_PASS:root
15 | - MONGODB_DATABASE=admin
16 | volumes:
17 | - mongo_data:/data/db
18 | ports:
19 | - 27017:27017
20 | networks:
21 | - network
22 | mongo-express:
23 | image: mongo-express
24 | container_name: mongo-express
25 | ports:
26 | - 8081:8081
27 | environment:
28 | ME_CONFIG_BASICAUTH_USERNAME: root
29 | ME_CONFIG_BASICAUTH_PASSWORD: root
30 | ME_CONFIG_MONGODB_SERVER: mongo
31 | ME_CONFIG_MONGODB_PORT: 27017
32 | ME_CONFIG_MONGODB_ADMINUSERNAME: root
33 | ME_CONFIG_MONGODB_ADMINPASSWORD: root
34 | links:
35 | - mongo:mongo
36 | networks:
37 | - network
38 | depends_on:
39 | - mongo
40 | volumes:
41 | mongo_data: {}
--------------------------------------------------------------------------------
/docker/docker-mongo-ssl/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mongo:3.6.2-jessie
2 |
3 | COPY scripts /home/mongodb/scripts
4 |
5 | COPY ssl /home/mongodb/ssl
6 |
7 | COPY mongod.conf /home/mongodb
8 |
9 | WORKDIR /home/mongodb
10 |
11 | RUN ["chmod", "+x", "/home/mongodb/scripts/"]
12 |
13 | CMD ["/home/mongodb/scripts/run.sh"]
--------------------------------------------------------------------------------
/docker/docker-mongo-ssl/mongod.conf:
--------------------------------------------------------------------------------
1 | net:
2 | bindIp: 0.0.0.0
3 | port: 27017
4 | ssl:
5 | CAFile: /home/mongodb/ssl/ca.pem
6 | PEMKeyFile: /home/mongodb/ssl/kaginari.pem
7 | mode: requireSSL
8 | disabledProtocols: "TLS1_0,TLS1_1"
9 | allowConnectionsWithoutCertificates: true
10 | storage:
11 | journal:
12 | enabled: true
--------------------------------------------------------------------------------
/docker/docker-mongo-ssl/scripts/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | sleep 5
4 |
5 | chown -R mongodb:mongodb /home/mongodb
6 |
7 | nohup gosu mongodb mongod --dbpath=/data/db &
8 |
9 | nohup gosu mongodb mongo admin --eval "help" > /dev/null 2>&1
10 | RET=$?
11 |
12 | while [[ "$RET" -ne 0 ]]; do
13 | echo "Waiting for MongoDB to start..."
14 | mongo admin --eval "help" > /dev/null 2>&1
15 | RET=$?
16 | sleep 2
17 | done
18 |
19 | bash /home/mongodb/scripts/setup_user.sh
20 |
21 | gosu mongodb mongod --dbpath=/data/db --config mongod.conf --bind_ip_all --auth
--------------------------------------------------------------------------------
/docker/docker-mongo-ssl/scripts/setup_user.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | echo "************************************************************"
4 | echo "Setting up users..."
5 | echo "************************************************************"
6 |
7 | # create root user
8 | nohup gosu mongodb mongo admin --eval "db.createUser({user: 'root', pwd: 'root', roles:[{ role: 'root', db: 'admin' }]});"
9 |
10 | # create app user/database
11 | nohup gosu mongodb mongo admin --eval "db.createUser({ user: 'admin', pwd: 'admin', roles: ['userAdminAnyDatabase', 'dbAdminAnyDatabase', 'readWriteAnyDatabase']});"
12 |
13 | echo "************************************************************"
14 | echo "Shutting down"
15 | echo "************************************************************"
16 | nohup gosu mongodb mongo admin --eval "db.shutdownServer();"
--------------------------------------------------------------------------------
/docker/docker-mongo-ssl/ssl/ca.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
3 | MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
4 | DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
5 | PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
6 | Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
7 | AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
8 | rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
9 | OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
10 | xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
11 | 7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
12 | aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
13 | HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
14 | SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
15 | ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
16 | AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
17 | R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
18 | JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
19 | Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
20 | -----END CERTIFICATE-----
21 | -----BEGIN CERTIFICATE-----
22 | MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
23 | MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
24 | DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
25 | SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
26 | GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
27 | AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
28 | q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
29 | SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
30 | Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
31 | a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
32 | /PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
33 | AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
34 | CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
35 | bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
36 | c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
37 | VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
38 | ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
39 | MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
40 | Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
41 | AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
42 | uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
43 | wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
44 | X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
45 | PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
46 | KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
47 | -----END CERTIFICATE-----
48 |
--------------------------------------------------------------------------------
/docker/docker-mongo-ssl/ssl/kaginari.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCgptuYwTaYmOqC
3 | nTN72QKBqEXHW/yN9gZLJyTmPlcDrBXR8WY0WiKaDpJbHvH8HTgt12wUjFW3P6py
4 | DtnkTdtz3OXt6BZjejXZgAPW/KA10+/3GyZgfDWFfUKe/r5D5RxUduK5QVEyOVHT
5 | kUqpcxl5WR7eK6Xt01ElLeKNO1yhjT0J11nOWezfI9w6Q443N+XV+/k3HJ36382A
6 | 1ZeXQ3NcLZdJs6eGitb+3gk1vFZVFE2+kF0ApMw/+Qt7LciciDCM99x/N5rFqBul
7 | n010WfUfpwDsnh6Iq98hmecTYLP1dP0xM1IWAGoRSOkNY8wHuxvzxajlBHS0iY4p
8 | r/ffNHkBAgMBAAECggEAHbwEdRd95WyYKyixeMDHx/u/PpD2A8h/jbVnDP6I2HMn
9 | br5BbnsoYF9GE3t8ym8WENYIeR0oWEx+XbIF/k2yypUeMZR9YFgkU2dwToBfntbl
10 | WVU7GyyiM1zl0cvQp3xma/O9LxC52JPnY0NHEGnvUxh9sB1gDs7H/BusDPvpvzS7
11 | /O+KSE056426fwmkGXpnNmQ8lKyMRKKIZNgcVW6TlLyU6i0ruChhYbMqYsqdHtEM
12 | 8rVU7M5kIiqUja6bdh4B14tvvz6BbrZkP9BrkTDhRIp77fK1Mn5h3YLoGjIQLj6w
13 | FbazUPhobOoJP/8WIWyxYl8/yWNr3Ru50ZaDnLtiCQKBgQDN7ytd5gl5ET6CzZmJ
14 | vLa+eqCD0E4raFzJMH4U07xvQ8ti7chUIx6q2/s89lSWTBIc/moPMbfs06a7mj12
15 | 0nEYf9/u6dYk+Gh5pebTGAZItV63cOajiNu6o8pSUJpz9/kEqXYNnBJV6LB0JK09
16 | 4fcdunzCpfdPX664ZvsiNK6R1wKBgQDHtWviapU08CKYFtl6pCeSIT8dljnZv9Pp
17 | GheUtmGODNCW5um5Vpa6rPvIs/duy0t4jcm0SjDvyeJ78JLtnHka431/srX9xlR2
18 | xasnIcXh6B0jnMDTp+ZWTQAhS3y2l5KLv4YJLdUPst0gviiv0eDOFSPg30uBQJpc
19 | l4Tm0awg5wKBgQCnu9rSzH+CwOztlZEtgyxF0ZPUSWKiMIsCxCCtzhh5d/q9RXga
20 | L9DW0f69FNao5KUMQJ0aayCoIWx4+ZR+p8G+dslqy8PEsSBHlT2BStwzdKcFO0xg
21 | fySZzLcKfOSQ+LU3et/RDgJRPwoaT5VcBiVFbZQY5x2c5Q5m3FpI7igSWQKBgB6j
22 | 6ByB68iGe1hIUS+u1d9muG9KqC+Pbezasvl/DfKkZrBwVzW3YkLb3XmKmxDlofuq
23 | DWNa6q0vlU8ctv47vpzwgEXCXofEERtz8nF7jge9/BKFr1QJ854UDEwPb9/322UT
24 | inYIESNqduDaLBXlpo8X0TxkJgp7pfNE0AA19SnLAoGAarXjfqkVWJu2R9skjH/0
25 | zfdb6CYFtHVpjrbZBlDnZ/3WpErbFtJNuAkEqItaCcxKA+PsB4RQJLRVkATd+WzA
26 | voZeEskCQ5EgdfamEOJCY7OdIOSOCSXyS3MaAsh8iub2ef6IBX4u6jqgtBkzsKMo
27 | fXRxB8ShNEvTjhpzL8iKDtk=
28 | -----END PRIVATE KEY-----
29 | -----BEGIN CERTIFICATE-----
30 | MIIFZDCCBEygAwIBAgISA8SqREPofGLDM8dZi7IG8VhWMA0GCSqGSIb3DQEBCwUA
31 | MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
32 | ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0yMDExMTcwOTEyMzJaFw0y
33 | MTAyMTUwOTEyMzJaMCExHzAdBgNVBAMTFmthZ2luYXJpLmhlcm9rdWFwcC5jb20w
34 | ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCgptuYwTaYmOqCnTN72QKB
35 | qEXHW/yN9gZLJyTmPlcDrBXR8WY0WiKaDpJbHvH8HTgt12wUjFW3P6pyDtnkTdtz
36 | 3OXt6BZjejXZgAPW/KA10+/3GyZgfDWFfUKe/r5D5RxUduK5QVEyOVHTkUqpcxl5
37 | WR7eK6Xt01ElLeKNO1yhjT0J11nOWezfI9w6Q443N+XV+/k3HJ36382A1ZeXQ3Nc
38 | LZdJs6eGitb+3gk1vFZVFE2+kF0ApMw/+Qt7LciciDCM99x/N5rFqBuln010WfUf
39 | pwDsnh6Iq98hmecTYLP1dP0xM1IWAGoRSOkNY8wHuxvzxajlBHS0iY4pr/ffNHkB
40 | AgMBAAGjggJrMIICZzAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUH
41 | AwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFPw4gn5Yl4PbX0RP
42 | 1Mo7qs7qcoG5MB8GA1UdIwQYMBaAFKhKamMEfd265tE5t6ZFZe/zqOyhMG8GCCsG
43 | AQUFBwEBBGMwYTAuBggrBgEFBQcwAYYiaHR0cDovL29jc3AuaW50LXgzLmxldHNl
44 | bmNyeXB0Lm9yZzAvBggrBgEFBQcwAoYjaHR0cDovL2NlcnQuaW50LXgzLmxldHNl
45 | bmNyeXB0Lm9yZy8wIQYDVR0RBBowGIIWa2FnaW5hcmkuaGVyb2t1YXBwLmNvbTBM
46 | BgNVHSAERTBDMAgGBmeBDAECATA3BgsrBgEEAYLfEwEBATAoMCYGCCsGAQUFBwIB
47 | FhpodHRwOi8vY3BzLmxldHNlbmNyeXB0Lm9yZzCCAQQGCisGAQQB1nkCBAIEgfUE
48 | gfIA8AB3AG9Tdqwx8DEZ2JkApFEV/3cVHBHZAsEAKQaNsgiaN9kTAAABddWxEcIA
49 | AAQDAEgwRgIhAJRDaIgJKCAg7lCAaGAK9onUh1gzx+uQvpHHdOZJ24txAiEA98Mb
50 | 6wJ3Rll3WkxZRwJOlfxUhcJuD13SscngM/8FKVkAdQD2XJQv0XcwIhRUGAgwlFaO
51 | 400TGTO/3wwvIAvMTvFk4wAAAXXVsRGVAAAEAwBGMEQCIAgeIRe/lTcktVumQcID
52 | RF2oh1+lLWlBi8G9inbMiOaSAiBvCLVPbnd5ePMSlOBcFFVkRW5Hxs7m7oDWgLEl
53 | cX0VCTANBgkqhkiG9w0BAQsFAAOCAQEAYO+7ahYDDhc4Pihstsewdcat/lixzHsV
54 | R2Rqv5c4EodsWqGykOqfMyiCLoiVAP1b9ztELdARD612Vd68cz6pFyIbz+i2b8Li
55 | 7hUNYAs4Q6GsOBv5SVqD6HSJdob07JxnLSl2XvfR49eylVISl8gzeOi6uqu/rO1O
56 | clCOk4TMNZ61EfnJogP74EecAEISi+cLbCIrAuO79h0Ex/Fbea83JNuG2VSNMOKK
57 | c9La4Cn0jcBrOfBLAcHbKWj2M1dZe9Zq631n3X0pyZCf0pe1lozrvCi6CDvAEjwu
58 | /ZXNwyua3gf3zn7g+MmO7BeKntkapcsYJMaAoNgDl/bZX0h0oQrBZA==
59 | -----END CERTIFICATE-----
60 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 |
2 | # MongoDB Provider
3 |
4 | The MongoDB provider is used to interact with the resources supported by [MongoDB](https://www.mongodb.com/). The provider needs to be configured with the proper credentials before it can be used.
5 |
6 | Use the navigation to the left to read about the available provider resources.
7 |
8 | You may want to consider pinning the [provider version](https://www.terraform.io/docs/configuration/providers.html#provider-versions) to ensure you have a chance to review and prepare for changes.
9 |
10 | ## Example Usage
11 |
12 | ```hcl
13 | # Configure the MongoDB Provider
14 | provider "mongodb" {
15 | host = "127.0.0.1"
16 | port = "27017"
17 | username = "root"
18 | password = "root"
19 | auth_database = "admin"
20 | ssl = true
21 | replica_set = "replica-set" #optional
22 | retrywrites = false # default true
23 | direct = true // default false
24 | proxy = "socks5://myproxy:8080" // Optional
25 |
26 | }
27 | ```
28 |
29 | ## Example Usage with ssl
30 |
31 | ```hcl
32 | # Configure the MongoDB Provider
33 | provider "mongodb" {
34 |
35 | insecure_skip_verify = true # default false (set to true to ignore hostname verification)
36 | # -> specify certificate path
37 | certificate = file(pathexpand("path/to/certificate/ca.pem"))
38 |
39 |
40 | }
41 | ```
42 |
43 | ### Environment variables
44 |
45 | You can also provide your credentials via the environment variables, MONGO_HOST, MONGO_PORT, MONGO_USR, and MONGO_PWD respectively:
46 |
47 | ```hcl
48 | provider "mongodb" {
49 | auth_database = "admin"
50 | }
51 | ```
52 |
53 | Usage (prefix the export commands with a space to avoid the keys being recorded in OS history):
54 |
55 | ```shell
56 | $ export MONGO_HOST="xxxx"
57 | $ export MONGO_PORT="xxxx"
58 | $ export MONGO_USR="xxxx"
59 | $ export MONGO_PWD="xxxx"
60 | $ terraform plan
61 | ```
62 |
63 |
64 |
65 |
66 | ## Certificate information :
67 | Specify certificate information either with a directory or directly with the content of the files for connecting to the Mongodb host via TLS.
68 |
69 | ```hcl
70 | provider "mongodb" {
71 | host = "127.0.0.1"
72 | port = "27017"
73 | username = "root"
74 | password = "root"
75 | auth_database = "admin"
76 | ssl = true
77 | # -> specify either
78 | certificate = pathexpand("~/.mongodb/ca.pem")
79 |
80 | }
81 | ```
82 | ## Argument Reference
83 |
84 | In addition to [generic `provider`
85 | arguments](https://www.terraform.io/docs/configuration/providers.html) (e.g.
86 | `alias` and `version`), the following arguments are supported in the MongoDB
87 | `provider` block:
88 |
89 | * `host` - (Optional) This is the host your MongoDB Server. It must be
90 | provided, but it can also be sourced from the `MONGO_HOST`
91 | environment variable.
92 | * `port` - (Optional) This is the port that your MongoDB Server uses. It must be
93 | provided, but it can also be sourced from the `MONGO_PORT`
94 | environment variable.
95 |
96 | * `certificate` - (Optional) Path to a directory with certificate files for connecting to the Docker host via TLS. I. If the path is blank, the MONGODB_CERT will also be checked.
97 |
98 | * `username ` - (Optional) Specifies a username with which to authenticate to the MongoDB database. It must be
99 | provided, but it can also be sourced from the `MONGO_USR`
100 | environment variable.
101 | * `password ` - (Optional) Specifies a password with which to authenticate to the MongoDB database. It must be
102 | provided, but it can also be sourced from the `MONGO_PWD`
103 | environment variable.
104 | * `auth_database ` - (Required) Specifies the authentication database where the specified `username` has been created.
105 | * `ssl ` - (Optional) `default = false `set it to true to connect to a deployment using TLS/SSL with SCRAM authentication.
106 | * `retrywrites ` - (Optional) `default = true `Retryable writes allow MongoDB drivers to automatically retry certain write operations a single time if they encounter network errors, or if they cannot find a healthy primary in the replica sets or sharded cluster.
107 | * `direct ` - (Optional) `default = false ` determine if a direct connection is needed..
108 | * `proxy ` - (Optional) `default = "" ` determine if connecting via a SOCKS5 proxy is needed, it can also be sourced from the `ALL_PROXY` or `all_proxy` environment variable.
109 |
110 |
--------------------------------------------------------------------------------
/docs/resources/database_role.md:
--------------------------------------------------------------------------------
1 | # mongodb_db_role
2 |
3 | `mongodb_db_role` provides a Custom DB Role resource. The customDBRoles resource lets you retrieve, create and modify the custom MongoDB roles in your mongo database server. Use custom MongoDB roles to specify custom sets of privileges.
4 |
5 |
6 | ## Example Usages
7 |
8 | ```hcl
9 | resource "mongodb_db_role" "example_role" {
10 | name = "role_name"
11 | database = "my_database"
12 | privilege {
13 | db = "admin"
14 | collection = "*"
15 | actions = ["collStats"]
16 | }
17 | privilege {
18 | db = "my_database"
19 | collection = ""
20 | actions = ["listCollections", "createCollection","createIndex", "dropIndex", "insert", "remove", "renameCollectionSameDB", "update"]
21 | }
22 |
23 |
24 | }
25 | ```
26 | ## Example Usage with inherited roles
27 |
28 | ```hcl
29 | resource "mongodb_db_role" "role" {
30 | database = "admin"
31 | name = "new_role"
32 | privilege {
33 | db = "admin"
34 | collection = ""
35 | actions = ["collStats"]
36 | }
37 | }
38 |
39 | resource "mongodb_db_role" "role_2" {
40 | depends_on = [mongodb_db_role.role]
41 | database = "admin"
42 | name = "new_role3"
43 |
44 | inherited_role {
45 | role = mongodb_db_role.role.name
46 | db = "admin"
47 | }
48 | }
49 | ```
50 | ## Argument Reference
51 |
52 | * `database` - (Optional) **default="admin"** The database of the role.
53 |
54 | ~> **IMPORTANT:** If a role is created in a specific database you can only use it as inherited in another role in the same database.
55 |
56 | * `name` - (Required) Name of the custom role.
57 |
58 | -> **NOTE:** The specified role name can only contain letters, digits, underscores, and dashes. Additionally, you cannot specify a role name which meets any of the following criteria:
59 |
60 | * Is a name already used by an existing custom role
61 | * Is a name of any of the built-in roles see [built-in-roles](https://docs.mongodb.com/manual/reference/built-in-roles/index.html)
62 |
63 | ### Privilege
64 | Each object in the privilege array represents an individual privilege action granted by the role. It is not required.
65 |
66 | * `actions` - (Required) Array of the privilege action. For a complete list of actions available , see [Custom Role Actions](https://docs.mongodb.com/manual/reference/privilege-actions/)
67 | -> **Note**: The privilege actions available to the Custom Roles API resource represent a subset of the privilege actions available in the Atlas Custom Roles UI.
68 | * `db` Database on which the action is granted.
69 | * `collection` - (Optional) Collection on which the action is granted.
70 | -> **Note**: If collection value is an empty string, the actions are granted on all collections within the database specified in the privilege.db field.
71 |
72 | ### Inherited Roles
73 | Each object in the inheritedRoles array represents a key-value pair indicating the inherited role and the database on which the role is granted. It is an optional field.
74 |
75 | * `db` (Required) Database on which the inherited role is granted.
76 |
77 | -> **NOTE** This value should be admin for all roles except read and readWrite.
78 |
79 | * `role` (Required) Name of the inherited role. This can either be another custom role or a [built-in role](https://docs.mongodb.com/manual/reference/built-in-roles/index.html).
80 |
81 |
82 | ## Import
83 |
84 | ## Import
85 |
86 | Mongodb users can be imported using the hex encoded id, e.g. for a user named `user_test` and his database id `test_db` :
87 |
88 | ```sh
89 | $ printf '%s' "test_db.role_test" | base64
90 | ## this is the output of the command above it will encode db.rolename to HEX
91 | dGVzdF9kYi5yb2xlX3Rlc3Q=
92 |
93 | $ terraform import mongodb_db_role.example_role dGVzdF9kYi5yb2xlX3Rlc3Q=
94 | ```
--------------------------------------------------------------------------------
/docs/resources/database_user.md:
--------------------------------------------------------------------------------
1 | # Mongo Database User
2 |
3 | Provides a Database User resource.
4 |
5 | Each user has a set of roles that provide access to the databases.
6 |
7 | ~> **IMPORTANT:** All arguments including the password will be stored in the raw state as plain-text. [Read more about sensitive data in state.](https://www.terraform.io/docs/state/sensitive-data.html)
8 |
9 | ## Example Usages
10 |
11 | ##### - create user with predefined role
12 | ```hcl
13 |
14 | resource "mongodb_db_user" "user" {
15 | auth_database = "my_database"
16 | name = "example"
17 | password = "example"
18 | role {
19 | role = "readAnyDatabase"
20 | db = "my_database"
21 | }
22 |
23 | }
24 | ```
25 |
26 | ##### - create user with [custom role]() `example_role`
27 | ```hcl
28 | variable "username" {
29 | description = "the user name"
30 | }
31 | variable "password" {
32 | description = "the user password"
33 | }
34 |
35 | resource "mongodb_db_user" "user_with_custom role" {
36 | depends_on = [mongodb_db_role.example_role]
37 | auth_database = "my_database"
38 | name = var.username
39 | password = var.password
40 | role {
41 | role = mongodb_db_role.example_role.name
42 | db = "my_database"
43 | }
44 | role {
45 | role = "readAnyDatabase"
46 | db = "admin"
47 | }
48 | }
49 | ```
50 | ## Argument Reference
51 |
52 | * `auth_database` - (Required) Database against which Mongo authenticates the user. A user must provide both a username and authentication database to log into MongoDB.
53 | * `role` - (optional) List of user’s roles and the databases / collections on which the roles apply. A role allows the user to perform particular actions on the specified database. A role on the admin database can include privileges that apply to the other databases as well. See [Role](#role) below for more details.
54 |
55 | * `name` - (Required) Username for authenticating to MongoDB.
56 | * `password` - (Required) User's initial password. A value is required to create the database user, however the argument but may be removed from your Terraform configuration after user creation without impacting the user, password or Terraform management.
57 |
58 | ~> **IMPORTANT:** --- Passwords may show up in Terraform related logs and it will be stored in the Terraform state file as plain-text. Password can be changed after creation using your preferred method, e.g. via the MongoDB Shell, to ensure security. If you do change management of the password to outside of Terraform be sure to remove the argument from the Terraform configuration so it is not inadvertently updated to the original password.
59 |
60 | ### Role
61 |
62 | Block mapping a user's role to a database / collection. A role allows the user to perform particular actions on the specified database. A role on the admin database can include privileges that apply to the other databases as well.
63 |
64 | -> **NOTE:** The available privilege actions for custom MongoDB roles support a subset of MongoDB commands.
65 |
66 | * `role` - (Required) Name of the role to grant. See [Create a Database User](https://docs.mongodb.com/manual/reference/method/db.createUser/#create-administrative-user-with-roles) `roles`.
67 |
68 | -> **NOTE:** you can also use [built-in-roles](https://docs.mongodb.com/manual/reference/built-in-roles/index.html)
69 | * `db` - (Required) Database on which the user has the specified role. A role on the `admin` database can include privileges that apply to the other databases.
70 |
71 |
72 |
73 | ## Import
74 |
75 | Mongodb users can be imported using the hex encoded id, e.g. for a user named `user_test` and his database id `test_db` :
76 |
77 | ```sh
78 | $ printf '%s' "test_db.user_test" | base64
79 | ## this is the output of the command above it will encode db.username to HEX
80 | dGVzdF9kYi51c2VyX3Rlc3Q=
81 |
82 | $ terraform import mongodb_db_user.example_user dGVzdF9kYi51c2VyX3Rlc3Q=
83 | ```
--------------------------------------------------------------------------------
/examples/Makefile:
--------------------------------------------------------------------------------
1 | TERRAFORM_PLUGINS_DIRECTORY=${HOME}/.terraform.d/plugins
2 |
3 | init:
4 | cd
5 | terraform init \
6 | -plugin-dir=${TERRAFORM_PLUGINS_DIRECTORY}
7 |
8 | apply:
9 | terraform apply
10 |
11 | plan:
12 | terraform plan
13 |
14 | destroy:
15 | terraform destroy
--------------------------------------------------------------------------------
/examples/documentDB/Makefile:
--------------------------------------------------------------------------------
1 | TERRAFORM_PLUGINS_DIRECTORY=${HOME}/.terraform.d/plugins
2 |
3 | init:
4 | cd
5 | terraform init \
6 | -plugin-dir=${TERRAFORM_PLUGINS_DIRECTORY}
7 |
8 | apply:
9 | terraform apply
10 |
11 | plan:
12 | terraform plan
13 |
14 | destroy:
15 | terraform destroy
--------------------------------------------------------------------------------
/examples/documentDB/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13"
3 |
4 | required_providers {
5 | mongodb = {
6 | source = "registry.terraform.io/Kaginari/mongodb"
7 | version = "9.9.9"
8 | }
9 | }
10 | }
11 | provider "mongodb" {
12 | host = "documentdb-test-terraform.cluster-ro-ctclcdufsrkx.eu-west-3.docdb.amazonaws.com"
13 | port = "27017"
14 | username = ""
15 | password = ""
16 | ssl = true
17 | direct = true
18 | certificate = file(pathexpand("rds-combined-ca-bundle.pem"))
19 | }
20 | resource "mongodb_db_user" "user" {
21 | auth_database = "admin"
22 | name = "monta"
23 | password = "monta"
24 | role {
25 | role = "readAnyDatabase"
26 | db = "admin"
27 | }
28 | role {
29 | role = "readWrite"
30 | db = "local"
31 | }
32 | role {
33 | role = "readWrite"
34 | db = "monta"
35 | }
36 |
37 |
38 | }
--------------------------------------------------------------------------------
/examples/documentDB/variables.tf:
--------------------------------------------------------------------------------
1 | variable "username" {
2 | description = "the user name"
3 | default = "monta_username"
4 | }
5 | variable "password" {
6 | description = "the user password"
7 | default = "monta_password"
8 | }
--------------------------------------------------------------------------------
/examples/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13"
3 |
4 | required_providers {
5 | mongodb = {
6 | source = "registry.terraform.io/Kaginari/mongodb"
7 | version = "9.9.9"
8 | }
9 | }
10 | }
11 |
12 | provider "mongodb" {
13 | host = "mongo"
14 | port = "27017"
15 | username = "root"
16 | password = "root"
17 | ssl = false
18 | auth_database = "admin"
19 | proxy = "socks5://localhost:1080"
20 | }
21 |
22 | variable "username" {
23 | description = "the user name"
24 | default = "monta"
25 | }
26 | variable "password" {
27 | description = "the user password"
28 | default = "monta"
29 | }
30 |
31 | resource "mongodb_db_role" "role" {
32 | name = "custom_role_test"
33 | privilege {
34 | db = "admin"
35 | collection = "*"
36 | actions = ["collStats"]
37 | }
38 | privilege {
39 | db = "ds"
40 | collection = "*"
41 | actions = ["collStats"]
42 | }
43 |
44 |
45 | }
46 |
47 | resource "mongodb_db_role" "role_2" {
48 | depends_on = [mongodb_db_role.role]
49 | database = "admin"
50 | name = "new_role3"
51 | inherited_role {
52 | role = mongodb_db_role.role.name
53 | db = "admin"
54 | }
55 | privilege {
56 | db = "not_inhireted"
57 | collection = "*"
58 | actions = ["collStats"]
59 | }
60 | }
61 | resource "mongodb_db_role" "role4" {
62 | depends_on = [mongodb_db_role.role]
63 | database = "exemple"
64 | name = "new_role4"
65 | }
66 |
67 | resource "mongodb_db_user" "user" {
68 | auth_database = "exemple"
69 | name = "monta"
70 | password = "monta"
71 | role {
72 | role = mongodb_db_role.role.name
73 | db = "admin"
74 | }
75 | role {
76 | role = "readAnyDatabase"
77 | db = "admin"
78 | }
79 | role {
80 | role = "readWrite"
81 | db = "local"
82 | }
83 | role {
84 | role = "readWrite"
85 | db = "monta"
86 | }
87 |
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/Kaginari/terraform-provider-mongodb
2 |
3 | go 1.17
4 |
5 | require (
6 | github.com/hashicorp/terraform-plugin-sdk/v2 v2.1.0
7 | github.com/mitchellh/mapstructure v1.1.2
8 | go.mongodb.org/mongo-driver v1.7.0
9 | golang.org/x/net v0.0.0-20200707034311-ab3426394381
10 | )
11 |
12 | require (
13 | github.com/agext/levenshtein v1.2.2 // indirect
14 | github.com/apparentlymart/go-textseg v1.0.0 // indirect
15 | github.com/go-stack/stack v1.8.0 // indirect
16 | github.com/golang/protobuf v1.4.2 // indirect
17 | github.com/golang/snappy v0.0.1 // indirect
18 | github.com/hashicorp/errwrap v1.0.0 // indirect
19 | github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect
20 | github.com/hashicorp/go-hclog v0.9.2 // indirect
21 | github.com/hashicorp/go-multierror v1.0.0 // indirect
22 | github.com/hashicorp/go-plugin v1.3.0 // indirect
23 | github.com/hashicorp/go-uuid v1.0.1 // indirect
24 | github.com/hashicorp/go-version v1.2.1 // indirect
25 | github.com/hashicorp/hcl/v2 v2.3.0 // indirect
26 | github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect
27 | github.com/klauspost/compress v1.9.5 // indirect
28 | github.com/mitchellh/copystructure v1.0.0 // indirect
29 | github.com/mitchellh/go-testing-interface v1.0.4 // indirect
30 | github.com/mitchellh/go-wordwrap v1.0.0 // indirect
31 | github.com/mitchellh/reflectwalk v1.0.1 // indirect
32 | github.com/oklog/run v1.0.0 // indirect
33 | github.com/pkg/errors v0.9.1 // indirect
34 | github.com/vmihailenco/msgpack v4.0.1+incompatible // indirect
35 | github.com/xdg-go/pbkdf2 v1.0.0 // indirect
36 | github.com/xdg-go/scram v1.0.2 // indirect
37 | github.com/xdg-go/stringprep v1.0.2 // indirect
38 | github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
39 | github.com/zclconf/go-cty v1.2.1 // indirect
40 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
41 | golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 // indirect
42 | golang.org/x/sys v0.0.0-20200523222454-059865788121 // indirect
43 | golang.org/x/text v0.3.5 // indirect
44 | google.golang.org/appengine v1.6.6 // indirect
45 | google.golang.org/genproto v0.0.0-20200711021454-869866162049 // indirect
46 | google.golang.org/grpc v1.30.0 // indirect
47 | google.golang.org/protobuf v1.25.0 // indirect
48 | )
49 |
--------------------------------------------------------------------------------
/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/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
16 | cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
17 | cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
18 | cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
19 | cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
20 | cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
21 | cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
22 | cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
23 | cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
24 | cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
25 | cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
26 | cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
27 | cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
28 | cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
29 | cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
30 | cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
31 | cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
32 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
33 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
34 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
35 | github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
36 | github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE=
37 | github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
38 | github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0=
39 | github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
40 | github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
41 | github.com/apparentlymart/go-cidr v1.0.1/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc=
42 | github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM=
43 | github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0 h1:MzVXffFUye+ZcSR6opIgz9Co7WcDx6ZcY+RjfFHoA0I=
44 | github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM=
45 | github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0=
46 | github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
47 | github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
48 | github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
49 | github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
50 | github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM=
51 | github.com/aws/aws-sdk-go v1.25.3/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
52 | github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
53 | github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
54 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
55 | github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
56 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
57 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
58 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
59 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
60 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
61 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
62 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
63 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
64 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
65 | github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
66 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
67 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
68 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
69 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
70 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
71 | github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
72 | github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
73 | github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
74 | github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
75 | github.com/go-git/go-git-fixtures/v4 v4.0.1/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
76 | github.com/go-git/go-git/v5 v5.1.0/go.mod h1:ZKfuPUoY1ZqIG4QG9BDBh3G4gLM5zvPuSJAozQrZuyM=
77 | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
78 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
79 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
80 | github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
81 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
82 | github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
83 | github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
84 | github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
85 | github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
86 | github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg=
87 | github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
88 | github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
89 | github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs=
90 | github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
91 | github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
92 | github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk=
93 | github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28=
94 | github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo=
95 | github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk=
96 | github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw=
97 | github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360=
98 | github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg=
99 | github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE=
100 | github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8=
101 | github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
102 | github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
103 | github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
104 | github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
105 | github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
106 | github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
107 | github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
108 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
109 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
110 | github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
111 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
112 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
113 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
114 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
115 | github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
116 | github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
117 | github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
118 | github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
119 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
120 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
121 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
122 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
123 | github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
124 | github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
125 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
126 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
127 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
128 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
129 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
130 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
131 | github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
132 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
133 | github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
134 | github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
135 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
136 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
137 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
138 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
139 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
140 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
141 | github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
142 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
143 | github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
144 | github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
145 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
146 | github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
147 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
148 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
149 | github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
150 | github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
151 | github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
152 | github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
153 | github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
154 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
155 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
156 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
157 | github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
158 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
159 | github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg=
160 | github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
161 | github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
162 | github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI=
163 | github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs=
164 | github.com/hashicorp/go-getter v1.4.0/go.mod h1:7qxyCd8rBfcShwsvxgIguu4KbS3l8bUCwg2Umn7RjeY=
165 | github.com/hashicorp/go-getter v1.5.0/go.mod h1:a7z7NPPfNQpJWcn4rSWFtdrSldqLdLPEF3d8nFMsSLM=
166 | github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
167 | github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
168 | github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
169 | github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
170 | github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
171 | github.com/hashicorp/go-plugin v1.3.0 h1:4d/wJojzvHV1I4i/rrjVaeuyxWrLzDE1mDCyDy8fXS8=
172 | github.com/hashicorp/go-plugin v1.3.0/go.mod h1:F9eH4LrE/ZsRdbwhfjs9k9HoDUwAHnYtXdgmf1AVNs0=
173 | github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
174 | github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
175 | github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=
176 | github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
177 | github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
178 | github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI=
179 | github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
180 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
181 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
182 | github.com/hashicorp/hcl/v2 v2.3.0 h1:iRly8YaMwTBAKhn1Ybk7VSdzbnopghktCD031P8ggUE=
183 | github.com/hashicorp/hcl/v2 v2.3.0/go.mod h1:d+FwDBbOLvpAM3Z6J7gPj/VoAGkNe/gm352ZhjJ/Zv8=
184 | github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
185 | github.com/hashicorp/terraform-exec v0.10.0/go.mod h1:tOT8j1J8rP05bZBGWXfMyU3HkLi1LWyqL3Bzsc3CJjo=
186 | github.com/hashicorp/terraform-json v0.5.0/go.mod h1:eAbqb4w0pSlRmdvl8fOyHAi/+8jnkVYN28gJkSJrLhU=
187 | github.com/hashicorp/terraform-plugin-sdk/v2 v2.1.0 h1:Z5K9y5UGVQO7gvLFk6NMA/v1JZW/HLzJ/TTSoLkqQyY=
188 | github.com/hashicorp/terraform-plugin-sdk/v2 v2.1.0/go.mod h1:GP0lmw4Y+XV1OfTmi/hK75t5KWGGzoOzEgUBPGZ6Wq4=
189 | github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
190 | github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=
191 | github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
192 | github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
193 | github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
194 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
195 | github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
196 | github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
197 | github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
198 | github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
199 | github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
200 | github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
201 | github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
202 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
203 | github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
204 | github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
205 | github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
206 | github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
207 | github.com/keybase/go-crypto v0.0.0-20161004153544-93f5b35093ba/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M=
208 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
209 | github.com/klauspost/compress v1.9.5 h1:U+CaK85mrNNb4k8BNOfgJtJ/gr6kswUCFj6miSzVC6M=
210 | github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
211 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
212 | github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
213 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
214 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
215 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
216 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
217 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
218 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
219 | github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
220 | github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
221 | github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
222 | github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
223 | github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
224 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
225 | github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
226 | github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
227 | github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
228 | github.com/mitchellh/cli v1.1.1/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
229 | github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
230 | github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
231 | github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
232 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
233 | github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
234 | github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
235 | github.com/mitchellh/go-testing-interface v1.0.4 h1:ZU1VNC02qyufSZsjjs7+khruk2fKvbQ3TwRV/IBCeFA=
236 | github.com/mitchellh/go-testing-interface v1.0.4/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
237 | github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
238 | github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
239 | github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
240 | github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
241 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
242 | github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
243 | github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE=
244 | github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
245 | github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
246 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
247 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
248 | github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
249 | github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
250 | github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
251 | github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
252 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
253 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
254 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
255 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
256 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
257 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
258 | github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
259 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
260 | github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
261 | github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
262 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
263 | github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
264 | github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
265 | github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
266 | github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
267 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
268 | github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
269 | github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
270 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
271 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
272 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
273 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
274 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
275 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
276 | github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
277 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
278 | github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
279 | github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
280 | github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
281 | github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
282 | github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
283 | github.com/vmihailenco/msgpack v4.0.1+incompatible h1:RMF1enSPeKTlXrXdOcqjFUElywVZjjC6pqse21bKbEU=
284 | github.com/vmihailenco/msgpack v4.0.1+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
285 | github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
286 | github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
287 | github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
288 | github.com/xdg-go/scram v1.0.2 h1:akYIkZ28e6A96dkWNJQu3nmCzH3YfwMPQExUYDaRv7w=
289 | github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
290 | github.com/xdg-go/stringprep v1.0.2 h1:6iq84/ryjjeRmMJwxutI51F2GIPlP5BfTvXHeYjyhBc=
291 | github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
292 | github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
293 | github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
294 | github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
295 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
296 | github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
297 | github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
298 | github.com/zclconf/go-cty v1.2.1 h1:vGMsygfmeCl4Xb6OA5U5XVAaQZ69FvoG7X2jUtQujb8=
299 | github.com/zclconf/go-cty v1.2.1/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
300 | go.mongodb.org/mongo-driver v1.7.0 h1:hHrvOBWlWB2c7+8Gh/Xi5jj82AgidK/t7KVXBZ+IyUA=
301 | go.mongodb.org/mongo-driver v1.7.0/go.mod h1:Q4oFMbo1+MSNqICAdYMlC/zSTrwCogR4R8NzkI+yfU8=
302 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
303 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
304 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
305 | go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
306 | go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
307 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
308 | golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
309 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
310 | golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
311 | golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
312 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
313 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
314 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
315 | golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
316 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
317 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
318 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
319 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
320 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
321 | golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
322 | golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
323 | golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
324 | golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
325 | golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
326 | golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
327 | golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
328 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
329 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
330 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
331 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
332 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
333 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
334 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
335 | golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
336 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
337 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
338 | golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
339 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
340 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
341 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
342 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
343 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
344 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
345 | golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
346 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
347 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
348 | golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
349 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
350 | golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
351 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
352 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
353 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
354 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
355 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
356 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
357 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
358 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
359 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
360 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
361 | golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
362 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
363 | golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
364 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
365 | golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
366 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
367 | golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
368 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
369 | golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
370 | golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
371 | golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
372 | golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
373 | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
374 | golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
375 | golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
376 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
377 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
378 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
379 | golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
380 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
381 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
382 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
383 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
384 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
385 | golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
386 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
387 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
388 | golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
389 | golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
390 | golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
391 | golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
392 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
393 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
394 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
395 | golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
396 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
397 | golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
398 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
399 | golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
400 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
401 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
402 | golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
403 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
404 | golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
405 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
406 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
407 | golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
408 | golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
409 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
410 | golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
411 | golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
412 | golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
413 | golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
414 | golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
415 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
416 | golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
417 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
418 | golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
419 | golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
420 | golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
421 | golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
422 | golang.org/x/sys v0.0.0-20200523222454-059865788121 h1:rITEj+UZHYC927n8GT97eC3zrpzXdb/voyeOuVKS46o=
423 | golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
424 | golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
425 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
426 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
427 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
428 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
429 | golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
430 | golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
431 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
432 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
433 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
434 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
435 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
436 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
437 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
438 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
439 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
440 | golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
441 | golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
442 | golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
443 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
444 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
445 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
446 | golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
447 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
448 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
449 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
450 | golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
451 | golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
452 | golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
453 | golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
454 | golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
455 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
456 | golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
457 | golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
458 | golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
459 | golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
460 | golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
461 | golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
462 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
463 | golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
464 | golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
465 | golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
466 | golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
467 | golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
468 | golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
469 | golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
470 | golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
471 | golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
472 | golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
473 | golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
474 | golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
475 | golang.org/x/tools v0.0.0-20200713011307-fd294ab11aed/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
476 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
477 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
478 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
479 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
480 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
481 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
482 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
483 | google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
484 | google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
485 | google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
486 | google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
487 | google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
488 | google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
489 | google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
490 | google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
491 | google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
492 | google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
493 | google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
494 | google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
495 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
496 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
497 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
498 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
499 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
500 | google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
501 | google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
502 | google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
503 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
504 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
505 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
506 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
507 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
508 | google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
509 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
510 | google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
511 | google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
512 | google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
513 | google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
514 | google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
515 | google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
516 | google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
517 | google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
518 | google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
519 | google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
520 | google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
521 | google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
522 | google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
523 | google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
524 | google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
525 | google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
526 | google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
527 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
528 | google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
529 | google.golang.org/genproto v0.0.0-20200711021454-869866162049 h1:YFTFpQhgvrLrmxtiIncJxFXeCyq84ixuKWVCaCAi9Oc=
530 | google.golang.org/genproto v0.0.0-20200711021454-869866162049/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
531 | google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
532 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
533 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
534 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
535 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
536 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
537 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
538 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
539 | google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
540 | google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
541 | google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
542 | google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE=
543 | google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
544 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
545 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
546 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
547 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
548 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
549 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
550 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
551 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
552 | google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
553 | google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
554 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
555 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
556 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
557 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
558 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
559 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
560 | gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
561 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
562 | gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
563 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
564 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
565 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
566 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
567 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
568 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
569 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
570 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
571 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
572 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
573 | honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
574 | honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
575 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
576 | rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
577 | rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
578 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/Kaginari/terraform-provider-mongodb/mongodb"
5 | "github.com/hashicorp/terraform-plugin-sdk/v2/plugin"
6 | )
7 |
8 | func main() {
9 | plugin.Serve(&plugin.ServeOpts{
10 | ProviderFunc: mongodb.Provider,
11 | })
12 | }
13 |
--------------------------------------------------------------------------------
/mmo.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/mongodb/config.go:
--------------------------------------------------------------------------------
1 | package mongodb
2 |
3 | import (
4 | "context"
5 | "crypto/tls"
6 | "crypto/x509"
7 | "errors"
8 | "fmt"
9 | "go.mongodb.org/mongo-driver/bson"
10 | "go.mongodb.org/mongo-driver/mongo"
11 | "go.mongodb.org/mongo-driver/mongo/options"
12 | "golang.org/x/net/proxy"
13 | "net/url"
14 | "strconv"
15 | "time"
16 | )
17 |
18 | type ClientConfig struct {
19 | Host string
20 | Port string
21 | Username string
22 | Password string
23 | DB string
24 | Ssl bool
25 | InsecureSkipVerify bool
26 | ReplicaSet string
27 | RetryWrites bool
28 | Certificate string
29 | Direct bool
30 | Proxy string
31 | }
32 | type DbUser struct {
33 | Name string `json:"name"`
34 | Password string `json:"password"`
35 | }
36 |
37 | type Role struct {
38 | Role string `json:"role"`
39 | Db string `json:"db"`
40 | }
41 |
42 | func (role Role) String() string {
43 | return fmt.Sprintf("{ role : %s , db : %s }", role.Role, role.Db)
44 | }
45 |
46 | type PrivilegeDto struct {
47 | Db string `json:"db"`
48 | Collection string `json:"collection"`
49 | Actions []string `json:"actions"`
50 | }
51 |
52 | type Privilege struct {
53 | Resource Resource `json:"resource"`
54 | Actions []string `json:"actions"`
55 | }
56 | type SingleResultGetUser struct {
57 | Users []struct {
58 | Id string `json:"_id"`
59 | User string `json:"user"`
60 | Db string `json:"db"`
61 | Roles []struct {
62 | Role string `json:"role"`
63 | Db string `json:"db"`
64 | } `json:"roles"`
65 | } `json:"users"`
66 | }
67 | type SingleResultGetRole struct {
68 | Roles []struct {
69 | Role string `json:"role"`
70 | Db string `json:"db"`
71 | InheritedRoles []struct {
72 | Role string `json:"role"`
73 | Db string `json:"db"`
74 | } `json:"inheritedRoles"`
75 | Privileges []struct {
76 | Resource struct {
77 | Db string `json:"db"`
78 | Collection string `json:"collection"`
79 | } `json:"resource"`
80 | Actions []string `json:"actions"`
81 | } `json:"privileges"`
82 | } `json:"roles"`
83 | }
84 |
85 | func addArgs(arguments string, newArg string) string {
86 | if arguments != "" {
87 | return arguments + "&" + newArg
88 | } else {
89 | return "/?" + newArg
90 | }
91 |
92 | }
93 |
94 | func (c *ClientConfig) MongoClient() (*mongo.Client, error) {
95 |
96 | var verify = false
97 | var arguments = ""
98 |
99 | arguments = addArgs(arguments, "retrywrites="+strconv.FormatBool(c.RetryWrites))
100 |
101 | if c.Ssl {
102 | arguments = addArgs(arguments, "ssl=true")
103 | }
104 |
105 | if c.ReplicaSet != "" && c.Direct == false {
106 | arguments = addArgs(arguments, "replicaSet="+c.ReplicaSet)
107 | }
108 |
109 | if c.Direct {
110 | arguments = addArgs(arguments, "connect="+"direct")
111 | }
112 |
113 | var uri = "mongodb://" + c.Host + ":" + c.Port + arguments
114 |
115 | dialer, dialerErr := proxyDialer(c)
116 |
117 | if dialerErr != nil {
118 | return nil, dialerErr
119 | }
120 | /*
121 | @Since: v0.0.9
122 | verify certificate
123 | */
124 | if c.InsecureSkipVerify {
125 | verify = true
126 | }
127 | /*
128 | @Since: v0.0.7
129 | add certificate support for documentDB
130 | */
131 | if c.Certificate != "" {
132 | tlsConfig, err := getTLSConfigWithAllServerCertificates([]byte(c.Certificate), verify)
133 | if err != nil {
134 | return nil, err
135 | }
136 | mongoClient, err := mongo.NewClient(options.Client().ApplyURI(uri).SetAuth(options.Credential{
137 | AuthSource: c.DB, Username: c.Username, Password: c.Password,
138 | }).SetTLSConfig(tlsConfig).SetDialer(dialer))
139 |
140 | return mongoClient, err
141 | }
142 |
143 | client, err := mongo.NewClient(options.Client().ApplyURI(uri).SetAuth(options.Credential{
144 | AuthSource: c.DB, Username: c.Username, Password: c.Password,
145 | }).SetDialer(dialer))
146 | return client, err
147 | }
148 |
149 | func getTLSConfigWithAllServerCertificates(ca []byte, verify bool) (*tls.Config, error) {
150 | /* As of version 1.2.1, the MongoDB Go Driver will only use the first CA server certificate found in sslcertificateauthorityfile.
151 | The code below addresses this limitation by manually appending all server certificates found in sslcertificateauthorityfile
152 | to a custom TLS configuration used during client creation. */
153 |
154 | tlsConfig := new(tls.Config)
155 |
156 | tlsConfig.InsecureSkipVerify = verify
157 | tlsConfig.RootCAs = x509.NewCertPool()
158 | ok := tlsConfig.RootCAs.AppendCertsFromPEM(ca)
159 |
160 | if !ok {
161 | return tlsConfig, errors.New("Failed parsing pem file")
162 | }
163 |
164 | return tlsConfig, nil
165 | }
166 |
167 | func (privilege Privilege) String() string {
168 | return fmt.Sprintf("{ resource : %s , actions : %s }", privilege.Resource, privilege.Actions)
169 | }
170 |
171 | type Resource struct {
172 | Db string `json:"db"`
173 | Collection string `json:"collection"`
174 | }
175 |
176 | func (resource Resource) String() string {
177 | return fmt.Sprintf(" { db : %s , collection : %s }", resource.Db, resource.Collection)
178 | }
179 |
180 | func createUser(client *mongo.Client, user DbUser, roles []Role, database string) error {
181 | var result *mongo.SingleResult
182 | if len(roles) != 0 {
183 | result = client.Database(database).RunCommand(context.Background(), bson.D{{Key: "createUser", Value: user.Name},
184 | {Key: "pwd", Value: user.Password}, {Key: "roles", Value: roles}})
185 | } else {
186 | result = client.Database(database).RunCommand(context.Background(), bson.D{{Key: "createUser", Value: user.Name},
187 | {Key: "pwd", Value: user.Password}, {Key: "roles", Value: []bson.M{}}})
188 | }
189 |
190 | if result.Err() != nil {
191 | return result.Err()
192 | }
193 | return nil
194 | }
195 |
196 | func getUser(client *mongo.Client, username string, database string) (SingleResultGetUser, error) {
197 | var result *mongo.SingleResult
198 | result = client.Database(database).RunCommand(context.Background(), bson.D{{Key: "usersInfo", Value: bson.D{
199 | {Key: "user", Value: username},
200 | {Key: "db", Value: database},
201 | },
202 | }})
203 | var decodedResult SingleResultGetUser
204 | err := result.Decode(&decodedResult)
205 | if err != nil {
206 | return decodedResult, err
207 | }
208 | return decodedResult, nil
209 | }
210 |
211 | func getRole(client *mongo.Client, roleName string, database string) (SingleResultGetRole, error) {
212 | var result *mongo.SingleResult
213 | result = client.Database(database).RunCommand(context.Background(), bson.D{{Key: "rolesInfo", Value: bson.D{
214 | {Key: "role", Value: roleName},
215 | {Key: "db", Value: database},
216 | },
217 | },
218 | {Key: "showPrivileges", Value: true},
219 | })
220 | var decodedResult SingleResultGetRole
221 | err := result.Decode(&decodedResult)
222 | if err != nil {
223 | return decodedResult, err
224 | }
225 | return decodedResult, nil
226 | }
227 |
228 | func createRole(client *mongo.Client, role string, roles []Role, privilege []PrivilegeDto, database string) error {
229 | var privileges []Privilege
230 | var result *mongo.SingleResult
231 | for _, element := range privilege {
232 | var prv Privilege
233 | prv.Resource = Resource{
234 | Db: element.Db,
235 | Collection: element.Collection,
236 | }
237 | prv.Actions = element.Actions
238 | privileges = append(privileges, prv)
239 | }
240 | if len(roles) != 0 && len(privileges) != 0 {
241 | result = client.Database(database).RunCommand(context.Background(), bson.D{{Key: "createRole", Value: role},
242 | {Key: "privileges", Value: privileges}, {Key: "roles", Value: roles}})
243 | } else if len(roles) == 0 && len(privileges) != 0 {
244 | result = client.Database(database).RunCommand(context.Background(), bson.D{{Key: "createRole", Value: role},
245 | {Key: "privileges", Value: privileges}, {Key: "roles", Value: []bson.M{}}})
246 | } else if len(roles) != 0 && len(privileges) == 0 {
247 | result = client.Database(database).RunCommand(context.Background(), bson.D{{Key: "createRole", Value: role},
248 | {Key: "privileges", Value: []bson.M{}}, {Key: "roles", Value: roles}})
249 | } else {
250 | result = client.Database(database).RunCommand(context.Background(), bson.D{{Key: "createRole", Value: role},
251 | {Key: "privileges", Value: []bson.M{}}, {Key: "roles", Value: []bson.M{}}})
252 | }
253 |
254 | if result.Err() != nil {
255 | return result.Err()
256 | }
257 | return nil
258 | }
259 |
260 | func MongoClientInit(conf *MongoDatabaseConfiguration) (*mongo.Client, error) {
261 |
262 | client, err := conf.Config.MongoClient()
263 | if err != nil {
264 | return nil, err
265 | }
266 | ctx, cancel := context.WithTimeout(context.Background(), conf.MaxConnLifetime*time.Second)
267 | defer cancel()
268 | err = client.Connect(ctx)
269 | if err != nil {
270 | return nil, err
271 | }
272 | err = client.Ping(ctx, nil)
273 | if err != nil {
274 | return nil, err
275 | }
276 | return client, nil
277 | }
278 |
279 | func proxyDialer(c *ClientConfig) (options.ContextDialer, error) {
280 | proxyFromEnv := proxy.FromEnvironment().(options.ContextDialer)
281 | proxyFromProvider := c.Proxy
282 |
283 | if len(proxyFromProvider) > 0 {
284 | proxyURL, err := url.Parse(proxyFromProvider)
285 | if err != nil {
286 | return nil, err
287 | }
288 | proxyDialer, err := proxy.FromURL(proxyURL, proxy.Direct)
289 | if err != nil {
290 | return nil, err
291 | }
292 |
293 | return proxyDialer.(options.ContextDialer), nil
294 | }
295 |
296 | return proxyFromEnv, nil
297 | }
298 |
--------------------------------------------------------------------------------
/mongodb/helpers.go:
--------------------------------------------------------------------------------
1 | package mongodb
2 |
3 | import (
4 | "fmt"
5 | "github.com/hashicorp/go-cty/cty"
6 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
7 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
8 | )
9 |
10 | func validateDiagFunc(validateFunc func(interface{}, string) ([]string, []error)) schema.SchemaValidateDiagFunc {
11 | return func(i interface{}, path cty.Path) diag.Diagnostics {
12 | warnings, errs := validateFunc(i, fmt.Sprintf("%+v", path))
13 | var diags diag.Diagnostics
14 | for _, warning := range warnings {
15 | diags = append(diags, diag.Diagnostic{
16 | Severity: diag.Warning,
17 | Summary: warning,
18 | })
19 | }
20 | for _, err := range errs {
21 | diags = append(diags, diag.Diagnostic{
22 | Severity: diag.Error,
23 | Summary: err.Error(),
24 | })
25 | }
26 | return diags
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/mongodb/provider.go:
--------------------------------------------------------------------------------
1 | package mongodb
2 |
3 | import (
4 | "context"
5 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
6 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
7 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
8 | "regexp"
9 | "time"
10 | )
11 |
12 | func Provider() *schema.Provider {
13 | return &schema.Provider{
14 | Schema: map[string]*schema.Schema{
15 | "host": {
16 | Type: schema.TypeString,
17 | Required: true,
18 | DefaultFunc: schema.EnvDefaultFunc("MONGO_HOST", "127.0.0.1"),
19 | Description: "The mongodb server address",
20 | },
21 | "port": {
22 | Type: schema.TypeString,
23 | Required: true,
24 | DefaultFunc: schema.EnvDefaultFunc("MONGO_PORT", "27017"),
25 | Description: "The mongodb server port",
26 | },
27 | "certificate": {
28 | Type: schema.TypeString,
29 | Optional: true,
30 | DefaultFunc: schema.EnvDefaultFunc("MONGODB_CERT", ""),
31 | Description: "PEM-encoded content of Mongodb host CA certificate",
32 | },
33 |
34 | "username": {
35 | Type: schema.TypeString,
36 | Required: true,
37 | DefaultFunc: schema.EnvDefaultFunc("MONGO_USR", nil),
38 | Description: "The mongodb user",
39 | },
40 | "password": {
41 | Type: schema.TypeString,
42 | Required: true,
43 | DefaultFunc: schema.EnvDefaultFunc("MONGO_PWD", nil),
44 | Description: "The mongodb password",
45 | },
46 | "auth_database": {
47 | Type: schema.TypeString,
48 | Optional: true,
49 | Default: "admin",
50 | Description: "The mongodb auth database",
51 | },
52 | "replica_set": {
53 | Type: schema.TypeString,
54 | Optional: true,
55 | Default: "",
56 | Description: "The mongodb replica set",
57 | },
58 | "insecure_skip_verify": {
59 | Type: schema.TypeBool,
60 | Optional: true,
61 | Default: false,
62 | Description: "ignore hostname verification",
63 | },
64 | "ssl": {
65 | Type: schema.TypeBool,
66 | Optional: true,
67 | Default: false,
68 | Description: "ssl activation",
69 | },
70 | "direct": {
71 | Type: schema.TypeBool,
72 | Optional: true,
73 | Default: false,
74 | Description: "enforces a direct connection instead of discovery",
75 | },
76 | "retrywrites": {
77 | Type: schema.TypeBool,
78 | Optional: true,
79 | Default: true,
80 | Description: "Retryable Writes",
81 | },
82 | "proxy": {
83 | Type: schema.TypeString,
84 | Optional: true,
85 | DefaultFunc: schema.MultiEnvDefaultFunc([]string{
86 | "ALL_PROXY",
87 | "all_proxy",
88 | }, nil),
89 | ValidateDiagFunc: validateDiagFunc(validation.StringMatch(regexp.MustCompile("^socks5h?://.*:\\d+$"), "The proxy URL is not a valid socks url.")),
90 | },
91 | },
92 | ResourcesMap: map[string]*schema.Resource{
93 | "mongodb_db_user": resourceDatabaseUser(),
94 | "mongodb_db_role": resourceDatabaseRole(),
95 | },
96 | DataSourcesMap: map[string]*schema.Resource{},
97 | ConfigureContextFunc: providerConfigure,
98 | }
99 | }
100 |
101 | type MongoDatabaseConfiguration struct {
102 | Config *ClientConfig
103 | MaxConnLifetime time.Duration
104 | }
105 |
106 | func providerConfigure(ctx context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) {
107 | var diags diag.Diagnostics
108 |
109 | clientConfig := ClientConfig{
110 | Host: d.Get("host").(string),
111 | Port: d.Get("port").(string),
112 | Username: d.Get("username").(string),
113 | Password: d.Get("password").(string),
114 | DB: d.Get("auth_database").(string),
115 | Ssl: d.Get("ssl").(bool),
116 | ReplicaSet: d.Get("replica_set").(string),
117 | Certificate: d.Get("certificate").(string),
118 | InsecureSkipVerify: d.Get("insecure_skip_verify").(bool),
119 | Direct: d.Get("direct").(bool),
120 | RetryWrites: d.Get("retrywrites").(bool),
121 | Proxy: d.Get("proxy").(string),
122 | }
123 |
124 | return &MongoDatabaseConfiguration{
125 | Config: &clientConfig,
126 | MaxConnLifetime: 10,
127 | }, diags
128 |
129 | }
130 |
--------------------------------------------------------------------------------
/mongodb/resource_db_role.go:
--------------------------------------------------------------------------------
1 | package mongodb
2 |
3 | import (
4 | "context"
5 | "encoding/base64"
6 | "fmt"
7 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
8 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9 | "github.com/mitchellh/mapstructure"
10 | "go.mongodb.org/mongo-driver/bson"
11 | "strings"
12 | )
13 |
14 | func resourceDatabaseRole() *schema.Resource {
15 | return &schema.Resource{
16 | CreateContext: resourceDatabaseRoleCreate,
17 | ReadContext: resourceDatabaseRoleRead,
18 | UpdateContext: resourceDatabaseRoleUpdate,
19 | DeleteContext: resourceDatabaseRoleDelete,
20 | Importer: &schema.ResourceImporter{
21 | StateContext: schema.ImportStatePassthroughContext,
22 | },
23 | Schema: map[string]*schema.Schema{
24 | "database": {
25 | Type: schema.TypeString,
26 | Optional: true,
27 | Default: "admin",
28 | },
29 | "name": {
30 | Type: schema.TypeString,
31 | Required: true,
32 | },
33 | "privilege": {
34 | Type: schema.TypeSet,
35 | Optional: true,
36 | MaxItems: 10,
37 | Elem: &schema.Resource{
38 | Schema: map[string]*schema.Schema{
39 |
40 | "db": {
41 | Type: schema.TypeString,
42 | Optional: true,
43 | },
44 | "collection": {
45 | Type: schema.TypeString,
46 | Optional: true,
47 | },
48 |
49 | "actions": {
50 | Type: schema.TypeList,
51 | Optional: true,
52 | Elem: &schema.Schema{
53 | Type: schema.TypeString,
54 | },
55 | },
56 | },
57 | },
58 | },
59 | "inherited_role": {
60 | Type: schema.TypeSet,
61 | Optional: true,
62 | MaxItems: 2,
63 | Elem: &schema.Resource{
64 | Schema: map[string]*schema.Schema{
65 | "db": {
66 | Type: schema.TypeString,
67 | Optional: true,
68 | },
69 | "role": {
70 | Type: schema.TypeString,
71 | Required: true,
72 | },
73 | },
74 | },
75 | },
76 | },
77 | }
78 | }
79 |
80 | func resourceDatabaseRoleCreate(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics {
81 | var config = i.(*MongoDatabaseConfiguration)
82 | client , connectionError := MongoClientInit(config)
83 | if connectionError != nil {
84 | return diag.Errorf("Error connecting to database : %s ", connectionError)
85 | }
86 | var role = data.Get("name").(string)
87 | var database = data.Get("database").(string)
88 | var roleList []Role
89 | var privileges []PrivilegeDto
90 |
91 | privilege := data.Get("privilege").(*schema.Set).List()
92 | roles := data.Get("inherited_role").(*schema.Set).List()
93 |
94 | roleMapErr := mapstructure.Decode(roles, &roleList)
95 | if roleMapErr != nil {
96 | return diag.Errorf("Error decoding map : %s ", roleMapErr)
97 | }
98 | privMapErr := mapstructure.Decode(privilege, &privileges)
99 | if privMapErr != nil {
100 | return diag.Errorf("Error decoding map : %s ", privMapErr)
101 | }
102 |
103 |
104 | err := createRole(client, role, roleList, privileges, database)
105 |
106 | if err != nil {
107 | return diag.Errorf("Could not create the role : %s ", err)
108 | }
109 | str := database+"."+role
110 | encoded := base64.StdEncoding.EncodeToString([]byte(str))
111 | data.SetId(encoded)
112 | return resourceDatabaseRoleRead(ctx, data, i)
113 | }
114 |
115 | func resourceDatabaseRoleDelete(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics {
116 | var config = i.(*MongoDatabaseConfiguration)
117 | client , connectionError := MongoClientInit(config)
118 | if connectionError != nil {
119 | return diag.Errorf("Error connecting to database : %s ", connectionError)
120 | }
121 | var stateId = data.State().ID
122 | roleName, database , err := resourceDatabaseRoleParseId(stateId)
123 |
124 | if err != nil {
125 | return diag.Errorf("%s", err)
126 | }
127 |
128 | db := client.Database(database)
129 | result := db.RunCommand(context.Background(), bson.D{{Key: "dropRole", Value: roleName}})
130 |
131 | if result.Err() != nil {
132 | return diag.Errorf("%s",result.Err())
133 | }
134 |
135 | return nil
136 | }
137 |
138 | func resourceDatabaseRoleUpdate(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics {
139 | var config = i.(*MongoDatabaseConfiguration)
140 | client , connectionError := MongoClientInit(config)
141 | if connectionError != nil {
142 | return diag.Errorf("Error connecting to database : %s ", connectionError)
143 | }
144 | var role = data.Get("name").(string)
145 | var stateId = data.State().ID
146 | roleName, database , err := resourceDatabaseRoleParseId(stateId)
147 |
148 | if err != nil {
149 | return diag.Errorf("%s",err)
150 | }
151 |
152 | db := client.Database(database)
153 | result := db.RunCommand(context.Background(), bson.D{{Key: "dropRole", Value: roleName}})
154 |
155 | if result.Err() != nil {
156 | return diag.Errorf("%s", result.Err())
157 | }
158 |
159 | var roleList []Role
160 | var privileges []PrivilegeDto
161 |
162 | privilege := data.Get("privilege").(*schema.Set).List()
163 | roles := data.Get("inherited_role").(*schema.Set).List()
164 |
165 | roleMapErr := mapstructure.Decode(roles, &roleList)
166 | if roleMapErr != nil {
167 | return diag.Errorf("Error decoding map : %s ", roleMapErr)
168 | }
169 | privMapErr := mapstructure.Decode(privilege, &privileges)
170 | if privMapErr != nil {
171 | return diag.Errorf("Error decoding map : %s ", privMapErr)
172 | }
173 |
174 | err2 := createRole(client, role, roleList, privileges, database)
175 |
176 | if err2 != nil {
177 | return diag.Errorf("Could not create the role : %s ", err)
178 | }
179 | str := database+"."+role
180 | encoded := base64.StdEncoding.EncodeToString([]byte(str))
181 | data.SetId(encoded)
182 |
183 |
184 | return resourceDatabaseRoleRead(ctx, data, i)
185 | }
186 |
187 | func resourceDatabaseRoleRead(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics {
188 | var diags diag.Diagnostics
189 | var config = i.(*MongoDatabaseConfiguration)
190 | client , connectionError := MongoClientInit(config)
191 | if connectionError != nil {
192 | return diag.Errorf("Error connecting to database : %s ", connectionError)
193 | }
194 | stateID := data.State().ID
195 | roleName, database , err := resourceDatabaseRoleParseId(stateID)
196 | if err != nil {
197 | return diag.Errorf("%s",err)
198 | }
199 | result , decodeError := getRole(client,roleName,database)
200 | if decodeError != nil {
201 | return diag.Errorf("Error decoding role : %s ", err)
202 | }
203 | if len(result.Roles) == 0 {
204 | return diag.Errorf("Role does not exist")
205 | }
206 | inheritedRoles := make([]interface{}, len(result.Roles[0].InheritedRoles))
207 |
208 | for i, s := range result.Roles[0].InheritedRoles {
209 | inheritedRoles[i] = map[string]interface{}{
210 | "db": s.Db,
211 | "role": s.Role,
212 | }
213 | }
214 | dataSetError := data.Set("inherited_role", inheritedRoles)
215 | if dataSetError != nil {
216 | return diag.Errorf("Error setting inherited roles : %s ", err)
217 | }
218 | privileges := make([]interface{}, len(result.Roles[0].Privileges))
219 |
220 | for i, s := range result.Roles[0].Privileges {
221 | privileges[i] = map[string]interface{}{
222 | "db": s.Resource.Db,
223 | "collection": s.Resource.Collection,
224 | "actions": s.Actions,
225 | }
226 | }
227 | dataSetError = data.Set("privilege", privileges)
228 | if dataSetError != nil {
229 | return diag.Errorf("Error setting role privilege : %s ", err)
230 | }
231 | dataSetError = data.Set("database", database)
232 | if dataSetError != nil {
233 | return diag.Errorf("Error setting role database : %s ", err)
234 | }
235 | dataSetError = data.Set("name", roleName)
236 | if dataSetError != nil {
237 | return diag.Errorf("Error setting role nam: %s ", err)
238 | }
239 |
240 | data.SetId(stateID)
241 | diags = nil
242 | return diags
243 | }
244 |
245 | func resourceDatabaseRoleParseId(id string) (string, string, error) {
246 | result , errEncoding := base64.StdEncoding.DecodeString(id)
247 |
248 | if errEncoding != nil {
249 | return "", "", fmt.Errorf("unexpected format of ID Error : %s", errEncoding)
250 | }
251 | parts := strings.SplitN(string(result), ".", 2)
252 | if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
253 | return "", "", fmt.Errorf("unexpected format of ID (%s), expected database.roleName", id)
254 | }
255 |
256 | database := parts[0]
257 | roleName := parts[1]
258 |
259 | return roleName , database , nil
260 | }
261 |
262 |
--------------------------------------------------------------------------------
/mongodb/resource_db_user.go:
--------------------------------------------------------------------------------
1 | package mongodb
2 |
3 | import (
4 | "context"
5 | "encoding/base64"
6 | "fmt"
7 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
8 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9 | "github.com/mitchellh/mapstructure"
10 | "go.mongodb.org/mongo-driver/bson"
11 | "strings"
12 | )
13 |
14 | func resourceDatabaseUser() *schema.Resource {
15 | return &schema.Resource{
16 | CreateContext: resourceDatabaseUserCreate,
17 | ReadContext: resourceDatabaseUserRead,
18 | UpdateContext: resourceDatabaseUserUpdate,
19 | DeleteContext: resourceDatabaseUserDelete,
20 | Importer: &schema.ResourceImporter{
21 | StateContext: schema.ImportStatePassthroughContext,
22 | },
23 | Schema: map[string]*schema.Schema{
24 | "auth_database": {
25 | Type: schema.TypeString,
26 | Required: true,
27 | },
28 | "name":{
29 | Type: schema.TypeString,
30 | Required: true,
31 | },
32 | "password":{
33 | Type: schema.TypeString,
34 | Required: true,
35 | },
36 | "role": {
37 | Type: schema.TypeSet,
38 | Optional: true,
39 | MaxItems: 25,
40 | Elem: &schema.Resource{
41 | Schema: map[string]*schema.Schema{
42 | "db": {
43 | Type: schema.TypeString,
44 | Optional: true,
45 | },
46 | "role": {
47 | Type: schema.TypeString,
48 | Required: true,
49 | },
50 | },
51 | },
52 | },
53 | },
54 | }
55 | }
56 |
57 |
58 |
59 | func resourceDatabaseUserDelete(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics {
60 | var config = i.(*MongoDatabaseConfiguration)
61 | client , connectionError := MongoClientInit(config)
62 | if connectionError != nil {
63 | return diag.Errorf("Error connecting to database : %s ", connectionError)
64 | }
65 | var stateId = data.State().ID
66 | var database = data.Get("auth_database").(string)
67 |
68 | id, errEncoding := base64.StdEncoding.DecodeString(stateId)
69 | if errEncoding != nil {
70 | return diag.Errorf("ID mismatch %s", errEncoding)
71 | }
72 |
73 | // StateID is a concatenation of database and username. We only use the username here.
74 | splitId := strings.Split(string(id), ".")
75 | userName := splitId[1]
76 |
77 | adminDB := client.Database(database)
78 |
79 | result := adminDB.RunCommand(context.Background(), bson.D{{Key: "dropUser", Value: userName}})
80 | if result.Err() != nil {
81 | return diag.Errorf("%s",result.Err())
82 | }
83 |
84 | return nil
85 | }
86 |
87 | func resourceDatabaseUserUpdate(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics {
88 | var config = i.(*MongoDatabaseConfiguration)
89 | client , connectionError := MongoClientInit(config)
90 | if connectionError != nil {
91 | return diag.Errorf("Error connecting to database : %s ", connectionError)
92 | }
93 | var stateId = data.State().ID
94 | _, errEncoding := base64.StdEncoding.DecodeString(stateId)
95 | if errEncoding != nil {
96 | return diag.Errorf("ID mismatch %s", errEncoding)
97 | }
98 |
99 | var userName = data.Get("name").(string)
100 | var database = data.Get("auth_database").(string)
101 | var userPassword = data.Get("password").(string)
102 |
103 | adminDB := client.Database(database)
104 |
105 | result := adminDB.RunCommand(context.Background(), bson.D{{Key: "dropUser", Value: userName}})
106 | if result.Err() != nil {
107 | return diag.Errorf("%s",result.Err())
108 | }
109 | var roleList []Role
110 | var user = DbUser{
111 | Name: userName,
112 | Password: userPassword,
113 | }
114 | roles := data.Get("role").(*schema.Set).List()
115 | roleMapErr := mapstructure.Decode(roles, &roleList)
116 | if roleMapErr != nil {
117 | return diag.Errorf("Error decoding map : %s ", roleMapErr)
118 | }
119 | err2 := createUser(client,user,roleList,database)
120 | if err2 != nil {
121 | return diag.Errorf("Could not create the user : %s ", err2)
122 | }
123 |
124 | newId := database+"."+userName
125 | encoded := base64.StdEncoding.EncodeToString([]byte(newId))
126 | data.SetId(encoded)
127 | return resourceDatabaseUserRead(ctx, data, i)
128 | }
129 |
130 | func resourceDatabaseUserRead(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics {
131 | var config = i.(*MongoDatabaseConfiguration)
132 | client , connectionError := MongoClientInit(config)
133 | if connectionError != nil {
134 | return diag.Errorf("Error connecting to database : %s ", connectionError)
135 | }
136 | stateID := data.State().ID
137 | username, database , err := resourceDatabaseUserParseId(stateID)
138 | if err != nil {
139 | return diag.Errorf("%s",err)
140 | }
141 | result , decodeError := getUser(client,username,database)
142 | if decodeError != nil {
143 | return diag.Errorf("Error decoding user : %s ", err)
144 | }
145 | if len(result.Users) == 0 {
146 | return diag.Errorf("user does not exist")
147 | }
148 | roles := make([]interface{}, len(result.Users[0].Roles))
149 |
150 | for i, s := range result.Users[0].Roles {
151 | roles[i] = map[string]interface{}{
152 | "db": s.Db,
153 | "role": s.Role,
154 | }
155 | }
156 | dataSetError := data.Set("role", roles)
157 | if dataSetError != nil {
158 | return diag.Errorf("error setting role : %s " , dataSetError)
159 | }
160 | dataSetError = data.Set("auth_database", database)
161 | if dataSetError != nil {
162 | return diag.Errorf("error setting auth_db : %s " , dataSetError)
163 | }
164 | dataSetError = data.Set("password", data.Get("password"))
165 | if dataSetError != nil {
166 | return diag.Errorf("error setting password : %s " , dataSetError)
167 | }
168 | data.SetId(stateID)
169 | return nil
170 | }
171 |
172 | func resourceDatabaseUserCreate(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics {
173 | var config = i.(*MongoDatabaseConfiguration)
174 | client , connectionError := MongoClientInit(config)
175 | if connectionError != nil {
176 | return diag.Errorf("Error connecting to database : %s ", connectionError)
177 | }
178 | var database = data.Get("auth_database").(string)
179 | var userName = data.Get("name").(string)
180 | var userPassword = data.Get("password").(string)
181 | var roleList []Role
182 | var user = DbUser{
183 | Name: userName,
184 | Password: userPassword,
185 | }
186 | roles := data.Get("role").(*schema.Set).List()
187 | roleMapErr := mapstructure.Decode(roles, &roleList)
188 | if roleMapErr != nil {
189 | return diag.Errorf("Error decoding map : %s ", roleMapErr)
190 | }
191 | err := createUser(client,user,roleList,database)
192 | if err != nil {
193 | return diag.Errorf("Could not create the user : %s ", err)
194 | }
195 | str := database+"."+userName
196 | encoded := base64.StdEncoding.EncodeToString([]byte(str))
197 | data.SetId(encoded)
198 | return resourceDatabaseUserRead(ctx, data, i)
199 | }
200 |
201 | func resourceDatabaseUserParseId(id string) (string, string, error){
202 | result , errEncoding := base64.StdEncoding.DecodeString(id)
203 |
204 | if errEncoding != nil {
205 | return "", "", fmt.Errorf("unexpected format of ID Error : %s", errEncoding)
206 | }
207 | parts := strings.SplitN(string(result), ".", 2)
208 | if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
209 | return "", "", fmt.Errorf("unexpected format of ID (%s), expected attribute1.attribute2", id)
210 | }
211 |
212 | database := parts[0]
213 | userName := parts[1]
214 |
215 | return userName , database , nil
216 | }
217 |
--------------------------------------------------------------------------------